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