2003-08-10 Havoc Pennington <hp@pobox.com>
[platform/upstream/dbus.git] / bus / activation.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* activation.c  Activation of services
3  *
4  * Copyright (C) 2003  CodeFactory AB
5  * Copyright (C) 2003  Red Hat, Inc.
6  *
7  * Licensed under the Academic Free License version 1.2
8  * 
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  * 
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  */
24 #include "activation.h"
25 #include "desktop-file.h"
26 #include "services.h"
27 #include "utils.h"
28 #include <dbus/dbus-internals.h>
29 #include <dbus/dbus-hash.h>
30 #include <dbus/dbus-list.h>
31 #include <dbus/dbus-spawn.h>
32 #include <dbus/dbus-timeout.h>
33 #include <sys/types.h>
34 #include <dirent.h>
35 #include <errno.h>
36
37 #define DBUS_SERVICE_SECTION "D-BUS Service"
38 #define DBUS_SERVICE_NAME "Name"
39 #define DBUS_SERVICE_EXEC "Exec"
40
41 struct BusActivation
42 {
43   int refcount;
44   DBusHashTable *entries;
45   DBusHashTable *pending_activations;
46   char *server_address;
47   BusContext *context;
48   int n_pending_activations; /**< This is in fact the number of BusPendingActivationEntry,
49                               * i.e. number of pending activation requests, not pending
50                               * activations per se
51                               */
52 };
53
54 typedef struct
55 {
56   char *name;
57   char *exec;
58 } BusActivationEntry;
59
60 typedef struct BusPendingActivationEntry BusPendingActivationEntry;
61
62 struct BusPendingActivationEntry
63 {
64   DBusMessage *activation_message;
65   DBusConnection *connection;
66 };
67
68 typedef struct
69 {
70   int refcount;
71   BusActivation *activation;
72   char *service_name;
73   DBusList *entries;
74   int n_entries;
75   DBusBabysitter *babysitter;
76   DBusTimeout *timeout;
77   unsigned int timeout_added : 1;
78 } BusPendingActivation;
79
80 static void
81 bus_pending_activation_entry_free (BusPendingActivationEntry *entry)
82 {
83   if (entry->activation_message)
84     dbus_message_unref (entry->activation_message);
85   
86   if (entry->connection)
87     dbus_connection_unref (entry->connection);
88   
89   dbus_free (entry);
90 }
91
92 static void
93 handle_timeout_callback (DBusTimeout   *timeout,
94                          void          *data)
95 {
96   BusPendingActivation *pending_activation = data;
97
98   while (!dbus_timeout_handle (pending_activation->timeout))
99     _dbus_wait_for_memory ();
100 }
101
102 static void
103 bus_pending_activation_ref (BusPendingActivation *pending_activation)
104 {
105   _dbus_assert (pending_activation->refcount > 0);
106   pending_activation->refcount += 1;
107 }
108
109 static void
110 bus_pending_activation_unref (BusPendingActivation *pending_activation)
111 {
112   DBusList *link;
113   
114   if (pending_activation == NULL) /* hash table requires this */
115     return;
116
117   _dbus_assert (pending_activation->refcount > 0);
118   pending_activation->refcount -= 1;
119
120   if (pending_activation->refcount > 0)
121     return;
122   
123   if (pending_activation->timeout_added)
124     {
125       _dbus_loop_remove_timeout (bus_context_get_loop (pending_activation->activation->context),
126                                  pending_activation->timeout,
127                                  handle_timeout_callback, pending_activation);
128       pending_activation->timeout_added = FALSE;
129     }
130
131   if (pending_activation->timeout)
132     _dbus_timeout_unref (pending_activation->timeout);
133   
134   if (pending_activation->babysitter)
135     {
136       if (!_dbus_babysitter_set_watch_functions (pending_activation->babysitter,
137                                                  NULL, NULL, NULL,
138                                                  pending_activation->babysitter,
139                                                  NULL))
140         _dbus_assert_not_reached ("setting watch functions to NULL failed");
141       
142       _dbus_babysitter_unref (pending_activation->babysitter);
143     }
144   
145   dbus_free (pending_activation->service_name);
146
147   link = _dbus_list_get_first_link (&pending_activation->entries);
148
149   while (link != NULL)
150     {
151       BusPendingActivationEntry *entry = link->data;
152
153       bus_pending_activation_entry_free (entry);
154
155       link = _dbus_list_get_next_link (&pending_activation->entries, link);
156     }
157   _dbus_list_clear (&pending_activation->entries);
158
159   pending_activation->activation->n_pending_activations -=
160     pending_activation->n_entries;
161
162   _dbus_assert (pending_activation->activation->n_pending_activations >= 0);
163   
164   dbus_free (pending_activation);
165 }
166
167 static void
168 bus_activation_entry_free (BusActivationEntry *entry)
169 {
170   if (!entry)
171     return;
172   
173   dbus_free (entry->name);
174   dbus_free (entry->exec);
175
176   dbus_free (entry);
177 }
178
179 static dbus_bool_t
180 add_desktop_file_entry (BusActivation  *activation,
181                         BusDesktopFile *desktop_file,
182                         DBusError      *error)
183 {
184   char *name, *exec;
185   BusActivationEntry *entry;
186
187   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
188   
189   name = NULL;
190   exec = NULL;
191   entry = NULL;
192   
193   if (!bus_desktop_file_get_string (desktop_file,
194                                     DBUS_SERVICE_SECTION,
195                                     DBUS_SERVICE_NAME,
196                                     &name))
197     {
198       dbus_set_error (error, DBUS_ERROR_FAILED,
199                       "No \""DBUS_SERVICE_NAME"\" key in .service file\n");
200       goto failed;
201     }
202
203   if (!bus_desktop_file_get_string (desktop_file,
204                                     DBUS_SERVICE_SECTION,
205                                     DBUS_SERVICE_EXEC,
206                                     &exec))
207     {
208       dbus_set_error (error, DBUS_ERROR_FAILED,
209                       "No \""DBUS_SERVICE_EXEC"\" key in .service file\n");
210       goto failed;
211     }
212
213   /* FIXME we need a better-defined algorithm for which service file to
214    * pick than "whichever one is first in the directory listing"
215    */
216   if (_dbus_hash_table_lookup_string (activation->entries, name))
217     {
218       dbus_set_error (error, DBUS_ERROR_FAILED,
219                       "Service %s already exists in activation entry list\n", name);
220       goto failed;
221     }
222   
223   entry = dbus_new0 (BusActivationEntry, 1);
224   if (entry == NULL)
225     {
226       BUS_SET_OOM (error);
227       goto failed;
228     }
229   
230   entry->name = name;
231   entry->exec = exec;
232
233   if (!_dbus_hash_table_insert_string (activation->entries, entry->name, entry))
234     {
235       BUS_SET_OOM (error);
236       goto failed;
237     }
238
239   _dbus_verbose ("Added \"%s\" to list of services\n", entry->name);
240   
241   return TRUE;
242
243  failed:
244   dbus_free (name);
245   dbus_free (exec);
246   dbus_free (entry);
247   
248   return FALSE;
249 }
250
251 /* warning: this doesn't fully "undo" itself on failure, i.e. doesn't strip
252  * hash entries it already added.
253  */
254 static dbus_bool_t
255 load_directory (BusActivation *activation,
256                 const char    *directory,
257                 DBusError     *error)
258 {
259   DBusDirIter *iter;
260   DBusString dir, filename;
261   DBusString full_path;
262   BusDesktopFile *desktop_file;
263   DBusError tmp_error;
264   dbus_bool_t retval;
265   
266   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
267   
268   _dbus_string_init_const (&dir, directory);
269
270   iter = NULL;
271   desktop_file = NULL;
272   
273   if (!_dbus_string_init (&filename))
274     {
275       BUS_SET_OOM (error);
276       return FALSE;
277     }
278
279   if (!_dbus_string_init (&full_path))
280     {
281       BUS_SET_OOM (error);
282       _dbus_string_free (&filename);
283       return FALSE;
284     }
285
286   retval = FALSE;
287   
288   /* from this point it's safe to "goto out" */
289   
290   iter = _dbus_directory_open (&dir, error);
291   if (iter == NULL)
292     {
293       _dbus_verbose ("Failed to open directory %s: %s\n",
294                      directory, error ? error->message : "unknown");
295       goto out;
296     }
297   
298   /* Now read the files */
299   dbus_error_init (&tmp_error);
300   while (_dbus_directory_get_next_file (iter, &filename, &tmp_error))
301     {
302       _dbus_assert (!dbus_error_is_set (&tmp_error));
303       
304       _dbus_string_set_length (&full_path, 0);
305       
306       if (!_dbus_string_append (&full_path, directory) ||
307           !_dbus_concat_dir_and_file (&full_path, &filename))
308         {
309           BUS_SET_OOM (error);
310           goto out;
311         }
312       
313       if (!_dbus_string_ends_with_c_str (&filename, ".service"))
314         {
315           _dbus_verbose ("Skipping non-.service file %s\n",
316                          _dbus_string_get_const_data (&filename));
317           continue;
318         }
319       
320       desktop_file = bus_desktop_file_load (&full_path, &tmp_error);
321
322       if (desktop_file == NULL)
323         {
324           _dbus_verbose ("Could not load %s: %s\n",
325                          _dbus_string_get_const_data (&full_path),
326                          tmp_error.message);
327
328           if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
329             {
330               dbus_move_error (&tmp_error, error);
331               goto out;
332             }
333           
334           dbus_error_free (&tmp_error);
335           continue;
336         }
337
338       if (!add_desktop_file_entry (activation, desktop_file, &tmp_error))
339         {
340           bus_desktop_file_free (desktop_file);
341           desktop_file = NULL;
342           
343           _dbus_verbose ("Could not add %s to activation entry list: %s\n",
344                          _dbus_string_get_const_data (&full_path), tmp_error.message);
345
346           if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
347             {
348               dbus_move_error (&tmp_error, error);
349               goto out;
350             }
351
352           dbus_error_free (&tmp_error);
353           continue;
354         }
355       else
356         {
357           bus_desktop_file_free (desktop_file);
358           desktop_file = NULL;
359           continue;
360         }
361     }
362
363   if (dbus_error_is_set (&tmp_error))
364     {
365       dbus_move_error (&tmp_error, error);
366       goto out;
367     }
368   
369   retval = TRUE;
370   
371  out:
372   if (!retval)
373     _DBUS_ASSERT_ERROR_IS_SET (error);
374   else
375     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
376   
377   if (iter != NULL)
378     _dbus_directory_close (iter);
379   if (desktop_file)
380     bus_desktop_file_free (desktop_file);
381   _dbus_string_free (&filename);
382   _dbus_string_free (&full_path);
383   
384   return retval;
385 }
386
387 BusActivation*
388 bus_activation_new (BusContext        *context,
389                     const DBusString  *address,
390                     DBusList         **directories,
391                     DBusError         *error)
392 {
393   BusActivation *activation;
394   DBusList *link;
395   
396   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
397   
398   activation = dbus_new0 (BusActivation, 1);
399   if (activation == NULL)
400     {
401       BUS_SET_OOM (error);
402       return NULL;
403     }
404   
405   activation->refcount = 1;
406   activation->context = context;
407   activation->n_pending_activations = 0;
408   
409   if (!_dbus_string_copy_data (address, &activation->server_address))
410     {
411       BUS_SET_OOM (error);
412       goto failed;
413     }
414   
415   activation->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
416                                              (DBusFreeFunction)bus_activation_entry_free);
417   if (activation->entries == NULL)
418     {      
419       BUS_SET_OOM (error);
420       goto failed;
421     }
422
423   activation->pending_activations = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
424                                                           (DBusFreeFunction)bus_pending_activation_unref);
425
426   if (activation->pending_activations == NULL)
427     {
428       BUS_SET_OOM (error);
429       goto failed;
430     }
431   
432   /* Load service files */
433   link = _dbus_list_get_first_link (directories);
434   while (link != NULL)
435     {
436       if (!load_directory (activation, link->data, error))
437         goto failed;
438       link = _dbus_list_get_next_link (directories, link);
439     }
440
441   return activation;
442   
443  failed:
444   bus_activation_unref (activation);  
445   return NULL;
446 }
447
448 void
449 bus_activation_ref (BusActivation *activation)
450 {
451   _dbus_assert (activation->refcount > 0);
452   
453   activation->refcount += 1;
454 }
455
456 void
457 bus_activation_unref (BusActivation *activation)
458 {
459   _dbus_assert (activation->refcount > 0);
460
461   activation->refcount -= 1;
462
463   if (activation->refcount == 0)
464     {
465       dbus_free (activation->server_address);
466       if (activation->entries)
467         _dbus_hash_table_unref (activation->entries);
468       if (activation->pending_activations)
469         _dbus_hash_table_unref (activation->pending_activations);
470       dbus_free (activation);
471     }
472 }
473
474 static void
475 child_setup (void *data)
476 {
477   BusActivation *activation = data;
478   const char *type;
479   
480   /* If no memory, we simply have the child exit, so it won't try
481    * to connect to the wrong thing.
482    */
483   if (!_dbus_setenv ("DBUS_ACTIVATION_ADDRESS", activation->server_address))
484     _dbus_exit (1);
485
486   type = bus_context_get_type (activation->context);
487   if (type != NULL)
488     {
489       if (!_dbus_setenv ("DBUS_BUS_TYPE", type))
490         _dbus_exit (1);
491     }
492 }
493
494 typedef struct
495 {
496   BusPendingActivation *pending_activation;
497   DBusPreallocatedHash *hash_entry;
498 } RestorePendingData;
499
500 static void
501 restore_pending (void *data)
502 {
503   RestorePendingData *d = data;
504
505   _dbus_assert (d->pending_activation != NULL);
506   _dbus_assert (d->hash_entry != NULL);
507
508   _dbus_verbose ("Restoring pending activation for service %s, has timeout = %d\n",
509                  d->pending_activation->service_name,
510                  d->pending_activation->timeout_added);
511   
512   _dbus_hash_table_insert_string_preallocated (d->pending_activation->activation->pending_activations,
513                                                d->hash_entry,
514                                                d->pending_activation->service_name, d->pending_activation);
515
516   bus_pending_activation_ref (d->pending_activation);
517   
518   d->hash_entry = NULL;
519 }
520
521 static void
522 free_pending_restore_data (void *data)
523 {
524   RestorePendingData *d = data;
525
526   if (d->hash_entry)
527     _dbus_hash_table_free_preallocated_entry (d->pending_activation->activation->pending_activations,
528                                               d->hash_entry);
529
530   bus_pending_activation_unref (d->pending_activation);
531   
532   dbus_free (d);
533 }
534
535 static dbus_bool_t
536 add_restore_pending_to_transaction (BusTransaction       *transaction,
537                                     BusPendingActivation *pending_activation)
538 {
539   RestorePendingData *d;
540
541   d = dbus_new (RestorePendingData, 1);
542   if (d == NULL)
543     return FALSE;
544   
545   d->pending_activation = pending_activation;
546   d->hash_entry = _dbus_hash_table_preallocate_entry (d->pending_activation->activation->pending_activations);
547   
548   bus_pending_activation_ref (d->pending_activation);
549   
550   if (d->hash_entry == NULL ||
551       !bus_transaction_add_cancel_hook (transaction, restore_pending, d,
552                                         free_pending_restore_data))
553     {
554       free_pending_restore_data (d);
555       return FALSE;
556     }
557
558   _dbus_verbose ("Saved pending activation to be restored if the transaction fails\n");
559   
560   return TRUE;
561 }
562
563 dbus_bool_t
564 bus_activation_service_created (BusActivation  *activation,
565                                 const char     *service_name,
566                                 BusTransaction *transaction,
567                                 DBusError      *error)
568 {
569   BusPendingActivation *pending_activation;
570   DBusMessage *message;
571   DBusList *link;
572
573   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
574   
575   /* Check if it's a pending activation */
576   pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, service_name);
577
578   if (!pending_activation)
579     return TRUE;
580
581   link = _dbus_list_get_first_link (&pending_activation->entries);
582   while (link != NULL)
583     {
584       BusPendingActivationEntry *entry = link->data;
585       DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
586       
587       if (dbus_connection_get_is_connected (entry->connection))
588         {
589           message = dbus_message_new_method_return (entry->activation_message);
590           if (!message)
591             {
592               BUS_SET_OOM (error);
593               goto error;
594             }
595
596           if (!dbus_message_append_args (message,
597                                          DBUS_TYPE_UINT32, DBUS_ACTIVATION_REPLY_ACTIVATED,
598                                          DBUS_TYPE_INVALID))
599             {
600               dbus_message_unref (message);
601               BUS_SET_OOM (error);
602               goto error;
603             }
604           
605           if (!bus_transaction_send_from_driver (transaction, entry->connection, message))
606             {
607               dbus_message_unref (message);
608               BUS_SET_OOM (error);
609               goto error;
610             }
611           
612           dbus_message_unref (message);
613         }
614
615       link = next;
616     }
617
618   if (!add_restore_pending_to_transaction (transaction, pending_activation))
619     {
620       _dbus_verbose ("Could not add cancel hook to transaction to revert removing pending activation\n");
621       BUS_SET_OOM (error);
622       goto error;
623     }
624   
625   _dbus_hash_table_remove_string (activation->pending_activations, service_name);
626
627   return TRUE;
628
629  error:
630   return FALSE;
631 }
632
633 /**
634  * FIXME @todo the error messages here would ideally be preallocated
635  * so we don't need to allocate memory to send them.
636  * Using the usual tactic, prealloc an OOM message, then
637  * if we can't alloc the real error send the OOM error instead.
638  */
639 static dbus_bool_t
640 try_send_activation_failure (BusPendingActivation *pending_activation,
641                              const DBusError      *how)
642 {
643   BusActivation *activation;
644   DBusList *link;
645   BusTransaction *transaction;
646   
647   activation = pending_activation->activation;
648
649   transaction = bus_transaction_new (activation->context);
650   if (transaction == NULL)
651     return FALSE;
652   
653   link = _dbus_list_get_first_link (&pending_activation->entries);
654   while (link != NULL)
655     {
656       BusPendingActivationEntry *entry = link->data;
657       DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
658       
659       if (dbus_connection_get_is_connected (entry->connection))
660         {
661           if (!bus_transaction_send_error_reply (transaction,
662                                                  entry->connection,
663                                                  how,
664                                                  entry->activation_message))
665             goto error;
666         }
667       
668       link = next;
669     }
670
671   bus_transaction_execute_and_free (transaction);
672   
673   return TRUE;
674
675  error:
676   if (transaction)
677     bus_transaction_cancel_and_free (transaction);
678   return FALSE;
679 }
680
681 /**
682  * Free the pending activation and send an error message to all the
683  * connections that were waiting for it.
684  */
685 static void
686 pending_activation_failed (BusPendingActivation *pending_activation,
687                            const DBusError      *how)
688 {
689   /* FIXME use preallocated OOM messages instead of bus_wait_for_memory() */
690   while (!try_send_activation_failure (pending_activation, how))
691     _dbus_wait_for_memory ();
692
693   /* Destroy this pending activation */
694   _dbus_hash_table_remove_string (pending_activation->activation->pending_activations,
695                                   pending_activation->service_name);
696 }
697
698 static dbus_bool_t
699 babysitter_watch_callback (DBusWatch     *watch,
700                            unsigned int   condition,
701                            void          *data)
702 {
703   BusPendingActivation *pending_activation = data;
704   dbus_bool_t retval;
705   DBusBabysitter *babysitter;
706
707   babysitter = pending_activation->babysitter;
708   
709   _dbus_babysitter_ref (babysitter);
710   
711   retval = dbus_watch_handle (watch, condition);
712
713   /* FIXME this is broken in the same way that
714    * connection watches used to be; there should be
715    * a separate callback for status change, instead
716    * of doing "if we handled a watch status might
717    * have changed"
718    *
719    * Fixing this lets us move dbus_watch_handle
720    * calls into dbus-mainloop.c
721    */
722   
723   if (_dbus_babysitter_get_child_exited (babysitter))
724     {
725       DBusError error;
726
727       dbus_error_init (&error);
728       _dbus_babysitter_set_child_exit_error (babysitter, &error);
729
730       /* Destroys the pending activation */
731       pending_activation_failed (pending_activation, &error);
732
733       dbus_error_free (&error);
734     }
735   
736   _dbus_babysitter_unref (babysitter);
737
738   return retval;
739 }
740
741 static dbus_bool_t
742 add_babysitter_watch (DBusWatch      *watch,
743                       void           *data)
744 {
745   BusPendingActivation *pending_activation = data;
746
747   return _dbus_loop_add_watch (bus_context_get_loop (pending_activation->activation->context),
748                                watch, babysitter_watch_callback, pending_activation,
749                                NULL);
750 }
751
752 static void
753 remove_babysitter_watch (DBusWatch      *watch,
754                          void           *data)
755 {
756   BusPendingActivation *pending_activation = data;
757   
758   _dbus_loop_remove_watch (bus_context_get_loop (pending_activation->activation->context),
759                            watch, babysitter_watch_callback, pending_activation);
760 }
761
762 static dbus_bool_t
763 pending_activation_timed_out (void *data)
764 {
765   BusPendingActivation *pending_activation = data;
766   DBusError error;
767   
768   /* Kill the spawned process, since it sucks
769    * (not sure this is what we want to do, but
770    * may as well try it for now)
771    */
772   _dbus_babysitter_kill_child (pending_activation->babysitter);
773
774   dbus_error_init (&error);
775
776   dbus_set_error (&error, DBUS_ERROR_TIMED_OUT,
777                   "Activation of %s timed out",
778                   pending_activation->service_name);
779
780   pending_activation_failed (pending_activation, &error);
781
782   dbus_error_free (&error);
783
784   return TRUE;
785 }
786
787 static void
788 cancel_pending (void *data)
789 {
790   BusPendingActivation *pending_activation = data;
791
792   _dbus_verbose ("Canceling pending activation of %s\n",
793                  pending_activation->service_name);
794
795   if (pending_activation->babysitter)
796     _dbus_babysitter_kill_child (pending_activation->babysitter);
797   
798   _dbus_hash_table_remove_string (pending_activation->activation->pending_activations,
799                                   pending_activation->service_name);
800 }
801
802 static void
803 free_pending_cancel_data (void *data)
804 {
805   BusPendingActivation *pending_activation = data;
806   
807   bus_pending_activation_unref (pending_activation);
808 }
809
810 static dbus_bool_t
811 add_cancel_pending_to_transaction (BusTransaction       *transaction,
812                                    BusPendingActivation *pending_activation)
813 {  
814   if (!bus_transaction_add_cancel_hook (transaction, cancel_pending,
815                                         pending_activation,
816                                         free_pending_cancel_data))
817     return FALSE;
818
819   bus_pending_activation_ref (pending_activation); 
820   
821   _dbus_verbose ("Saved pending activation to be canceled if the transaction fails\n");
822   
823   return TRUE;
824 }
825
826 dbus_bool_t
827 bus_activation_activate_service (BusActivation  *activation,
828                                  DBusConnection *connection,
829                                  BusTransaction *transaction,
830                                  DBusMessage    *activation_message,
831                                  const char     *service_name,
832                                  DBusError      *error)
833 {
834   BusActivationEntry *entry;
835   BusPendingActivation *pending_activation;
836   BusPendingActivationEntry *pending_activation_entry;
837   DBusMessage *message;
838   DBusString service_str;
839   char *argv[2];
840   dbus_bool_t retval;
841
842   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
843
844   if (activation->n_pending_activations >=
845       bus_context_get_max_pending_activations (activation->context))
846     {
847       dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
848                       "The maximum number of pending activations has been reached, activation of %s failed",
849                       service_name);
850       return FALSE;
851     }
852   
853   entry = _dbus_hash_table_lookup_string (activation->entries, service_name);
854
855   if (!entry)
856     {
857       dbus_set_error (error, DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND,
858                       "The service %s was not found in the activation entry list",
859                       service_name);
860       return FALSE;
861     }
862
863   /* Check if the service is active */
864   _dbus_string_init_const (&service_str, service_name);
865   if (bus_registry_lookup (bus_context_get_registry (activation->context), &service_str) != NULL)
866     {
867       _dbus_verbose ("Service \"%s\" is already active\n", service_name);
868       
869       message = dbus_message_new_method_return (activation_message);
870
871       if (!message)
872         {
873           _dbus_verbose ("No memory to create reply to activate message\n");
874           BUS_SET_OOM (error);
875           return FALSE;
876         }
877
878       if (!dbus_message_append_args (message,
879                                      DBUS_TYPE_UINT32, DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE, 
880                                      DBUS_TYPE_INVALID))
881         {
882           _dbus_verbose ("No memory to set args of reply to activate message\n");
883           BUS_SET_OOM (error);
884           dbus_message_unref (message);
885           return FALSE;
886         }
887
888       retval = bus_transaction_send_from_driver (transaction, connection, message);
889       dbus_message_unref (message);
890       if (!retval)
891         {
892           _dbus_verbose ("Failed to send reply\n");
893           BUS_SET_OOM (error);
894         }
895
896       return retval;
897     }
898
899   pending_activation_entry = dbus_new0 (BusPendingActivationEntry, 1);
900   if (!pending_activation_entry)
901     {
902       _dbus_verbose ("Failed to create pending activation entry\n");
903       BUS_SET_OOM (error);
904       return FALSE;
905     }
906
907   pending_activation_entry->activation_message = activation_message;
908   dbus_message_ref (activation_message);
909   pending_activation_entry->connection = connection;
910   dbus_connection_ref (connection);
911   
912   /* Check if the service is being activated */
913   pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, service_name);
914   if (pending_activation)
915     {
916       if (!_dbus_list_append (&pending_activation->entries, pending_activation_entry))
917         {
918           _dbus_verbose ("Failed to append a new entry to pending activation\n");
919           
920           BUS_SET_OOM (error);
921           bus_pending_activation_entry_free (pending_activation_entry);
922           return FALSE;
923         }
924
925       pending_activation->n_entries += 1;
926       pending_activation->activation->n_pending_activations += 1;
927     }
928   else
929     {
930       pending_activation = dbus_new0 (BusPendingActivation, 1);
931       if (!pending_activation)
932         {
933           _dbus_verbose ("Failed to create pending activation\n");
934           
935           BUS_SET_OOM (error);
936           bus_pending_activation_entry_free (pending_activation_entry);   
937           return FALSE;
938         }
939
940       pending_activation->activation = activation;
941       pending_activation->refcount = 1;
942       
943       pending_activation->service_name = _dbus_strdup (service_name);
944       if (!pending_activation->service_name)
945         {
946           _dbus_verbose ("Failed to copy service name for pending activation\n");
947           
948           BUS_SET_OOM (error);
949           bus_pending_activation_unref (pending_activation);
950           bus_pending_activation_entry_free (pending_activation_entry);   
951           return FALSE;
952         }
953
954       pending_activation->timeout =
955         _dbus_timeout_new (bus_context_get_activation_timeout (activation->context),
956                            pending_activation_timed_out,
957                            pending_activation,
958                            NULL);
959       if (!pending_activation->timeout)
960         {
961           _dbus_verbose ("Failed to create timeout for pending activation\n");
962           
963           BUS_SET_OOM (error);
964           bus_pending_activation_unref (pending_activation);
965           bus_pending_activation_entry_free (pending_activation_entry);   
966           return FALSE;
967         }
968
969       if (!_dbus_loop_add_timeout (bus_context_get_loop (activation->context),
970                                    pending_activation->timeout,
971                                    handle_timeout_callback,
972                                    pending_activation,
973                                    NULL))
974         {
975           _dbus_verbose ("Failed to add timeout for pending activation\n");
976           
977           BUS_SET_OOM (error);
978           bus_pending_activation_unref (pending_activation);
979           bus_pending_activation_entry_free (pending_activation_entry);   
980           return FALSE;
981         }
982
983       pending_activation->timeout_added = TRUE;
984       
985       if (!_dbus_list_append (&pending_activation->entries, pending_activation_entry))
986         {
987           _dbus_verbose ("Failed to add entry to just-created pending activation\n");
988           
989           BUS_SET_OOM (error);
990           bus_pending_activation_unref (pending_activation);
991           bus_pending_activation_entry_free (pending_activation_entry);   
992           return FALSE;
993         }
994
995       pending_activation->n_entries += 1;
996       pending_activation->activation->n_pending_activations += 1;
997       
998       if (!_dbus_hash_table_insert_string (activation->pending_activations,
999                                            pending_activation->service_name,
1000                                            pending_activation))
1001         {
1002           _dbus_verbose ("Failed to put pending activation in hash table\n");
1003           
1004           BUS_SET_OOM (error);
1005           bus_pending_activation_unref (pending_activation);
1006           return FALSE;
1007         }
1008     }
1009
1010   if (!add_cancel_pending_to_transaction (transaction, pending_activation))
1011     {
1012       _dbus_verbose ("Failed to add pending activation cancel hook to transaction\n");
1013       BUS_SET_OOM (error);
1014       _dbus_hash_table_remove_string (activation->pending_activations,
1015                                       pending_activation->service_name);
1016       return FALSE;
1017     }
1018   
1019   /* FIXME we need to support a full command line, not just a single
1020    * argv[0]
1021    */
1022   
1023   /* Now try to spawn the process */
1024   argv[0] = entry->exec;
1025   argv[1] = NULL;
1026
1027   if (!_dbus_spawn_async_with_babysitter (&pending_activation->babysitter, argv,
1028                                           child_setup, activation, 
1029                                           error))
1030     {
1031       _dbus_verbose ("Failed to spawn child\n");
1032       _DBUS_ASSERT_ERROR_IS_SET (error);
1033       return FALSE;
1034     }
1035
1036   _dbus_assert (pending_activation->babysitter != NULL);
1037   
1038   if (!_dbus_babysitter_set_watch_functions (pending_activation->babysitter,
1039                                              add_babysitter_watch,
1040                                              remove_babysitter_watch,
1041                                              NULL,
1042                                              pending_activation,
1043                                              NULL))
1044     {
1045       BUS_SET_OOM (error);
1046       _dbus_verbose ("Failed to set babysitter watch functions\n");
1047       return FALSE;
1048     }
1049   
1050   return TRUE;
1051 }