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