54ddd948b669b0fc3a16d797973ddeb8bf461b78
[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 };
49
50 typedef struct
51 {
52   char *name;
53   char *exec;
54 } BusActivationEntry;
55
56 typedef struct BusPendingActivationEntry BusPendingActivationEntry;
57
58 struct BusPendingActivationEntry
59 {
60   DBusMessage *activation_message;
61   DBusConnection *connection;
62 };
63
64 typedef struct
65 {
66   BusActivation *activation;
67   char *service_name;
68   DBusList *entries;
69   DBusBabysitter *babysitter;
70   DBusTimeout *timeout;
71   unsigned int timeout_added : 1;
72 } BusPendingActivation;
73
74 static void
75 bus_pending_activation_entry_free (BusPendingActivationEntry *entry)
76 {
77   if (entry->activation_message)
78     dbus_message_unref (entry->activation_message);
79   
80   if (entry->connection)
81     dbus_connection_unref (entry->connection);
82   
83   dbus_free (entry);
84 }
85
86 static void
87 handle_timeout_callback (DBusTimeout   *timeout,
88                          void          *data)
89 {
90   BusPendingActivation *pending_activation = data;
91
92   while (!dbus_timeout_handle (pending_activation->timeout))
93     bus_wait_for_memory ();
94 }
95
96 static void
97 bus_pending_activation_free (BusPendingActivation *pending_activation)
98 {
99   DBusList *link;
100   
101   if (pending_activation == NULL) /* hash table requires this */
102     return;
103
104   if (pending_activation->timeout_added)
105     {
106       bus_loop_remove_timeout (bus_context_get_loop (pending_activation->activation->context),
107                                pending_activation->timeout,
108                                handle_timeout_callback, pending_activation);
109       pending_activation->timeout_added = FALSE;
110     }
111
112   if (pending_activation->timeout)
113     _dbus_timeout_unref (pending_activation->timeout);
114   
115   if (pending_activation->babysitter)
116     {
117       if (!_dbus_babysitter_set_watch_functions (pending_activation->babysitter,
118                                                  NULL, NULL, NULL,
119                                                  pending_activation->babysitter,
120                                                  NULL))
121         _dbus_assert_not_reached ("setting watch functions to NULL failed");
122       
123       _dbus_babysitter_unref (pending_activation->babysitter);
124     }
125   
126   dbus_free (pending_activation->service_name);
127
128   link = _dbus_list_get_first_link (&pending_activation->entries);
129
130   while (link != NULL)
131     {
132       BusPendingActivationEntry *entry = link->data;
133
134       bus_pending_activation_entry_free (entry);
135
136       link = _dbus_list_get_next_link (&pending_activation->entries, link);
137     }
138   _dbus_list_clear (&pending_activation->entries);
139   
140   dbus_free (pending_activation);
141 }
142
143 static void
144 bus_activation_entry_free (BusActivationEntry *entry)
145 {
146   if (!entry)
147     return;
148   
149   dbus_free (entry->name);
150   dbus_free (entry->exec);
151
152   dbus_free (entry);
153 }
154
155 static dbus_bool_t
156 add_desktop_file_entry (BusActivation  *activation,
157                         BusDesktopFile *desktop_file,
158                         DBusError      *error)
159 {
160   char *name, *exec;
161   BusActivationEntry *entry;
162
163   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
164   
165   name = NULL;
166   exec = NULL;
167   entry = NULL;
168   
169   if (!bus_desktop_file_get_string (desktop_file,
170                                     DBUS_SERVICE_SECTION,
171                                     DBUS_SERVICE_NAME,
172                                     &name))
173     {
174       dbus_set_error (error, DBUS_ERROR_FAILED,
175                       "No \""DBUS_SERVICE_NAME"\" key in .service file\n");
176       goto failed;
177     }
178
179   if (!bus_desktop_file_get_string (desktop_file,
180                                     DBUS_SERVICE_SECTION,
181                                     DBUS_SERVICE_EXEC,
182                                     &exec))
183     {
184       dbus_set_error (error, DBUS_ERROR_FAILED,
185                       "No \""DBUS_SERVICE_EXEC"\" key in .service file\n");
186       goto failed;
187     }
188
189   /* FIXME we need a better-defined algorithm for which service file to
190    * pick than "whichever one is first in the directory listing"
191    */
192   if (_dbus_hash_table_lookup_string (activation->entries, name))
193     {
194       dbus_set_error (error, DBUS_ERROR_FAILED,
195                       "Service %s already exists in activation entry list\n", name);
196       goto failed;
197     }
198   
199   entry = dbus_new0 (BusActivationEntry, 1);
200   if (entry == NULL)
201     {
202       BUS_SET_OOM (error);
203       goto failed;
204     }
205   
206   entry->name = name;
207   entry->exec = exec;
208
209   if (!_dbus_hash_table_insert_string (activation->entries, entry->name, entry))
210     {
211       BUS_SET_OOM (error);
212       goto failed;
213     }
214
215   _dbus_verbose ("Added \"%s\" to list of services\n", entry->name);
216   
217   return TRUE;
218
219  failed:
220   dbus_free (name);
221   dbus_free (exec);
222   dbus_free (entry);
223   
224   return FALSE;
225 }
226
227 /* warning: this doesn't fully "undo" itself on failure, i.e. doesn't strip
228  * hash entries it already added.
229  */
230 static dbus_bool_t
231 load_directory (BusActivation *activation,
232                 const char    *directory,
233                 DBusError     *error)
234 {
235   DBusDirIter *iter;
236   DBusString dir, filename;
237   DBusString full_path;
238   BusDesktopFile *desktop_file;
239   DBusError tmp_error;
240   dbus_bool_t retval;
241   
242   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
243   
244   _dbus_string_init_const (&dir, directory);
245
246   iter = NULL;
247   desktop_file = NULL;
248   
249   if (!_dbus_string_init (&filename))
250     {
251       BUS_SET_OOM (error);
252       return FALSE;
253     }
254
255   if (!_dbus_string_init (&full_path))
256     {
257       BUS_SET_OOM (error);
258       _dbus_string_free (&filename);
259       return FALSE;
260     }
261
262   retval = FALSE;
263   
264   /* from this point it's safe to "goto out" */
265   
266   iter = _dbus_directory_open (&dir, error);
267   if (iter == NULL)
268     {
269       _dbus_verbose ("Failed to open directory %s: %s\n",
270                      directory, error ? error->message : "unknown");
271       goto out;
272     }
273   
274   /* Now read the files */
275   dbus_error_init (&tmp_error);
276   while (_dbus_directory_get_next_file (iter, &filename, &tmp_error))
277     {
278       _dbus_assert (!dbus_error_is_set (&tmp_error));
279       
280       _dbus_string_set_length (&full_path, 0);
281       
282       if (!_dbus_string_append (&full_path, directory) ||
283           !_dbus_concat_dir_and_file (&full_path, &filename))
284         {
285           BUS_SET_OOM (error);
286           goto out;
287         }
288       
289       if (!_dbus_string_ends_with_c_str (&filename, ".service"))
290         {
291           _dbus_verbose ("Skipping non-.service file %s\n",
292                          _dbus_string_get_const_data (&filename));
293           continue;
294         }
295       
296       desktop_file = bus_desktop_file_load (&full_path, &tmp_error);
297
298       if (desktop_file == NULL)
299         {
300           _dbus_verbose ("Could not load %s: %s\n",
301                          _dbus_string_get_const_data (&full_path),
302                          tmp_error.message);
303
304           if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
305             {
306               dbus_move_error (&tmp_error, error);
307               goto out;
308             }
309           
310           dbus_error_free (&tmp_error);
311           continue;
312         }
313
314       if (!add_desktop_file_entry (activation, desktop_file, &tmp_error))
315         {
316           bus_desktop_file_free (desktop_file);
317           desktop_file = NULL;
318           
319           _dbus_verbose ("Could not add %s to activation entry list: %s\n",
320                          _dbus_string_get_const_data (&full_path), tmp_error.message);
321
322           if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
323             {
324               dbus_move_error (&tmp_error, error);
325               goto out;
326             }
327
328           dbus_error_free (&tmp_error);
329           continue;
330         }
331       else
332         {
333           bus_desktop_file_free (desktop_file);
334           desktop_file = NULL;
335           continue;
336         }
337     }
338
339   if (dbus_error_is_set (&tmp_error))
340     {
341       dbus_move_error (&tmp_error, error);
342       goto out;
343     }
344   
345   retval = TRUE;
346   
347  out:
348   if (!retval)
349     _DBUS_ASSERT_ERROR_IS_SET (error);
350   else
351     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
352   
353   if (iter != NULL)
354     _dbus_directory_close (iter);
355   if (desktop_file)
356     bus_desktop_file_free (desktop_file);
357   _dbus_string_free (&filename);
358   _dbus_string_free (&full_path);
359   
360   return retval;
361 }
362
363 BusActivation*
364 bus_activation_new (BusContext        *context,
365                     const DBusString  *address,
366                     DBusList         **directories,
367                     DBusError         *error)
368 {
369   BusActivation *activation;
370   DBusList *link;
371   
372   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
373   
374   activation = dbus_new0 (BusActivation, 1);
375   if (activation == NULL)
376     {
377       BUS_SET_OOM (error);
378       return NULL;
379     }
380   
381   activation->refcount = 1;
382   activation->context = context;
383   
384   if (!_dbus_string_copy_data (address, &activation->server_address))
385     {
386       BUS_SET_OOM (error);
387       goto failed;
388     }
389   
390   activation->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
391                                              (DBusFreeFunction)bus_activation_entry_free);
392   if (activation->entries == NULL)
393     {      
394       BUS_SET_OOM (error);
395       goto failed;
396     }
397
398   activation->pending_activations = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
399                                                           (DBusFreeFunction)bus_pending_activation_free);
400
401   if (activation->pending_activations == NULL)
402     {
403       BUS_SET_OOM (error);
404       goto failed;
405     }
406   
407   /* Load service files */
408   link = _dbus_list_get_first_link (directories);
409   while (link != NULL)
410     {
411       if (!load_directory (activation, link->data, error))
412         goto failed;
413       link = _dbus_list_get_next_link (directories, link);
414     }
415
416   return activation;
417   
418  failed:
419   bus_activation_unref (activation);  
420   return NULL;
421 }
422
423 void
424 bus_activation_ref (BusActivation *activation)
425 {
426   _dbus_assert (activation->refcount > 0);
427   
428   activation->refcount += 1;
429 }
430
431 void
432 bus_activation_unref (BusActivation *activation)
433 {
434   _dbus_assert (activation->refcount > 0);
435
436   activation->refcount -= 1;
437
438   if (activation->refcount == 0)
439     {
440       dbus_free (activation->server_address);
441       if (activation->entries)
442         _dbus_hash_table_unref (activation->entries);
443       if (activation->pending_activations)
444         _dbus_hash_table_unref (activation->pending_activations);
445       dbus_free (activation);
446     }
447 }
448
449 static void
450 child_setup (void *data)
451 {
452   BusActivation *activation = data;
453   const char *type;
454   
455   /* If no memory, we simply have the child exit, so it won't try
456    * to connect to the wrong thing.
457    */
458   if (!_dbus_setenv ("DBUS_ACTIVATION_ADDRESS", activation->server_address))
459     _dbus_exit (1);
460
461   type = bus_context_get_type (activation->context);
462   if (type != NULL)
463     {
464       if (!_dbus_setenv ("DBUS_BUS_TYPE", type))
465         _dbus_exit (1);
466     }
467 }
468
469 dbus_bool_t
470 bus_activation_service_created (BusActivation  *activation,
471                                 const char     *service_name,
472                                 BusTransaction *transaction,
473                                 DBusError      *error)
474 {
475   BusPendingActivation *pending_activation;
476   DBusMessage *message;
477   DBusList *link;
478
479   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
480   
481   /* Check if it's a pending activation */
482   pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, service_name);
483
484   if (!pending_activation)
485     return TRUE;
486
487   link = _dbus_list_get_first_link (&pending_activation->entries);
488   while (link != NULL)
489     {
490       BusPendingActivationEntry *entry = link->data;
491       DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
492       
493       if (dbus_connection_get_is_connected (entry->connection))
494         {
495           message = dbus_message_new_reply (entry->activation_message);
496           if (!message)
497             {
498               BUS_SET_OOM (error);
499               goto error;
500             }
501
502           if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS) ||
503               !dbus_message_append_args (message,
504                                          DBUS_TYPE_UINT32, DBUS_ACTIVATION_REPLY_ACTIVATED,
505                                          0))
506             {
507               dbus_message_unref (message);
508               BUS_SET_OOM (error);
509               goto error;
510             }
511           
512           if (!bus_transaction_send_message (transaction, entry->connection, message))
513             {
514               dbus_message_unref (message);
515               BUS_SET_OOM (error);
516               goto error;
517             }
518
519           dbus_message_unref (message);
520         }
521
522       link = next;
523     }
524   
525   _dbus_hash_table_remove_string (activation->pending_activations, service_name);
526
527   return TRUE;
528
529  error:
530   _dbus_hash_table_remove_string (activation->pending_activations, service_name);
531   return FALSE;
532 }
533
534 /**
535  * FIXME @todo the error messages here would ideally be preallocated
536  * so we don't need to allocate memory to send them.
537  * Using the usual tactic, prealloc an OOM message, then
538  * if we can't alloc the real error send the OOM error instead.
539  */
540 static dbus_bool_t
541 try_send_activation_failure (BusPendingActivation *pending_activation,
542                              const DBusError      *how)
543 {
544   BusActivation *activation;
545   DBusMessage *message;
546   DBusList *link;
547   BusTransaction *transaction;
548   
549   activation = pending_activation->activation;
550
551   transaction = bus_transaction_new (activation->context);
552   if (transaction == NULL)
553     return FALSE;
554   
555   link = _dbus_list_get_first_link (&pending_activation->entries);
556   while (link != NULL)
557     {
558       BusPendingActivationEntry *entry = link->data;
559       DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
560       
561       if (dbus_connection_get_is_connected (entry->connection))
562         {
563           message = dbus_message_new_error_reply (entry->activation_message,
564                                                   how->name,
565                                                   how->message);
566           if (!message)
567             goto error;
568
569           if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
570             {
571               dbus_message_unref (message);
572               goto error;
573             }
574           
575           if (!bus_transaction_send_message (transaction, entry->connection, message))
576             {
577               dbus_message_unref (message);
578               goto error;
579             }
580
581           dbus_message_unref (message);
582         }
583
584       link = next;
585     }
586
587   bus_transaction_execute_and_free (transaction);
588   
589   return TRUE;
590
591  error:
592   if (transaction)
593     bus_transaction_cancel_and_free (transaction);
594   return FALSE;
595 }
596
597 /**
598  * Free the pending activation and send an error message to all the
599  * connections that were waiting for it.
600  */
601 static void
602 pending_activation_failed (BusPendingActivation *pending_activation,
603                            const DBusError      *how)
604 {
605   /* FIXME use preallocated OOM messages instead of bus_wait_for_memory() */
606   while (!try_send_activation_failure (pending_activation, how))
607     bus_wait_for_memory ();
608
609   /* Destroy this pending activation */
610   _dbus_hash_table_remove_string (pending_activation->activation->pending_activations,
611                                   pending_activation->service_name);
612 }
613
614 static dbus_bool_t
615 babysitter_watch_callback (DBusWatch     *watch,
616                            unsigned int   condition,
617                            void          *data)
618 {
619   BusPendingActivation *pending_activation = data;
620   dbus_bool_t retval;
621   DBusBabysitter *babysitter;
622
623   babysitter = pending_activation->babysitter;
624   
625   _dbus_babysitter_ref (babysitter);
626   
627   retval = _dbus_babysitter_handle_watch (babysitter, watch, condition);
628
629   if (_dbus_babysitter_get_child_exited (babysitter))
630     {
631       DBusError error;
632
633       dbus_error_init (&error);
634       _dbus_babysitter_set_child_exit_error (babysitter, &error);
635
636       /* Destroys the pending activation */
637       pending_activation_failed (pending_activation, &error);
638
639       dbus_error_free (&error);
640     }
641   
642   _dbus_babysitter_unref (babysitter);
643
644   return retval;
645 }
646
647 static dbus_bool_t
648 add_babysitter_watch (DBusWatch      *watch,
649                       void           *data)
650 {
651   BusPendingActivation *pending_activation = data;
652
653   return bus_loop_add_watch (bus_context_get_loop (pending_activation->activation->context),
654                              watch, babysitter_watch_callback, pending_activation,
655                              NULL);
656 }
657
658 static void
659 remove_babysitter_watch (DBusWatch      *watch,
660                          void           *data)
661 {
662   BusPendingActivation *pending_activation = data;
663   
664   bus_loop_remove_watch (bus_context_get_loop (pending_activation->activation->context),
665                          watch, babysitter_watch_callback, pending_activation);
666 }
667
668 static dbus_bool_t
669 pending_activation_timed_out (void *data)
670 {
671   BusPendingActivation *pending_activation = data;
672   DBusError error;
673   
674   /* Kill the spawned process, since it sucks
675    * (not sure this is what we want to do, but
676    * may as well try it for now)
677    */
678   _dbus_babysitter_kill_child (pending_activation->babysitter);
679
680   dbus_error_init (&error);
681
682   dbus_set_error (&error, DBUS_ERROR_TIMED_OUT,
683                   "Activation of %s timed out",
684                   pending_activation->service_name);
685
686   pending_activation_failed (pending_activation, &error);
687
688   dbus_error_free (&error);
689
690   return TRUE;
691 }
692
693 dbus_bool_t
694 bus_activation_activate_service (BusActivation  *activation,
695                                  DBusConnection *connection,
696                                  BusTransaction *transaction,
697                                  DBusMessage    *activation_message,
698                                  const char     *service_name,
699                                  DBusError      *error)
700 {
701   BusActivationEntry *entry;
702   BusPendingActivation *pending_activation;
703   BusPendingActivationEntry *pending_activation_entry;
704   DBusMessage *message;
705   DBusString service_str;
706   char *argv[2];
707   dbus_bool_t retval;
708
709   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
710   
711   entry = _dbus_hash_table_lookup_string (activation->entries, service_name);
712
713   if (!entry)
714     {
715       dbus_set_error (error, DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND,
716                       "The service %s was not found in the activation entry list",
717                       service_name);
718       return FALSE;
719     }
720
721   /* Check if the service is active */
722   _dbus_string_init_const (&service_str, service_name);
723   if (bus_registry_lookup (bus_context_get_registry (activation->context), &service_str) != NULL)
724     {
725       message = dbus_message_new_reply (activation_message);
726
727       if (!message)
728         {
729           BUS_SET_OOM (error);
730           return FALSE;
731         }
732
733       if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS) ||
734           !dbus_message_append_args (message,
735                                      DBUS_TYPE_UINT32, DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE, 
736                                      0))
737         {
738           BUS_SET_OOM (error);
739           dbus_message_unref (message);
740           return FALSE;
741         }
742
743       retval = bus_transaction_send_message (transaction, connection, message);
744       dbus_message_unref (message);
745       if (!retval)
746         BUS_SET_OOM (error);
747
748       return retval;
749     }
750
751   pending_activation_entry = dbus_new0 (BusPendingActivationEntry, 1);
752   if (!pending_activation_entry)
753     {
754       BUS_SET_OOM (error);
755       return FALSE;
756     }
757
758   pending_activation_entry->activation_message = activation_message;
759   dbus_message_ref (activation_message);
760   pending_activation_entry->connection = connection;
761   dbus_connection_ref (connection);
762   
763   /* Check if the service is being activated */
764   pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, service_name);
765   if (pending_activation)
766     {
767       if (!_dbus_list_append (&pending_activation->entries, pending_activation_entry))
768         {
769           BUS_SET_OOM (error);
770           bus_pending_activation_entry_free (pending_activation_entry);
771
772           return FALSE;
773         }
774     }
775   else
776     {
777       pending_activation = dbus_new0 (BusPendingActivation, 1);
778       if (!pending_activation)
779         {
780           BUS_SET_OOM (error);
781           bus_pending_activation_entry_free (pending_activation_entry);   
782           return FALSE;
783         }
784
785       pending_activation->activation = activation;
786       
787       pending_activation->service_name = _dbus_strdup (service_name);
788       if (!pending_activation->service_name)
789         {
790           BUS_SET_OOM (error);
791           bus_pending_activation_free (pending_activation);
792           bus_pending_activation_entry_free (pending_activation_entry);   
793           return FALSE;
794         }
795
796       pending_activation->timeout =
797         _dbus_timeout_new (bus_context_get_activation_timeout (activation->context),
798                            pending_activation_timed_out,
799                            pending_activation,
800                            NULL);
801       if (!pending_activation->timeout)
802         {
803           BUS_SET_OOM (error);
804           bus_pending_activation_free (pending_activation);
805           bus_pending_activation_entry_free (pending_activation_entry);   
806           return FALSE;
807         }
808
809       if (!bus_loop_add_timeout (bus_context_get_loop (activation->context),
810                                  pending_activation->timeout,
811                                  handle_timeout_callback,
812                                  pending_activation,
813                                  NULL))
814         {
815           BUS_SET_OOM (error);
816           bus_pending_activation_free (pending_activation);
817           bus_pending_activation_entry_free (pending_activation_entry);   
818           return FALSE;
819         }
820
821       pending_activation->timeout_added = TRUE;
822       
823       if (!_dbus_list_append (&pending_activation->entries, pending_activation_entry))
824         {
825           BUS_SET_OOM (error);
826           bus_pending_activation_free (pending_activation);
827           bus_pending_activation_entry_free (pending_activation_entry);   
828           return FALSE;
829         }
830       
831       if (!_dbus_hash_table_insert_string (activation->pending_activations,
832                                            pending_activation->service_name, pending_activation))
833         {
834           BUS_SET_OOM (error);
835           bus_pending_activation_free (pending_activation);
836           return FALSE;
837         }
838     }
839   
840   /* FIXME we need to support a full command line, not just a single
841    * argv[0]
842    */
843   
844   /* Now try to spawn the process */
845   argv[0] = entry->exec;
846   argv[1] = NULL;
847
848   if (!_dbus_spawn_async_with_babysitter (&pending_activation->babysitter, argv,
849                                           child_setup, activation, 
850                                           error))
851     {
852       _dbus_hash_table_remove_string (activation->pending_activations,
853                                       pending_activation->service_name);
854       return FALSE;
855     }
856
857   _dbus_assert (pending_activation->babysitter != NULL);
858   
859   if (!_dbus_babysitter_set_watch_functions (pending_activation->babysitter,
860                                              add_babysitter_watch,
861                                              remove_babysitter_watch,
862                                              NULL,
863                                              pending_activation,
864                                              NULL))
865     {
866       BUS_SET_OOM (error);
867       
868       _dbus_hash_table_remove_string (activation->pending_activations,
869                                       pending_activation->service_name);
870       return FALSE;
871     }
872   
873   return TRUE;
874 }