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