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