Merge branch 'my-dbus-1.2'
[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 dbus_bool_t
739 bus_activation_reload (BusActivation     *activation,
740                        const DBusString  *address,
741                        DBusList         **directories,
742                        DBusError         *error)
743 {
744   DBusList      *link;
745   char          *dir;
746
747   if (activation->server_address != NULL)
748     dbus_free (activation->server_address);
749   if (!_dbus_string_copy_data (address, &activation->server_address))
750     {
751       BUS_SET_OOM (error);
752       goto failed;
753     }
754
755   if (activation->entries != NULL)
756     _dbus_hash_table_unref (activation->entries);
757   activation->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
758                                              (DBusFreeFunction)bus_activation_entry_unref);
759   if (activation->entries == NULL)
760     {
761       BUS_SET_OOM (error);
762       goto failed;
763     }
764
765   if (activation->directories != NULL)
766     _dbus_hash_table_unref (activation->directories);
767   activation->directories = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
768                                                   (DBusFreeFunction)bus_service_directory_unref);
769
770   if (activation->directories == NULL)
771     {
772       BUS_SET_OOM (error);
773       goto failed;
774     }
775
776   link = _dbus_list_get_first_link (directories);
777   while (link != NULL)
778     {
779       BusServiceDirectory *s_dir;
780
781       dir = _dbus_strdup ((const char *) link->data);
782       if (!dir)
783         {
784           BUS_SET_OOM (error);
785           goto failed;
786         }
787
788       s_dir = dbus_new0 (BusServiceDirectory, 1);
789       if (!s_dir)
790         {
791           dbus_free (dir);
792           BUS_SET_OOM (error);
793           goto failed;
794         }
795
796       s_dir->refcount = 1;
797       s_dir->dir_c = dir;
798
799       s_dir->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
800                                              (DBusFreeFunction)bus_activation_entry_unref);
801
802       if (!s_dir->entries)
803         {
804           bus_service_directory_unref (s_dir);
805           BUS_SET_OOM (error);
806           goto failed;
807         }
808
809       if (!_dbus_hash_table_insert_string (activation->directories, s_dir->dir_c, s_dir))
810         {
811           bus_service_directory_unref (s_dir);
812           BUS_SET_OOM (error);
813           goto failed;
814         }
815
816       /* only fail on OOM, it is ok if we can't read the directory */
817       if (!update_directory (activation, s_dir, error))
818         {
819           if (dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY))
820             goto failed;
821           else
822             dbus_error_free (error);
823         }
824
825       link = _dbus_list_get_next_link (directories, link);
826     }
827
828   return TRUE;
829  failed:
830   return FALSE;
831 }
832
833 BusActivation*
834 bus_activation_new (BusContext        *context,
835                     const DBusString  *address,
836                     DBusList         **directories,
837                     DBusError         *error)
838 {
839   BusActivation *activation;
840   DBusList      *link;
841   char          *dir;
842
843   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
844
845   activation = dbus_new0 (BusActivation, 1);
846   if (activation == NULL)
847     {
848       BUS_SET_OOM (error);
849       return NULL;
850     }
851
852   activation->refcount = 1;
853   activation->context = context;
854   activation->n_pending_activations = 0;
855
856   if (!bus_activation_reload (activation, address, directories, error))
857     goto failed;
858
859    /* Initialize this hash table once, we don't want to lose pending
860    * activations on reload. */
861   activation->pending_activations = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
862                                                           (DBusFreeFunction)bus_pending_activation_unref);
863
864   if (activation->pending_activations == NULL)
865     {
866       BUS_SET_OOM (error);
867       goto failed;
868     }
869
870   activation->environment = _dbus_hash_table_new (DBUS_HASH_STRING,
871                                                   (DBusFreeFunction) dbus_free,
872                                                   (DBusFreeFunction) dbus_free);
873
874   if (activation->environment == NULL) 
875     {
876       BUS_SET_OOM (error);
877       goto failed;
878     }
879
880   if (!populate_environment (activation))
881     {
882       BUS_SET_OOM (error);
883       goto failed;
884     }
885
886   return activation;
887   
888  failed:
889   bus_activation_unref (activation);  
890   return NULL;
891 }
892
893 BusActivation *
894 bus_activation_ref (BusActivation *activation)
895 {
896   _dbus_assert (activation->refcount > 0);
897   
898   activation->refcount += 1;
899
900   return activation;
901 }
902
903 void
904 bus_activation_unref (BusActivation *activation)
905 {
906   _dbus_assert (activation->refcount > 0);
907
908   activation->refcount -= 1;
909
910   if (activation->refcount > 0)
911     return;
912   
913   dbus_free (activation->server_address);
914   if (activation->entries)
915     _dbus_hash_table_unref (activation->entries);
916   if (activation->pending_activations)
917     _dbus_hash_table_unref (activation->pending_activations);
918   if (activation->directories)  
919     _dbus_hash_table_unref (activation->directories);
920   if (activation->environment)
921     _dbus_hash_table_unref (activation->environment);
922
923   dbus_free (activation);
924 }
925
926 static dbus_bool_t
927 add_bus_environment (BusActivation *activation,
928                      DBusError     *error)
929 {
930   const char *type;
931   
932   if (!bus_activation_set_environment_variable (activation,
933                                                 "DBUS_STARTER_ADDRESS",
934                                                 activation->server_address,
935                                                 error))
936     return FALSE;
937   
938   type = bus_context_get_type (activation->context);
939   if (type != NULL)
940     {
941       if (!bus_activation_set_environment_variable (activation,
942                                                     "DBUS_STARTER_BUS_TYPE", type,
943                                                     error))
944         return FALSE;
945
946       if (strcmp (type, "session") == 0)
947         {
948           if (!bus_activation_set_environment_variable (activation,
949                                                         "DBUS_SESSION_BUS_ADDRESS",
950                                                         activation->server_address,
951                                                         error))
952             return FALSE;
953         }
954       else if (strcmp (type, "system") == 0)
955         {
956           if (!bus_activation_set_environment_variable (activation,
957                                                         "DBUS_SYSTEM_BUS_ADDRESS",
958                                                         activation->server_address,
959                                                         error))
960             return FALSE;
961         }
962     }
963
964   return TRUE;
965 }
966
967 typedef struct
968 {
969   BusPendingActivation *pending_activation;
970   DBusPreallocatedHash *hash_entry;
971 } RestorePendingData;
972
973 static void
974 restore_pending (void *data)
975 {
976   RestorePendingData *d = data;
977
978   _dbus_assert (d->pending_activation != NULL);
979   _dbus_assert (d->hash_entry != NULL);
980
981   _dbus_verbose ("Restoring pending activation for service %s, has timeout = %d\n",
982                  d->pending_activation->service_name,
983                  d->pending_activation->timeout_added);
984   
985   _dbus_hash_table_insert_string_preallocated (d->pending_activation->activation->pending_activations,
986                                                d->hash_entry,
987                                                d->pending_activation->service_name, d->pending_activation);
988
989   bus_pending_activation_ref (d->pending_activation);
990   
991   d->hash_entry = NULL;
992 }
993
994 static void
995 free_pending_restore_data (void *data)
996 {
997   RestorePendingData *d = data;
998
999   if (d->hash_entry)
1000     _dbus_hash_table_free_preallocated_entry (d->pending_activation->activation->pending_activations,
1001                                               d->hash_entry);
1002
1003   bus_pending_activation_unref (d->pending_activation);
1004   
1005   dbus_free (d);
1006 }
1007
1008 static dbus_bool_t
1009 add_restore_pending_to_transaction (BusTransaction       *transaction,
1010                                     BusPendingActivation *pending_activation)
1011 {
1012   RestorePendingData *d;
1013
1014   d = dbus_new (RestorePendingData, 1);
1015   if (d == NULL)
1016     return FALSE;
1017   
1018   d->pending_activation = pending_activation;
1019   d->hash_entry = _dbus_hash_table_preallocate_entry (d->pending_activation->activation->pending_activations);
1020   
1021   bus_pending_activation_ref (d->pending_activation);
1022   
1023   if (d->hash_entry == NULL ||
1024       !bus_transaction_add_cancel_hook (transaction, restore_pending, d,
1025                                         free_pending_restore_data))
1026     {
1027       free_pending_restore_data (d);
1028       return FALSE;
1029     }
1030
1031   _dbus_verbose ("Saved pending activation to be restored if the transaction fails\n");
1032   
1033   return TRUE;
1034 }
1035
1036 dbus_bool_t
1037 bus_activation_service_created (BusActivation  *activation,
1038                                 const char     *service_name,
1039                                 BusTransaction *transaction,
1040                                 DBusError      *error)
1041 {
1042   BusPendingActivation *pending_activation;
1043   DBusMessage *message;
1044   DBusList *link;
1045
1046   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1047   
1048   /* Check if it's a pending activation */
1049   pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, service_name);
1050
1051   if (!pending_activation)
1052     return TRUE;
1053
1054   link = _dbus_list_get_first_link (&pending_activation->entries);
1055   while (link != NULL)
1056     {
1057       BusPendingActivationEntry *entry = link->data;
1058       DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
1059       
1060       if (dbus_connection_get_is_connected (entry->connection))
1061         {
1062           /* Only send activation replies to regular activation requests. */
1063           if (!entry->auto_activation)
1064             {
1065               dbus_uint32_t result;
1066               
1067               message = dbus_message_new_method_return (entry->activation_message);
1068               if (!message)
1069                 {
1070                   BUS_SET_OOM (error);
1071                   goto error;
1072                 }
1073
1074               result = DBUS_START_REPLY_SUCCESS;
1075               
1076               if (!dbus_message_append_args (message,
1077                                              DBUS_TYPE_UINT32, &result,
1078                                              DBUS_TYPE_INVALID))
1079                 {
1080                   dbus_message_unref (message);
1081                   BUS_SET_OOM (error);
1082                   goto error;
1083                 }
1084               
1085               if (!bus_transaction_send_from_driver (transaction, entry->connection, message))
1086                 {
1087                   dbus_message_unref (message);
1088                   BUS_SET_OOM (error);
1089                   goto error;
1090                 }
1091               
1092               dbus_message_unref (message);
1093             }
1094         }
1095       
1096       link = next;
1097     }
1098
1099   return TRUE;
1100
1101  error:
1102   return FALSE;
1103 }
1104
1105 dbus_bool_t
1106 bus_activation_send_pending_auto_activation_messages (BusActivation  *activation,
1107                                                       BusService     *service,
1108                                                       BusTransaction *transaction,
1109                                                       DBusError      *error)
1110 {
1111   BusPendingActivation *pending_activation;
1112   DBusList *link;
1113
1114   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1115   
1116   /* Check if it's a pending activation */
1117   pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations,
1118                                                        bus_service_get_name (service));
1119
1120   if (!pending_activation)
1121     return TRUE;
1122
1123   link = _dbus_list_get_first_link (&pending_activation->entries);
1124   while (link != NULL)
1125     {
1126       BusPendingActivationEntry *entry = link->data;
1127       DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
1128
1129       if (entry->auto_activation && dbus_connection_get_is_connected (entry->connection))
1130         {
1131           DBusConnection *addressed_recipient;
1132           
1133           addressed_recipient = bus_service_get_primary_owners_connection (service);
1134
1135           /* Check the security policy, which has the side-effect of adding an
1136            * expected pending reply.
1137            */
1138           if (!bus_context_check_security_policy (activation->context, transaction,
1139                                                   entry->connection,
1140                                                   addressed_recipient,
1141                                                   addressed_recipient,
1142                                                   entry->activation_message, error))
1143             goto error;
1144
1145           if (!bus_transaction_send (transaction, addressed_recipient, entry->activation_message))
1146             {
1147               BUS_SET_OOM (error);
1148               goto error;
1149             }
1150         }
1151
1152       link = next;
1153     }
1154
1155   if (!add_restore_pending_to_transaction (transaction, pending_activation))
1156     {
1157       _dbus_verbose ("Could not add cancel hook to transaction to revert removing pending activation\n");
1158       BUS_SET_OOM (error);
1159       goto error;
1160     }
1161   
1162   _dbus_hash_table_remove_string (activation->pending_activations, bus_service_get_name (service));
1163
1164   return TRUE;
1165
1166  error:
1167   return FALSE;
1168 }
1169
1170 /**
1171  * FIXME @todo the error messages here would ideally be preallocated
1172  * so we don't need to allocate memory to send them.
1173  * Using the usual tactic, prealloc an OOM message, then
1174  * if we can't alloc the real error send the OOM error instead.
1175  */
1176 static dbus_bool_t
1177 try_send_activation_failure (BusPendingActivation *pending_activation,
1178                              const DBusError      *how)
1179 {
1180   BusActivation *activation;
1181   DBusList *link;
1182   BusTransaction *transaction;
1183   
1184   activation = pending_activation->activation;
1185
1186   transaction = bus_transaction_new (activation->context);
1187   if (transaction == NULL)
1188     return FALSE;
1189   
1190   link = _dbus_list_get_first_link (&pending_activation->entries);
1191   while (link != NULL)
1192     {
1193       BusPendingActivationEntry *entry = link->data;
1194       DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
1195       
1196       if (dbus_connection_get_is_connected (entry->connection))
1197         {
1198           if (!bus_transaction_send_error_reply (transaction,
1199                                                  entry->connection,
1200                                                  how,
1201                                                  entry->activation_message))
1202             goto error;
1203         }
1204       
1205       link = next;
1206     }
1207
1208   bus_transaction_execute_and_free (transaction);
1209   
1210   return TRUE;
1211
1212  error:
1213   if (transaction)
1214     bus_transaction_cancel_and_free (transaction);
1215   return FALSE;
1216 }
1217
1218 /**
1219  * Free the pending activation and send an error message to all the
1220  * connections that were waiting for it.
1221  */
1222 static void
1223 pending_activation_failed (BusPendingActivation *pending_activation,
1224                            const DBusError      *how)
1225 {
1226   /* FIXME use preallocated OOM messages instead of bus_wait_for_memory() */
1227   while (!try_send_activation_failure (pending_activation, how))
1228     _dbus_wait_for_memory ();
1229
1230   /* Destroy this pending activation */
1231   _dbus_hash_table_remove_string (pending_activation->activation->pending_activations,
1232                                   pending_activation->service_name);
1233 }
1234
1235 /**
1236  * Depending on the exit code of the helper, set the error accordingly
1237  */
1238 static void
1239 handle_servicehelper_exit_error (int        exit_code,
1240                                  DBusError *error)
1241 {
1242   switch (exit_code)
1243     {
1244     case BUS_SPAWN_EXIT_CODE_NO_MEMORY:
1245       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
1246                       "Launcher could not run (out of memory)");
1247       break;
1248     case BUS_SPAWN_EXIT_CODE_SETUP_FAILED:
1249       dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED,
1250                       "Failed to setup environment correctly");
1251       break;
1252     case BUS_SPAWN_EXIT_CODE_NAME_INVALID:
1253       dbus_set_error (error, DBUS_ERROR_SPAWN_SERVICE_INVALID,
1254                       "Bus name is not valid or missing");
1255       break;
1256     case BUS_SPAWN_EXIT_CODE_SERVICE_NOT_FOUND:
1257       dbus_set_error (error, DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND,
1258                       "Bus name not found in system service directory");
1259       break;
1260     case BUS_SPAWN_EXIT_CODE_PERMISSIONS_INVALID:
1261       dbus_set_error (error, DBUS_ERROR_SPAWN_PERMISSIONS_INVALID,
1262                       "The permission of the setuid helper is not correct");
1263       break;
1264     case BUS_SPAWN_EXIT_CODE_FILE_INVALID:
1265       dbus_set_error (error, DBUS_ERROR_SPAWN_PERMISSIONS_INVALID,
1266                       "The service file is incorrect or does not have all required attributes");
1267       break;
1268     case BUS_SPAWN_EXIT_CODE_EXEC_FAILED:
1269       dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
1270                       "Cannot launch daemon, file not found or permissions invalid");
1271       break;
1272     case BUS_SPAWN_EXIT_CODE_INVALID_ARGS:
1273       dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1274                       "Invalid arguments to command line");
1275       break;
1276     case BUS_SPAWN_EXIT_CODE_CHILD_SIGNALED:
1277       dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_SIGNALED,
1278                       "Launched child was signaled, it probably crashed");
1279       break;
1280     default:
1281       dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
1282                       "Launch helper exited with unknown return code %i", exit_code);
1283       break;
1284     }
1285 }
1286
1287 static dbus_bool_t
1288 babysitter_watch_callback (DBusWatch     *watch,
1289                            unsigned int   condition,
1290                            void          *data)
1291 {
1292   BusPendingActivation *pending_activation = data;
1293   dbus_bool_t retval;
1294   DBusBabysitter *babysitter;
1295   dbus_bool_t uses_servicehelper;
1296
1297   babysitter = pending_activation->babysitter;
1298
1299   _dbus_babysitter_ref (babysitter);
1300
1301   retval = dbus_watch_handle (watch, condition);
1302
1303   /* There are two major cases here; are we the system bus or the session?  Here this
1304    * is distinguished by whether or not we use a setuid helper launcher.  With the launch helper,
1305    * some process exit codes are meaningful, processed by handle_servicehelper_exit_error.
1306    *
1307    * In both cases though, just ignore when a process exits with status 0; it's possible for
1308    * a program to (misguidedly) "daemonize", and that appears to us as an exit.  This closes a race
1309    * condition between this code and the child process claiming the bus name.
1310    */
1311   uses_servicehelper = bus_context_get_servicehelper (pending_activation->activation->context) != NULL;
1312
1313   /* FIXME this is broken in the same way that
1314    * connection watches used to be; there should be
1315    * a separate callback for status change, instead
1316    * of doing "if we handled a watch status might
1317    * have changed"
1318    *
1319    * Fixing this lets us move dbus_watch_handle
1320    * calls into dbus-mainloop.c
1321    */
1322   if (_dbus_babysitter_get_child_exited (babysitter))
1323     {
1324       DBusError error;
1325       DBusHashIter iter;
1326       dbus_bool_t activation_failed;
1327       int exit_code = 0;
1328
1329       dbus_error_init (&error);
1330
1331       _dbus_babysitter_set_child_exit_error (babysitter, &error);
1332
1333       /* Explicitly check for SPAWN_CHILD_EXITED to avoid overwriting an
1334        * exec error */
1335       if (dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)
1336           && _dbus_babysitter_get_child_exit_status (babysitter, &exit_code))
1337         {
1338           activation_failed = exit_code != 0;
1339
1340           dbus_error_free(&error);
1341
1342           if (activation_failed)
1343             {
1344               if (uses_servicehelper)
1345                 handle_servicehelper_exit_error (exit_code, &error);
1346               else
1347                 _dbus_babysitter_set_child_exit_error (babysitter, &error);
1348             }
1349         }
1350       else
1351         {
1352           activation_failed = TRUE;
1353         }
1354
1355       if (activation_failed)
1356         {
1357           /* Destroy all pending activations with the same exec */
1358           _dbus_hash_iter_init (pending_activation->activation->pending_activations,
1359                                 &iter);
1360           while (_dbus_hash_iter_next (&iter))
1361             {
1362               BusPendingActivation *p = _dbus_hash_iter_get_value (&iter);
1363
1364               if (p != pending_activation && strcmp (p->exec, pending_activation->exec) == 0)
1365                 pending_activation_failed (p, &error);
1366             }
1367
1368           /* Destroys the pending activation */
1369           pending_activation_failed (pending_activation, &error);
1370
1371           dbus_error_free (&error);
1372         }
1373     }
1374
1375   _dbus_babysitter_unref (babysitter);
1376
1377   return retval;
1378 }
1379
1380 static dbus_bool_t
1381 add_babysitter_watch (DBusWatch      *watch,
1382                       void           *data)
1383 {
1384   BusPendingActivation *pending_activation = data;
1385
1386   return _dbus_loop_add_watch (bus_context_get_loop (pending_activation->activation->context),
1387                                watch, babysitter_watch_callback, pending_activation,
1388                                NULL);
1389 }
1390
1391 static void
1392 remove_babysitter_watch (DBusWatch      *watch,
1393                          void           *data)
1394 {
1395   BusPendingActivation *pending_activation = data;
1396   
1397   _dbus_loop_remove_watch (bus_context_get_loop (pending_activation->activation->context),
1398                            watch, babysitter_watch_callback, pending_activation);
1399 }
1400
1401 static dbus_bool_t
1402 pending_activation_timed_out (void *data)
1403 {
1404   BusPendingActivation *pending_activation = data;
1405   DBusError error;
1406   
1407   /* Kill the spawned process, since it sucks
1408    * (not sure this is what we want to do, but
1409    * may as well try it for now)
1410    */
1411   if (pending_activation->babysitter) 
1412     _dbus_babysitter_kill_child (pending_activation->babysitter);
1413
1414   dbus_error_init (&error);
1415
1416   dbus_set_error (&error, DBUS_ERROR_TIMED_OUT,
1417                   "Activation of %s timed out",
1418                   pending_activation->service_name);
1419
1420   pending_activation_failed (pending_activation, &error);
1421
1422   dbus_error_free (&error);
1423
1424   return TRUE;
1425 }
1426
1427 static void
1428 cancel_pending (void *data)
1429 {
1430   BusPendingActivation *pending_activation = data;
1431
1432   _dbus_verbose ("Canceling pending activation of %s\n",
1433                  pending_activation->service_name);
1434
1435   if (pending_activation->babysitter)
1436     _dbus_babysitter_kill_child (pending_activation->babysitter);
1437   
1438   _dbus_hash_table_remove_string (pending_activation->activation->pending_activations,
1439                                   pending_activation->service_name);
1440 }
1441
1442 static void
1443 free_pending_cancel_data (void *data)
1444 {
1445   BusPendingActivation *pending_activation = data;
1446   
1447   bus_pending_activation_unref (pending_activation);
1448 }
1449
1450 static dbus_bool_t
1451 add_cancel_pending_to_transaction (BusTransaction       *transaction,
1452                                    BusPendingActivation *pending_activation)
1453 {  
1454   if (!bus_transaction_add_cancel_hook (transaction, cancel_pending,
1455                                         pending_activation,
1456                                         free_pending_cancel_data))
1457     return FALSE;
1458
1459   bus_pending_activation_ref (pending_activation); 
1460   
1461   _dbus_verbose ("Saved pending activation to be canceled if the transaction fails\n");
1462   
1463   return TRUE;
1464 }
1465
1466 static dbus_bool_t 
1467 update_service_cache (BusActivation *activation, DBusError *error)
1468 {
1469   DBusHashIter iter;
1470  
1471   _dbus_hash_iter_init (activation->directories, &iter);
1472   while (_dbus_hash_iter_next (&iter))
1473     {
1474       DBusError tmp_error;
1475       BusServiceDirectory *s_dir;
1476
1477       s_dir = _dbus_hash_iter_get_value (&iter);
1478
1479       dbus_error_init (&tmp_error);
1480       if (!update_directory (activation, s_dir, &tmp_error))
1481         {
1482           if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
1483             {
1484               dbus_move_error (&tmp_error, error);
1485               return FALSE;
1486             }
1487
1488           dbus_error_free (&tmp_error);
1489           continue;
1490         }
1491     }
1492   
1493   return TRUE;
1494 }
1495
1496 static BusActivationEntry *
1497 activation_find_entry (BusActivation *activation, 
1498                        const char    *service_name,
1499                        DBusError     *error)
1500 {
1501   BusActivationEntry *entry;
1502   
1503   entry = _dbus_hash_table_lookup_string (activation->entries, service_name);
1504   if (!entry)
1505     { 
1506       if (!update_service_cache (activation, error)) 
1507         return NULL;
1508
1509       entry = _dbus_hash_table_lookup_string (activation->entries,
1510                                               service_name);
1511     }
1512   else 
1513     {
1514       BusActivationEntry *updated_entry;
1515
1516       if (!check_service_file (activation, entry, &updated_entry, error)) 
1517         return NULL;
1518
1519       entry = updated_entry;
1520     }
1521
1522   if (!entry) 
1523     {
1524       dbus_set_error (error, DBUS_ERROR_SERVICE_UNKNOWN,
1525                       "The name %s was not provided by any .service files",
1526                       service_name);
1527       return NULL;
1528     }
1529
1530   return entry;
1531 }
1532
1533 static char **
1534 bus_activation_get_environment (BusActivation *activation)
1535 {
1536   char **environment;
1537   int i, length;
1538   DBusString entry;
1539   DBusHashIter iter;
1540
1541   length = _dbus_hash_table_get_n_entries (activation->environment);
1542
1543   environment = dbus_new0 (char *, length + 1);
1544
1545   if (environment == NULL)
1546     return NULL;
1547
1548   i = 0;
1549   _dbus_hash_iter_init (activation->environment, &iter);
1550
1551   if (!_dbus_string_init (&entry))
1552     {
1553       dbus_free_string_array (environment);
1554       return NULL;
1555     }
1556
1557   while (_dbus_hash_iter_next (&iter))
1558     {
1559       const char *key, *value;
1560
1561       key = (const char *) _dbus_hash_iter_get_string_key (&iter);
1562       value = (const char *) _dbus_hash_iter_get_value (&iter);
1563
1564       if (!_dbus_string_append_printf (&entry, "%s=%s", key, value))
1565         break;
1566
1567       if (!_dbus_string_steal_data (&entry, environment + i))
1568         break;
1569       i++;
1570     }
1571
1572   _dbus_string_free (&entry);
1573
1574   if (i != length)
1575     {
1576       dbus_free_string_array (environment);
1577       environment = NULL;
1578     }
1579
1580   return environment;
1581 }
1582
1583 dbus_bool_t
1584 bus_activation_set_environment_variable (BusActivation     *activation,
1585                                          const char        *key,
1586                                          const char        *value,
1587                                          DBusError         *error)
1588 {
1589   char        *hash_key;
1590   char        *hash_value;
1591   dbus_bool_t  retval;
1592
1593   retval = FALSE;
1594   hash_key = NULL;
1595   hash_value = NULL;
1596   hash_key = _dbus_strdup (key);
1597
1598   if (hash_key == NULL)
1599     goto out;
1600
1601   hash_value = _dbus_strdup (value);
1602
1603   if (hash_value == NULL)
1604     goto out;
1605
1606   if (!_dbus_hash_table_insert_string (activation->environment,
1607                                        hash_key, hash_value))
1608     goto out;
1609
1610   retval = TRUE;
1611 out:
1612   if (retval == FALSE)
1613     {
1614       dbus_free (hash_key);
1615       dbus_free (hash_value);
1616       BUS_SET_OOM (error);
1617     }
1618
1619   return retval;
1620 }
1621
1622 dbus_bool_t
1623 bus_activation_activate_service (BusActivation  *activation,
1624                                  DBusConnection *connection,
1625                                  BusTransaction *transaction,
1626                                  dbus_bool_t     auto_activation,
1627                                  DBusMessage    *activation_message,
1628                                  const char     *service_name,
1629                                  DBusError      *error)
1630 {
1631   BusActivationEntry *entry;
1632   BusPendingActivation *pending_activation;
1633   BusPendingActivationEntry *pending_activation_entry;
1634   DBusMessage *message;
1635   DBusString service_str;
1636   const char *servicehelper;
1637   char **argv;
1638   char **envp = NULL;
1639   int argc;
1640   dbus_bool_t retval;
1641   DBusHashIter iter;
1642   dbus_bool_t activated;
1643   DBusString command;
1644   
1645   activated = TRUE;
1646
1647   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1648
1649   if (activation->n_pending_activations >=
1650       bus_context_get_max_pending_activations (activation->context))
1651     {
1652       dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
1653                       "The maximum number of pending activations has been reached, activation of %s failed",
1654                       service_name);
1655       return FALSE;
1656     }
1657
1658   entry = activation_find_entry (activation, service_name, error);
1659   if (!entry) 
1660     return FALSE;
1661
1662   /* Bypass the registry lookup if we're auto-activating, bus_dispatch would not
1663    * call us if the service is already active.
1664    */
1665   if (!auto_activation)
1666     {
1667       /* Check if the service is active */
1668       _dbus_string_init_const (&service_str, service_name);
1669       if (bus_registry_lookup (bus_context_get_registry (activation->context), &service_str) != NULL)
1670         {
1671           dbus_uint32_t result;
1672           
1673           _dbus_verbose ("Service \"%s\" is already active\n", service_name);
1674       
1675           message = dbus_message_new_method_return (activation_message);
1676
1677           if (!message)
1678             {
1679               _dbus_verbose ("No memory to create reply to activate message\n");
1680               BUS_SET_OOM (error);
1681               return FALSE;
1682             }
1683
1684           result = DBUS_START_REPLY_ALREADY_RUNNING;
1685           
1686           if (!dbus_message_append_args (message,
1687                                          DBUS_TYPE_UINT32, &result,
1688                                          DBUS_TYPE_INVALID))
1689             {
1690               _dbus_verbose ("No memory to set args of reply to activate message\n");
1691               BUS_SET_OOM (error);
1692               dbus_message_unref (message);
1693               return FALSE;
1694             }
1695
1696           retval = bus_transaction_send_from_driver (transaction, connection, message);
1697           dbus_message_unref (message);
1698           if (!retval)
1699             {
1700               _dbus_verbose ("Failed to send reply\n");
1701               BUS_SET_OOM (error);
1702             }
1703
1704           return retval;
1705         }
1706     }
1707   
1708   pending_activation_entry = dbus_new0 (BusPendingActivationEntry, 1);
1709   if (!pending_activation_entry)
1710     {
1711       _dbus_verbose ("Failed to create pending activation entry\n");
1712       BUS_SET_OOM (error);
1713       return FALSE;
1714     }
1715
1716   pending_activation_entry->auto_activation = auto_activation;
1717
1718   pending_activation_entry->activation_message = activation_message;
1719   dbus_message_ref (activation_message);
1720   pending_activation_entry->connection = connection;
1721   dbus_connection_ref (connection);
1722   
1723   /* Check if the service is being activated */
1724   pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, service_name);
1725   if (pending_activation)
1726     {
1727       if (!_dbus_list_append (&pending_activation->entries, pending_activation_entry))
1728         {
1729           _dbus_verbose ("Failed to append a new entry to pending activation\n");
1730           
1731           BUS_SET_OOM (error);
1732           bus_pending_activation_entry_free (pending_activation_entry);
1733           return FALSE;
1734         }
1735
1736       pending_activation->n_entries += 1;
1737       pending_activation->activation->n_pending_activations += 1;
1738     }
1739   else
1740     {
1741       pending_activation = dbus_new0 (BusPendingActivation, 1);
1742       if (!pending_activation)
1743         {
1744           _dbus_verbose ("Failed to create pending activation\n");
1745           
1746           BUS_SET_OOM (error);
1747           bus_pending_activation_entry_free (pending_activation_entry);          
1748           return FALSE;
1749         }
1750
1751       pending_activation->activation = activation;
1752       pending_activation->refcount = 1;
1753       
1754       pending_activation->service_name = _dbus_strdup (service_name);
1755       if (!pending_activation->service_name)
1756         {
1757           _dbus_verbose ("Failed to copy service name for 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->exec = _dbus_strdup (entry->exec);
1766       if (!pending_activation->exec)
1767         {
1768           _dbus_verbose ("Failed to copy service exec for pending activation\n");
1769           BUS_SET_OOM (error);
1770           bus_pending_activation_unref (pending_activation);
1771           bus_pending_activation_entry_free (pending_activation_entry);
1772           return FALSE;
1773         }
1774
1775       pending_activation->timeout =
1776         _dbus_timeout_new (bus_context_get_activation_timeout (activation->context),
1777                            pending_activation_timed_out,
1778                            pending_activation,
1779                            NULL);
1780       if (!pending_activation->timeout)
1781         {
1782           _dbus_verbose ("Failed to create timeout for pending activation\n");
1783           
1784           BUS_SET_OOM (error);
1785           bus_pending_activation_unref (pending_activation);
1786           bus_pending_activation_entry_free (pending_activation_entry);
1787           return FALSE;
1788         }
1789
1790       if (!_dbus_loop_add_timeout (bus_context_get_loop (activation->context),
1791                                    pending_activation->timeout,
1792                                    handle_timeout_callback,
1793                                    pending_activation,
1794                                    NULL))
1795         {
1796           _dbus_verbose ("Failed to add timeout for pending activation\n");
1797           
1798           BUS_SET_OOM (error);
1799           bus_pending_activation_unref (pending_activation);
1800           bus_pending_activation_entry_free (pending_activation_entry);          
1801           return FALSE;
1802         }
1803
1804       pending_activation->timeout_added = TRUE;
1805       
1806       if (!_dbus_list_append (&pending_activation->entries, pending_activation_entry))
1807         {
1808           _dbus_verbose ("Failed to add entry to just-created pending activation\n");
1809           
1810           BUS_SET_OOM (error);
1811           bus_pending_activation_unref (pending_activation);
1812           bus_pending_activation_entry_free (pending_activation_entry);          
1813           return FALSE;
1814         }
1815
1816       pending_activation->n_entries += 1;
1817       pending_activation->activation->n_pending_activations += 1;
1818     
1819       activated = FALSE;
1820       _dbus_hash_iter_init (activation->pending_activations, &iter);
1821       while (_dbus_hash_iter_next (&iter))
1822         {
1823           BusPendingActivation *p = _dbus_hash_iter_get_value (&iter);
1824           
1825           if (strcmp (p->exec, entry->exec) == 0) 
1826             {
1827               activated = TRUE;
1828               break;
1829             }
1830         }
1831      
1832       if (!_dbus_hash_table_insert_string (activation->pending_activations,
1833                                            pending_activation->service_name,
1834                                            pending_activation))
1835         {
1836           _dbus_verbose ("Failed to put pending activation in hash table\n");
1837           
1838           BUS_SET_OOM (error);
1839           bus_pending_activation_unref (pending_activation);
1840           return FALSE;
1841         }
1842     }
1843   
1844   if (!add_cancel_pending_to_transaction (transaction, pending_activation))
1845     {
1846       _dbus_verbose ("Failed to add pending activation cancel hook to transaction\n");
1847       BUS_SET_OOM (error);
1848       _dbus_hash_table_remove_string (activation->pending_activations,
1849                                       pending_activation->service_name);
1850
1851       return FALSE;
1852     }
1853   
1854   if (activated)
1855     return TRUE;
1856
1857   /* use command as system and session different */
1858   if (!_dbus_string_init (&command))
1859     {
1860       BUS_SET_OOM (error);
1861       return FALSE;
1862     }
1863
1864   /* does the bus use a helper? */
1865   servicehelper = bus_context_get_servicehelper (activation->context);
1866   if (servicehelper != NULL)
1867     {
1868       if (entry->user == NULL)
1869         {
1870           _dbus_string_free (&command);
1871           dbus_set_error (error, DBUS_ERROR_SPAWN_FILE_INVALID,
1872                           "Cannot do system-bus activation with no user\n");
1873           return FALSE;
1874         }
1875
1876       /* join the helper path and the service name */
1877       if (!_dbus_string_append (&command, servicehelper))
1878         {
1879           _dbus_string_free (&command);
1880           BUS_SET_OOM (error);
1881           return FALSE;
1882         }
1883       if (!_dbus_string_append (&command, " "))
1884         {
1885           _dbus_string_free (&command);
1886           BUS_SET_OOM (error);
1887           return FALSE;
1888         }
1889       if (!_dbus_string_append (&command, service_name))
1890         {
1891           _dbus_string_free (&command);
1892           BUS_SET_OOM (error);
1893           return FALSE;
1894         }
1895     }
1896   else
1897     {
1898       /* the bus does not use a helper, so we can append arguments with the exec line */
1899       if (!_dbus_string_append (&command, entry->exec))
1900         {
1901           _dbus_string_free (&command);
1902           BUS_SET_OOM (error);
1903           return FALSE;
1904         }
1905     }
1906
1907   /* convert command into arguments */
1908   if (!_dbus_shell_parse_argv (_dbus_string_get_const_data (&command), &argc, &argv, error))
1909     {
1910       _dbus_verbose ("Failed to parse command line: %s\n", entry->exec);
1911       _DBUS_ASSERT_ERROR_IS_SET (error);
1912       
1913       _dbus_hash_table_remove_string (activation->pending_activations,
1914                                       pending_activation->service_name);
1915
1916       _dbus_string_free (&command);
1917       return FALSE;
1918     }
1919   _dbus_string_free (&command);
1920
1921   if (!add_bus_environment (activation, error))
1922     {
1923       _DBUS_ASSERT_ERROR_IS_SET (error);
1924       dbus_free_string_array (argv);
1925       return FALSE;
1926     }
1927
1928   envp = bus_activation_get_environment (activation);
1929
1930   if (envp == NULL)
1931     {
1932       BUS_SET_OOM (error);
1933       dbus_free_string_array (argv);
1934       return FALSE;
1935     }
1936
1937   _dbus_verbose ("Spawning %s ...\n", argv[0]);
1938   if (!_dbus_spawn_async_with_babysitter (&pending_activation->babysitter, argv,
1939                                           envp,
1940                                           NULL, activation, 
1941                                           error))
1942     {
1943       _dbus_verbose ("Failed to spawn child\n");
1944       _DBUS_ASSERT_ERROR_IS_SET (error);
1945       dbus_free_string_array (argv);
1946       dbus_free_string_array (envp);
1947
1948       return FALSE;
1949     }
1950
1951   dbus_free_string_array (argv);
1952   envp = NULL;
1953
1954   _dbus_assert (pending_activation->babysitter != NULL);
1955   
1956   if (!_dbus_babysitter_set_watch_functions (pending_activation->babysitter,
1957                                              add_babysitter_watch,
1958                                              remove_babysitter_watch,
1959                                              NULL,
1960                                              pending_activation,
1961                                              NULL))
1962     {
1963       BUS_SET_OOM (error);
1964       _dbus_verbose ("Failed to set babysitter watch functions\n");
1965       return FALSE;
1966     }
1967   
1968   return TRUE;
1969 }
1970
1971 dbus_bool_t
1972 bus_activation_list_services (BusActivation *activation,
1973                               char        ***listp,
1974                               int           *array_len)
1975 {
1976   int i, j, len;
1977   char **retval;
1978   DBusHashIter iter;
1979
1980   len = _dbus_hash_table_get_n_entries (activation->entries);
1981   retval = dbus_new (char *, len + 1);
1982
1983   if (retval == NULL)
1984     return FALSE;
1985
1986   _dbus_hash_iter_init (activation->entries, &iter);
1987   i = 0;
1988   while (_dbus_hash_iter_next (&iter))
1989     {
1990       BusActivationEntry *entry = _dbus_hash_iter_get_value (&iter);
1991
1992       retval[i] = _dbus_strdup (entry->name);
1993       if (retval[i] == NULL)
1994         goto error;
1995
1996       i++;
1997     }
1998
1999   retval[i] = NULL;
2000
2001   if (array_len)
2002     *array_len = len;
2003
2004   *listp = retval;
2005   return TRUE;
2006
2007  error:
2008   for (j = 0; j < i; j++)
2009     dbus_free (retval[i]);
2010   dbus_free (retval);
2011
2012   return FALSE;
2013 }
2014   
2015
2016 #ifdef DBUS_BUILD_TESTS
2017
2018 #include <stdio.h>
2019
2020 #define SERVICE_NAME_1 "MyService1"
2021 #define SERVICE_NAME_2 "MyService2"
2022 #define SERVICE_NAME_3 "MyService3"
2023
2024 #define SERVICE_FILE_1 "service-1.service"
2025 #define SERVICE_FILE_2 "service-2.service"
2026 #define SERVICE_FILE_3 "service-3.service"
2027
2028 static dbus_bool_t
2029 test_create_service_file (DBusString *dir,
2030                           const char *filename, 
2031                           const char *name, 
2032                           const char *exec)
2033 {
2034   DBusString  file_name, full_path;
2035   FILE        *file;
2036   dbus_bool_t  ret_val;
2037
2038   ret_val = TRUE;
2039   _dbus_string_init_const (&file_name, filename);
2040
2041   if (!_dbus_string_init (&full_path))
2042     return FALSE;
2043
2044   if (!_dbus_string_append (&full_path, _dbus_string_get_const_data (dir)) ||
2045       !_dbus_concat_dir_and_file (&full_path, &file_name))
2046     {
2047       ret_val = FALSE;
2048       goto out;
2049     }
2050   
2051   file = fopen (_dbus_string_get_const_data (&full_path), "w");
2052   if (!file)
2053     {
2054       ret_val = FALSE;
2055       goto out;
2056     }
2057
2058   fprintf (file, "[D-BUS Service]\nName=%s\nExec=%s\n", name, exec);
2059   fclose (file);
2060
2061 out:
2062   _dbus_string_free (&full_path);
2063   return ret_val;
2064 }
2065
2066 static dbus_bool_t
2067 test_remove_service_file (DBusString *dir, const char *filename)
2068 {
2069   DBusString  file_name, full_path;
2070   dbus_bool_t ret_val;
2071   
2072   ret_val = TRUE;
2073  
2074   _dbus_string_init_const (&file_name, filename);
2075
2076   if (!_dbus_string_init (&full_path))
2077     return FALSE;
2078
2079   if (!_dbus_string_append (&full_path, _dbus_string_get_const_data (dir)) ||
2080       !_dbus_concat_dir_and_file (&full_path, &file_name))
2081     {
2082       ret_val = FALSE;
2083       goto out;
2084     }
2085
2086   if (!_dbus_delete_file (&full_path, NULL))
2087     {
2088       ret_val = FALSE;
2089       goto out;
2090     }
2091
2092 out:
2093   _dbus_string_free (&full_path);
2094   return ret_val;
2095 }
2096
2097 static dbus_bool_t
2098 test_remove_directory (DBusString *dir)
2099 {
2100   DBusDirIter *iter;
2101   DBusString   filename, full_path;
2102   dbus_bool_t  ret_val;
2103   
2104   ret_val = TRUE;
2105   
2106   if (!_dbus_string_init (&filename))
2107     return FALSE;
2108
2109   if (!_dbus_string_init (&full_path))
2110     {
2111       _dbus_string_free (&filename);
2112       return FALSE;
2113     }
2114     
2115   iter = _dbus_directory_open (dir, NULL);
2116   if (iter == NULL)
2117     {
2118       ret_val = FALSE;
2119       goto out;
2120     }
2121   
2122   while (_dbus_directory_get_next_file (iter, &filename, NULL)) 
2123     {
2124       if (!test_remove_service_file (dir, _dbus_string_get_const_data (&filename)))
2125         {
2126           ret_val = FALSE;
2127           goto out;
2128         }
2129     }
2130   _dbus_directory_close (iter);
2131
2132   if (!_dbus_delete_directory (dir, NULL))
2133     {
2134       ret_val = FALSE;
2135       goto out;
2136     }
2137
2138 out:
2139   _dbus_string_free (&filename);
2140   _dbus_string_free (&full_path);
2141
2142   return ret_val;
2143 }
2144
2145 static dbus_bool_t
2146 init_service_reload_test (DBusString *dir)
2147 {
2148   DBusStat stat_buf;
2149  
2150   if (!_dbus_stat (dir, &stat_buf, NULL))
2151     {
2152       if (!_dbus_create_directory (dir, NULL))
2153         return FALSE;
2154     }
2155   else 
2156     {
2157       if (!test_remove_directory (dir))
2158         return FALSE;
2159
2160       if (!_dbus_create_directory (dir, NULL))
2161         return FALSE;
2162     }
2163
2164   /* Create one initial file */
2165   if (!test_create_service_file (dir, SERVICE_FILE_1, SERVICE_NAME_1, "exec-1"))
2166     return FALSE;
2167
2168   return TRUE;
2169 }
2170
2171 static dbus_bool_t
2172 cleanup_service_reload_test (DBusString *dir)
2173 {
2174   if (!test_remove_directory (dir))
2175     return FALSE;
2176
2177   return TRUE;
2178 }
2179
2180 typedef struct 
2181 {
2182   BusActivation *activation;
2183   const char    *service_name;
2184   dbus_bool_t    expecting_find;
2185 } CheckData;
2186
2187 static dbus_bool_t
2188 check_func (void *data)
2189 {
2190   CheckData          *d;
2191   BusActivationEntry *entry;
2192   DBusError           error;
2193   dbus_bool_t         ret_val;
2194   
2195   ret_val = TRUE;
2196   d = data;
2197   
2198   dbus_error_init (&error);
2199  
2200   entry = activation_find_entry (d->activation, d->service_name, &error);
2201   if (entry == NULL)
2202     {
2203       if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) 
2204         {
2205           ret_val = TRUE;
2206         }
2207       else
2208         {
2209           if (d->expecting_find)
2210             ret_val = FALSE;
2211         }
2212       
2213       dbus_error_free (&error);
2214     }
2215   else 
2216     {
2217       if (!d->expecting_find)
2218         ret_val = FALSE;
2219     }
2220
2221   return ret_val;
2222 }
2223
2224 static dbus_bool_t
2225 do_test (const char *description, dbus_bool_t oom_test, CheckData *data)
2226 {
2227   dbus_bool_t err;
2228
2229   if (oom_test)
2230     err = !_dbus_test_oom_handling (description, check_func, data);
2231   else
2232     err = !check_func (data);
2233
2234   if (err) 
2235     _dbus_assert_not_reached ("Test failed");
2236
2237   return TRUE;
2238 }
2239
2240 static dbus_bool_t
2241 do_service_reload_test (DBusString *dir, dbus_bool_t oom_test)
2242 {
2243   BusActivation *activation;
2244   DBusString     address;
2245   DBusList      *directories;
2246   CheckData      d;
2247   
2248   directories = NULL;
2249   _dbus_string_init_const (&address, "");
2250  
2251   if (!_dbus_list_append (&directories, _dbus_string_get_data (dir)))
2252     return FALSE; 
2253
2254   activation = bus_activation_new (NULL, &address, &directories, NULL);
2255   if (!activation)
2256     return FALSE;
2257
2258   d.activation = activation;
2259   
2260   /* Check for existing service file */
2261   d.expecting_find = TRUE;
2262   d.service_name = SERVICE_NAME_1;
2263
2264   if (!do_test ("Existing service file", oom_test, &d))
2265     return FALSE;
2266
2267   /* Check for non-existing service file */
2268   d.expecting_find = FALSE;
2269   d.service_name = SERVICE_NAME_3;
2270
2271   if (!do_test ("Nonexisting service file", oom_test, &d))
2272     return FALSE;
2273
2274   /* Check for added service file */
2275   if (!test_create_service_file (dir, SERVICE_FILE_2, SERVICE_NAME_2, "exec-2"))
2276     return FALSE;
2277
2278   d.expecting_find = TRUE;
2279   d.service_name = SERVICE_NAME_2;
2280   
2281   if (!do_test ("Added service file", oom_test, &d))
2282     return FALSE;
2283   
2284   /* Check for removed service file */
2285   if (!test_remove_service_file (dir, SERVICE_FILE_2))
2286     return FALSE;
2287
2288   d.expecting_find = FALSE;
2289   d.service_name = SERVICE_FILE_2;
2290
2291   if (!do_test ("Removed service file", oom_test, &d))
2292     return FALSE;
2293   
2294   /* Check for updated service file */
2295   
2296   _dbus_sleep_milliseconds (1000); /* Sleep a second to make sure the mtime is updated */
2297
2298   if (!test_create_service_file (dir, SERVICE_FILE_1, SERVICE_NAME_3, "exec-3"))
2299     return FALSE;
2300
2301   d.expecting_find = TRUE;
2302   d.service_name = SERVICE_NAME_3;
2303
2304   if (!do_test ("Updated service file, part 1", oom_test, &d))
2305     return FALSE;
2306
2307   d.expecting_find = FALSE;
2308   d.service_name = SERVICE_NAME_1;
2309
2310   if (!do_test ("Updated service file, part 2", oom_test, &d))
2311     return FALSE; 
2312
2313   bus_activation_unref (activation);
2314   _dbus_list_clear (&directories);
2315
2316   return TRUE;
2317 }
2318
2319 dbus_bool_t
2320 bus_activation_service_reload_test (const DBusString *test_data_dir)
2321 {
2322   DBusString directory;
2323
2324   if (!_dbus_string_init (&directory))
2325     return FALSE;
2326   
2327   if (!_dbus_string_append (&directory, _dbus_get_tmpdir()))
2328     return FALSE;
2329   
2330   if (!_dbus_string_append (&directory, "/dbus-reload-test-") ||
2331       !_dbus_generate_random_ascii (&directory, 6))
2332      {
2333        return FALSE;
2334      }
2335    
2336   /* Do normal tests */
2337   if (!init_service_reload_test (&directory))
2338     _dbus_assert_not_reached ("could not initiate service reload test");
2339  
2340   if (!do_service_reload_test (&directory, FALSE))
2341     ; /* Do nothing? */
2342   
2343   /* Do OOM tests */
2344   if (!init_service_reload_test (&directory))
2345     _dbus_assert_not_reached ("could not initiate service reload test");
2346  
2347   if (!do_service_reload_test (&directory, TRUE))
2348     ; /* Do nothing? */
2349  
2350   /* Cleanup test directory */
2351   if (!cleanup_service_reload_test (&directory))
2352     return FALSE;
2353   
2354   _dbus_string_free (&directory);
2355   
2356   return TRUE;
2357 }
2358
2359 #endif /* DBUS_BUILD_TESTS */