00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "activation.h"
00025 #include "desktop-file.h"
00026 #include "services.h"
00027 #include "utils.h"
00028 #include <dbus/dbus-internals.h>
00029 #include <dbus/dbus-hash.h>
00030 #include <dbus/dbus-list.h>
00031 #include <dbus/dbus-spawn.h>
00032 #include <dbus/dbus-timeout.h>
00033 #include <sys/types.h>
00034 #include <dirent.h>
00035 #include <errno.h>
00036
00037 #define DBUS_SERVICE_SECTION "D-BUS Service"
00038 #define DBUS_SERVICE_NAME "Name"
00039 #define DBUS_SERVICE_EXEC "Exec"
00040
00041 struct BusActivation
00042 {
00043 int refcount;
00044 DBusHashTable *entries;
00045 DBusHashTable *pending_activations;
00046 char *server_address;
00047 BusContext *context;
00048 int n_pending_activations;
00052 };
00053
00054 typedef struct
00055 {
00056 char *name;
00057 char *exec;
00058 } BusActivationEntry;
00059
00060 typedef struct BusPendingActivationEntry BusPendingActivationEntry;
00061
00062 struct BusPendingActivationEntry
00063 {
00064 DBusMessage *activation_message;
00065 DBusConnection *connection;
00066 };
00067
00068 typedef struct
00069 {
00070 int refcount;
00071 BusActivation *activation;
00072 char *service_name;
00073 DBusList *entries;
00074 int n_entries;
00075 DBusBabysitter *babysitter;
00076 DBusTimeout *timeout;
00077 unsigned int timeout_added : 1;
00078 } BusPendingActivation;
00079
00080 static void
00081 bus_pending_activation_entry_free (BusPendingActivationEntry *entry)
00082 {
00083 if (entry->activation_message)
00084 dbus_message_unref (entry->activation_message);
00085
00086 if (entry->connection)
00087 dbus_connection_unref (entry->connection);
00088
00089 dbus_free (entry);
00090 }
00091
00092 static void
00093 handle_timeout_callback (DBusTimeout *timeout,
00094 void *data)
00095 {
00096 BusPendingActivation *pending_activation = data;
00097
00098 while (!dbus_timeout_handle (pending_activation->timeout))
00099 _dbus_wait_for_memory ();
00100 }
00101
00102 static void
00103 bus_pending_activation_ref (BusPendingActivation *pending_activation)
00104 {
00105 _dbus_assert (pending_activation->refcount > 0);
00106 pending_activation->refcount += 1;
00107 }
00108
00109 static void
00110 bus_pending_activation_unref (BusPendingActivation *pending_activation)
00111 {
00112 DBusList *link;
00113
00114 if (pending_activation == NULL)
00115 return;
00116
00117 _dbus_assert (pending_activation->refcount > 0);
00118 pending_activation->refcount -= 1;
00119
00120 if (pending_activation->refcount > 0)
00121 return;
00122
00123 if (pending_activation->timeout_added)
00124 {
00125 _dbus_loop_remove_timeout (bus_context_get_loop (pending_activation->activation->context),
00126 pending_activation->timeout,
00127 handle_timeout_callback, pending_activation);
00128 pending_activation->timeout_added = FALSE;
00129 }
00130
00131 if (pending_activation->timeout)
00132 _dbus_timeout_unref (pending_activation->timeout);
00133
00134 if (pending_activation->babysitter)
00135 {
00136 if (!_dbus_babysitter_set_watch_functions (pending_activation->babysitter,
00137 NULL, NULL, NULL,
00138 pending_activation->babysitter,
00139 NULL))
00140 _dbus_assert_not_reached ("setting watch functions to NULL failed");
00141
00142 _dbus_babysitter_unref (pending_activation->babysitter);
00143 }
00144
00145 dbus_free (pending_activation->service_name);
00146
00147 link = _dbus_list_get_first_link (&pending_activation->entries);
00148
00149 while (link != NULL)
00150 {
00151 BusPendingActivationEntry *entry = link->data;
00152
00153 bus_pending_activation_entry_free (entry);
00154
00155 link = _dbus_list_get_next_link (&pending_activation->entries, link);
00156 }
00157 _dbus_list_clear (&pending_activation->entries);
00158
00159 pending_activation->activation->n_pending_activations -=
00160 pending_activation->n_entries;
00161
00162 _dbus_assert (pending_activation->activation->n_pending_activations >= 0);
00163
00164 dbus_free (pending_activation);
00165 }
00166
00167 static void
00168 bus_activation_entry_free (BusActivationEntry *entry)
00169 {
00170 if (!entry)
00171 return;
00172
00173 dbus_free (entry->name);
00174 dbus_free (entry->exec);
00175
00176 dbus_free (entry);
00177 }
00178
00179 static dbus_bool_t
00180 add_desktop_file_entry (BusActivation *activation,
00181 BusDesktopFile *desktop_file,
00182 DBusError *error)
00183 {
00184 char *name, *exec;
00185 BusActivationEntry *entry;
00186
00187 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00188
00189 name = NULL;
00190 exec = NULL;
00191 entry = NULL;
00192
00193 if (!bus_desktop_file_get_string (desktop_file,
00194 DBUS_SERVICE_SECTION,
00195 DBUS_SERVICE_NAME,
00196 &name))
00197 {
00198 dbus_set_error (error, DBUS_ERROR_FAILED,
00199 "No \""DBUS_SERVICE_NAME"\" key in .service file\n");
00200 goto failed;
00201 }
00202
00203 if (!bus_desktop_file_get_string (desktop_file,
00204 DBUS_SERVICE_SECTION,
00205 DBUS_SERVICE_EXEC,
00206 &exec))
00207 {
00208 dbus_set_error (error, DBUS_ERROR_FAILED,
00209 "No \""DBUS_SERVICE_EXEC"\" key in .service file\n");
00210 goto failed;
00211 }
00212
00213
00214
00215
00216 if (_dbus_hash_table_lookup_string (activation->entries, name))
00217 {
00218 dbus_set_error (error, DBUS_ERROR_FAILED,
00219 "Service %s already exists in activation entry list\n", name);
00220 goto failed;
00221 }
00222
00223 entry = dbus_new0 (BusActivationEntry, 1);
00224 if (entry == NULL)
00225 {
00226 BUS_SET_OOM (error);
00227 goto failed;
00228 }
00229
00230 entry->name = name;
00231 entry->exec = exec;
00232
00233 if (!_dbus_hash_table_insert_string (activation->entries, entry->name, entry))
00234 {
00235 BUS_SET_OOM (error);
00236 goto failed;
00237 }
00238
00239 _dbus_verbose ("Added \"%s\" to list of services\n", entry->name);
00240
00241 return TRUE;
00242
00243 failed:
00244 dbus_free (name);
00245 dbus_free (exec);
00246 dbus_free (entry);
00247
00248 return FALSE;
00249 }
00250
00251
00252
00253
00254 static dbus_bool_t
00255 load_directory (BusActivation *activation,
00256 const char *directory,
00257 DBusError *error)
00258 {
00259 DBusDirIter *iter;
00260 DBusString dir, filename;
00261 DBusString full_path;
00262 BusDesktopFile *desktop_file;
00263 DBusError tmp_error;
00264 dbus_bool_t retval;
00265
00266 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00267
00268 _dbus_string_init_const (&dir, directory);
00269
00270 iter = NULL;
00271 desktop_file = NULL;
00272
00273 if (!_dbus_string_init (&filename))
00274 {
00275 BUS_SET_OOM (error);
00276 return FALSE;
00277 }
00278
00279 if (!_dbus_string_init (&full_path))
00280 {
00281 BUS_SET_OOM (error);
00282 _dbus_string_free (&filename);
00283 return FALSE;
00284 }
00285
00286 retval = FALSE;
00287
00288
00289
00290 iter = _dbus_directory_open (&dir, error);
00291 if (iter == NULL)
00292 {
00293 _dbus_verbose ("Failed to open directory %s: %s\n",
00294 directory, error ? error->message : "unknown");
00295 goto out;
00296 }
00297
00298
00299 dbus_error_init (&tmp_error);
00300 while (_dbus_directory_get_next_file (iter, &filename, &tmp_error))
00301 {
00302 _dbus_assert (!dbus_error_is_set (&tmp_error));
00303
00304 _dbus_string_set_length (&full_path, 0);
00305
00306 if (!_dbus_string_append (&full_path, directory) ||
00307 !_dbus_concat_dir_and_file (&full_path, &filename))
00308 {
00309 BUS_SET_OOM (error);
00310 goto out;
00311 }
00312
00313 if (!_dbus_string_ends_with_c_str (&filename, ".service"))
00314 {
00315 _dbus_verbose ("Skipping non-.service file %s\n",
00316 _dbus_string_get_const_data (&filename));
00317 continue;
00318 }
00319
00320 desktop_file = bus_desktop_file_load (&full_path, &tmp_error);
00321
00322 if (desktop_file == NULL)
00323 {
00324 _dbus_verbose ("Could not load %s: %s\n",
00325 _dbus_string_get_const_data (&full_path),
00326 tmp_error.message);
00327
00328 if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
00329 {
00330 dbus_move_error (&tmp_error, error);
00331 goto out;
00332 }
00333
00334 dbus_error_free (&tmp_error);
00335 continue;
00336 }
00337
00338 if (!add_desktop_file_entry (activation, desktop_file, &tmp_error))
00339 {
00340 bus_desktop_file_free (desktop_file);
00341 desktop_file = NULL;
00342
00343 _dbus_verbose ("Could not add %s to activation entry list: %s\n",
00344 _dbus_string_get_const_data (&full_path), tmp_error.message);
00345
00346 if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
00347 {
00348 dbus_move_error (&tmp_error, error);
00349 goto out;
00350 }
00351
00352 dbus_error_free (&tmp_error);
00353 continue;
00354 }
00355 else
00356 {
00357 bus_desktop_file_free (desktop_file);
00358 desktop_file = NULL;
00359 continue;
00360 }
00361 }
00362
00363 if (dbus_error_is_set (&tmp_error))
00364 {
00365 dbus_move_error (&tmp_error, error);
00366 goto out;
00367 }
00368
00369 retval = TRUE;
00370
00371 out:
00372 if (!retval)
00373 _DBUS_ASSERT_ERROR_IS_SET (error);
00374 else
00375 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00376
00377 if (iter != NULL)
00378 _dbus_directory_close (iter);
00379 if (desktop_file)
00380 bus_desktop_file_free (desktop_file);
00381 _dbus_string_free (&filename);
00382 _dbus_string_free (&full_path);
00383
00384 return retval;
00385 }
00386
00387 BusActivation*
00388 bus_activation_new (BusContext *context,
00389 const DBusString *address,
00390 DBusList **directories,
00391 DBusError *error)
00392 {
00393 BusActivation *activation;
00394 DBusList *link;
00395
00396 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00397
00398 activation = dbus_new0 (BusActivation, 1);
00399 if (activation == NULL)
00400 {
00401 BUS_SET_OOM (error);
00402 return NULL;
00403 }
00404
00405 activation->refcount = 1;
00406 activation->context = context;
00407 activation->n_pending_activations = 0;
00408
00409 if (!_dbus_string_copy_data (address, &activation->server_address))
00410 {
00411 BUS_SET_OOM (error);
00412 goto failed;
00413 }
00414
00415 activation->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
00416 (DBusFreeFunction)bus_activation_entry_free);
00417 if (activation->entries == NULL)
00418 {
00419 BUS_SET_OOM (error);
00420 goto failed;
00421 }
00422
00423 activation->pending_activations = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
00424 (DBusFreeFunction)bus_pending_activation_unref);
00425
00426 if (activation->pending_activations == NULL)
00427 {
00428 BUS_SET_OOM (error);
00429 goto failed;
00430 }
00431
00432
00433 link = _dbus_list_get_first_link (directories);
00434 while (link != NULL)
00435 {
00436 if (!load_directory (activation, link->data, error))
00437 goto failed;
00438 link = _dbus_list_get_next_link (directories, link);
00439 }
00440
00441 return activation;
00442
00443 failed:
00444 bus_activation_unref (activation);
00445 return NULL;
00446 }
00447
00448 void
00449 bus_activation_ref (BusActivation *activation)
00450 {
00451 _dbus_assert (activation->refcount > 0);
00452
00453 activation->refcount += 1;
00454 }
00455
00456 void
00457 bus_activation_unref (BusActivation *activation)
00458 {
00459 _dbus_assert (activation->refcount > 0);
00460
00461 activation->refcount -= 1;
00462
00463 if (activation->refcount == 0)
00464 {
00465 dbus_free (activation->server_address);
00466 if (activation->entries)
00467 _dbus_hash_table_unref (activation->entries);
00468 if (activation->pending_activations)
00469 _dbus_hash_table_unref (activation->pending_activations);
00470 dbus_free (activation);
00471 }
00472 }
00473
00474 static void
00475 child_setup (void *data)
00476 {
00477 BusActivation *activation = data;
00478 const char *type;
00479
00480
00481
00482
00483 if (!_dbus_setenv ("DBUS_ACTIVATION_ADDRESS", activation->server_address))
00484 _dbus_exit (1);
00485
00486 type = bus_context_get_type (activation->context);
00487 if (type != NULL)
00488 {
00489 if (!_dbus_setenv ("DBUS_BUS_TYPE", type))
00490 _dbus_exit (1);
00491 }
00492 }
00493
00494 typedef struct
00495 {
00496 BusPendingActivation *pending_activation;
00497 DBusPreallocatedHash *hash_entry;
00498 } RestorePendingData;
00499
00500 static void
00501 restore_pending (void *data)
00502 {
00503 RestorePendingData *d = data;
00504
00505 _dbus_assert (d->pending_activation != NULL);
00506 _dbus_assert (d->hash_entry != NULL);
00507
00508 _dbus_verbose ("Restoring pending activation for service %s, has timeout = %d\n",
00509 d->pending_activation->service_name,
00510 d->pending_activation->timeout_added);
00511
00512 _dbus_hash_table_insert_string_preallocated (d->pending_activation->activation->pending_activations,
00513 d->hash_entry,
00514 d->pending_activation->service_name, d->pending_activation);
00515
00516 bus_pending_activation_ref (d->pending_activation);
00517
00518 d->hash_entry = NULL;
00519 }
00520
00521 static void
00522 free_pending_restore_data (void *data)
00523 {
00524 RestorePendingData *d = data;
00525
00526 if (d->hash_entry)
00527 _dbus_hash_table_free_preallocated_entry (d->pending_activation->activation->pending_activations,
00528 d->hash_entry);
00529
00530 bus_pending_activation_unref (d->pending_activation);
00531
00532 dbus_free (d);
00533 }
00534
00535 static dbus_bool_t
00536 add_restore_pending_to_transaction (BusTransaction *transaction,
00537 BusPendingActivation *pending_activation)
00538 {
00539 RestorePendingData *d;
00540
00541 d = dbus_new (RestorePendingData, 1);
00542 if (d == NULL)
00543 return FALSE;
00544
00545 d->pending_activation = pending_activation;
00546 d->hash_entry = _dbus_hash_table_preallocate_entry (d->pending_activation->activation->pending_activations);
00547
00548 bus_pending_activation_ref (d->pending_activation);
00549
00550 if (d->hash_entry == NULL ||
00551 !bus_transaction_add_cancel_hook (transaction, restore_pending, d,
00552 free_pending_restore_data))
00553 {
00554 free_pending_restore_data (d);
00555 return FALSE;
00556 }
00557
00558 _dbus_verbose ("Saved pending activation to be restored if the transaction fails\n");
00559
00560 return TRUE;
00561 }
00562
00563 dbus_bool_t
00564 bus_activation_service_created (BusActivation *activation,
00565 const char *service_name,
00566 BusTransaction *transaction,
00567 DBusError *error)
00568 {
00569 BusPendingActivation *pending_activation;
00570 DBusMessage *message;
00571 DBusList *link;
00572
00573 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00574
00575
00576 pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, service_name);
00577
00578 if (!pending_activation)
00579 return TRUE;
00580
00581 link = _dbus_list_get_first_link (&pending_activation->entries);
00582 while (link != NULL)
00583 {
00584 BusPendingActivationEntry *entry = link->data;
00585 DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
00586
00587 if (dbus_connection_get_is_connected (entry->connection))
00588 {
00589 message = dbus_message_new_reply (entry->activation_message);
00590 if (!message)
00591 {
00592 BUS_SET_OOM (error);
00593 goto error;
00594 }
00595
00596 if (!dbus_message_append_args (message,
00597 DBUS_TYPE_UINT32, DBUS_ACTIVATION_REPLY_ACTIVATED,
00598 DBUS_TYPE_INVALID))
00599 {
00600 dbus_message_unref (message);
00601 BUS_SET_OOM (error);
00602 goto error;
00603 }
00604
00605 if (!bus_transaction_send_from_driver (transaction, entry->connection, message))
00606 {
00607 dbus_message_unref (message);
00608 BUS_SET_OOM (error);
00609 goto error;
00610 }
00611
00612 dbus_message_unref (message);
00613 }
00614
00615 link = next;
00616 }
00617
00618 if (!add_restore_pending_to_transaction (transaction, pending_activation))
00619 {
00620 _dbus_verbose ("Could not add cancel hook to transaction to revert removing pending activation\n");
00621 BUS_SET_OOM (error);
00622 goto error;
00623 }
00624
00625 _dbus_hash_table_remove_string (activation->pending_activations, service_name);
00626
00627 return TRUE;
00628
00629 error:
00630 return FALSE;
00631 }
00632
00639 static dbus_bool_t
00640 try_send_activation_failure (BusPendingActivation *pending_activation,
00641 const DBusError *how)
00642 {
00643 BusActivation *activation;
00644 DBusList *link;
00645 BusTransaction *transaction;
00646
00647 activation = pending_activation->activation;
00648
00649 transaction = bus_transaction_new (activation->context);
00650 if (transaction == NULL)
00651 return FALSE;
00652
00653 link = _dbus_list_get_first_link (&pending_activation->entries);
00654 while (link != NULL)
00655 {
00656 BusPendingActivationEntry *entry = link->data;
00657 DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
00658
00659 if (dbus_connection_get_is_connected (entry->connection))
00660 {
00661 if (!bus_transaction_send_error_reply (transaction,
00662 entry->connection,
00663 how,
00664 entry->activation_message))
00665 goto error;
00666 }
00667
00668 link = next;
00669 }
00670
00671 bus_transaction_execute_and_free (transaction);
00672
00673 return TRUE;
00674
00675 error:
00676 if (transaction)
00677 bus_transaction_cancel_and_free (transaction);
00678 return FALSE;
00679 }
00680
00685 static void
00686 pending_activation_failed (BusPendingActivation *pending_activation,
00687 const DBusError *how)
00688 {
00689
00690 while (!try_send_activation_failure (pending_activation, how))
00691 _dbus_wait_for_memory ();
00692
00693
00694 _dbus_hash_table_remove_string (pending_activation->activation->pending_activations,
00695 pending_activation->service_name);
00696 }
00697
00698 static dbus_bool_t
00699 babysitter_watch_callback (DBusWatch *watch,
00700 unsigned int condition,
00701 void *data)
00702 {
00703 BusPendingActivation *pending_activation = data;
00704 dbus_bool_t retval;
00705 DBusBabysitter *babysitter;
00706
00707 babysitter = pending_activation->babysitter;
00708
00709 _dbus_babysitter_ref (babysitter);
00710
00711 retval = dbus_watch_handle (watch, condition);
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723 if (_dbus_babysitter_get_child_exited (babysitter))
00724 {
00725 DBusError error;
00726
00727 dbus_error_init (&error);
00728 _dbus_babysitter_set_child_exit_error (babysitter, &error);
00729
00730
00731 pending_activation_failed (pending_activation, &error);
00732
00733 dbus_error_free (&error);
00734 }
00735
00736 _dbus_babysitter_unref (babysitter);
00737
00738 return retval;
00739 }
00740
00741 static dbus_bool_t
00742 add_babysitter_watch (DBusWatch *watch,
00743 void *data)
00744 {
00745 BusPendingActivation *pending_activation = data;
00746
00747 return _dbus_loop_add_watch (bus_context_get_loop (pending_activation->activation->context),
00748 watch, babysitter_watch_callback, pending_activation,
00749 NULL);
00750 }
00751
00752 static void
00753 remove_babysitter_watch (DBusWatch *watch,
00754 void *data)
00755 {
00756 BusPendingActivation *pending_activation = data;
00757
00758 _dbus_loop_remove_watch (bus_context_get_loop (pending_activation->activation->context),
00759 watch, babysitter_watch_callback, pending_activation);
00760 }
00761
00762 static dbus_bool_t
00763 pending_activation_timed_out (void *data)
00764 {
00765 BusPendingActivation *pending_activation = data;
00766 DBusError error;
00767
00768
00769
00770
00771
00772 _dbus_babysitter_kill_child (pending_activation->babysitter);
00773
00774 dbus_error_init (&error);
00775
00776 dbus_set_error (&error, DBUS_ERROR_TIMED_OUT,
00777 "Activation of %s timed out",
00778 pending_activation->service_name);
00779
00780 pending_activation_failed (pending_activation, &error);
00781
00782 dbus_error_free (&error);
00783
00784 return TRUE;
00785 }
00786
00787 static void
00788 cancel_pending (void *data)
00789 {
00790 BusPendingActivation *pending_activation = data;
00791
00792 _dbus_verbose ("Canceling pending activation of %s\n",
00793 pending_activation->service_name);
00794
00795 if (pending_activation->babysitter)
00796 _dbus_babysitter_kill_child (pending_activation->babysitter);
00797
00798 _dbus_hash_table_remove_string (pending_activation->activation->pending_activations,
00799 pending_activation->service_name);
00800 }
00801
00802 static void
00803 free_pending_cancel_data (void *data)
00804 {
00805 BusPendingActivation *pending_activation = data;
00806
00807 bus_pending_activation_unref (pending_activation);
00808 }
00809
00810 static dbus_bool_t
00811 add_cancel_pending_to_transaction (BusTransaction *transaction,
00812 BusPendingActivation *pending_activation)
00813 {
00814 if (!bus_transaction_add_cancel_hook (transaction, cancel_pending,
00815 pending_activation,
00816 free_pending_cancel_data))
00817 return FALSE;
00818
00819 bus_pending_activation_ref (pending_activation);
00820
00821 _dbus_verbose ("Saved pending activation to be canceled if the transaction fails\n");
00822
00823 return TRUE;
00824 }
00825
00826 dbus_bool_t
00827 bus_activation_activate_service (BusActivation *activation,
00828 DBusConnection *connection,
00829 BusTransaction *transaction,
00830 DBusMessage *activation_message,
00831 const char *service_name,
00832 DBusError *error)
00833 {
00834 BusActivationEntry *entry;
00835 BusPendingActivation *pending_activation;
00836 BusPendingActivationEntry *pending_activation_entry;
00837 DBusMessage *message;
00838 DBusString service_str;
00839 char *argv[2];
00840 dbus_bool_t retval;
00841
00842 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00843
00844 if (activation->n_pending_activations >=
00845 bus_context_get_max_pending_activations (activation->context))
00846 {
00847 dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
00848 "The maximum number of pending activations has been reached, activation of %s failed",
00849 service_name);
00850 return FALSE;
00851 }
00852
00853 entry = _dbus_hash_table_lookup_string (activation->entries, service_name);
00854
00855 if (!entry)
00856 {
00857 dbus_set_error (error, DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND,
00858 "The service %s was not found in the activation entry list",
00859 service_name);
00860 return FALSE;
00861 }
00862
00863
00864 _dbus_string_init_const (&service_str, service_name);
00865 if (bus_registry_lookup (bus_context_get_registry (activation->context), &service_str) != NULL)
00866 {
00867 _dbus_verbose ("Service \"%s\" is already active\n", service_name);
00868
00869 message = dbus_message_new_reply (activation_message);
00870
00871 if (!message)
00872 {
00873 _dbus_verbose ("No memory to create reply to activate message\n");
00874 BUS_SET_OOM (error);
00875 return FALSE;
00876 }
00877
00878 if (!dbus_message_append_args (message,
00879 DBUS_TYPE_UINT32, DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE,
00880 DBUS_TYPE_INVALID))
00881 {
00882 _dbus_verbose ("No memory to set args of reply to activate message\n");
00883 BUS_SET_OOM (error);
00884 dbus_message_unref (message);
00885 return FALSE;
00886 }
00887
00888 retval = bus_transaction_send_from_driver (transaction, connection, message);
00889 dbus_message_unref (message);
00890 if (!retval)
00891 {
00892 _dbus_verbose ("Failed to send reply\n");
00893 BUS_SET_OOM (error);
00894 }
00895
00896 return retval;
00897 }
00898
00899 pending_activation_entry = dbus_new0 (BusPendingActivationEntry, 1);
00900 if (!pending_activation_entry)
00901 {
00902 _dbus_verbose ("Failed to create pending activation entry\n");
00903 BUS_SET_OOM (error);
00904 return FALSE;
00905 }
00906
00907 pending_activation_entry->activation_message = activation_message;
00908 dbus_message_ref (activation_message);
00909 pending_activation_entry->connection = connection;
00910 dbus_connection_ref (connection);
00911
00912
00913 pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, service_name);
00914 if (pending_activation)
00915 {
00916 if (!_dbus_list_append (&pending_activation->entries, pending_activation_entry))
00917 {
00918 _dbus_verbose ("Failed to append a new entry to pending activation\n");
00919
00920 BUS_SET_OOM (error);
00921 bus_pending_activation_entry_free (pending_activation_entry);
00922 return FALSE;
00923 }
00924
00925 pending_activation->n_entries += 1;
00926 pending_activation->activation->n_pending_activations += 1;
00927 }
00928 else
00929 {
00930 pending_activation = dbus_new0 (BusPendingActivation, 1);
00931 if (!pending_activation)
00932 {
00933 _dbus_verbose ("Failed to create pending activation\n");
00934
00935 BUS_SET_OOM (error);
00936 bus_pending_activation_entry_free (pending_activation_entry);
00937 return FALSE;
00938 }
00939
00940 pending_activation->activation = activation;
00941 pending_activation->refcount = 1;
00942
00943 pending_activation->service_name = _dbus_strdup (service_name);
00944 if (!pending_activation->service_name)
00945 {
00946 _dbus_verbose ("Failed to copy service name for pending activation\n");
00947
00948 BUS_SET_OOM (error);
00949 bus_pending_activation_unref (pending_activation);
00950 bus_pending_activation_entry_free (pending_activation_entry);
00951 return FALSE;
00952 }
00953
00954 pending_activation->timeout =
00955 _dbus_timeout_new (bus_context_get_activation_timeout (activation->context),
00956 pending_activation_timed_out,
00957 pending_activation,
00958 NULL);
00959 if (!pending_activation->timeout)
00960 {
00961 _dbus_verbose ("Failed to create timeout for pending activation\n");
00962
00963 BUS_SET_OOM (error);
00964 bus_pending_activation_unref (pending_activation);
00965 bus_pending_activation_entry_free (pending_activation_entry);
00966 return FALSE;
00967 }
00968
00969 if (!_dbus_loop_add_timeout (bus_context_get_loop (activation->context),
00970 pending_activation->timeout,
00971 handle_timeout_callback,
00972 pending_activation,
00973 NULL))
00974 {
00975 _dbus_verbose ("Failed to add timeout for pending activation\n");
00976
00977 BUS_SET_OOM (error);
00978 bus_pending_activation_unref (pending_activation);
00979 bus_pending_activation_entry_free (pending_activation_entry);
00980 return FALSE;
00981 }
00982
00983 pending_activation->timeout_added = TRUE;
00984
00985 if (!_dbus_list_append (&pending_activation->entries, pending_activation_entry))
00986 {
00987 _dbus_verbose ("Failed to add entry to just-created pending activation\n");
00988
00989 BUS_SET_OOM (error);
00990 bus_pending_activation_unref (pending_activation);
00991 bus_pending_activation_entry_free (pending_activation_entry);
00992 return FALSE;
00993 }
00994
00995 pending_activation->n_entries += 1;
00996 pending_activation->activation->n_pending_activations += 1;
00997
00998 if (!_dbus_hash_table_insert_string (activation->pending_activations,
00999 pending_activation->service_name,
01000 pending_activation))
01001 {
01002 _dbus_verbose ("Failed to put pending activation in hash table\n");
01003
01004 BUS_SET_OOM (error);
01005 bus_pending_activation_unref (pending_activation);
01006 return FALSE;
01007 }
01008 }
01009
01010 if (!add_cancel_pending_to_transaction (transaction, pending_activation))
01011 {
01012 _dbus_verbose ("Failed to add pending activation cancel hook to transaction\n");
01013 BUS_SET_OOM (error);
01014 _dbus_hash_table_remove_string (activation->pending_activations,
01015 pending_activation->service_name);
01016 return FALSE;
01017 }
01018
01019
01020
01021
01022
01023
01024 argv[0] = entry->exec;
01025 argv[1] = NULL;
01026
01027 if (!_dbus_spawn_async_with_babysitter (&pending_activation->babysitter, argv,
01028 child_setup, activation,
01029 error))
01030 {
01031 _dbus_verbose ("Failed to spawn child\n");
01032 _DBUS_ASSERT_ERROR_IS_SET (error);
01033 return FALSE;
01034 }
01035
01036 _dbus_assert (pending_activation->babysitter != NULL);
01037
01038 if (!_dbus_babysitter_set_watch_functions (pending_activation->babysitter,
01039 add_babysitter_watch,
01040 remove_babysitter_watch,
01041 NULL,
01042 pending_activation,
01043 NULL))
01044 {
01045 BUS_SET_OOM (error);
01046 _dbus_verbose ("Failed to set babysitter watch functions\n");
01047 return FALSE;
01048 }
01049
01050 return TRUE;
01051 }