Merge branch 'fd-passing'
[platform/upstream/dbus.git] / bus / activation.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* activation.c  Activation of services
3  *
4  * Copyright (C) 2003  CodeFactory AB
5  * Copyright (C) 2003  Red Hat, Inc.
6  * Copyright (C) 2004  Imendio HB
7  *
8  * Licensed under the Academic Free License version 2.1
9  * 
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  * 
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23  *
24  */
25 #include "activation.h"
26 #include "activation-exit-codes.h"
27 #include "desktop-file.h"
28 #include "services.h"
29 #include "test.h"
30 #include "utils.h"
31 #include <dbus/dbus-internals.h>
32 #include <dbus/dbus-hash.h>
33 #include <dbus/dbus-list.h>
34 #include <dbus/dbus-shell.h>
35 #include <dbus/dbus-spawn.h>
36 #include <dbus/dbus-timeout.h>
37 #include <dbus/dbus-sysdeps.h>
38 #ifdef HAVE_ERRNO_H
39 #include <errno.h>
40 #endif
41
42 struct BusActivation
43 {
44   int refcount;
45   DBusHashTable *entries;
46   DBusHashTable *pending_activations;
47   char *server_address;
48   BusContext *context;
49   int n_pending_activations; /**< This is in fact the number of BusPendingActivationEntry,
50                               * i.e. number of pending activation requests, not pending
51                               * activations per se
52                               */
53   DBusHashTable *directories;
54   DBusHashTable *environment;
55 };
56
57 typedef struct
58 {
59   int refcount;
60   char *dir_c;
61   DBusHashTable *entries;
62 } BusServiceDirectory;
63
64 typedef struct
65 {
66   int refcount;
67   char *name;
68   char *exec;
69   char *user;
70   unsigned long mtime;
71   BusServiceDirectory *s_dir;
72   char *filename;
73 } BusActivationEntry;
74
75 typedef struct BusPendingActivationEntry BusPendingActivationEntry;
76
77 struct BusPendingActivationEntry
78 {
79   DBusMessage *activation_message;
80   DBusConnection *connection;
81
82   dbus_bool_t auto_activation;
83 };
84
85 typedef struct
86 {
87   int refcount;
88   BusActivation *activation;
89   char *service_name;
90   char *exec;
91   DBusList *entries;
92   int n_entries;
93   DBusBabysitter *babysitter;
94   DBusTimeout *timeout;
95   unsigned int timeout_added : 1;
96 } BusPendingActivation;
97
98 #if 0
99 static BusServiceDirectory *
100 bus_service_directory_ref (BusServiceDirectory *dir)
101 {
102   _dbus_assert (dir->refcount);
103   
104   dir->refcount++;
105
106   return dir;
107 }
108 #endif
109
110 static void
111 bus_service_directory_unref (BusServiceDirectory *dir)
112 {
113   if (dir == NULL) 
114     return; 
115
116   _dbus_assert (dir->refcount > 0);
117   dir->refcount--;
118
119   if (dir->refcount > 0)
120     return;
121
122   if (dir->entries)
123     _dbus_hash_table_unref (dir->entries);
124
125   dbus_free (dir->dir_c);
126   dbus_free (dir);
127 }
128
129 static void
130 bus_pending_activation_entry_free (BusPendingActivationEntry *entry)
131 {
132   if (entry->activation_message)
133     dbus_message_unref (entry->activation_message);
134   
135   if (entry->connection)
136     dbus_connection_unref (entry->connection);
137   
138   dbus_free (entry);
139 }
140
141 static void
142 handle_timeout_callback (DBusTimeout   *timeout,
143                          void          *data)
144 {
145   BusPendingActivation *pending_activation = data;
146
147   while (!dbus_timeout_handle (pending_activation->timeout))
148     _dbus_wait_for_memory ();
149 }
150
151 static BusPendingActivation * 
152 bus_pending_activation_ref (BusPendingActivation *pending_activation)
153 {
154   _dbus_assert (pending_activation->refcount > 0);
155   pending_activation->refcount += 1;
156
157   return pending_activation;
158 }
159
160 static void
161 bus_pending_activation_unref (BusPendingActivation *pending_activation)
162 {
163   DBusList *link;
164   
165   if (pending_activation == NULL) /* hash table requires this */
166     return;
167
168   _dbus_assert (pending_activation->refcount > 0);
169   pending_activation->refcount -= 1;
170
171   if (pending_activation->refcount > 0)
172     return;
173   
174   if (pending_activation->timeout_added)
175     {
176       _dbus_loop_remove_timeout (bus_context_get_loop (pending_activation->activation->context),
177                                  pending_activation->timeout,
178                                  handle_timeout_callback, pending_activation);
179       pending_activation->timeout_added = FALSE;
180     }
181
182   if (pending_activation->timeout)
183     _dbus_timeout_unref (pending_activation->timeout);
184   
185   if (pending_activation->babysitter)
186     {
187       if (!_dbus_babysitter_set_watch_functions (pending_activation->babysitter,
188                                                  NULL, NULL, NULL,
189                                                  pending_activation->babysitter,
190                                                  NULL))
191         _dbus_assert_not_reached ("setting watch functions to NULL failed");
192       
193       _dbus_babysitter_unref (pending_activation->babysitter);
194     }
195   
196   dbus_free (pending_activation->service_name);
197   dbus_free (pending_activation->exec);
198
199   link = _dbus_list_get_first_link (&pending_activation->entries);
200
201   while (link != NULL)
202     {
203       BusPendingActivationEntry *entry = link->data;
204
205       bus_pending_activation_entry_free (entry);
206
207       link = _dbus_list_get_next_link (&pending_activation->entries, link);
208     }
209   _dbus_list_clear (&pending_activation->entries);
210
211   pending_activation->activation->n_pending_activations -=
212     pending_activation->n_entries;
213
214   _dbus_assert (pending_activation->activation->n_pending_activations >= 0);
215   
216   dbus_free (pending_activation);
217 }
218
219 static BusActivationEntry *
220 bus_activation_entry_ref (BusActivationEntry *entry)
221 {
222   _dbus_assert (entry->refcount > 0);
223   entry->refcount++;
224
225   return entry;
226 }
227
228 static void
229 bus_activation_entry_unref (BusActivationEntry *entry)
230 {
231   if (entry == NULL) /* hash table requires this */
232     return;
233   
234   _dbus_assert (entry->refcount > 0);
235   entry->refcount--;
236   
237   if (entry->refcount > 0) 
238     return;
239   
240   dbus_free (entry->name);
241   dbus_free (entry->exec);
242   dbus_free (entry->user);
243   dbus_free (entry->filename);
244
245   dbus_free (entry);
246 }
247
248 static dbus_bool_t
249 update_desktop_file_entry (BusActivation       *activation,
250                            BusServiceDirectory *s_dir,
251                            DBusString          *filename,
252                            BusDesktopFile      *desktop_file,
253                            DBusError           *error)
254 {
255   char *name, *exec, *user;
256   BusActivationEntry *entry;
257   DBusStat stat_buf;
258   DBusString file_path;
259   DBusError tmp_error;
260
261   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
262   
263   name = NULL;
264   exec = NULL;
265   user = NULL;
266   entry = NULL;
267   
268   dbus_error_init (&tmp_error);
269
270   if (!_dbus_string_init (&file_path))
271     {
272       BUS_SET_OOM (error);
273       return FALSE;
274     }
275  
276   if (!_dbus_string_append (&file_path, s_dir->dir_c) ||
277       !_dbus_concat_dir_and_file (&file_path, filename))
278     {
279       BUS_SET_OOM (error);
280       goto failed;
281     }
282  
283   if (!_dbus_stat (&file_path, &stat_buf, NULL)) 
284     {
285       dbus_set_error (error, DBUS_ERROR_FAILED,
286                       "Can't stat the service file\n");
287       goto failed;
288     }
289  
290   if (!bus_desktop_file_get_string (desktop_file,
291                                     DBUS_SERVICE_SECTION,
292                                     DBUS_SERVICE_NAME,
293                                     &name,
294                                     error))
295     goto failed;
296
297   if (!bus_desktop_file_get_string (desktop_file,
298                                     DBUS_SERVICE_SECTION,
299                                     DBUS_SERVICE_EXEC,
300                                     &exec,
301                                     error))
302     goto failed;
303
304   /* user is not _required_ unless we are using system activation */
305   if (!bus_desktop_file_get_string (desktop_file,
306                                     DBUS_SERVICE_SECTION,
307                                     DBUS_SERVICE_USER,
308                                     &user, &tmp_error))
309     {
310       _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
311       /* if we got OOM, then exit */
312       if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
313         {
314           dbus_move_error (&tmp_error, error);
315           goto failed;
316         }
317       else
318         {
319           /* if we have error because we didn't find anything then continue */
320           dbus_error_free (&tmp_error);
321           dbus_free (user);
322           user = NULL;
323         }
324     }
325   _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
326
327   entry = _dbus_hash_table_lookup_string (s_dir->entries, 
328                                           _dbus_string_get_const_data (filename));
329   if (entry == NULL) /* New file */
330     { 
331       /* FIXME we need a better-defined algorithm for which service file to
332        * pick than "whichever one is first in the directory listing"
333        */
334       if (_dbus_hash_table_lookup_string (activation->entries, name))
335         {
336           dbus_set_error (error, DBUS_ERROR_FAILED,
337                           "Service %s already exists in activation entry list\n", name);
338           goto failed;
339         }
340       
341       entry = dbus_new0 (BusActivationEntry, 1);
342       if (entry == NULL)
343         {
344           BUS_SET_OOM (error);
345           goto failed;
346         }
347      
348       entry->name = name;
349       entry->exec = exec;
350       entry->user = user;
351       entry->refcount = 1;
352     
353       entry->s_dir = s_dir;
354       entry->filename = _dbus_strdup (_dbus_string_get_const_data (filename));
355       if (!entry->filename)
356         {
357           BUS_SET_OOM (error);
358           goto failed;
359         }
360
361       if (!_dbus_hash_table_insert_string (activation->entries, entry->name, bus_activation_entry_ref (entry)))
362         {
363           BUS_SET_OOM (error);
364           goto failed;
365         }
366      
367       if (!_dbus_hash_table_insert_string (s_dir->entries, entry->filename, bus_activation_entry_ref (entry)))
368         {
369           /* Revert the insertion in the entries table */
370           _dbus_hash_table_remove_string (activation->entries, entry->name);
371           BUS_SET_OOM (error);
372           goto failed;
373         }
374
375       _dbus_verbose ("Added \"%s\" to list of services\n", entry->name);
376     }
377   else /* Just update the entry */
378     {
379       bus_activation_entry_ref (entry);
380       _dbus_hash_table_remove_string (activation->entries, entry->name);
381
382       if (_dbus_hash_table_lookup_string (activation->entries, name))
383         {
384           _dbus_verbose ("The new service name \"%s\" of service file \"%s\" already in cache, ignoring\n",
385                          name, _dbus_string_get_const_data (&file_path));
386           goto failed;
387         }
388  
389       dbus_free (entry->name);
390       dbus_free (entry->exec);
391       dbus_free (entry->user);
392       entry->name = name;
393       entry->exec = exec;
394       entry->user = user;
395       if (!_dbus_hash_table_insert_string (activation->entries,
396                                            entry->name, bus_activation_entry_ref(entry)))
397         {
398           BUS_SET_OOM (error);
399           /* Also remove path to entries hash since we want this in sync with
400            * the entries hash table */
401           _dbus_hash_table_remove_string (entry->s_dir->entries, 
402                                           entry->filename);
403           bus_activation_entry_unref (entry);
404           return FALSE;
405         }
406     }
407   
408   entry->mtime = stat_buf.mtime;
409   
410   _dbus_string_free (&file_path);
411   bus_activation_entry_unref (entry);
412
413   return TRUE;
414
415 failed:
416   dbus_free (name);
417   dbus_free (exec);
418   dbus_free (user);
419   _dbus_string_free (&file_path);
420
421   if (entry)
422     bus_activation_entry_unref (entry);
423   
424   return FALSE;
425 }
426
427 static dbus_bool_t
428 check_service_file (BusActivation       *activation,
429                     BusActivationEntry  *entry,
430                     BusActivationEntry **updated_entry,
431                     DBusError           *error)
432 {
433   DBusStat stat_buf;
434   dbus_bool_t retval;
435   BusActivationEntry *tmp_entry;
436   DBusString file_path;
437   DBusString filename;
438
439   retval = TRUE;
440   tmp_entry = entry;
441   
442   _dbus_string_init_const (&filename, entry->filename);
443   
444   if (!_dbus_string_init (&file_path))
445     {
446       BUS_SET_OOM (error);
447       return FALSE;
448     }
449  
450   if (!_dbus_string_append (&file_path, entry->s_dir->dir_c) ||
451       !_dbus_concat_dir_and_file (&file_path, &filename))
452     {
453       BUS_SET_OOM (error);
454       retval = FALSE;
455       goto out;
456     }
457   
458   if (!_dbus_stat (&file_path, &stat_buf, NULL))
459     {
460       _dbus_verbose ("****** Can't stat file \"%s\", removing from cache\n",
461                      _dbus_string_get_const_data (&file_path));
462
463       _dbus_hash_table_remove_string (activation->entries, entry->name);
464       _dbus_hash_table_remove_string (entry->s_dir->entries, entry->filename);
465
466       tmp_entry = NULL;
467       retval = TRUE;
468       goto out;
469     }
470   else 
471     {
472       if (stat_buf.mtime > entry->mtime) 
473         {
474           BusDesktopFile *desktop_file;
475           DBusError tmp_error;
476           
477           dbus_error_init (&tmp_error);
478           
479           desktop_file = bus_desktop_file_load (&file_path, &tmp_error);
480           if (desktop_file == NULL)
481             {
482               _dbus_verbose ("Could not load %s: %s\n",
483                              _dbus_string_get_const_data (&file_path), 
484                              tmp_error.message);
485               if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
486                 {
487                   dbus_move_error (&tmp_error, error);
488                   retval = FALSE;
489                   goto out;
490                 }
491               dbus_error_free (&tmp_error);
492               retval = TRUE;
493               goto out;
494             }
495          
496           /* @todo We can return OOM or a DBUS_ERROR_FAILED error 
497            *       Handle these both better
498            */ 
499           if (!update_desktop_file_entry (activation, entry->s_dir, &filename, desktop_file, &tmp_error))
500             {
501               bus_desktop_file_free (desktop_file);
502               if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
503                 {
504                   dbus_move_error (&tmp_error, error);
505                   retval = FALSE;
506                   goto out;
507                 }
508               dbus_error_free (&tmp_error);
509               retval = TRUE;
510               goto out;
511             }
512          
513           bus_desktop_file_free (desktop_file);
514           retval = TRUE;
515         }
516     }
517   
518 out:
519   _dbus_string_free (&file_path);
520
521   if (updated_entry != NULL)
522     *updated_entry = tmp_entry;
523   return retval;
524 }
525
526
527 /* warning: this doesn't fully "undo" itself on failure, i.e. doesn't strip
528  * hash entries it already added.
529  */
530 static dbus_bool_t
531 update_directory (BusActivation       *activation,
532                   BusServiceDirectory *s_dir,
533                   DBusError           *error)
534 {
535   DBusDirIter *iter;
536   DBusString dir, filename;
537   BusDesktopFile *desktop_file;
538   DBusError tmp_error;
539   dbus_bool_t retval;
540   BusActivationEntry *entry;
541   DBusString full_path;
542   
543   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
544   
545   iter = NULL;
546   desktop_file = NULL;
547   
548   _dbus_string_init_const (&dir, s_dir->dir_c);
549   
550   if (!_dbus_string_init (&filename))
551     {
552       BUS_SET_OOM (error);
553       return FALSE;
554     }
555
556   if (!_dbus_string_init (&full_path))
557     {
558       BUS_SET_OOM (error);
559       _dbus_string_free (&filename);
560       return FALSE;
561     }
562
563   retval = FALSE;
564
565   /* from this point it's safe to "goto out" */
566   
567   iter = _dbus_directory_open (&dir, error);
568   if (iter == NULL)
569     {
570       _dbus_verbose ("Failed to open directory %s: %s\n",
571                      s_dir->dir_c, 
572                      error ? error->message : "unknown");
573       goto out;
574     }
575   
576   /* Now read the files */
577   dbus_error_init (&tmp_error);
578   while (_dbus_directory_get_next_file (iter, &filename, &tmp_error))
579     {
580       _dbus_assert (!dbus_error_is_set (&tmp_error));
581       
582       _dbus_string_set_length (&full_path, 0);
583       
584       if (!_dbus_string_ends_with_c_str (&filename, ".service"))
585         {
586           _dbus_verbose ("Skipping non-.service file %s\n",
587                          _dbus_string_get_const_data (&filename));
588           continue;
589         }
590
591       entry = _dbus_hash_table_lookup_string (s_dir->entries, _dbus_string_get_const_data (&filename));
592       if (entry) /* Already has this service file in the cache */ 
593         {
594           if (!check_service_file (activation, entry, NULL, error))
595             goto out;
596
597           continue;
598         }
599       
600       if (!_dbus_string_append (&full_path, s_dir->dir_c) ||
601           !_dbus_concat_dir_and_file (&full_path, &filename))
602         {
603           BUS_SET_OOM (error);
604           goto out;
605         }
606           
607       /* New file */
608       desktop_file = bus_desktop_file_load (&full_path, &tmp_error);
609       if (desktop_file == NULL)
610         {
611           _dbus_verbose ("Could not load %s: %s\n",
612                          _dbus_string_get_const_data (&full_path),
613                          tmp_error.message);
614
615           if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
616             {
617               dbus_move_error (&tmp_error, error);
618               goto out;
619             }
620           
621           dbus_error_free (&tmp_error);
622           continue;
623         }
624
625       /* @todo We can return OOM or a DBUS_ERROR_FAILED error 
626        *       Handle these both better
627        */ 
628       if (!update_desktop_file_entry (activation, s_dir, &filename, desktop_file, &tmp_error))
629         {
630           bus_desktop_file_free (desktop_file);
631           desktop_file = NULL;
632           
633           _dbus_verbose ("Could not add %s to activation entry list: %s\n",
634                          _dbus_string_get_const_data (&full_path), tmp_error.message);
635
636           if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
637             {
638               dbus_move_error (&tmp_error, error);
639               goto out;
640             }
641
642           dbus_error_free (&tmp_error);
643           continue;
644         }
645       else
646         {
647           bus_desktop_file_free (desktop_file);
648           desktop_file = NULL;
649           continue;
650         }
651     }
652
653   if (dbus_error_is_set (&tmp_error))
654     {
655       dbus_move_error (&tmp_error, error);
656       goto out;
657     }
658   
659   retval = TRUE;
660
661  out:
662   if (!retval)
663     _DBUS_ASSERT_ERROR_IS_SET (error);
664   else
665     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
666   
667   if (iter != NULL)
668     _dbus_directory_close (iter);
669   _dbus_string_free (&filename);
670   _dbus_string_free (&full_path);
671   
672   return retval;
673 }
674
675 static dbus_bool_t
676 populate_environment (BusActivation *activation)
677 {
678   DBusString   key;
679   DBusString   value;
680   int          i;
681   char       **environment;
682   dbus_bool_t  retval = FALSE;
683
684   environment = _dbus_get_environment ();
685
686   if (environment == NULL)
687     return FALSE;
688
689   if (!_dbus_string_init (&key))
690     {
691         dbus_free_string_array (environment);
692         return FALSE;
693     }
694
695   if (!_dbus_string_init (&value))
696     {
697       _dbus_string_free (&key);
698       dbus_free_string_array (environment);
699       return FALSE;
700     }
701
702   for (i = 0; environment[i] != NULL; i++)
703     {
704       if (!_dbus_string_append (&key, environment[i]))
705         break;
706
707       if (_dbus_string_split_on_byte (&key, '=', &value))
708         {
709           char *hash_key, *hash_value;
710
711           if (!_dbus_string_steal_data (&key, &hash_key))
712             break;
713
714           if (!_dbus_string_steal_data (&value, &hash_value))
715             break;
716
717           if (!_dbus_hash_table_insert_string (activation->environment,
718                                                hash_key, hash_value))
719             break;
720         }
721       _dbus_string_set_length (&key, 0);
722       _dbus_string_set_length (&value, 0);
723     }
724
725   if (environment[i] != NULL)
726     goto out;
727
728   retval = TRUE;
729 out:
730
731   _dbus_string_free (&key);
732   _dbus_string_free (&value);
733   dbus_free_string_array (environment);
734
735   return retval;
736 }
737
738 BusActivation*
739 bus_activation_new (BusContext        *context,
740                     const DBusString  *address,
741                     DBusList         **directories,
742                     DBusError         *error)
743 {
744   BusActivation *activation;
745   DBusList      *link;
746   char          *dir;
747   
748   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
749   
750   activation = dbus_new0 (BusActivation, 1);
751   if (activation == NULL)
752     {
753       BUS_SET_OOM (error);
754       return NULL;
755     }
756   
757   activation->refcount = 1;
758   activation->context = context;
759   activation->n_pending_activations = 0;
760   
761   if (!_dbus_string_copy_data (address, &activation->server_address))
762     {
763       BUS_SET_OOM (error);
764       goto failed;
765     }
766   
767   activation->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
768                                              (DBusFreeFunction)bus_activation_entry_unref);
769   if (activation->entries == NULL)
770     {      
771       BUS_SET_OOM (error);
772       goto failed;
773     }
774
775   activation->pending_activations = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
776                                                           (DBusFreeFunction)bus_pending_activation_unref);
777
778   if (activation->pending_activations == NULL)
779     {
780       BUS_SET_OOM (error);
781       goto failed;
782     }
783
784   activation->directories = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
785                                                   (DBusFreeFunction)bus_service_directory_unref);
786   
787   if (activation->directories == NULL) 
788     {
789       BUS_SET_OOM (error);
790       goto failed;
791     }
792  
793   /* Load service files */
794   link = _dbus_list_get_first_link (directories);
795   while (link != NULL)
796     {
797       BusServiceDirectory *s_dir;
798       
799       dir = _dbus_strdup ((const char *) link->data);
800       if (!dir)
801         {
802           BUS_SET_OOM (error);
803           goto failed;
804         }
805       
806       s_dir = dbus_new0 (BusServiceDirectory, 1);
807       if (!s_dir)
808         {
809           dbus_free (dir);
810           BUS_SET_OOM (error);
811           goto failed;
812         }
813
814       s_dir->refcount = 1;
815       s_dir->dir_c = dir;
816       
817       s_dir->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
818                                              (DBusFreeFunction)bus_activation_entry_unref);
819
820       if (!s_dir->entries)
821         {
822           bus_service_directory_unref (s_dir);
823           BUS_SET_OOM (error);
824           goto failed;
825         }
826
827       if (!_dbus_hash_table_insert_string (activation->directories, s_dir->dir_c, s_dir))
828         {
829           bus_service_directory_unref (s_dir);
830           BUS_SET_OOM (error);
831           goto failed;
832         }
833
834       /* only fail on OOM, it is ok if we can't read the directory */
835       if (!update_directory (activation, s_dir, error))
836         { 
837           if (dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY)) 
838             goto failed;
839           else
840             dbus_error_free (error);
841         }
842
843       link = _dbus_list_get_next_link (directories, link);
844     }
845
846   activation->environment = _dbus_hash_table_new (DBUS_HASH_STRING,
847                                                   (DBusFreeFunction) dbus_free,
848                                                   (DBusFreeFunction) dbus_free);
849   
850   if (activation->environment == NULL) 
851     {
852       BUS_SET_OOM (error);
853       goto failed;
854     }
855
856   if (!populate_environment (activation))
857     {
858       BUS_SET_OOM (error);
859       goto failed;
860     }
861
862   return activation;
863   
864  failed:
865   bus_activation_unref (activation);  
866   return NULL;
867 }
868
869 BusActivation *
870 bus_activation_ref (BusActivation *activation)
871 {
872   _dbus_assert (activation->refcount > 0);
873   
874   activation->refcount += 1;
875
876   return activation;
877 }
878
879 void
880 bus_activation_unref (BusActivation *activation)
881 {
882   _dbus_assert (activation->refcount > 0);
883
884   activation->refcount -= 1;
885
886   if (activation->refcount > 0)
887     return;
888   
889   dbus_free (activation->server_address);
890   if (activation->entries)
891     _dbus_hash_table_unref (activation->entries);
892   if (activation->pending_activations)
893     _dbus_hash_table_unref (activation->pending_activations);
894   if (activation->directories)  
895     _dbus_hash_table_unref (activation->directories);
896   if (activation->environment)
897     _dbus_hash_table_unref (activation->environment);
898
899   dbus_free (activation);
900 }
901
902 static dbus_bool_t
903 add_bus_environment (BusActivation *activation,
904                      DBusError     *error)
905 {
906   const char *type;
907   
908   if (!bus_activation_set_environment_variable (activation,
909                                                 "DBUS_STARTER_ADDRESS",
910                                                 activation->server_address,
911                                                 error))
912     return FALSE;
913   
914   type = bus_context_get_type (activation->context);
915   if (type != NULL)
916     {
917       if (!bus_activation_set_environment_variable (activation,
918                                                     "DBUS_STARTER_BUS_TYPE", type,
919                                                     error))
920         return FALSE;
921
922       if (strcmp (type, "session") == 0)
923         {
924           if (!bus_activation_set_environment_variable (activation,
925                                                         "DBUS_SESSION_BUS_ADDRESS",
926                                                         activation->server_address,
927                                                         error))
928             return FALSE;
929         }
930       else if (strcmp (type, "system") == 0)
931         {
932           if (!bus_activation_set_environment_variable (activation,
933                                                         "DBUS_SYSTEM_BUS_ADDRESS",
934                                                         activation->server_address,
935                                                         error))
936             return FALSE;
937         }
938     }
939
940   return TRUE;
941 }
942
943 typedef struct
944 {
945   BusPendingActivation *pending_activation;
946   DBusPreallocatedHash *hash_entry;
947 } RestorePendingData;
948
949 static void
950 restore_pending (void *data)
951 {
952   RestorePendingData *d = data;
953
954   _dbus_assert (d->pending_activation != NULL);
955   _dbus_assert (d->hash_entry != NULL);
956
957   _dbus_verbose ("Restoring pending activation for service %s, has timeout = %d\n",
958                  d->pending_activation->service_name,
959                  d->pending_activation->timeout_added);
960   
961   _dbus_hash_table_insert_string_preallocated (d->pending_activation->activation->pending_activations,
962                                                d->hash_entry,
963                                                d->pending_activation->service_name, d->pending_activation);
964
965   bus_pending_activation_ref (d->pending_activation);
966   
967   d->hash_entry = NULL;
968 }
969
970 static void
971 free_pending_restore_data (void *data)
972 {
973   RestorePendingData *d = data;
974
975   if (d->hash_entry)
976     _dbus_hash_table_free_preallocated_entry (d->pending_activation->activation->pending_activations,
977                                               d->hash_entry);
978
979   bus_pending_activation_unref (d->pending_activation);
980   
981   dbus_free (d);
982 }
983
984 static dbus_bool_t
985 add_restore_pending_to_transaction (BusTransaction       *transaction,
986                                     BusPendingActivation *pending_activation)
987 {
988   RestorePendingData *d;
989
990   d = dbus_new (RestorePendingData, 1);
991   if (d == NULL)
992     return FALSE;
993   
994   d->pending_activation = pending_activation;
995   d->hash_entry = _dbus_hash_table_preallocate_entry (d->pending_activation->activation->pending_activations);
996   
997   bus_pending_activation_ref (d->pending_activation);
998   
999   if (d->hash_entry == NULL ||
1000       !bus_transaction_add_cancel_hook (transaction, restore_pending, d,
1001                                         free_pending_restore_data))
1002     {
1003       free_pending_restore_data (d);
1004       return FALSE;
1005     }
1006
1007   _dbus_verbose ("Saved pending activation to be restored if the transaction fails\n");
1008   
1009   return TRUE;
1010 }
1011
1012 dbus_bool_t
1013 bus_activation_service_created (BusActivation  *activation,
1014                                 const char     *service_name,
1015                                 BusTransaction *transaction,
1016                                 DBusError      *error)
1017 {
1018   BusPendingActivation *pending_activation;
1019   DBusMessage *message;
1020   DBusList *link;
1021
1022   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1023   
1024   /* Check if it's a pending activation */
1025   pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, service_name);
1026
1027   if (!pending_activation)
1028     return TRUE;
1029
1030   link = _dbus_list_get_first_link (&pending_activation->entries);
1031   while (link != NULL)
1032     {
1033       BusPendingActivationEntry *entry = link->data;
1034       DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
1035       
1036       if (dbus_connection_get_is_connected (entry->connection))
1037         {
1038           /* Only send activation replies to regular activation requests. */
1039           if (!entry->auto_activation)
1040             {
1041               dbus_uint32_t result;
1042               
1043               message = dbus_message_new_method_return (entry->activation_message);
1044               if (!message)
1045                 {
1046                   BUS_SET_OOM (error);
1047                   goto error;
1048                 }
1049
1050               result = DBUS_START_REPLY_SUCCESS;
1051               
1052               if (!dbus_message_append_args (message,
1053                                              DBUS_TYPE_UINT32, &result,
1054                                              DBUS_TYPE_INVALID))
1055                 {
1056                   dbus_message_unref (message);
1057                   BUS_SET_OOM (error);
1058                   goto error;
1059                 }
1060               
1061               if (!bus_transaction_send_from_driver (transaction, entry->connection, message))
1062                 {
1063                   dbus_message_unref (message);
1064                   BUS_SET_OOM (error);
1065                   goto error;
1066                 }
1067               
1068               dbus_message_unref (message);
1069             }
1070         }
1071       
1072       link = next;
1073     }
1074
1075   return TRUE;
1076
1077  error:
1078   return FALSE;
1079 }
1080
1081 dbus_bool_t
1082 bus_activation_send_pending_auto_activation_messages (BusActivation  *activation,
1083                                                       BusService     *service,
1084                                                       BusTransaction *transaction,
1085                                                       DBusError      *error)
1086 {
1087   BusPendingActivation *pending_activation;
1088   DBusList *link;
1089
1090   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1091   
1092   /* Check if it's a pending activation */
1093   pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations,
1094                                                        bus_service_get_name (service));
1095
1096   if (!pending_activation)
1097     return TRUE;
1098
1099   link = _dbus_list_get_first_link (&pending_activation->entries);
1100   while (link != NULL)
1101     {
1102       BusPendingActivationEntry *entry = link->data;
1103       DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
1104
1105       if (entry->auto_activation && dbus_connection_get_is_connected (entry->connection))
1106         {
1107           DBusConnection *addressed_recipient;
1108           
1109           addressed_recipient = bus_service_get_primary_owners_connection (service);
1110
1111           /* Check the security policy, which has the side-effect of adding an
1112            * expected pending reply.
1113            */
1114           if (!bus_context_check_security_policy (activation->context, transaction,
1115                                                   entry->connection,
1116                                                   addressed_recipient,
1117                                                   addressed_recipient,
1118                                                   entry->activation_message, error))
1119             goto error;
1120
1121           if (!bus_transaction_send (transaction, addressed_recipient, entry->activation_message))
1122             {
1123               BUS_SET_OOM (error);
1124               goto error;
1125             }
1126         }
1127
1128       link = next;
1129     }
1130
1131   if (!add_restore_pending_to_transaction (transaction, pending_activation))
1132     {
1133       _dbus_verbose ("Could not add cancel hook to transaction to revert removing pending activation\n");
1134       BUS_SET_OOM (error);
1135       goto error;
1136     }
1137   
1138   _dbus_hash_table_remove_string (activation->pending_activations, bus_service_get_name (service));
1139
1140   return TRUE;
1141
1142  error:
1143   return FALSE;
1144 }
1145
1146 /**
1147  * FIXME @todo the error messages here would ideally be preallocated
1148  * so we don't need to allocate memory to send them.
1149  * Using the usual tactic, prealloc an OOM message, then
1150  * if we can't alloc the real error send the OOM error instead.
1151  */
1152 static dbus_bool_t
1153 try_send_activation_failure (BusPendingActivation *pending_activation,
1154                              const DBusError      *how)
1155 {
1156   BusActivation *activation;
1157   DBusList *link;
1158   BusTransaction *transaction;
1159   
1160   activation = pending_activation->activation;
1161
1162   transaction = bus_transaction_new (activation->context);
1163   if (transaction == NULL)
1164     return FALSE;
1165   
1166   link = _dbus_list_get_first_link (&pending_activation->entries);
1167   while (link != NULL)
1168     {
1169       BusPendingActivationEntry *entry = link->data;
1170       DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
1171       
1172       if (dbus_connection_get_is_connected (entry->connection))
1173         {
1174           if (!bus_transaction_send_error_reply (transaction,
1175                                                  entry->connection,
1176                                                  how,
1177                                                  entry->activation_message))
1178             goto error;
1179         }
1180       
1181       link = next;
1182     }
1183
1184   bus_transaction_execute_and_free (transaction);
1185   
1186   return TRUE;
1187
1188  error:
1189   if (transaction)
1190     bus_transaction_cancel_and_free (transaction);
1191   return FALSE;
1192 }
1193
1194 /**
1195  * Free the pending activation and send an error message to all the
1196  * connections that were waiting for it.
1197  */
1198 static void
1199 pending_activation_failed (BusPendingActivation *pending_activation,
1200                            const DBusError      *how)
1201 {
1202   /* FIXME use preallocated OOM messages instead of bus_wait_for_memory() */
1203   while (!try_send_activation_failure (pending_activation, how))
1204     _dbus_wait_for_memory ();
1205
1206   /* Destroy this pending activation */
1207   _dbus_hash_table_remove_string (pending_activation->activation->pending_activations,
1208                                   pending_activation->service_name);
1209 }
1210
1211 /**
1212  * Depending on the exit code of the helper, set the error accordingly
1213  */
1214 static void
1215 handle_activation_exit_error (int        exit_code,
1216                               DBusError *error)
1217 {
1218   switch (exit_code)
1219     {
1220     case BUS_SPAWN_EXIT_CODE_NO_MEMORY:
1221       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
1222                       "Launcher could not run (out of memory)");
1223       break;
1224     case BUS_SPAWN_EXIT_CODE_SETUP_FAILED:
1225       dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED,
1226                       "Failed to setup environment correctly");
1227       break;
1228     case BUS_SPAWN_EXIT_CODE_NAME_INVALID:
1229       dbus_set_error (error, DBUS_ERROR_SPAWN_SERVICE_INVALID,
1230                       "Bus name is not valid or missing");
1231       break;
1232     case BUS_SPAWN_EXIT_CODE_SERVICE_NOT_FOUND:
1233       dbus_set_error (error, DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND,
1234                       "Bus name not found in system service directory");
1235       break;
1236     case BUS_SPAWN_EXIT_CODE_PERMISSIONS_INVALID:
1237       dbus_set_error (error, DBUS_ERROR_SPAWN_PERMISSIONS_INVALID,
1238                       "The permission of the setuid helper is not correct");
1239       break;
1240     case BUS_SPAWN_EXIT_CODE_FILE_INVALID:
1241       dbus_set_error (error, DBUS_ERROR_SPAWN_PERMISSIONS_INVALID,
1242                       "The service file is incorrect or does not have all required attributes");
1243       break;
1244     case BUS_SPAWN_EXIT_CODE_EXEC_FAILED:
1245       dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
1246                       "Cannot launch daemon, file not found or permissions invalid");
1247       break;
1248     case BUS_SPAWN_EXIT_CODE_INVALID_ARGS:
1249       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1250                       "Invalid arguments to command line");
1251       break;
1252     case BUS_SPAWN_EXIT_CODE_CHILD_SIGNALED:
1253       dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_SIGNALED,
1254                       "Launched child was signaled, it probably crashed");
1255       break;
1256     default:
1257       dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
1258                       "Launch helper exited with unknown return code %i", exit_code);
1259       break;
1260     }
1261 }
1262
1263 static dbus_bool_t
1264 babysitter_watch_callback (DBusWatch     *watch,
1265                            unsigned int   condition,
1266                            void          *data)
1267 {
1268   BusPendingActivation *pending_activation = data;
1269   dbus_bool_t retval;
1270   DBusBabysitter *babysitter;
1271
1272   babysitter = pending_activation->babysitter;
1273   
1274   _dbus_babysitter_ref (babysitter);
1275   
1276   retval = dbus_watch_handle (watch, condition);
1277
1278   /* FIXME this is broken in the same way that
1279    * connection watches used to be; there should be
1280    * a separate callback for status change, instead
1281    * of doing "if we handled a watch status might
1282    * have changed"
1283    *
1284    * Fixing this lets us move dbus_watch_handle
1285    * calls into dbus-mainloop.c
1286    */
1287   
1288   if (_dbus_babysitter_get_child_exited (babysitter))
1289     {
1290       DBusError error;
1291       DBusHashIter iter;
1292       
1293       dbus_error_init (&error);
1294       _dbus_babysitter_set_child_exit_error (babysitter, &error);
1295
1296       /* refine the error code if we got an exit code */
1297       if (dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED))
1298         {
1299           int exit_code = 0;
1300           if (_dbus_babysitter_get_child_exit_status (babysitter, &exit_code))
1301             {
1302               dbus_error_free (&error);
1303               handle_activation_exit_error (exit_code, &error);
1304             }
1305         }
1306
1307       /* Destroy all pending activations with the same exec */
1308       _dbus_hash_iter_init (pending_activation->activation->pending_activations,
1309                             &iter);
1310       while (_dbus_hash_iter_next (&iter))
1311         {
1312           BusPendingActivation *p = _dbus_hash_iter_get_value (&iter);
1313          
1314           if (p != pending_activation && strcmp (p->exec, pending_activation->exec) == 0)
1315             pending_activation_failed (p, &error);
1316         }
1317       
1318       /* Destroys the pending activation */
1319       pending_activation_failed (pending_activation, &error);
1320
1321       dbus_error_free (&error);
1322     }
1323   
1324   _dbus_babysitter_unref (babysitter);
1325
1326   return retval;
1327 }
1328
1329 static dbus_bool_t
1330 add_babysitter_watch (DBusWatch      *watch,
1331                       void           *data)
1332 {
1333   BusPendingActivation *pending_activation = data;
1334
1335   return _dbus_loop_add_watch (bus_context_get_loop (pending_activation->activation->context),
1336                                watch, babysitter_watch_callback, pending_activation,
1337                                NULL);
1338 }
1339
1340 static void
1341 remove_babysitter_watch (DBusWatch      *watch,
1342                          void           *data)
1343 {
1344   BusPendingActivation *pending_activation = data;
1345   
1346   _dbus_loop_remove_watch (bus_context_get_loop (pending_activation->activation->context),
1347                            watch, babysitter_watch_callback, pending_activation);
1348 }
1349
1350 static dbus_bool_t
1351 pending_activation_timed_out (void *data)
1352 {
1353   BusPendingActivation *pending_activation = data;
1354   DBusError error;
1355   
1356   /* Kill the spawned process, since it sucks
1357    * (not sure this is what we want to do, but
1358    * may as well try it for now)
1359    */
1360   if (pending_activation->babysitter) 
1361     _dbus_babysitter_kill_child (pending_activation->babysitter);
1362
1363   dbus_error_init (&error);
1364
1365   dbus_set_error (&error, DBUS_ERROR_TIMED_OUT,
1366                   "Activation of %s timed out",
1367                   pending_activation->service_name);
1368
1369   pending_activation_failed (pending_activation, &error);
1370
1371   dbus_error_free (&error);
1372
1373   return TRUE;
1374 }
1375
1376 static void
1377 cancel_pending (void *data)
1378 {
1379   BusPendingActivation *pending_activation = data;
1380
1381   _dbus_verbose ("Canceling pending activation of %s\n",
1382                  pending_activation->service_name);
1383
1384   if (pending_activation->babysitter)
1385     _dbus_babysitter_kill_child (pending_activation->babysitter);
1386   
1387   _dbus_hash_table_remove_string (pending_activation->activation->pending_activations,
1388                                   pending_activation->service_name);
1389 }
1390
1391 static void
1392 free_pending_cancel_data (void *data)
1393 {
1394   BusPendingActivation *pending_activation = data;
1395   
1396   bus_pending_activation_unref (pending_activation);
1397 }
1398
1399 static dbus_bool_t
1400 add_cancel_pending_to_transaction (BusTransaction       *transaction,
1401                                    BusPendingActivation *pending_activation)
1402 {  
1403   if (!bus_transaction_add_cancel_hook (transaction, cancel_pending,
1404                                         pending_activation,
1405                                         free_pending_cancel_data))
1406     return FALSE;
1407
1408   bus_pending_activation_ref (pending_activation); 
1409   
1410   _dbus_verbose ("Saved pending activation to be canceled if the transaction fails\n");
1411   
1412   return TRUE;
1413 }
1414
1415 static dbus_bool_t 
1416 update_service_cache (BusActivation *activation, DBusError *error)
1417 {
1418   DBusHashIter iter;
1419  
1420   _dbus_hash_iter_init (activation->directories, &iter);
1421   while (_dbus_hash_iter_next (&iter))
1422     {
1423       DBusError tmp_error;
1424       BusServiceDirectory *s_dir;
1425
1426       s_dir = _dbus_hash_iter_get_value (&iter);
1427
1428       dbus_error_init (&tmp_error);
1429       if (!update_directory (activation, s_dir, &tmp_error))
1430         {
1431           if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
1432             {
1433               dbus_move_error (&tmp_error, error);
1434               return FALSE;
1435             }
1436
1437           dbus_error_free (&tmp_error);
1438           continue;
1439         }
1440     }
1441   
1442   return TRUE;
1443 }
1444
1445 static BusActivationEntry *
1446 activation_find_entry (BusActivation *activation, 
1447                        const char    *service_name,
1448                        DBusError     *error)
1449 {
1450   BusActivationEntry *entry;
1451   
1452   entry = _dbus_hash_table_lookup_string (activation->entries, service_name);
1453   if (!entry)
1454     { 
1455       if (!update_service_cache (activation, error)) 
1456         return NULL;
1457
1458       entry = _dbus_hash_table_lookup_string (activation->entries,
1459                                               service_name);
1460     }
1461   else 
1462     {
1463       BusActivationEntry *updated_entry;
1464
1465       if (!check_service_file (activation, entry, &updated_entry, error)) 
1466         return NULL;
1467
1468       entry = updated_entry;
1469     }
1470
1471   if (!entry) 
1472     {
1473       dbus_set_error (error, DBUS_ERROR_SERVICE_UNKNOWN,
1474                       "The name %s was not provided by any .service files",
1475                       service_name);
1476       return NULL;
1477     }
1478
1479   return entry;
1480 }
1481
1482 static char **
1483 bus_activation_get_environment (BusActivation *activation)
1484 {
1485   char **environment;
1486   int i, length;
1487   DBusString entry;
1488   DBusHashIter iter;
1489
1490   length = _dbus_hash_table_get_n_entries (activation->environment);
1491
1492   environment = dbus_new0 (char *, length + 1);
1493
1494   if (environment == NULL)
1495     return NULL;
1496
1497   i = 0;
1498   _dbus_hash_iter_init (activation->environment, &iter);
1499
1500   if (!_dbus_string_init (&entry))
1501     {
1502       dbus_free_string_array (environment);
1503       return NULL;
1504     }
1505
1506   while (_dbus_hash_iter_next (&iter))
1507     {
1508       const char *key, *value;
1509
1510       key = (const char *) _dbus_hash_iter_get_string_key (&iter);
1511       value = (const char *) _dbus_hash_iter_get_value (&iter);
1512
1513       if (!_dbus_string_append_printf (&entry, "%s=%s", key, value))
1514         break;
1515
1516       if (!_dbus_string_steal_data (&entry, environment + i))
1517         break;
1518       i++;
1519     }
1520
1521   _dbus_string_free (&entry);
1522
1523   if (i != length)
1524     {
1525       dbus_free_string_array (environment);
1526       environment = NULL;
1527     }
1528
1529   return environment;
1530 }
1531
1532 dbus_bool_t
1533 bus_activation_set_environment_variable (BusActivation     *activation,
1534                                          const char        *key,
1535                                          const char        *value,
1536                                          DBusError         *error)
1537 {
1538   char        *hash_key;
1539   char        *hash_value;
1540   dbus_bool_t  retval;
1541
1542   retval = FALSE;
1543   hash_key = NULL;
1544   hash_value = NULL;
1545   hash_key = _dbus_strdup (key);
1546
1547   if (hash_key == NULL)
1548     goto out;
1549
1550   hash_value = _dbus_strdup (value);
1551
1552   if (hash_value == NULL)
1553     goto out;
1554
1555   if (!_dbus_hash_table_insert_string (activation->environment,
1556                                        hash_key, hash_value))
1557     goto out;
1558
1559   retval = TRUE;
1560 out:
1561   if (retval == FALSE)
1562     {
1563       dbus_free (hash_key);
1564       dbus_free (hash_value);
1565       BUS_SET_OOM (error);
1566     }
1567
1568   return retval;
1569 }
1570
1571 dbus_bool_t
1572 bus_activation_activate_service (BusActivation  *activation,
1573                                  DBusConnection *connection,
1574                                  BusTransaction *transaction,
1575                                  dbus_bool_t     auto_activation,
1576                                  DBusMessage    *activation_message,
1577                                  const char     *service_name,
1578                                  DBusError      *error)
1579 {
1580   BusActivationEntry *entry;
1581   BusPendingActivation *pending_activation;
1582   BusPendingActivationEntry *pending_activation_entry;
1583   DBusMessage *message;
1584   DBusString service_str;
1585   const char *servicehelper;
1586   char **argv;
1587   char **envp = NULL;
1588   int argc;
1589   dbus_bool_t retval;
1590   DBusHashIter iter;
1591   dbus_bool_t activated;
1592   DBusString command;
1593   
1594   activated = TRUE;
1595
1596   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1597
1598   if (activation->n_pending_activations >=
1599       bus_context_get_max_pending_activations (activation->context))
1600     {
1601       dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
1602                       "The maximum number of pending activations has been reached, activation of %s failed",
1603                       service_name);
1604       return FALSE;
1605     }
1606
1607   entry = activation_find_entry (activation, service_name, error);
1608   if (!entry) 
1609     return FALSE;
1610
1611   /* Bypass the registry lookup if we're auto-activating, bus_dispatch would not
1612    * call us if the service is already active.
1613    */
1614   if (!auto_activation)
1615     {
1616       /* Check if the service is active */
1617       _dbus_string_init_const (&service_str, service_name);
1618       if (bus_registry_lookup (bus_context_get_registry (activation->context), &service_str) != NULL)
1619         {
1620           dbus_uint32_t result;
1621           
1622           _dbus_verbose ("Service \"%s\" is already active\n", service_name);
1623       
1624           message = dbus_message_new_method_return (activation_message);
1625
1626           if (!message)
1627             {
1628               _dbus_verbose ("No memory to create reply to activate message\n");
1629               BUS_SET_OOM (error);
1630               return FALSE;
1631             }
1632
1633           result = DBUS_START_REPLY_ALREADY_RUNNING;
1634           
1635           if (!dbus_message_append_args (message,
1636                                          DBUS_TYPE_UINT32, &result,
1637                                          DBUS_TYPE_INVALID))
1638             {
1639               _dbus_verbose ("No memory to set args of reply to activate message\n");
1640               BUS_SET_OOM (error);
1641               dbus_message_unref (message);
1642               return FALSE;
1643             }
1644
1645           retval = bus_transaction_send_from_driver (transaction, connection, message);
1646           dbus_message_unref (message);
1647           if (!retval)
1648             {
1649               _dbus_verbose ("Failed to send reply\n");
1650               BUS_SET_OOM (error);
1651             }
1652
1653           return retval;
1654         }
1655     }
1656   
1657   pending_activation_entry = dbus_new0 (BusPendingActivationEntry, 1);
1658   if (!pending_activation_entry)
1659     {
1660       _dbus_verbose ("Failed to create pending activation entry\n");
1661       BUS_SET_OOM (error);
1662       return FALSE;
1663     }
1664
1665   pending_activation_entry->auto_activation = auto_activation;
1666
1667   pending_activation_entry->activation_message = activation_message;
1668   dbus_message_ref (activation_message);
1669   pending_activation_entry->connection = connection;
1670   dbus_connection_ref (connection);
1671   
1672   /* Check if the service is being activated */
1673   pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, service_name);
1674   if (pending_activation)
1675     {
1676       if (!_dbus_list_append (&pending_activation->entries, pending_activation_entry))
1677         {
1678           _dbus_verbose ("Failed to append a new entry to pending activation\n");
1679           
1680           BUS_SET_OOM (error);
1681           bus_pending_activation_entry_free (pending_activation_entry);
1682           return FALSE;
1683         }
1684
1685       pending_activation->n_entries += 1;
1686       pending_activation->activation->n_pending_activations += 1;
1687     }
1688   else
1689     {
1690       pending_activation = dbus_new0 (BusPendingActivation, 1);
1691       if (!pending_activation)
1692         {
1693           _dbus_verbose ("Failed to create pending activation\n");
1694           
1695           BUS_SET_OOM (error);
1696           bus_pending_activation_entry_free (pending_activation_entry);          
1697           return FALSE;
1698         }
1699
1700       pending_activation->activation = activation;
1701       pending_activation->refcount = 1;
1702       
1703       pending_activation->service_name = _dbus_strdup (service_name);
1704       if (!pending_activation->service_name)
1705         {
1706           _dbus_verbose ("Failed to copy service name for pending activation\n");
1707           
1708           BUS_SET_OOM (error);
1709           bus_pending_activation_unref (pending_activation);
1710           bus_pending_activation_entry_free (pending_activation_entry);          
1711           return FALSE;
1712         }
1713
1714       pending_activation->exec = _dbus_strdup (entry->exec);
1715       if (!pending_activation->exec)
1716         {
1717           _dbus_verbose ("Failed to copy service exec for pending activation\n");
1718           BUS_SET_OOM (error);
1719           bus_pending_activation_unref (pending_activation);
1720           bus_pending_activation_entry_free (pending_activation_entry);
1721           return FALSE;
1722         }
1723
1724       pending_activation->timeout =
1725         _dbus_timeout_new (bus_context_get_activation_timeout (activation->context),
1726                            pending_activation_timed_out,
1727                            pending_activation,
1728                            NULL);
1729       if (!pending_activation->timeout)
1730         {
1731           _dbus_verbose ("Failed to create timeout for pending activation\n");
1732           
1733           BUS_SET_OOM (error);
1734           bus_pending_activation_unref (pending_activation);
1735           bus_pending_activation_entry_free (pending_activation_entry);
1736           return FALSE;
1737         }
1738
1739       if (!_dbus_loop_add_timeout (bus_context_get_loop (activation->context),
1740                                    pending_activation->timeout,
1741                                    handle_timeout_callback,
1742                                    pending_activation,
1743                                    NULL))
1744         {
1745           _dbus_verbose ("Failed to add timeout for pending activation\n");
1746           
1747           BUS_SET_OOM (error);
1748           bus_pending_activation_unref (pending_activation);
1749           bus_pending_activation_entry_free (pending_activation_entry);          
1750           return FALSE;
1751         }
1752
1753       pending_activation->timeout_added = TRUE;
1754       
1755       if (!_dbus_list_append (&pending_activation->entries, pending_activation_entry))
1756         {
1757           _dbus_verbose ("Failed to add entry to just-created pending activation\n");
1758           
1759           BUS_SET_OOM (error);
1760           bus_pending_activation_unref (pending_activation);
1761           bus_pending_activation_entry_free (pending_activation_entry);          
1762           return FALSE;
1763         }
1764
1765       pending_activation->n_entries += 1;
1766       pending_activation->activation->n_pending_activations += 1;
1767     
1768       activated = FALSE;
1769       _dbus_hash_iter_init (activation->pending_activations, &iter);
1770       while (_dbus_hash_iter_next (&iter))
1771         {
1772           BusPendingActivation *p = _dbus_hash_iter_get_value (&iter);
1773           
1774           if (strcmp (p->exec, entry->exec) == 0) 
1775             {
1776               activated = TRUE;
1777               break;
1778             }
1779         }
1780      
1781       if (!_dbus_hash_table_insert_string (activation->pending_activations,
1782                                            pending_activation->service_name,
1783                                            pending_activation))
1784         {
1785           _dbus_verbose ("Failed to put pending activation in hash table\n");
1786           
1787           BUS_SET_OOM (error);
1788           bus_pending_activation_unref (pending_activation);
1789           return FALSE;
1790         }
1791     }
1792   
1793   if (!add_cancel_pending_to_transaction (transaction, pending_activation))
1794     {
1795       _dbus_verbose ("Failed to add pending activation cancel hook to transaction\n");
1796       BUS_SET_OOM (error);
1797       _dbus_hash_table_remove_string (activation->pending_activations,
1798                                       pending_activation->service_name);
1799
1800       return FALSE;
1801     }
1802   
1803   if (activated)
1804     return TRUE;
1805
1806   /* use command as system and session different */
1807   if (!_dbus_string_init (&command))
1808     {
1809       BUS_SET_OOM (error);
1810       return FALSE;
1811     }
1812
1813   /* does the bus use a helper? */
1814   servicehelper = bus_context_get_servicehelper (activation->context);
1815   if (servicehelper != NULL)
1816     {
1817       if (entry->user == NULL)
1818         {
1819           _dbus_string_free (&command);
1820           dbus_set_error (error, DBUS_ERROR_SPAWN_FILE_INVALID,
1821                           "Cannot do system-bus activation with no user\n");
1822           return FALSE;
1823         }
1824
1825       /* join the helper path and the service name */
1826       if (!_dbus_string_append (&command, servicehelper))
1827         {
1828           _dbus_string_free (&command);
1829           BUS_SET_OOM (error);
1830           return FALSE;
1831         }
1832       if (!_dbus_string_append (&command, " "))
1833         {
1834           _dbus_string_free (&command);
1835           BUS_SET_OOM (error);
1836           return FALSE;
1837         }
1838       if (!_dbus_string_append (&command, service_name))
1839         {
1840           _dbus_string_free (&command);
1841           BUS_SET_OOM (error);
1842           return FALSE;
1843         }
1844     }
1845   else
1846     {
1847       /* the bus does not use a helper, so we can append arguments with the exec line */
1848       if (!_dbus_string_append (&command, entry->exec))
1849         {
1850           _dbus_string_free (&command);
1851           BUS_SET_OOM (error);
1852           return FALSE;
1853         }
1854     }
1855
1856   /* convert command into arguments */
1857   if (!_dbus_shell_parse_argv (_dbus_string_get_const_data (&command), &argc, &argv, error))
1858     {
1859       _dbus_verbose ("Failed to parse command line: %s\n", entry->exec);
1860       _DBUS_ASSERT_ERROR_IS_SET (error);
1861       
1862       _dbus_hash_table_remove_string (activation->pending_activations,
1863                                       pending_activation->service_name);
1864
1865       _dbus_string_free (&command);
1866       return FALSE;
1867     }
1868   _dbus_string_free (&command);
1869
1870   if (!add_bus_environment (activation, error))
1871     {
1872       _DBUS_ASSERT_ERROR_IS_SET (error);
1873       dbus_free_string_array (argv);
1874       return FALSE;
1875     }
1876
1877   envp = bus_activation_get_environment (activation);
1878
1879   if (envp == NULL)
1880     {
1881       BUS_SET_OOM (error);
1882       dbus_free_string_array (argv);
1883       return FALSE;
1884     }
1885
1886   _dbus_verbose ("Spawning %s ...\n", argv[0]);
1887   if (!_dbus_spawn_async_with_babysitter (&pending_activation->babysitter, argv,
1888                                           envp,
1889                                           NULL, activation, 
1890                                           error))
1891     {
1892       _dbus_verbose ("Failed to spawn child\n");
1893       _DBUS_ASSERT_ERROR_IS_SET (error);
1894       dbus_free_string_array (argv);
1895       dbus_free_string_array (envp);
1896
1897       return FALSE;
1898     }
1899
1900   dbus_free_string_array (argv);
1901   envp = NULL;
1902
1903   _dbus_assert (pending_activation->babysitter != NULL);
1904   
1905   if (!_dbus_babysitter_set_watch_functions (pending_activation->babysitter,
1906                                              add_babysitter_watch,
1907                                              remove_babysitter_watch,
1908                                              NULL,
1909                                              pending_activation,
1910                                              NULL))
1911     {
1912       BUS_SET_OOM (error);
1913       _dbus_verbose ("Failed to set babysitter watch functions\n");
1914       return FALSE;
1915     }
1916   
1917   return TRUE;
1918 }
1919
1920 dbus_bool_t
1921 bus_activation_list_services (BusActivation *activation,
1922                               char        ***listp,
1923                               int           *array_len)
1924 {
1925   int i, j, len;
1926   char **retval;
1927   DBusHashIter iter;
1928
1929   len = _dbus_hash_table_get_n_entries (activation->entries);
1930   retval = dbus_new (char *, len + 1);
1931
1932   if (retval == NULL)
1933     return FALSE;
1934
1935   _dbus_hash_iter_init (activation->entries, &iter);
1936   i = 0;
1937   while (_dbus_hash_iter_next (&iter))
1938     {
1939       BusActivationEntry *entry = _dbus_hash_iter_get_value (&iter);
1940
1941       retval[i] = _dbus_strdup (entry->name);
1942       if (retval[i] == NULL)
1943         goto error;
1944
1945       i++;
1946     }
1947
1948   retval[i] = NULL;
1949
1950   if (array_len)
1951     *array_len = len;
1952
1953   *listp = retval;
1954   return TRUE;
1955
1956  error:
1957   for (j = 0; j < i; j++)
1958     dbus_free (retval[i]);
1959   dbus_free (retval);
1960
1961   return FALSE;
1962 }
1963   
1964
1965 #ifdef DBUS_BUILD_TESTS
1966
1967 #include <stdio.h>
1968
1969 #define SERVICE_NAME_1 "MyService1"
1970 #define SERVICE_NAME_2 "MyService2"
1971 #define SERVICE_NAME_3 "MyService3"
1972
1973 #define SERVICE_FILE_1 "service-1.service"
1974 #define SERVICE_FILE_2 "service-2.service"
1975 #define SERVICE_FILE_3 "service-3.service"
1976
1977 static dbus_bool_t
1978 test_create_service_file (DBusString *dir,
1979                           const char *filename, 
1980                           const char *name, 
1981                           const char *exec)
1982 {
1983   DBusString  file_name, full_path;
1984   FILE        *file;
1985   dbus_bool_t  ret_val;
1986
1987   ret_val = TRUE;
1988   _dbus_string_init_const (&file_name, filename);
1989
1990   if (!_dbus_string_init (&full_path))
1991     return FALSE;
1992
1993   if (!_dbus_string_append (&full_path, _dbus_string_get_const_data (dir)) ||
1994       !_dbus_concat_dir_and_file (&full_path, &file_name))
1995     {
1996       ret_val = FALSE;
1997       goto out;
1998     }
1999   
2000   file = fopen (_dbus_string_get_const_data (&full_path), "w");
2001   if (!file)
2002     {
2003       ret_val = FALSE;
2004       goto out;
2005     }
2006
2007   fprintf (file, "[D-BUS Service]\nName=%s\nExec=%s\n", name, exec);
2008   fclose (file);
2009
2010 out:
2011   _dbus_string_free (&full_path);
2012   return ret_val;
2013 }
2014
2015 static dbus_bool_t
2016 test_remove_service_file (DBusString *dir, const char *filename)
2017 {
2018   DBusString  file_name, full_path;
2019   dbus_bool_t ret_val;
2020   
2021   ret_val = TRUE;
2022  
2023   _dbus_string_init_const (&file_name, filename);
2024
2025   if (!_dbus_string_init (&full_path))
2026     return FALSE;
2027
2028   if (!_dbus_string_append (&full_path, _dbus_string_get_const_data (dir)) ||
2029       !_dbus_concat_dir_and_file (&full_path, &file_name))
2030     {
2031       ret_val = FALSE;
2032       goto out;
2033     }
2034
2035   if (!_dbus_delete_file (&full_path, NULL))
2036     {
2037       ret_val = FALSE;
2038       goto out;
2039     }
2040
2041 out:
2042   _dbus_string_free (&full_path);
2043   return ret_val;
2044 }
2045
2046 static dbus_bool_t
2047 test_remove_directory (DBusString *dir)
2048 {
2049   DBusDirIter *iter;
2050   DBusString   filename, full_path;
2051   dbus_bool_t  ret_val;
2052   
2053   ret_val = TRUE;
2054   
2055   if (!_dbus_string_init (&filename))
2056     return FALSE;
2057
2058   if (!_dbus_string_init (&full_path))
2059     {
2060       _dbus_string_free (&filename);
2061       return FALSE;
2062     }
2063     
2064   iter = _dbus_directory_open (dir, NULL);
2065   if (iter == NULL)
2066     {
2067       ret_val = FALSE;
2068       goto out;
2069     }
2070   
2071   while (_dbus_directory_get_next_file (iter, &filename, NULL)) 
2072     {
2073       if (!test_remove_service_file (dir, _dbus_string_get_const_data (&filename)))
2074         {
2075           ret_val = FALSE;
2076           goto out;
2077         }
2078     }
2079   _dbus_directory_close (iter);
2080
2081   if (!_dbus_delete_directory (dir, NULL))
2082     {
2083       ret_val = FALSE;
2084       goto out;
2085     }
2086
2087 out:
2088   _dbus_string_free (&filename);
2089   _dbus_string_free (&full_path);
2090
2091   return ret_val;
2092 }
2093
2094 static dbus_bool_t
2095 init_service_reload_test (DBusString *dir)
2096 {
2097   DBusStat stat_buf;
2098  
2099   if (!_dbus_stat (dir, &stat_buf, NULL))
2100     {
2101       if (!_dbus_create_directory (dir, NULL))
2102         return FALSE;
2103     }
2104   else 
2105     {
2106       if (!test_remove_directory (dir))
2107         return FALSE;
2108
2109       if (!_dbus_create_directory (dir, NULL))
2110         return FALSE;
2111     }
2112
2113   /* Create one initial file */
2114   if (!test_create_service_file (dir, SERVICE_FILE_1, SERVICE_NAME_1, "exec-1"))
2115     return FALSE;
2116
2117   return TRUE;
2118 }
2119
2120 static dbus_bool_t
2121 cleanup_service_reload_test (DBusString *dir)
2122 {
2123   if (!test_remove_directory (dir))
2124     return FALSE;
2125
2126   return TRUE;
2127 }
2128
2129 typedef struct 
2130 {
2131   BusActivation *activation;
2132   const char    *service_name;
2133   dbus_bool_t    expecting_find;
2134 } CheckData;
2135
2136 static dbus_bool_t
2137 check_func (void *data)
2138 {
2139   CheckData          *d;
2140   BusActivationEntry *entry;
2141   DBusError           error;
2142   dbus_bool_t         ret_val;
2143   
2144   ret_val = TRUE;
2145   d = data;
2146   
2147   dbus_error_init (&error);
2148  
2149   entry = activation_find_entry (d->activation, d->service_name, &error);
2150   if (entry == NULL)
2151     {
2152       if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) 
2153         {
2154           ret_val = TRUE;
2155         }
2156       else
2157         {
2158           if (d->expecting_find)
2159             ret_val = FALSE;
2160         }
2161       
2162       dbus_error_free (&error);
2163     }
2164   else 
2165     {
2166       if (!d->expecting_find)
2167         ret_val = FALSE;
2168     }
2169
2170   return ret_val;
2171 }
2172
2173 static dbus_bool_t
2174 do_test (const char *description, dbus_bool_t oom_test, CheckData *data)
2175 {
2176   dbus_bool_t err;
2177
2178   if (oom_test)
2179     err = !_dbus_test_oom_handling (description, check_func, data);
2180   else
2181     err = !check_func (data);
2182
2183   if (err) 
2184     _dbus_assert_not_reached ("Test failed");
2185
2186   return TRUE;
2187 }
2188
2189 static dbus_bool_t
2190 do_service_reload_test (DBusString *dir, dbus_bool_t oom_test)
2191 {
2192   BusActivation *activation;
2193   DBusString     address;
2194   DBusList      *directories;
2195   CheckData      d;
2196   
2197   directories = NULL;
2198   _dbus_string_init_const (&address, "");
2199  
2200   if (!_dbus_list_append (&directories, _dbus_string_get_data (dir)))
2201     return FALSE; 
2202
2203   activation = bus_activation_new (NULL, &address, &directories, NULL);
2204   if (!activation)
2205     return FALSE;
2206
2207   d.activation = activation;
2208   
2209   /* Check for existing service file */
2210   d.expecting_find = TRUE;
2211   d.service_name = SERVICE_NAME_1;
2212
2213   if (!do_test ("Existing service file", oom_test, &d))
2214     return FALSE;
2215
2216   /* Check for non-existing service file */
2217   d.expecting_find = FALSE;
2218   d.service_name = SERVICE_NAME_3;
2219
2220   if (!do_test ("Nonexisting service file", oom_test, &d))
2221     return FALSE;
2222
2223   /* Check for added service file */
2224   if (!test_create_service_file (dir, SERVICE_FILE_2, SERVICE_NAME_2, "exec-2"))
2225     return FALSE;
2226
2227   d.expecting_find = TRUE;
2228   d.service_name = SERVICE_NAME_2;
2229   
2230   if (!do_test ("Added service file", oom_test, &d))
2231     return FALSE;
2232   
2233   /* Check for removed service file */
2234   if (!test_remove_service_file (dir, SERVICE_FILE_2))
2235     return FALSE;
2236
2237   d.expecting_find = FALSE;
2238   d.service_name = SERVICE_FILE_2;
2239
2240   if (!do_test ("Removed service file", oom_test, &d))
2241     return FALSE;
2242   
2243   /* Check for updated service file */
2244   
2245   _dbus_sleep_milliseconds (1000); /* Sleep a second to make sure the mtime is updated */
2246
2247   if (!test_create_service_file (dir, SERVICE_FILE_1, SERVICE_NAME_3, "exec-3"))
2248     return FALSE;
2249
2250   d.expecting_find = TRUE;
2251   d.service_name = SERVICE_NAME_3;
2252
2253   if (!do_test ("Updated service file, part 1", oom_test, &d))
2254     return FALSE;
2255
2256   d.expecting_find = FALSE;
2257   d.service_name = SERVICE_NAME_1;
2258
2259   if (!do_test ("Updated service file, part 2", oom_test, &d))
2260     return FALSE; 
2261
2262   bus_activation_unref (activation);
2263   _dbus_list_clear (&directories);
2264
2265   return TRUE;
2266 }
2267
2268 dbus_bool_t
2269 bus_activation_service_reload_test (const DBusString *test_data_dir)
2270 {
2271   DBusString directory;
2272
2273   if (!_dbus_string_init (&directory))
2274     return FALSE;
2275   
2276   if (!_dbus_string_append (&directory, _dbus_get_tmpdir()))
2277     return FALSE;
2278   
2279   if (!_dbus_string_append (&directory, "/dbus-reload-test-") ||
2280       !_dbus_generate_random_ascii (&directory, 6))
2281      {
2282        return FALSE;
2283      }
2284    
2285   /* Do normal tests */
2286   if (!init_service_reload_test (&directory))
2287     _dbus_assert_not_reached ("could not initiate service reload test");
2288  
2289   if (!do_service_reload_test (&directory, FALSE))
2290     ; /* Do nothing? */
2291   
2292   /* Do OOM tests */
2293   if (!init_service_reload_test (&directory))
2294     _dbus_assert_not_reached ("could not initiate service reload test");
2295  
2296   if (!do_service_reload_test (&directory, TRUE))
2297     ; /* Do nothing? */
2298  
2299   /* Cleanup test directory */
2300   if (!cleanup_service_reload_test (&directory))
2301     return FALSE;
2302   
2303   _dbus_string_free (&directory);
2304   
2305   return TRUE;
2306 }
2307
2308 #endif /* DBUS_BUILD_TESTS */