1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 2 /* activation.c Activation of services 3 * 4 * Copyright (C) 2003 CodeFactory AB 5 * Copyright (C) 2003 Red Hat, Inc. 6 * Copyright (C) 2004 Imendio HB 7 * 8 * Licensed under the Academic Free License version 2.1 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 23 * 24 */ 25 26 #include <config.h> 27 #include "activation.h" 28 #include "activation-exit-codes.h" 29 #include "desktop-file.h" 30 #include "dispatch.h" 31 #include "services.h" 32 #include "test.h" 33 #include "utils.h" 34 #include <dbus/dbus-internals.h> 35 #include <dbus/dbus-hash.h> 36 #include <dbus/dbus-list.h> 37 #include <dbus/dbus-shell.h> 38 #include <dbus/dbus-spawn.h> 39 #include <dbus/dbus-timeout.h> 40 #include <dbus/dbus-sysdeps.h> 41 #ifdef HAVE_ERRNO_H 42 #include <errno.h> 43 #endif 44 45 struct BusActivation 46 { 47 int refcount; 48 DBusHashTable *entries; 49 DBusHashTable *pending_activations; 50 char *server_address; 51 BusContext *context; 52 int n_pending_activations; /**< This is in fact the number of BusPendingActivationEntry, 53 * i.e. number of pending activation requests, not pending 54 * activations per se 55 */ 56 DBusHashTable *directories; 57 DBusHashTable *environment; 58 }; 59 60 typedef struct 61 { 62 int refcount; 63 char *dir_c; 64 DBusHashTable *entries; 65 } BusServiceDirectory; 66 67 typedef struct 68 { 69 int refcount; 70 char *name; 71 char *exec; 72 char *user; 73 char *systemd_service; 74 unsigned long mtime; 75 BusServiceDirectory *s_dir; 76 char *filename; 77 } BusActivationEntry; 78 79 typedef struct BusPendingActivationEntry BusPendingActivationEntry; 80 81 struct BusPendingActivationEntry 82 { 83 DBusMessage *activation_message; 84 DBusConnection *connection; 85 86 dbus_bool_t auto_activation; 87 }; 88 89 typedef struct 90 { 91 int refcount; 92 BusActivation *activation; 93 char *service_name; 94 char *exec; 95 char *systemd_service; 96 DBusList *entries; 97 int n_entries; 98 DBusBabysitter *babysitter; 99 DBusTimeout *timeout; 100 unsigned int timeout_added : 1; 101 } BusPendingActivation; 102 103 #if 0 104 static BusServiceDirectory * 105 bus_service_directory_ref (BusServiceDirectory *dir) 106 { 107 _dbus_assert (dir->refcount); 108 109 dir->refcount++; 110 111 return dir; 112 } 113 #endif 114 115 static void 116 bus_service_directory_unref (BusServiceDirectory *dir) 117 { 118 if (dir == NULL) 119 return; 120 121 _dbus_assert (dir->refcount > 0); 122 dir->refcount--; 123 124 if (dir->refcount > 0) 125 return; 126 127 if (dir->entries) 128 _dbus_hash_table_unref (dir->entries); 129 130 dbus_free (dir->dir_c); 131 dbus_free (dir); 132 } 133 134 static void 135 bus_pending_activation_entry_free (BusPendingActivationEntry *entry) 136 { 137 if (entry->activation_message) 138 dbus_message_unref (entry->activation_message); 139 140 if (entry->connection) 141 dbus_connection_unref (entry->connection); 142 143 dbus_free (entry); 144 } 145 146 static void 147 handle_timeout_callback (DBusTimeout *timeout, 148 void *data) 149 { 150 BusPendingActivation *pending_activation = data; 151 152 while (!dbus_timeout_handle (pending_activation->timeout)) 153 _dbus_wait_for_memory (); 154 } 155 156 static BusPendingActivation * 157 bus_pending_activation_ref (BusPendingActivation *pending_activation) 158 { 159 _dbus_assert (pending_activation->refcount > 0); 160 pending_activation->refcount += 1; 161 162 return pending_activation; 163 } 164 165 static void 166 bus_pending_activation_unref (BusPendingActivation *pending_activation) 167 { 168 DBusList *link; 169 170 if (pending_activation == NULL) /* hash table requires this */ 171 return; 172 173 _dbus_assert (pending_activation->refcount > 0); 174 pending_activation->refcount -= 1; 175 176 if (pending_activation->refcount > 0) 177 return; 178 179 if (pending_activation->timeout_added) 180 { 181 _dbus_loop_remove_timeout (bus_context_get_loop (pending_activation->activation->context), 182 pending_activation->timeout, 183 handle_timeout_callback, pending_activation); 184 pending_activation->timeout_added = FALSE; 185 } 186 187 if (pending_activation->timeout) 188 _dbus_timeout_unref (pending_activation->timeout); 189 190 if (pending_activation->babysitter) 191 { 192 if (!_dbus_babysitter_set_watch_functions (pending_activation->babysitter, 193 NULL, NULL, NULL, 194 pending_activation->babysitter, 195 NULL)) 196 _dbus_assert_not_reached ("setting watch functions to NULL failed"); 197 198 _dbus_babysitter_unref (pending_activation->babysitter); 199 } 200 201 dbus_free (pending_activation->service_name); 202 dbus_free (pending_activation->exec); 203 dbus_free (pending_activation->systemd_service); 204 205 link = _dbus_list_get_first_link (&pending_activation->entries); 206 207 while (link != NULL) 208 { 209 BusPendingActivationEntry *entry = link->data; 210 211 bus_pending_activation_entry_free (entry); 212 213 link = _dbus_list_get_next_link (&pending_activation->entries, link); 214 } 215 _dbus_list_clear (&pending_activation->entries); 216 217 pending_activation->activation->n_pending_activations -= 218 pending_activation->n_entries; 219 220 _dbus_assert (pending_activation->activation->n_pending_activations >= 0); 221 222 dbus_free (pending_activation); 223 } 224 225 static BusActivationEntry * 226 bus_activation_entry_ref (BusActivationEntry *entry) 227 { 228 _dbus_assert (entry->refcount > 0); 229 entry->refcount++; 230 231 return entry; 232 } 233 234 static void 235 bus_activation_entry_unref (BusActivationEntry *entry) 236 { 237 if (entry == NULL) /* hash table requires this */ 238 return; 239 240 _dbus_assert (entry->refcount > 0); 241 entry->refcount--; 242 243 if (entry->refcount > 0) 244 return; 245 246 dbus_free (entry->name); 247 dbus_free (entry->exec); 248 dbus_free (entry->user); 249 dbus_free (entry->filename); 250 dbus_free (entry->systemd_service); 251 252 dbus_free (entry); 253 } 254 255 static dbus_bool_t 256 update_desktop_file_entry (BusActivation *activation, 257 BusServiceDirectory *s_dir, 258 DBusString *filename, 259 BusDesktopFile *desktop_file, 260 DBusError *error) 261 { 262 char *name, *exec, *user, *exec_tmp, *systemd_service; 263 BusActivationEntry *entry; 264 DBusStat stat_buf; 265 DBusString file_path; 266 DBusError tmp_error; 267 268 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 269 270 name = NULL; 271 exec = NULL; 272 user = NULL; 273 exec_tmp = NULL; 274 entry = NULL; 275 systemd_service = NULL; 276 277 dbus_error_init (&tmp_error); 278 279 if (!_dbus_string_init (&file_path)) 280 { 281 BUS_SET_OOM (error); 282 return FALSE; 283 } 284 285 if (!_dbus_string_append (&file_path, s_dir->dir_c) || 286 !_dbus_concat_dir_and_file (&file_path, filename)) 287 { 288 BUS_SET_OOM (error); 289 goto failed; 290 } 291 292 if (!_dbus_stat (&file_path, &stat_buf, NULL)) 293 { 294 dbus_set_error (error, DBUS_ERROR_FAILED, 295 "Can't stat the service file\n"); 296 goto failed; 297 } 298 299 if (!bus_desktop_file_get_string (desktop_file, 300 DBUS_SERVICE_SECTION, 301 DBUS_SERVICE_NAME, 302 &name, 303 error)) 304 goto failed; 305 306 if (!bus_desktop_file_get_string (desktop_file, 307 DBUS_SERVICE_SECTION, 308 DBUS_SERVICE_EXEC, 309 &exec_tmp, 310 error)) 311 goto failed; 312 313 /* user is not _required_ unless we are using system activation */ 314 if (!bus_desktop_file_get_string (desktop_file, 315 DBUS_SERVICE_SECTION, 316 DBUS_SERVICE_USER, 317 &user, &tmp_error)) 318 { 319 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 320 /* if we got OOM, then exit */ 321 if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY)) 322 { 323 dbus_move_error (&tmp_error, error); 324 goto failed; 325 } 326 else 327 { 328 /* if we have error because we didn't find anything then continue */ 329 dbus_error_free (&tmp_error); 330 dbus_free (user); 331 user = NULL; 332 } 333 } 334 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 335 336 /* systemd service is never required */ 337 if (!bus_desktop_file_get_string (desktop_file, 338 DBUS_SERVICE_SECTION, 339 DBUS_SERVICE_SYSTEMD_SERVICE, 340 &systemd_service, &tmp_error)) 341 { 342 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 343 /* if we got OOM, then exit */ 344 if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY)) 345 { 346 dbus_move_error (&tmp_error, error); 347 goto failed; 348 } 349 else 350 { 351 /* if we have error because we didn't find anything then continue */ 352 dbus_error_free (&tmp_error); 353 dbus_free (systemd_service); 354 systemd_service = NULL; 355 } 356 } 357 358 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 359 360 entry = _dbus_hash_table_lookup_string (s_dir->entries, 361 _dbus_string_get_const_data (filename)); 362 363 exec = strdup (_dbus_replace_install_prefix (exec_tmp)); 364 365 if (entry == NULL) /* New file */ 366 { 367 /* FIXME we need a better-defined algorithm for which service file to 368 * pick than "whichever one is first in the directory listing" 369 */ 370 if (_dbus_hash_table_lookup_string (activation->entries, name)) 371 { 372 dbus_set_error (error, DBUS_ERROR_FAILED, 373 "Service %s already exists in activation entry list\n", name); 374 goto failed; 375 } 376 377 entry = dbus_new0 (BusActivationEntry, 1); 378 if (entry == NULL) 379 { 380 BUS_SET_OOM (error); 381 goto failed; 382 } 383 384 entry->name = name; 385 entry->exec = exec; 386 entry->user = user; 387 entry->systemd_service = systemd_service; 388 entry->refcount = 1; 389 390 entry->s_dir = s_dir; 391 entry->filename = _dbus_strdup (_dbus_string_get_const_data (filename)); 392 if (!entry->filename) 393 { 394 BUS_SET_OOM (error); 395 goto failed; 396 } 397 398 if (!_dbus_hash_table_insert_string (activation->entries, entry->name, bus_activation_entry_ref (entry))) 399 { 400 BUS_SET_OOM (error); 401 goto failed; 402 } 403 404 if (!_dbus_hash_table_insert_string (s_dir->entries, entry->filename, bus_activation_entry_ref (entry))) 405 { 406 /* Revert the insertion in the entries table */ 407 _dbus_hash_table_remove_string (activation->entries, entry->name); 408 BUS_SET_OOM (error); 409 goto failed; 410 } 411 412 _dbus_verbose ("Added \"%s\" to list of services\n", entry->name); 413 } 414 else /* Just update the entry */ 415 { 416 bus_activation_entry_ref (entry); 417 _dbus_hash_table_remove_string (activation->entries, entry->name); 418 419 if (_dbus_hash_table_lookup_string (activation->entries, name)) 420 { 421 _dbus_verbose ("The new service name \"%s\" of service file \"%s\" already in cache, ignoring\n", 422 name, _dbus_string_get_const_data (&file_path)); 423 goto failed; 424 } 425 426 dbus_free (entry->name); 427 dbus_free (entry->exec); 428 dbus_free (entry->user); 429 dbus_free (entry->systemd_service); 430 entry->systemd_service = systemd_service; 431 entry->name = name; 432 entry->exec = exec; 433 entry->user = user; 434 if (!_dbus_hash_table_insert_string (activation->entries, 435 entry->name, bus_activation_entry_ref(entry))) 436 { 437 BUS_SET_OOM (error); 438 /* Also remove path to entries hash since we want this in sync with 439 * the entries hash table */ 440 _dbus_hash_table_remove_string (entry->s_dir->entries, 441 entry->filename); 442 bus_activation_entry_unref (entry); 443 return FALSE; 444 } 445 } 446 447 entry->mtime = stat_buf.mtime; 448 449 _dbus_string_free (&file_path); 450 bus_activation_entry_unref (entry); 451 452 return TRUE; 453 454 failed: 455 dbus_free (name); 456 dbus_free (exec_tmp); 457 dbus_free (user); 458 dbus_free (systemd_service); 459 _dbus_string_free (&file_path); 460 461 if (entry) 462 bus_activation_entry_unref (entry); 463 464 return FALSE; 465 } 466 467 static dbus_bool_t 468 check_service_file (BusActivation *activation, 469 BusActivationEntry *entry, 470 BusActivationEntry **updated_entry, 471 DBusError *error) 472 { 473 DBusStat stat_buf; 474 dbus_bool_t retval; 475 BusActivationEntry *tmp_entry; 476 DBusString file_path; 477 DBusString filename; 478 479 retval = TRUE; 480 tmp_entry = entry; 481 482 _dbus_string_init_const (&filename, entry->filename); 483 484 if (!_dbus_string_init (&file_path)) 485 { 486 BUS_SET_OOM (error); 487 return FALSE; 488 } 489 490 if (!_dbus_string_append (&file_path, entry->s_dir->dir_c) || 491 !_dbus_concat_dir_and_file (&file_path, &filename)) 492 { 493 BUS_SET_OOM (error); 494 retval = FALSE; 495 goto out; 496 } 497 498 if (!_dbus_stat (&file_path, &stat_buf, NULL)) 499 { 500 _dbus_verbose ("****** Can't stat file \"%s\", removing from cache\n", 501 _dbus_string_get_const_data (&file_path)); 502 503 _dbus_hash_table_remove_string (activation->entries, entry->name); 504 _dbus_hash_table_remove_string (entry->s_dir->entries, entry->filename); 505 506 tmp_entry = NULL; 507 retval = TRUE; 508 goto out; 509 } 510 else 511 { 512 if (stat_buf.mtime > entry->mtime) 513 { 514 BusDesktopFile *desktop_file; 515 DBusError tmp_error; 516 517 dbus_error_init (&tmp_error); 518 519 desktop_file = bus_desktop_file_load (&file_path, &tmp_error); 520 if (desktop_file == NULL) 521 { 522 _dbus_verbose ("Could not load %s: %s\n", 523 _dbus_string_get_const_data (&file_path), 524 tmp_error.message); 525 if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY)) 526 { 527 dbus_move_error (&tmp_error, error); 528 retval = FALSE; 529 goto out; 530 } 531 dbus_error_free (&tmp_error); 532 retval = TRUE; 533 goto out; 534 } 535 536 /* @todo We can return OOM or a DBUS_ERROR_FAILED error 537 * Handle these both better 538 */ 539 if (!update_desktop_file_entry (activation, entry->s_dir, &filename, desktop_file, &tmp_error)) 540 { 541 bus_desktop_file_free (desktop_file); 542 if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY)) 543 { 544 dbus_move_error (&tmp_error, error); 545 retval = FALSE; 546 goto out; 547 } 548 dbus_error_free (&tmp_error); 549 retval = TRUE; 550 goto out; 551 } 552 553 bus_desktop_file_free (desktop_file); 554 retval = TRUE; 555 } 556 } 557 558 out: 559 _dbus_string_free (&file_path); 560 561 if (updated_entry != NULL) 562 *updated_entry = tmp_entry; 563 return retval; 564 } 565 566 567 /* warning: this doesn't fully "undo" itself on failure, i.e. doesn't strip 568 * hash entries it already added. 569 */ 570 static dbus_bool_t 571 update_directory (BusActivation *activation, 572 BusServiceDirectory *s_dir, 573 DBusError *error) 574 { 575 DBusDirIter *iter; 576 DBusString dir, filename; 577 BusDesktopFile *desktop_file; 578 DBusError tmp_error; 579 dbus_bool_t retval; 580 BusActivationEntry *entry; 581 DBusString full_path; 582 583 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 584 585 iter = NULL; 586 desktop_file = NULL; 587 588 _dbus_string_init_const (&dir, s_dir->dir_c); 589 590 if (!_dbus_string_init (&filename)) 591 { 592 BUS_SET_OOM (error); 593 return FALSE; 594 } 595 596 if (!_dbus_string_init (&full_path)) 597 { 598 BUS_SET_OOM (error); 599 _dbus_string_free (&filename); 600 return FALSE; 601 } 602 603 retval = FALSE; 604 605 /* from this point it's safe to "goto out" */ 606 607 iter = _dbus_directory_open (&dir, error); 608 if (iter == NULL) 609 { 610 _dbus_verbose ("Failed to open directory %s: %s\n", 611 s_dir->dir_c, 612 error ? error->message : "unknown"); 613 goto out; 614 } 615 616 /* Now read the files */ 617 dbus_error_init (&tmp_error); 618 while (_dbus_directory_get_next_file (iter, &filename, &tmp_error)) 619 { 620 _dbus_assert (!dbus_error_is_set (&tmp_error)); 621 622 _dbus_string_set_length (&full_path, 0); 623 624 if (!_dbus_string_ends_with_c_str (&filename, ".service")) 625 { 626 _dbus_verbose ("Skipping non-.service file %s\n", 627 _dbus_string_get_const_data (&filename)); 628 continue; 629 } 630 631 entry = _dbus_hash_table_lookup_string (s_dir->entries, _dbus_string_get_const_data (&filename)); 632 if (entry) /* Already has this service file in the cache */ 633 { 634 if (!check_service_file (activation, entry, NULL, error)) 635 goto out; 636 637 continue; 638 } 639 640 if (!_dbus_string_append (&full_path, s_dir->dir_c) || 641 !_dbus_concat_dir_and_file (&full_path, &filename)) 642 { 643 BUS_SET_OOM (error); 644 goto out; 645 } 646 647 /* New file */ 648 desktop_file = bus_desktop_file_load (&full_path, &tmp_error); 649 if (desktop_file == NULL) 650 { 651 _dbus_verbose ("Could not load %s: %s\n", 652 _dbus_string_get_const_data (&full_path), 653 tmp_error.message); 654 655 if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY)) 656 { 657 dbus_move_error (&tmp_error, error); 658 goto out; 659 } 660 661 dbus_error_free (&tmp_error); 662 continue; 663 } 664 665 /* @todo We can return OOM or a DBUS_ERROR_FAILED error 666 * Handle these both better 667 */ 668 if (!update_desktop_file_entry (activation, s_dir, &filename, desktop_file, &tmp_error)) 669 { 670 bus_desktop_file_free (desktop_file); 671 desktop_file = NULL; 672 673 _dbus_verbose ("Could not add %s to activation entry list: %s\n", 674 _dbus_string_get_const_data (&full_path), tmp_error.message); 675 676 if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY)) 677 { 678 dbus_move_error (&tmp_error, error); 679 goto out; 680 } 681 682 dbus_error_free (&tmp_error); 683 continue; 684 } 685 else 686 { 687 bus_desktop_file_free (desktop_file); 688 desktop_file = NULL; 689 continue; 690 } 691 } 692 693 if (dbus_error_is_set (&tmp_error)) 694 { 695 dbus_move_error (&tmp_error, error); 696 goto out; 697 } 698 699 retval = TRUE; 700 701 out: 702 if (!retval) 703 _DBUS_ASSERT_ERROR_IS_SET (error); 704 else 705 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 706 707 if (iter != NULL) 708 _dbus_directory_close (iter); 709 _dbus_string_free (&filename); 710 _dbus_string_free (&full_path); 711 712 return retval; 713 } 714 715 static dbus_bool_t 716 populate_environment (BusActivation *activation) 717 { 718 DBusString key; 719 DBusString value; 720 int i; 721 char **environment; 722 dbus_bool_t retval = FALSE; 723 724 environment = _dbus_get_environment (); 725 726 if (environment == NULL) 727 return FALSE; 728 729 if (!_dbus_string_init (&key)) 730 { 731 dbus_free_string_array (environment); 732 return FALSE; 733 } 734 735 if (!_dbus_string_init (&value)) 736 { 737 _dbus_string_free (&key); 738 dbus_free_string_array (environment); 739 return FALSE; 740 } 741 742 for (i = 0; environment[i] != NULL; i++) 743 { 744 if (!_dbus_string_append (&key, environment[i])) 745 break; 746 747 if (_dbus_string_split_on_byte (&key, '=', &value)) 748 { 749 char *hash_key, *hash_value; 750 751 if (!_dbus_string_steal_data (&key, &hash_key)) 752 break; 753 754 if (!_dbus_string_steal_data (&value, &hash_value)) 755 break; 756 757 if (!_dbus_hash_table_insert_string (activation->environment, 758 hash_key, hash_value)) 759 break; 760 } 761 _dbus_string_set_length (&key, 0); 762 _dbus_string_set_length (&value, 0); 763 } 764 765 if (environment[i] != NULL) 766 goto out; 767 768 retval = TRUE; 769 out: 770 771 _dbus_string_free (&key); 772 _dbus_string_free (&value); 773 dbus_free_string_array (environment); 774 775 return retval; 776 } 777 778 dbus_bool_t 779 bus_activation_reload (BusActivation *activation, 780 const DBusString *address, 781 DBusList **directories, 782 DBusError *error) 783 { 784 DBusList *link; 785 char *dir; 786 787 if (activation->server_address != NULL) 788 dbus_free (activation->server_address); 789 if (!_dbus_string_copy_data (address, &activation->server_address)) 790 { 791 BUS_SET_OOM (error); 792 goto failed; 793 } 794 795 if (activation->entries != NULL) 796 _dbus_hash_table_unref (activation->entries); 797 activation->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, 798 (DBusFreeFunction)bus_activation_entry_unref); 799 if (activation->entries == NULL) 800 { 801 BUS_SET_OOM (error); 802 goto failed; 803 } 804 805 if (activation->directories != NULL) 806 _dbus_hash_table_unref (activation->directories); 807 activation->directories = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, 808 (DBusFreeFunction)bus_service_directory_unref); 809 810 if (activation->directories == NULL) 811 { 812 BUS_SET_OOM (error); 813 goto failed; 814 } 815 816 link = _dbus_list_get_first_link (directories); 817 while (link != NULL) 818 { 819 BusServiceDirectory *s_dir; 820 821 dir = _dbus_strdup ((const char *) link->data); 822 if (!dir) 823 { 824 BUS_SET_OOM (error); 825 goto failed; 826 } 827 828 s_dir = dbus_new0 (BusServiceDirectory, 1); 829 if (!s_dir) 830 { 831 dbus_free (dir); 832 BUS_SET_OOM (error); 833 goto failed; 834 } 835 836 s_dir->refcount = 1; 837 s_dir->dir_c = dir; 838 839 s_dir->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, 840 (DBusFreeFunction)bus_activation_entry_unref); 841 842 if (!s_dir->entries) 843 { 844 bus_service_directory_unref (s_dir); 845 BUS_SET_OOM (error); 846 goto failed; 847 } 848 849 if (!_dbus_hash_table_insert_string (activation->directories, s_dir->dir_c, s_dir)) 850 { 851 bus_service_directory_unref (s_dir); 852 BUS_SET_OOM (error); 853 goto failed; 854 } 855 856 /* only fail on OOM, it is ok if we can't read the directory */ 857 if (!update_directory (activation, s_dir, error)) 858 { 859 if (dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY)) 860 goto failed; 861 else 862 dbus_error_free (error); 863 } 864 865 link = _dbus_list_get_next_link (directories, link); 866 } 867 868 return TRUE; 869 failed: 870 return FALSE; 871 } 872 873 BusActivation* 874 bus_activation_new (BusContext *context, 875 const DBusString *address, 876 DBusList **directories, 877 DBusError *error) 878 { 879 BusActivation *activation; 880 DBusList *link; 881 char *dir; 882 883 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 884 885 activation = dbus_new0 (BusActivation, 1); 886 if (activation == NULL) 887 { 888 BUS_SET_OOM (error); 889 return NULL; 890 } 891 892 activation->refcount = 1; 893 activation->context = context; 894 activation->n_pending_activations = 0; 895 896 if (!bus_activation_reload (activation, address, directories, error)) 897 goto failed; 898 899 /* Initialize this hash table once, we don't want to lose pending 900 * activations on reload. */ 901 activation->pending_activations = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, 902 (DBusFreeFunction)bus_pending_activation_unref); 903 904 if (activation->pending_activations == NULL) 905 { 906 BUS_SET_OOM (error); 907 goto failed; 908 } 909 910 activation->environment = _dbus_hash_table_new (DBUS_HASH_STRING, 911 (DBusFreeFunction) dbus_free, 912 (DBusFreeFunction) dbus_free); 913 914 if (activation->environment == NULL) 915 { 916 BUS_SET_OOM (error); 917 goto failed; 918 } 919 920 if (!populate_environment (activation)) 921 { 922 BUS_SET_OOM (error); 923 goto failed; 924 } 925 926 return activation; 927 928 failed: 929 bus_activation_unref (activation); 930 return NULL; 931 } 932 933 BusActivation * 934 bus_activation_ref (BusActivation *activation) 935 { 936 _dbus_assert (activation->refcount > 0); 937 938 activation->refcount += 1; 939 940 return activation; 941 } 942 943 void 944 bus_activation_unref (BusActivation *activation) 945 { 946 _dbus_assert (activation->refcount > 0); 947 948 activation->refcount -= 1; 949 950 if (activation->refcount > 0) 951 return; 952 953 dbus_free (activation->server_address); 954 if (activation->entries) 955 _dbus_hash_table_unref (activation->entries); 956 if (activation->pending_activations) 957 _dbus_hash_table_unref (activation->pending_activations); 958 if (activation->directories) 959 _dbus_hash_table_unref (activation->directories); 960 if (activation->environment) 961 _dbus_hash_table_unref (activation->environment); 962 963 dbus_free (activation); 964 } 965 966 static dbus_bool_t 967 add_bus_environment (BusActivation *activation, 968 DBusError *error) 969 { 970 const char *type; 971 972 if (!bus_activation_set_environment_variable (activation, 973 "DBUS_STARTER_ADDRESS", 974 activation->server_address, 975 error)) 976 return FALSE; 977 978 type = bus_context_get_type (activation->context); 979 if (type != NULL) 980 { 981 if (!bus_activation_set_environment_variable (activation, 982 "DBUS_STARTER_BUS_TYPE", type, 983 error)) 984 return FALSE; 985 986 if (strcmp (type, "session") == 0) 987 { 988 if (!bus_activation_set_environment_variable (activation, 989 "DBUS_SESSION_BUS_ADDRESS", 990 activation->server_address, 991 error)) 992 return FALSE; 993 } 994 else if (strcmp (type, "system") == 0) 995 { 996 if (!bus_activation_set_environment_variable (activation, 997 "DBUS_SYSTEM_BUS_ADDRESS", 998 activation->server_address, 999 error)) 1000 return FALSE; 1001 } 1002 } 1003 1004 return TRUE; 1005 } 1006 1007 typedef struct 1008 { 1009 BusPendingActivation *pending_activation; 1010 DBusPreallocatedHash *hash_entry; 1011 } RestorePendingData; 1012 1013 static void 1014 restore_pending (void *data) 1015 { 1016 RestorePendingData *d = data; 1017 1018 _dbus_assert (d->pending_activation != NULL); 1019 _dbus_assert (d->hash_entry != NULL); 1020 1021 _dbus_verbose ("Restoring pending activation for service %s, has timeout = %d\n", 1022 d->pending_activation->service_name, 1023 d->pending_activation->timeout_added); 1024 1025 _dbus_hash_table_insert_string_preallocated (d->pending_activation->activation->pending_activations, 1026 d->hash_entry, 1027 d->pending_activation->service_name, d->pending_activation); 1028 1029 bus_pending_activation_ref (d->pending_activation); 1030 1031 d->hash_entry = NULL; 1032 } 1033 1034 static void 1035 free_pending_restore_data (void *data) 1036 { 1037 RestorePendingData *d = data; 1038 1039 if (d->hash_entry) 1040 _dbus_hash_table_free_preallocated_entry (d->pending_activation->activation->pending_activations, 1041 d->hash_entry); 1042 1043 bus_pending_activation_unref (d->pending_activation); 1044 1045 dbus_free (d); 1046 } 1047 1048 static dbus_bool_t 1049 add_restore_pending_to_transaction (BusTransaction *transaction, 1050 BusPendingActivation *pending_activation) 1051 { 1052 RestorePendingData *d; 1053 1054 d = dbus_new (RestorePendingData, 1); 1055 if (d == NULL) 1056 return FALSE; 1057 1058 d->pending_activation = pending_activation; 1059 d->hash_entry = _dbus_hash_table_preallocate_entry (d->pending_activation->activation->pending_activations); 1060 1061 bus_pending_activation_ref (d->pending_activation); 1062 1063 if (d->hash_entry == NULL || 1064 !bus_transaction_add_cancel_hook (transaction, restore_pending, d, 1065 free_pending_restore_data)) 1066 { 1067 free_pending_restore_data (d); 1068 return FALSE; 1069 } 1070 1071 _dbus_verbose ("Saved pending activation to be restored if the transaction fails\n"); 1072 1073 return TRUE; 1074 } 1075 1076 dbus_bool_t 1077 bus_activation_service_created (BusActivation *activation, 1078 const char *service_name, 1079 BusTransaction *transaction, 1080 DBusError *error) 1081 { 1082 BusPendingActivation *pending_activation; 1083 DBusMessage *message; 1084 DBusList *link; 1085 1086 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 1087 1088 /* Check if it's a pending activation */ 1089 pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, service_name); 1090 1091 if (!pending_activation) 1092 return TRUE; 1093 1094 link = _dbus_list_get_first_link (&pending_activation->entries); 1095 while (link != NULL) 1096 { 1097 BusPendingActivationEntry *entry = link->data; 1098 DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link); 1099 1100 if (dbus_connection_get_is_connected (entry->connection)) 1101 { 1102 /* Only send activation replies to regular activation requests. */ 1103 if (!entry->auto_activation) 1104 { 1105 dbus_uint32_t result; 1106 1107 message = dbus_message_new_method_return (entry->activation_message); 1108 if (!message) 1109 { 1110 BUS_SET_OOM (error); 1111 goto error; 1112 } 1113 1114 result = DBUS_START_REPLY_SUCCESS; 1115 1116 if (!dbus_message_append_args (message, 1117 DBUS_TYPE_UINT32, &result, 1118 DBUS_TYPE_INVALID)) 1119 { 1120 dbus_message_unref (message); 1121 BUS_SET_OOM (error); 1122 goto error; 1123 } 1124 1125 if (!bus_transaction_send_from_driver (transaction, entry->connection, message)) 1126 { 1127 dbus_message_unref (message); 1128 BUS_SET_OOM (error); 1129 goto error; 1130 } 1131 1132 dbus_message_unref (message); 1133 } 1134 } 1135 1136 link = next; 1137 } 1138 1139 return TRUE; 1140 1141 error: 1142 return FALSE; 1143 } 1144 1145 dbus_bool_t 1146 bus_activation_send_pending_auto_activation_messages (BusActivation *activation, 1147 BusService *service, 1148 BusTransaction *transaction, 1149 DBusError *error) 1150 { 1151 BusPendingActivation *pending_activation; 1152 DBusList *link; 1153 1154 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 1155 1156 /* Check if it's a pending activation */ 1157 pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, 1158 bus_service_get_name (service)); 1159 1160 if (!pending_activation) 1161 return TRUE; 1162 1163 link = _dbus_list_get_first_link (&pending_activation->entries); 1164 while (link != NULL) 1165 { 1166 BusPendingActivationEntry *entry = link->data; 1167 DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link); 1168 1169 if (entry->auto_activation && dbus_connection_get_is_connected (entry->connection)) 1170 { 1171 DBusConnection *addressed_recipient; 1172 1173 addressed_recipient = bus_service_get_primary_owners_connection (service); 1174 1175 /* Resume dispatching where we left off in bus_dispatch() */ 1176 if (!bus_dispatch_matches (transaction, 1177 entry->connection, 1178 addressed_recipient, 1179 entry->activation_message, error)) 1180 goto error; 1181 } 1182 1183 link = next; 1184 } 1185 1186 if (!add_restore_pending_to_transaction (transaction, pending_activation)) 1187 { 1188 _dbus_verbose ("Could not add cancel hook to transaction to revert removing pending activation\n"); 1189 BUS_SET_OOM (error); 1190 goto error; 1191 } 1192 1193 _dbus_hash_table_remove_string (activation->pending_activations, bus_service_get_name (service)); 1194 1195 return TRUE; 1196 1197 error: 1198 return FALSE; 1199 } 1200 1201 /** 1202 * FIXME @todo the error messages here would ideally be preallocated 1203 * so we don't need to allocate memory to send them. 1204 * Using the usual tactic, prealloc an OOM message, then 1205 * if we can't alloc the real error send the OOM error instead. 1206 */ 1207 static dbus_bool_t 1208 try_send_activation_failure (BusPendingActivation *pending_activation, 1209 const DBusError *how) 1210 { 1211 BusActivation *activation; 1212 DBusList *link; 1213 BusTransaction *transaction; 1214 1215 activation = pending_activation->activation; 1216 1217 transaction = bus_transaction_new (activation->context); 1218 if (transaction == NULL) 1219 return FALSE; 1220 1221 link = _dbus_list_get_first_link (&pending_activation->entries); 1222 while (link != NULL) 1223 { 1224 BusPendingActivationEntry *entry = link->data; 1225 DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link); 1226 1227 if (dbus_connection_get_is_connected (entry->connection)) 1228 { 1229 if (!bus_transaction_send_error_reply (transaction, 1230 entry->connection, 1231 how, 1232 entry->activation_message)) 1233 goto error; 1234 } 1235 1236 link = next; 1237 } 1238 1239 bus_transaction_execute_and_free (transaction); 1240 1241 return TRUE; 1242 1243 error: 1244 if (transaction) 1245 bus_transaction_cancel_and_free (transaction); 1246 return FALSE; 1247 } 1248 1249 /** 1250 * Free the pending activation and send an error message to all the 1251 * connections that were waiting for it. 1252 */ 1253 static void 1254 pending_activation_failed (BusPendingActivation *pending_activation, 1255 const DBusError *how) 1256 { 1257 /* FIXME use preallocated OOM messages instead of bus_wait_for_memory() */ 1258 while (!try_send_activation_failure (pending_activation, how)) 1259 _dbus_wait_for_memory (); 1260 1261 /* Destroy this pending activation */ 1262 _dbus_hash_table_remove_string (pending_activation->activation->pending_activations, 1263 pending_activation->service_name); 1264 } 1265 1266 /** 1267 * Depending on the exit code of the helper, set the error accordingly 1268 */ 1269 static void 1270 handle_servicehelper_exit_error (int exit_code, 1271 DBusError *error) 1272 { 1273 switch (exit_code) 1274 { 1275 case BUS_SPAWN_EXIT_CODE_NO_MEMORY: 1276 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, 1277 "Launcher could not run (out of memory)"); 1278 break; 1279 case BUS_SPAWN_EXIT_CODE_SETUP_FAILED: 1280 dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED, 1281 "Failed to setup environment correctly"); 1282 break; 1283 case BUS_SPAWN_EXIT_CODE_NAME_INVALID: 1284 dbus_set_error (error, DBUS_ERROR_SPAWN_SERVICE_INVALID, 1285 "Bus name is not valid or missing"); 1286 break; 1287 case BUS_SPAWN_EXIT_CODE_SERVICE_NOT_FOUND: 1288 dbus_set_error (error, DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND, 1289 "Bus name not found in system service directory"); 1290 break; 1291 case BUS_SPAWN_EXIT_CODE_PERMISSIONS_INVALID: 1292 dbus_set_error (error, DBUS_ERROR_SPAWN_PERMISSIONS_INVALID, 1293 "The permission of the setuid helper is not correct"); 1294 break; 1295 case BUS_SPAWN_EXIT_CODE_FILE_INVALID: 1296 dbus_set_error (error, DBUS_ERROR_SPAWN_PERMISSIONS_INVALID, 1297 "The service file is incorrect or does not have all required attributes"); 1298 break; 1299 case BUS_SPAWN_EXIT_CODE_EXEC_FAILED: 1300 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, 1301 "Cannot launch daemon, file not found or permissions invalid"); 1302 break; 1303 case BUS_SPAWN_EXIT_CODE_INVALID_ARGS: 1304 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, 1305 "Invalid arguments to command line"); 1306 break; 1307 case BUS_SPAWN_EXIT_CODE_CHILD_SIGNALED: 1308 dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_SIGNALED, 1309 "Launched child was signaled, it probably crashed"); 1310 break; 1311 default: 1312 dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED, 1313 "Launch helper exited with unknown return code %i", exit_code); 1314 break; 1315 } 1316 } 1317 1318 static dbus_bool_t 1319 babysitter_watch_callback (DBusWatch *watch, 1320 unsigned int condition, 1321 void *data) 1322 { 1323 BusPendingActivation *pending_activation = data; 1324 dbus_bool_t retval; 1325 DBusBabysitter *babysitter; 1326 dbus_bool_t uses_servicehelper; 1327 1328 babysitter = pending_activation->babysitter; 1329 1330 _dbus_babysitter_ref (babysitter); 1331 1332 retval = dbus_watch_handle (watch, condition); 1333 1334 /* There are two major cases here; are we the system bus or the session? Here this 1335 * is distinguished by whether or not we use a setuid helper launcher. With the launch helper, 1336 * some process exit codes are meaningful, processed by handle_servicehelper_exit_error. 1337 * 1338 * In both cases though, just ignore when a process exits with status 0; it's possible for 1339 * a program to (misguidedly) "daemonize", and that appears to us as an exit. This closes a race 1340 * condition between this code and the child process claiming the bus name. 1341 */ 1342 uses_servicehelper = bus_context_get_servicehelper (pending_activation->activation->context) != NULL; 1343 1344 /* FIXME this is broken in the same way that 1345 * connection watches used to be; there should be 1346 * a separate callback for status change, instead 1347 * of doing "if we handled a watch status might 1348 * have changed" 1349 * 1350 * Fixing this lets us move dbus_watch_handle 1351 * calls into dbus-mainloop.c 1352 */ 1353 if (_dbus_babysitter_get_child_exited (babysitter)) 1354 { 1355 DBusError error; 1356 DBusHashIter iter; 1357 dbus_bool_t activation_failed; 1358 int exit_code = 0; 1359 1360 dbus_error_init (&error); 1361 1362 _dbus_babysitter_set_child_exit_error (babysitter, &error); 1363 1364 /* Explicitly check for SPAWN_CHILD_EXITED to avoid overwriting an 1365 * exec error */ 1366 if (dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED) 1367 && _dbus_babysitter_get_child_exit_status (babysitter, &exit_code)) 1368 { 1369 activation_failed = exit_code != 0; 1370 1371 dbus_error_free(&error); 1372 1373 if (activation_failed) 1374 { 1375 if (uses_servicehelper) 1376 handle_servicehelper_exit_error (exit_code, &error); 1377 else 1378 _dbus_babysitter_set_child_exit_error (babysitter, &error); 1379 } 1380 } 1381 else 1382 { 1383 activation_failed = TRUE; 1384 } 1385 1386 if (activation_failed) 1387 { 1388 /* Destroy all pending activations with the same exec */ 1389 _dbus_hash_iter_init (pending_activation->activation->pending_activations, 1390 &iter); 1391 while (_dbus_hash_iter_next (&iter)) 1392 { 1393 BusPendingActivation *p = _dbus_hash_iter_get_value (&iter); 1394 1395 if (p != pending_activation && strcmp (p->exec, pending_activation->exec) == 0) 1396 pending_activation_failed (p, &error); 1397 } 1398 1399 /* Destroys the pending activation */ 1400 pending_activation_failed (pending_activation, &error); 1401 1402 dbus_error_free (&error); 1403 } 1404 } 1405 1406 _dbus_babysitter_unref (babysitter); 1407 1408 return retval; 1409 } 1410 1411 static dbus_bool_t 1412 add_babysitter_watch (DBusWatch *watch, 1413 void *data) 1414 { 1415 BusPendingActivation *pending_activation = data; 1416 1417 return _dbus_loop_add_watch (bus_context_get_loop (pending_activation->activation->context), 1418 watch, babysitter_watch_callback, pending_activation, 1419 NULL); 1420 } 1421 1422 static void 1423 remove_babysitter_watch (DBusWatch *watch, 1424 void *data) 1425 { 1426 BusPendingActivation *pending_activation = data; 1427 1428 _dbus_loop_remove_watch (bus_context_get_loop (pending_activation->activation->context), 1429 watch, babysitter_watch_callback, pending_activation); 1430 } 1431 1432 static dbus_bool_t 1433 pending_activation_timed_out (void *data) 1434 { 1435 BusPendingActivation *pending_activation = data; 1436 DBusError error; 1437 1438 /* Kill the spawned process, since it sucks 1439 * (not sure this is what we want to do, but 1440 * may as well try it for now) 1441 */ 1442 if (pending_activation->babysitter) 1443 _dbus_babysitter_kill_child (pending_activation->babysitter); 1444 1445 dbus_error_init (&error); 1446 1447 dbus_set_error (&error, DBUS_ERROR_TIMED_OUT, 1448 "Activation of %s timed out", 1449 pending_activation->service_name); 1450 1451 pending_activation_failed (pending_activation, &error); 1452 1453 dbus_error_free (&error); 1454 1455 return TRUE; 1456 } 1457 1458 static void 1459 cancel_pending (void *data) 1460 { 1461 BusPendingActivation *pending_activation = data; 1462 1463 _dbus_verbose ("Canceling pending activation of %s\n", 1464 pending_activation->service_name); 1465 1466 if (pending_activation->babysitter) 1467 _dbus_babysitter_kill_child (pending_activation->babysitter); 1468 1469 _dbus_hash_table_remove_string (pending_activation->activation->pending_activations, 1470 pending_activation->service_name); 1471 } 1472 1473 static void 1474 free_pending_cancel_data (void *data) 1475 { 1476 BusPendingActivation *pending_activation = data; 1477 1478 bus_pending_activation_unref (pending_activation); 1479 } 1480 1481 static dbus_bool_t 1482 add_cancel_pending_to_transaction (BusTransaction *transaction, 1483 BusPendingActivation *pending_activation) 1484 { 1485 if (!bus_transaction_add_cancel_hook (transaction, cancel_pending, 1486 pending_activation, 1487 free_pending_cancel_data)) 1488 return FALSE; 1489 1490 bus_pending_activation_ref (pending_activation); 1491 1492 _dbus_verbose ("Saved pending activation to be canceled if the transaction fails\n"); 1493 1494 return TRUE; 1495 } 1496 1497 static dbus_bool_t 1498 update_service_cache (BusActivation *activation, DBusError *error) 1499 { 1500 DBusHashIter iter; 1501 1502 _dbus_hash_iter_init (activation->directories, &iter); 1503 while (_dbus_hash_iter_next (&iter)) 1504 { 1505 DBusError tmp_error; 1506 BusServiceDirectory *s_dir; 1507 1508 s_dir = _dbus_hash_iter_get_value (&iter); 1509 1510 dbus_error_init (&tmp_error); 1511 if (!update_directory (activation, s_dir, &tmp_error)) 1512 { 1513 if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY)) 1514 { 1515 dbus_move_error (&tmp_error, error); 1516 return FALSE; 1517 } 1518 1519 dbus_error_free (&tmp_error); 1520 continue; 1521 } 1522 } 1523 1524 return TRUE; 1525 } 1526 1527 static BusActivationEntry * 1528 activation_find_entry (BusActivation *activation, 1529 const char *service_name, 1530 DBusError *error) 1531 { 1532 BusActivationEntry *entry; 1533 1534 entry = _dbus_hash_table_lookup_string (activation->entries, service_name); 1535 if (!entry) 1536 { 1537 if (!update_service_cache (activation, error)) 1538 return NULL; 1539 1540 entry = _dbus_hash_table_lookup_string (activation->entries, 1541 service_name); 1542 } 1543 else 1544 { 1545 BusActivationEntry *updated_entry; 1546 1547 if (!check_service_file (activation, entry, &updated_entry, error)) 1548 return NULL; 1549 1550 entry = updated_entry; 1551 } 1552 1553 if (!entry) 1554 { 1555 dbus_set_error (error, DBUS_ERROR_SERVICE_UNKNOWN, 1556 "The name %s was not provided by any .service files", 1557 service_name); 1558 return NULL; 1559 } 1560 1561 return entry; 1562 } 1563 1564 static char ** 1565 bus_activation_get_environment (BusActivation *activation) 1566 { 1567 char **environment; 1568 int i, length; 1569 DBusString entry; 1570 DBusHashIter iter; 1571 1572 length = _dbus_hash_table_get_n_entries (activation->environment); 1573 1574 environment = dbus_new0 (char *, length + 1); 1575 1576 if (environment == NULL) 1577 return NULL; 1578 1579 i = 0; 1580 _dbus_hash_iter_init (activation->environment, &iter); 1581 1582 if (!_dbus_string_init (&entry)) 1583 { 1584 dbus_free_string_array (environment); 1585 return NULL; 1586 } 1587 1588 while (_dbus_hash_iter_next (&iter)) 1589 { 1590 const char *key, *value; 1591 1592 key = (const char *) _dbus_hash_iter_get_string_key (&iter); 1593 value = (const char *) _dbus_hash_iter_get_value (&iter); 1594 1595 if (!_dbus_string_append_printf (&entry, "%s=%s", key, value)) 1596 break; 1597 1598 if (!_dbus_string_steal_data (&entry, environment + i)) 1599 break; 1600 i++; 1601 } 1602 1603 _dbus_string_free (&entry); 1604 1605 if (i != length) 1606 { 1607 dbus_free_string_array (environment); 1608 environment = NULL; 1609 } 1610 1611 return environment; 1612 } 1613 1614 dbus_bool_t 1615 bus_activation_set_environment_variable (BusActivation *activation, 1616 const char *key, 1617 const char *value, 1618 DBusError *error) 1619 { 1620 char *hash_key; 1621 char *hash_value; 1622 dbus_bool_t retval; 1623 1624 retval = FALSE; 1625 hash_key = NULL; 1626 hash_value = NULL; 1627 hash_key = _dbus_strdup (key); 1628 1629 if (hash_key == NULL) 1630 goto out; 1631 1632 hash_value = _dbus_strdup (value); 1633 1634 if (hash_value == NULL) 1635 goto out; 1636 1637 if (!_dbus_hash_table_insert_string (activation->environment, 1638 hash_key, hash_value)) 1639 goto out; 1640 1641 retval = TRUE; 1642 out: 1643 if (retval == FALSE) 1644 { 1645 dbus_free (hash_key); 1646 dbus_free (hash_value); 1647 BUS_SET_OOM (error); 1648 } 1649 1650 return retval; 1651 } 1652 1653 dbus_bool_t 1654 bus_activation_activate_service (BusActivation *activation, 1655 DBusConnection *connection, 1656 BusTransaction *transaction, 1657 dbus_bool_t auto_activation, 1658 DBusMessage *activation_message, 1659 const char *service_name, 1660 DBusError *error) 1661 { 1662 BusActivationEntry *entry; 1663 BusPendingActivation *pending_activation; 1664 BusPendingActivationEntry *pending_activation_entry; 1665 DBusMessage *message; 1666 DBusString service_str; 1667 const char *servicehelper; 1668 char **argv; 1669 char **envp = NULL; 1670 int argc; 1671 dbus_bool_t retval; 1672 DBusHashIter iter; 1673 dbus_bool_t activated; 1674 DBusString command; 1675 1676 activated = TRUE; 1677 1678 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 1679 1680 if (activation->n_pending_activations >= 1681 bus_context_get_max_pending_activations (activation->context)) 1682 { 1683 dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED, 1684 "The maximum number of pending activations has been reached, activation of %s failed", 1685 service_name); 1686 return FALSE; 1687 } 1688 1689 entry = activation_find_entry (activation, service_name, error); 1690 if (!entry) 1691 return FALSE; 1692 1693 /* Bypass the registry lookup if we're auto-activating, bus_dispatch would not 1694 * call us if the service is already active. 1695 */ 1696 if (!auto_activation) 1697 { 1698 /* Check if the service is active */ 1699 _dbus_string_init_const (&service_str, service_name); 1700 if (bus_registry_lookup (bus_context_get_registry (activation->context), &service_str) != NULL) 1701 { 1702 dbus_uint32_t result; 1703 1704 _dbus_verbose ("Service \"%s\" is already active\n", service_name); 1705 1706 message = dbus_message_new_method_return (activation_message); 1707 1708 if (!message) 1709 { 1710 _dbus_verbose ("No memory to create reply to activate message\n"); 1711 BUS_SET_OOM (error); 1712 return FALSE; 1713 } 1714 1715 result = DBUS_START_REPLY_ALREADY_RUNNING; 1716 1717 if (!dbus_message_append_args (message, 1718 DBUS_TYPE_UINT32, &result, 1719 DBUS_TYPE_INVALID)) 1720 { 1721 _dbus_verbose ("No memory to set args of reply to activate message\n"); 1722 BUS_SET_OOM (error); 1723 dbus_message_unref (message); 1724 return FALSE; 1725 } 1726 1727 retval = bus_transaction_send_from_driver (transaction, connection, message); 1728 dbus_message_unref (message); 1729 if (!retval) 1730 { 1731 _dbus_verbose ("Failed to send reply\n"); 1732 BUS_SET_OOM (error); 1733 } 1734 1735 return retval; 1736 } 1737 } 1738 1739 pending_activation_entry = dbus_new0 (BusPendingActivationEntry, 1); 1740 if (!pending_activation_entry) 1741 { 1742 _dbus_verbose ("Failed to create pending activation entry\n"); 1743 BUS_SET_OOM (error); 1744 return FALSE; 1745 } 1746 1747 pending_activation_entry->auto_activation = auto_activation; 1748 1749 pending_activation_entry->activation_message = activation_message; 1750 dbus_message_ref (activation_message); 1751 pending_activation_entry->connection = connection; 1752 dbus_connection_ref (connection); 1753 1754 /* Check if the service is being activated */ 1755 pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, service_name); 1756 if (pending_activation) 1757 { 1758 if (!_dbus_list_append (&pending_activation->entries, pending_activation_entry)) 1759 { 1760 _dbus_verbose ("Failed to append a new entry to pending activation\n"); 1761 1762 BUS_SET_OOM (error); 1763 bus_pending_activation_entry_free (pending_activation_entry); 1764 return FALSE; 1765 } 1766 1767 pending_activation->n_entries += 1; 1768 pending_activation->activation->n_pending_activations += 1; 1769 } 1770 else 1771 { 1772 pending_activation = dbus_new0 (BusPendingActivation, 1); 1773 if (!pending_activation) 1774 { 1775 _dbus_verbose ("Failed to create pending activation\n"); 1776 1777 BUS_SET_OOM (error); 1778 bus_pending_activation_entry_free (pending_activation_entry); 1779 return FALSE; 1780 } 1781 1782 pending_activation->activation = activation; 1783 pending_activation->refcount = 1; 1784 1785 pending_activation->service_name = _dbus_strdup (service_name); 1786 if (!pending_activation->service_name) 1787 { 1788 _dbus_verbose ("Failed to copy service name for pending activation\n"); 1789 1790 BUS_SET_OOM (error); 1791 bus_pending_activation_unref (pending_activation); 1792 bus_pending_activation_entry_free (pending_activation_entry); 1793 return FALSE; 1794 } 1795 1796 pending_activation->exec = _dbus_strdup (entry->exec); 1797 if (!pending_activation->exec) 1798 { 1799 _dbus_verbose ("Failed to copy service exec for pending activation\n"); 1800 BUS_SET_OOM (error); 1801 bus_pending_activation_unref (pending_activation); 1802 bus_pending_activation_entry_free (pending_activation_entry); 1803 return FALSE; 1804 } 1805 1806 if (entry->systemd_service) 1807 { 1808 pending_activation->systemd_service = _dbus_strdup (entry->systemd_service); 1809 if (!pending_activation->systemd_service) 1810 { 1811 _dbus_verbose ("Failed to copy systemd service for pending activation\n"); 1812 BUS_SET_OOM (error); 1813 bus_pending_activation_unref (pending_activation); 1814 bus_pending_activation_entry_free (pending_activation_entry); 1815 return FALSE; 1816 } 1817 } 1818 1819 pending_activation->timeout = 1820 _dbus_timeout_new (bus_context_get_activation_timeout (activation->context), 1821 pending_activation_timed_out, 1822 pending_activation, 1823 NULL); 1824 if (!pending_activation->timeout) 1825 { 1826 _dbus_verbose ("Failed to create timeout for pending activation\n"); 1827 1828 BUS_SET_OOM (error); 1829 bus_pending_activation_unref (pending_activation); 1830 bus_pending_activation_entry_free (pending_activation_entry); 1831 return FALSE; 1832 } 1833 1834 if (!_dbus_loop_add_timeout (bus_context_get_loop (activation->context), 1835 pending_activation->timeout, 1836 handle_timeout_callback, 1837 pending_activation, 1838 NULL)) 1839 { 1840 _dbus_verbose ("Failed to add timeout for pending activation\n"); 1841 1842 BUS_SET_OOM (error); 1843 bus_pending_activation_unref (pending_activation); 1844 bus_pending_activation_entry_free (pending_activation_entry); 1845 return FALSE; 1846 } 1847 1848 pending_activation->timeout_added = TRUE; 1849 1850 if (!_dbus_list_append (&pending_activation->entries, pending_activation_entry)) 1851 { 1852 _dbus_verbose ("Failed to add entry to just-created pending activation\n"); 1853 1854 BUS_SET_OOM (error); 1855 bus_pending_activation_unref (pending_activation); 1856 bus_pending_activation_entry_free (pending_activation_entry); 1857 return FALSE; 1858 } 1859 1860 pending_activation->n_entries += 1; 1861 pending_activation->activation->n_pending_activations += 1; 1862 1863 activated = FALSE; 1864 _dbus_hash_iter_init (activation->pending_activations, &iter); 1865 while (_dbus_hash_iter_next (&iter)) 1866 { 1867 BusPendingActivation *p = _dbus_hash_iter_get_value (&iter); 1868 1869 if (strcmp (p->exec, entry->exec) == 0) 1870 { 1871 activated = TRUE; 1872 break; 1873 } 1874 } 1875 1876 if (!_dbus_hash_table_insert_string (activation->pending_activations, 1877 pending_activation->service_name, 1878 pending_activation)) 1879 { 1880 _dbus_verbose ("Failed to put pending activation in hash table\n"); 1881 1882 BUS_SET_OOM (error); 1883 bus_pending_activation_unref (pending_activation); 1884 return FALSE; 1885 } 1886 } 1887 1888 if (!add_cancel_pending_to_transaction (transaction, pending_activation)) 1889 { 1890 _dbus_verbose ("Failed to add pending activation cancel hook to transaction\n"); 1891 BUS_SET_OOM (error); 1892 _dbus_hash_table_remove_string (activation->pending_activations, 1893 pending_activation->service_name); 1894 1895 return FALSE; 1896 } 1897 1898 if (activated) 1899 return TRUE; 1900 1901 if (bus_context_get_systemd_activation (activation->context)) 1902 { 1903 if (strcmp (service_name, "org.freedesktop.systemd1") == 0) 1904 /* systemd itself is missing apparently. That can happen 1905 only during early startup. Let's just wait until systemd 1906 connects to us and do nothing. */ 1907 return TRUE; 1908 1909 if (entry->systemd_service) 1910 { 1911 BusTransaction *activation_transaction; 1912 DBusString service_string; 1913 BusService *service; 1914 BusRegistry *registry; 1915 1916 /* OK, we have a systemd service configured for this entry, 1917 hence let's enqueue an activation request message. This 1918 is implemented as a directed signal, not a method call, 1919 for three reasons: 1) we don't expect a response on 1920 success, where we just expect a name appearing on the 1921 bus; 2) at this time the systemd service might not yet 1922 have connected, so we wouldn't know the message serial at 1923 this point to set up a pending call; 3) it is ugly if the 1924 bus suddenly becomes the caller of a remote method. */ 1925 1926 message = dbus_message_new_signal (DBUS_PATH_DBUS, 1927 "org.freedesktop.systemd1.Activator", 1928 "ActivationRequest"); 1929 if (!message) 1930 { 1931 _dbus_verbose ("No memory to create activation message\n"); 1932 BUS_SET_OOM (error); 1933 return FALSE; 1934 } 1935 1936 if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS) || 1937 !dbus_message_set_destination (message, "org.freedesktop.systemd1") || 1938 !dbus_message_append_args (message, 1939 DBUS_TYPE_STRING, &entry->systemd_service, 1940 DBUS_TYPE_INVALID)) 1941 { 1942 _dbus_verbose ("No memory to set args of activation message\n"); 1943 dbus_message_unref (message); 1944 BUS_SET_OOM (error); 1945 return FALSE; 1946 } 1947 1948 /* Create our transaction */ 1949 activation_transaction = bus_transaction_new (activation->context); 1950 if (activation_transaction == NULL) 1951 { 1952 _dbus_verbose ("No memory to create activation transaction\n"); 1953 dbus_message_unref (message); 1954 BUS_SET_OOM (error); 1955 return FALSE; 1956 } 1957 1958 /* Check whether systemd is already connected */ 1959 registry = bus_connection_get_registry (connection); 1960 _dbus_string_init_const (&service_string, "org.freedesktop.systemd1"); 1961 service = bus_registry_lookup (registry, &service_string); 1962 1963 if (service != NULL) 1964 /* Wonderful, systemd is connected, let's just send the msg */ 1965 retval = bus_dispatch_matches (activation_transaction, NULL, bus_service_get_primary_owners_connection (service), 1966 message, error); 1967 else 1968 /* systemd is not around, let's "activate" it. */ 1969 retval = bus_activation_activate_service (activation, connection, activation_transaction, TRUE, 1970 message, "org.freedesktop.systemd1", error); 1971 1972 dbus_message_unref (message); 1973 1974 if (!retval) 1975 { 1976 _DBUS_ASSERT_ERROR_IS_SET (error); 1977 _dbus_verbose ("failed to send activation message: %s\n", error->name); 1978 bus_transaction_cancel_and_free (activation_transaction); 1979 return FALSE; 1980 } 1981 1982 bus_transaction_execute_and_free (activation_transaction); 1983 return TRUE; 1984 } 1985 1986 /* OK, we have no configured systemd service, hence let's 1987 proceed with traditional activation. */ 1988 } 1989 1990 /* use command as system and session different */ 1991 if (!_dbus_string_init (&command)) 1992 { 1993 BUS_SET_OOM (error); 1994 return FALSE; 1995 } 1996 1997 /* does the bus use a helper? */ 1998 servicehelper = bus_context_get_servicehelper (activation->context); 1999 if (servicehelper != NULL) 2000 { 2001 if (entry->user == NULL) 2002 { 2003 _dbus_string_free (&command); 2004 dbus_set_error (error, DBUS_ERROR_SPAWN_FILE_INVALID, 2005 "Cannot do system-bus activation with no user\n"); 2006 return FALSE; 2007 } 2008 2009 /* join the helper path and the service name */ 2010 if (!_dbus_string_append (&command, servicehelper)) 2011 { 2012 _dbus_string_free (&command); 2013 BUS_SET_OOM (error); 2014 return FALSE; 2015 } 2016 if (!_dbus_string_append (&command, " ")) 2017 { 2018 _dbus_string_free (&command); 2019 BUS_SET_OOM (error); 2020 return FALSE; 2021 } 2022 if (!_dbus_string_append (&command, service_name)) 2023 { 2024 _dbus_string_free (&command); 2025 BUS_SET_OOM (error); 2026 return FALSE; 2027 } 2028 } 2029 else 2030 { 2031 /* the bus does not use a helper, so we can append arguments with the exec line */ 2032 if (!_dbus_string_append (&command, entry->exec)) 2033 { 2034 _dbus_string_free (&command); 2035 BUS_SET_OOM (error); 2036 return FALSE; 2037 } 2038 } 2039 2040 /* convert command into arguments */ 2041 if (!_dbus_shell_parse_argv (_dbus_string_get_const_data (&command), &argc, &argv, error)) 2042 { 2043 _dbus_verbose ("Failed to parse command line: %s\n", entry->exec); 2044 _DBUS_ASSERT_ERROR_IS_SET (error); 2045 2046 _dbus_hash_table_remove_string (activation->pending_activations, 2047 pending_activation->service_name); 2048 2049 _dbus_string_free (&command); 2050 return FALSE; 2051 } 2052 _dbus_string_free (&command); 2053 2054 if (!add_bus_environment (activation, error)) 2055 { 2056 _DBUS_ASSERT_ERROR_IS_SET (error); 2057 dbus_free_string_array (argv); 2058 return FALSE; 2059 } 2060 2061 envp = bus_activation_get_environment (activation); 2062 2063 if (envp == NULL) 2064 { 2065 BUS_SET_OOM (error); 2066 dbus_free_string_array (argv); 2067 return FALSE; 2068 } 2069 2070 _dbus_verbose ("Spawning %s ...\n", argv[0]); 2071 if (!_dbus_spawn_async_with_babysitter (&pending_activation->babysitter, argv, 2072 envp, 2073 NULL, activation, 2074 error)) 2075 { 2076 _dbus_verbose ("Failed to spawn child\n"); 2077 _DBUS_ASSERT_ERROR_IS_SET (error); 2078 dbus_free_string_array (argv); 2079 dbus_free_string_array (envp); 2080 2081 return FALSE; 2082 } 2083 2084 dbus_free_string_array (argv); 2085 envp = NULL; 2086 2087 _dbus_assert (pending_activation->babysitter != NULL); 2088 2089 if (!_dbus_babysitter_set_watch_functions (pending_activation->babysitter, 2090 add_babysitter_watch, 2091 remove_babysitter_watch, 2092 NULL, 2093 pending_activation, 2094 NULL)) 2095 { 2096 BUS_SET_OOM (error); 2097 _dbus_verbose ("Failed to set babysitter watch functions\n"); 2098 return FALSE; 2099 } 2100 2101 return TRUE; 2102 } 2103 2104 dbus_bool_t 2105 bus_activation_list_services (BusActivation *activation, 2106 char ***listp, 2107 int *array_len) 2108 { 2109 int i, j, len; 2110 char **retval; 2111 DBusHashIter iter; 2112 2113 len = _dbus_hash_table_get_n_entries (activation->entries); 2114 retval = dbus_new (char *, len + 1); 2115 2116 if (retval == NULL) 2117 return FALSE; 2118 2119 _dbus_hash_iter_init (activation->entries, &iter); 2120 i = 0; 2121 while (_dbus_hash_iter_next (&iter)) 2122 { 2123 BusActivationEntry *entry = _dbus_hash_iter_get_value (&iter); 2124 2125 retval[i] = _dbus_strdup (entry->name); 2126 if (retval[i] == NULL) 2127 goto error; 2128 2129 i++; 2130 } 2131 2132 retval[i] = NULL; 2133 2134 if (array_len) 2135 *array_len = len; 2136 2137 *listp = retval; 2138 return TRUE; 2139 2140 error: 2141 for (j = 0; j < i; j++) 2142 dbus_free (retval[i]); 2143 dbus_free (retval); 2144 2145 return FALSE; 2146 } 2147 2148 dbus_bool_t 2149 dbus_activation_systemd_failure (BusActivation *activation, 2150 DBusMessage *message) 2151 { 2152 DBusError error; 2153 const char *code, *str, *unit = NULL; 2154 2155 dbus_error_init(&error); 2156 2157 /* This is called whenever the systemd activator sent us a 2158 response. We'll invalidate all pending activations that match the 2159 unit name. */ 2160 2161 if (dbus_message_get_args (message, &error, 2162 DBUS_TYPE_STRING, &unit, 2163 DBUS_TYPE_STRING, &code, 2164 DBUS_TYPE_STRING, &str, 2165 DBUS_TYPE_INVALID)) 2166 dbus_set_error(&error, code, str); 2167 2168 if (unit) 2169 { 2170 DBusHashIter iter; 2171 2172 _dbus_hash_iter_init (activation->pending_activations, 2173 &iter); 2174 2175 while (_dbus_hash_iter_next (&iter)) 2176 { 2177 BusPendingActivation *p = _dbus_hash_iter_get_value (&iter); 2178 2179 if (p->systemd_service && strcmp (p->systemd_service, unit) == 0) 2180 pending_activation_failed(p, &error); 2181 } 2182 } 2183 2184 dbus_error_free(&error); 2185 2186 return TRUE; 2187 } 2188 2189 #ifdef DBUS_BUILD_TESTS 2190 2191 #include <stdio.h> 2192 2193 #define SERVICE_NAME_1 "MyService1" 2194 #define SERVICE_NAME_2 "MyService2" 2195 #define SERVICE_NAME_3 "MyService3" 2196 2197 #define SERVICE_FILE_1 "service-1.service" 2198 #define SERVICE_FILE_2 "service-2.service" 2199 #define SERVICE_FILE_3 "service-3.service" 2200 2201 static dbus_bool_t 2202 test_create_service_file (DBusString *dir, 2203 const char *filename, 2204 const char *name, 2205 const char *exec) 2206 { 2207 DBusString file_name, full_path; 2208 FILE *file; 2209 dbus_bool_t ret_val; 2210 2211 ret_val = TRUE; 2212 _dbus_string_init_const (&file_name, filename); 2213 2214 if (!_dbus_string_init (&full_path)) 2215 return FALSE; 2216 2217 if (!_dbus_string_append (&full_path, _dbus_string_get_const_data (dir)) || 2218 !_dbus_concat_dir_and_file (&full_path, &file_name)) 2219 { 2220 ret_val = FALSE; 2221 goto out; 2222 } 2223 2224 file = fopen (_dbus_string_get_const_data (&full_path), "w"); 2225 if (!file) 2226 { 2227 ret_val = FALSE; 2228 goto out; 2229 } 2230 2231 fprintf (file, "[D-BUS Service]\nName=%s\nExec=%s\n", name, exec); 2232 fclose (file); 2233 2234 out: 2235 _dbus_string_free (&full_path); 2236 return ret_val; 2237 } 2238 2239 static dbus_bool_t 2240 test_remove_service_file (DBusString *dir, const char *filename) 2241 { 2242 DBusString file_name, full_path; 2243 dbus_bool_t ret_val; 2244 2245 ret_val = TRUE; 2246 2247 _dbus_string_init_const (&file_name, filename); 2248 2249 if (!_dbus_string_init (&full_path)) 2250 return FALSE; 2251 2252 if (!_dbus_string_append (&full_path, _dbus_string_get_const_data (dir)) || 2253 !_dbus_concat_dir_and_file (&full_path, &file_name)) 2254 { 2255 ret_val = FALSE; 2256 goto out; 2257 } 2258 2259 if (!_dbus_delete_file (&full_path, NULL)) 2260 { 2261 ret_val = FALSE; 2262 goto out; 2263 } 2264 2265 out: 2266 _dbus_string_free (&full_path); 2267 return ret_val; 2268 } 2269 2270 static dbus_bool_t 2271 test_remove_directory (DBusString *dir) 2272 { 2273 DBusDirIter *iter; 2274 DBusString filename, full_path; 2275 dbus_bool_t ret_val; 2276 2277 ret_val = TRUE; 2278 2279 if (!_dbus_string_init (&filename)) 2280 return FALSE; 2281 2282 if (!_dbus_string_init (&full_path)) 2283 { 2284 _dbus_string_free (&filename); 2285 return FALSE; 2286 } 2287 2288 iter = _dbus_directory_open (dir, NULL); 2289 if (iter == NULL) 2290 { 2291 ret_val = FALSE; 2292 goto out; 2293 } 2294 2295 while (_dbus_directory_get_next_file (iter, &filename, NULL)) 2296 { 2297 if (!test_remove_service_file (dir, _dbus_string_get_const_data (&filename))) 2298 { 2299 ret_val = FALSE; 2300 goto out; 2301 } 2302 } 2303 _dbus_directory_close (iter); 2304 2305 if (!_dbus_delete_directory (dir, NULL)) 2306 { 2307 ret_val = FALSE; 2308 goto out; 2309 } 2310 2311 out: 2312 _dbus_string_free (&filename); 2313 _dbus_string_free (&full_path); 2314 2315 return ret_val; 2316 } 2317 2318 static dbus_bool_t 2319 init_service_reload_test (DBusString *dir) 2320 { 2321 DBusStat stat_buf; 2322 2323 if (!_dbus_stat (dir, &stat_buf, NULL)) 2324 { 2325 if (!_dbus_create_directory (dir, NULL)) 2326 return FALSE; 2327 } 2328 else 2329 { 2330 if (!test_remove_directory (dir)) 2331 return FALSE; 2332 2333 if (!_dbus_create_directory (dir, NULL)) 2334 return FALSE; 2335 } 2336 2337 /* Create one initial file */ 2338 if (!test_create_service_file (dir, SERVICE_FILE_1, SERVICE_NAME_1, "exec-1")) 2339 return FALSE; 2340 2341 return TRUE; 2342 } 2343 2344 static dbus_bool_t 2345 cleanup_service_reload_test (DBusString *dir) 2346 { 2347 if (!test_remove_directory (dir)) 2348 return FALSE; 2349 2350 return TRUE; 2351 } 2352 2353 typedef struct 2354 { 2355 BusActivation *activation; 2356 const char *service_name; 2357 dbus_bool_t expecting_find; 2358 } CheckData; 2359 2360 static dbus_bool_t 2361 check_func (void *data) 2362 { 2363 CheckData *d; 2364 BusActivationEntry *entry; 2365 DBusError error; 2366 dbus_bool_t ret_val; 2367 2368 ret_val = TRUE; 2369 d = data; 2370 2371 dbus_error_init (&error); 2372 2373 entry = activation_find_entry (d->activation, d->service_name, &error); 2374 if (entry == NULL) 2375 { 2376 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) 2377 { 2378 ret_val = TRUE; 2379 } 2380 else 2381 { 2382 if (d->expecting_find) 2383 ret_val = FALSE; 2384 } 2385 2386 dbus_error_free (&error); 2387 } 2388 else 2389 { 2390 if (!d->expecting_find) 2391 ret_val = FALSE; 2392 } 2393 2394 return ret_val; 2395 } 2396 2397 static dbus_bool_t 2398 do_test (const char *description, dbus_bool_t oom_test, CheckData *data) 2399 { 2400 dbus_bool_t err; 2401 2402 if (oom_test) 2403 err = !_dbus_test_oom_handling (description, check_func, data); 2404 else 2405 err = !check_func (data); 2406 2407 if (err) 2408 _dbus_assert_not_reached ("Test failed"); 2409 2410 return TRUE; 2411 } 2412 2413 static dbus_bool_t 2414 do_service_reload_test (DBusString *dir, dbus_bool_t oom_test) 2415 { 2416 BusActivation *activation; 2417 DBusString address; 2418 DBusList *directories; 2419 CheckData d; 2420 2421 directories = NULL; 2422 _dbus_string_init_const (&address, ""); 2423 2424 if (!_dbus_list_append (&directories, _dbus_string_get_data (dir))) 2425 return FALSE; 2426 2427 activation = bus_activation_new (NULL, &address, &directories, NULL); 2428 if (!activation) 2429 return FALSE; 2430 2431 d.activation = activation; 2432 2433 /* Check for existing service file */ 2434 d.expecting_find = TRUE; 2435 d.service_name = SERVICE_NAME_1; 2436 2437 if (!do_test ("Existing service file", oom_test, &d)) 2438 return FALSE; 2439 2440 /* Check for non-existing service file */ 2441 d.expecting_find = FALSE; 2442 d.service_name = SERVICE_NAME_3; 2443 2444 if (!do_test ("Nonexisting service file", oom_test, &d)) 2445 return FALSE; 2446 2447 /* Check for added service file */ 2448 if (!test_create_service_file (dir, SERVICE_FILE_2, SERVICE_NAME_2, "exec-2")) 2449 return FALSE; 2450 2451 d.expecting_find = TRUE; 2452 d.service_name = SERVICE_NAME_2; 2453 2454 if (!do_test ("Added service file", oom_test, &d)) 2455 return FALSE; 2456 2457 /* Check for removed service file */ 2458 if (!test_remove_service_file (dir, SERVICE_FILE_2)) 2459 return FALSE; 2460 2461 d.expecting_find = FALSE; 2462 d.service_name = SERVICE_FILE_2; 2463 2464 if (!do_test ("Removed service file", oom_test, &d)) 2465 return FALSE; 2466 2467 /* Check for updated service file */ 2468 2469 _dbus_sleep_milliseconds (1000); /* Sleep a second to make sure the mtime is updated */ 2470 2471 if (!test_create_service_file (dir, SERVICE_FILE_1, SERVICE_NAME_3, "exec-3")) 2472 return FALSE; 2473 2474 d.expecting_find = TRUE; 2475 d.service_name = SERVICE_NAME_3; 2476 2477 if (!do_test ("Updated service file, part 1", oom_test, &d)) 2478 return FALSE; 2479 2480 d.expecting_find = FALSE; 2481 d.service_name = SERVICE_NAME_1; 2482 2483 if (!do_test ("Updated service file, part 2", oom_test, &d)) 2484 return FALSE; 2485 2486 bus_activation_unref (activation); 2487 _dbus_list_clear (&directories); 2488 2489 return TRUE; 2490 } 2491 2492 dbus_bool_t 2493 bus_activation_service_reload_test (const DBusString *test_data_dir) 2494 { 2495 DBusString directory; 2496 2497 if (!_dbus_string_init (&directory)) 2498 return FALSE; 2499 2500 if (!_dbus_string_append (&directory, _dbus_get_tmpdir())) 2501 return FALSE; 2502 2503 if (!_dbus_string_append (&directory, "/dbus-reload-test-") || 2504 !_dbus_generate_random_ascii (&directory, 6)) 2505 { 2506 return FALSE; 2507 } 2508 2509 /* Do normal tests */ 2510 if (!init_service_reload_test (&directory)) 2511 _dbus_assert_not_reached ("could not initiate service reload test"); 2512 2513 if (!do_service_reload_test (&directory, FALSE)) 2514 ; /* Do nothing? */ 2515 2516 /* Do OOM tests */ 2517 if (!init_service_reload_test (&directory)) 2518 _dbus_assert_not_reached ("could not initiate service reload test"); 2519 2520 if (!do_service_reload_test (&directory, TRUE)) 2521 ; /* Do nothing? */ 2522 2523 /* Cleanup test directory */ 2524 if (!cleanup_service_reload_test (&directory)) 2525 return FALSE; 2526 2527 _dbus_string_free (&directory); 2528 2529 return TRUE; 2530 } 2531 2532 #endif /* DBUS_BUILD_TESTS */ 2533