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