Merge lp:~ubuntu-branches/ubuntu/natty/dbus/natty-201103250227 into lp:ubuntu/natty/dbus

Proposed by James Westby
Status: Work in progress
Proposed branch: lp:~ubuntu-branches/ubuntu/natty/dbus/natty-201103250227
Merge into: lp:ubuntu/natty/dbus
Diff against target: 26449 lines (+23403/-1193) (has conflicts)
85 files modified
.pc/.quilt_patches (+1/-0)
.pc/.quilt_series (+1/-0)
.pc/0001-activation-allow-for-more-variation-than-just-system.patch/bus/activation.c (+2532/-0)
.pc/0001-activation-allow-for-more-variation-than-just-system.patch/bus/bus.c (+1638/-0)
.pc/0001-activation-allow-for-more-variation-than-just-system.patch/bus/bus.h (+128/-0)
.pc/0001-activation-allow-for-more-variation-than-just-system.patch/bus/main.c (+527/-0)
.pc/0002-bus-change-systemd-activation-to-activation-systemd.patch/bus/dbus.service.in (+10/-0)
.pc/0002-bus-change-systemd-activation-to-activation-systemd.patch/bus/main.c (+527/-0)
.pc/0002-bus-change-systemd-activation-to-activation-systemd.patch/doc/dbus-daemon.1.in (+752/-0)
.pc/0003-upstart-add-upstart-as-a-possible-activation-type.patch/bus/bus.h (+134/-0)
.pc/0003-upstart-add-upstart-as-a-possible-activation-type.patch/bus/main.c (+542/-0)
.pc/0003-upstart-add-upstart-as-a-possible-activation-type.patch/doc/dbus-daemon.1.in (+752/-0)
.pc/0004-upstart-add-UpstartJob-to-service-desktop-files.patch/bus/activation.c (+2532/-0)
.pc/0004-upstart-add-UpstartJob-to-service-desktop-files.patch/bus/desktop-file.h (+57/-0)
.pc/0005-activation-implement-upstart-activation.patch/bus/activation.c (+2552/-0)
.pc/00_dbus-quiesce-startup-errors.patch/bus/config-parser.c (+3529/-0)
.pc/applied-patches (+22/-9)
Makefile.am (+10/-0)
Makefile.in (+12/-0)
NEWS (+15/-0)
aclocal.m4 (+9/-0)
bus/Makefile.in (+7/-0)
bus/activation.c (+7/-0)
bus/config-parser.c (+15/-0)
cmake/CMakeLists.txt (+612/-0)
cmake/config.h.cmake (+253/-0)
cmake/cross-compile.sh (+108/-0)
cmake/dbus/CMakeLists.txt (+624/-308)
cmake/test/CMakeLists.txt (+340/-165)
compile (+10/-11)
configure (+186/-2)
configure.in (+14/-1)
dbus/Makefile.in (+7/-0)
dbus/dbus-arch-deps.h.OTHER (+67/-0)
dbus/dbus-sysdeps-unix.c (+28/-0)
dbus/dbus-sysdeps-win.c (+250/-122)
debian/changelog (+1572/-0)
debian/compat (+4/-0)
debian/control (+142/-0)
debian/dbus.install (+17/-0)
debian/dbus.postinst (+62/-0)
debian/dbus.preinst (+29/-0)
debian/libdbus-1-3.install (+4/-0)
debian/libdbus-1-3.symbols (+230/-0)
debian/libdbus-1-dev.install (+3/-0)
debian/patches/0001-activation-allow-for-more-variation-than-just-system.patch (+184/-0)
debian/patches/0002-bus-change-systemd-activation-to-activation-systemd.patch (+79/-0)
debian/patches/0003-upstart-add-upstart-as-a-possible-activation-type.patch (+67/-0)
debian/patches/0004-upstart-add-UpstartJob-to-service-desktop-files.patch (+108/-0)
debian/patches/0005-activation-implement-upstart-activation.patch (+199/-0)
debian/patches/00_dbus-quiesce-startup-errors.patch (+25/-0)
debian/patches/01_no-fatal-warnings.patch (+16/-0)
debian/patches/series (+22/-9)
debian/rules (+65/-0)
depcomp (+36/-136)
doc/Makefile.am (+41/-0)
doc/Makefile.in (+119/-0)
doc/dbus-daemon.1 (+752/-0)
doc/dbus-faq.html (+96/-0)
doc/dbus-specification.html (+170/-0)
doc/dbus-test-plan.html (+8/-0)
install-sh (+172/-369)
missing (+44/-60)
test/Makefile.in (+7/-0)
test/data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoService.service.OTHER (+4/-0)
test/data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoUser.service.OTHER (+4/-0)
test/data/valid-config-files-system/debug-allow-all-fail.conf.OTHER (+17/-0)
test/data/valid-config-files-system/debug-allow-all-pass.conf.OTHER (+17/-0)
test/data/valid-config-files/debug-allow-all-sha1.conf.OTHER (+16/-0)
test/data/valid-config-files/debug-allow-all.conf.OTHER (+15/-0)
test/data/valid-config-files/system.conf.OTHER (+83/-0)
test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteEchoService.service.OTHER (+5/-0)
test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteSegfaultService.service.OTHER (+5/-0)
test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteShellEchoServiceFail.service.OTHER (+5/-0)
test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess.service.OTHER (+5/-0)
test/data/valid-service-files/org.freedesktop.DBus.TestSuite.PrivServer.service.OTHER (+4/-0)
test/data/valid-service-files/org.freedesktop.DBus.TestSuiteEchoService.service.OTHER (+4/-0)
test/data/valid-service-files/org.freedesktop.DBus.TestSuiteForkingEchoService.service.OTHER (+3/-0)
test/data/valid-service-files/org.freedesktop.DBus.TestSuiteSegfaultService.service.OTHER (+4/-0)
test/data/valid-service-files/org.freedesktop.DBus.TestSuiteShellEchoServiceFail.service.OTHER (+4/-0)
test/data/valid-service-files/org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess.service.OTHER (+4/-0)
test/name-test/Makefile.am (+11/-1)
test/name-test/Makefile.in (+12/-0)
test/name-test/run-with-tmp-session-bus.conf (+91/-0)
tools/Makefile.in (+7/-0)
Conflict adding file .pc/0001-activation-allow-for-more-variation-than-just-system.patch.  Moved existing file to .pc/0001-activation-allow-for-more-variation-than-just-system.patch.moved.
Conflict adding file .pc/0002-bus-change-systemd-activation-to-activation-systemd.patch.  Moved existing file to .pc/0002-bus-change-systemd-activation-to-activation-systemd.patch.moved.
Conflict adding file .pc/0003-upstart-add-upstart-as-a-possible-activation-type.patch.  Moved existing file to .pc/0003-upstart-add-upstart-as-a-possible-activation-type.patch.moved.
Conflict adding file .pc/0004-upstart-add-UpstartJob-to-service-desktop-files.patch.  Moved existing file to .pc/0004-upstart-add-UpstartJob-to-service-desktop-files.patch.moved.
Conflict adding file .pc/0005-activation-implement-upstart-activation.patch.  Moved existing file to .pc/0005-activation-implement-upstart-activation.patch.moved.
Text conflict in .pc/applied-patches
Text conflict in Makefile.am
Text conflict in Makefile.in
Text conflict in NEWS
Text conflict in aclocal.m4
Text conflict in bus/Makefile.in
Text conflict in bus/activation.c
Text conflict in bus/config-parser.c
Text conflict in cmake/CMakeLists.txt
Text conflict in cmake/config.h.cmake
Text conflict in cmake/cross-compile.sh
Text conflict in cmake/dbus/CMakeLists.txt
Text conflict in cmake/test/CMakeLists.txt
Text conflict in configure
Text conflict in configure.in
Text conflict in dbus/Makefile.in
Contents conflict in dbus/dbus-arch-deps.h
Text conflict in dbus/dbus-sysdeps-unix.c
Text conflict in dbus/dbus-sysdeps-win.c
Text conflict in debian/changelog
Text conflict in debian/compat
Text conflict in debian/control
Text conflict in debian/dbus.install
Text conflict in debian/dbus.postinst
Text conflict in debian/libdbus-1-3.install
Text conflict in debian/libdbus-1-3.symbols
Conflict adding file debian/patches/0001-activation-allow-for-more-variation-than-just-system.patch.  Moved existing file to debian/patches/0001-activation-allow-for-more-variation-than-just-system.patch.moved.
Conflict adding file debian/patches/0002-bus-change-systemd-activation-to-activation-systemd.patch.  Moved existing file to debian/patches/0002-bus-change-systemd-activation-to-activation-systemd.patch.moved.
Conflict adding file debian/patches/0003-upstart-add-upstart-as-a-possible-activation-type.patch.  Moved existing file to debian/patches/0003-upstart-add-upstart-as-a-possible-activation-type.patch.moved.
Conflict adding file debian/patches/0004-upstart-add-UpstartJob-to-service-desktop-files.patch.  Moved existing file to debian/patches/0004-upstart-add-UpstartJob-to-service-desktop-files.patch.moved.
Conflict adding file debian/patches/0005-activation-implement-upstart-activation.patch.  Moved existing file to debian/patches/0005-activation-implement-upstart-activation.patch.moved.
Text conflict in debian/patches/01_no-fatal-warnings.patch
Text conflict in debian/patches/series
Text conflict in debian/rules
Text conflict in doc/Makefile.am
Text conflict in doc/Makefile.in
Text conflict in doc/dbus-faq.html
Text conflict in doc/dbus-specification.html
Text conflict in doc/dbus-test-plan.html
Text conflict in test/Makefile.in
Contents conflict in test/data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoService.service
Contents conflict in test/data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoUser.service
Contents conflict in test/data/valid-config-files-system/debug-allow-all-fail.conf
Contents conflict in test/data/valid-config-files-system/debug-allow-all-pass.conf
Contents conflict in test/data/valid-config-files/debug-allow-all-sha1.conf
Contents conflict in test/data/valid-config-files/debug-allow-all.conf
Contents conflict in test/data/valid-config-files/system.conf
Contents conflict in test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteEchoService.service
Contents conflict in test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteSegfaultService.service
Contents conflict in test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteShellEchoServiceFail.service
Contents conflict in test/data/valid-service-files-system/org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess.service
Contents conflict in test/data/valid-service-files/org.freedesktop.DBus.TestSuite.PrivServer.service
Contents conflict in test/data/valid-service-files/org.freedesktop.DBus.TestSuiteEchoService.service
Contents conflict in test/data/valid-service-files/org.freedesktop.DBus.TestSuiteForkingEchoService.service
Contents conflict in test/data/valid-service-files/org.freedesktop.DBus.TestSuiteSegfaultService.service
Contents conflict in test/data/valid-service-files/org.freedesktop.DBus.TestSuiteShellEchoServiceFail.service
Contents conflict in test/data/valid-service-files/org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess.service
Text conflict in test/name-test/Makefile.am
Text conflict in test/name-test/Makefile.in
Text conflict in tools/Makefile.in
To merge this branch: bzr merge lp:~ubuntu-branches/ubuntu/natty/dbus/natty-201103250227
Reviewer Review Type Date Requested Status
Ubuntu branches Pending
Review via email: mp+55073@code.launchpad.net

Description of the change

The package history in the archive and the history in the bzr branch differ. As the archive is authoritative the history of lp:ubuntu/natty/dbus now reflects that and the old bzr branch has been pushed to lp:~ubuntu-branches/ubuntu/natty/dbus/natty-201103250227. A merge should be performed if necessary.

To post a comment you must log in.

Unmerged revisions

99. By Scott James Remnant (Canonical)

merge to fix

98. By Scott James Remnant (Canonical)

releasing version 1.4.1-0ubuntu2

97. By Scott James Remnant (Canonical)

Switch to using Upstart activation for the system bus.

96. By Scott James Remnant (Canonical)

Apply patches to implement Upstart service activation.

95. By Scott James Remnant (Canonical)

remove previous patch from quilt's brain

94. By Scott James Remnant (Canonical)

releasing version 1.4.1-0ubuntu1

93. By Scott James Remnant (Canonical)

Dropped patch from 1.4.0-0ubuntu2 since it's now included upstream

92. By Scott James Remnant (Canonical)

Update changelog

91. By Scott James Remnant (Canonical)

New upstream release.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file '.pc/.quilt_patches'
2--- .pc/.quilt_patches 1970-01-01 00:00:00 +0000
3+++ .pc/.quilt_patches 2011-03-28 07:17:28 +0000
4@@ -0,0 +1,1 @@
5+debian/patches
6
7=== added file '.pc/.quilt_series'
8--- .pc/.quilt_series 1970-01-01 00:00:00 +0000
9+++ .pc/.quilt_series 2011-03-28 07:17:28 +0000
10@@ -0,0 +1,1 @@
11+series
12
13=== added directory '.pc/0001-activation-allow-for-more-variation-than-just-system.patch'
14=== renamed directory '.pc/0001-activation-allow-for-more-variation-than-just-system.patch' => '.pc/0001-activation-allow-for-more-variation-than-just-system.patch.moved'
15=== added file '.pc/0001-activation-allow-for-more-variation-than-just-system.patch/.timestamp'
16=== added directory '.pc/0001-activation-allow-for-more-variation-than-just-system.patch/bus'
17=== added file '.pc/0001-activation-allow-for-more-variation-than-just-system.patch/bus/activation.c'
18--- .pc/0001-activation-allow-for-more-variation-than-just-system.patch/bus/activation.c 1970-01-01 00:00:00 +0000
19+++ .pc/0001-activation-allow-for-more-variation-than-just-system.patch/bus/activation.c 2011-03-28 07:17:28 +0000
20@@ -0,0 +1,2532 @@
21+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
22+/* activation.c Activation of services
23+ *
24+ * Copyright (C) 2003 CodeFactory AB
25+ * Copyright (C) 2003 Red Hat, Inc.
26+ * Copyright (C) 2004 Imendio HB
27+ *
28+ * Licensed under the Academic Free License version 2.1
29+ *
30+ * This program is free software; you can redistribute it and/or modify
31+ * it under the terms of the GNU General Public License as published by
32+ * the Free Software Foundation; either version 2 of the License, or
33+ * (at your option) any later version.
34+ *
35+ * This program is distributed in the hope that it will be useful,
36+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
37+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38+ * GNU General Public License for more details.
39+ *
40+ * You should have received a copy of the GNU General Public License
41+ * along with this program; if not, write to the Free Software
42+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
43+ *
44+ */
45+
46+#include <config.h>
47+#include "activation.h"
48+#include "activation-exit-codes.h"
49+#include "desktop-file.h"
50+#include "dispatch.h"
51+#include "services.h"
52+#include "test.h"
53+#include "utils.h"
54+#include <dbus/dbus-internals.h>
55+#include <dbus/dbus-hash.h>
56+#include <dbus/dbus-list.h>
57+#include <dbus/dbus-shell.h>
58+#include <dbus/dbus-spawn.h>
59+#include <dbus/dbus-timeout.h>
60+#include <dbus/dbus-sysdeps.h>
61+#ifdef HAVE_ERRNO_H
62+#include <errno.h>
63+#endif
64+
65+struct BusActivation
66+{
67+ int refcount;
68+ DBusHashTable *entries;
69+ DBusHashTable *pending_activations;
70+ char *server_address;
71+ BusContext *context;
72+ int n_pending_activations; /**< This is in fact the number of BusPendingActivationEntry,
73+ * i.e. number of pending activation requests, not pending
74+ * activations per se
75+ */
76+ DBusHashTable *directories;
77+ DBusHashTable *environment;
78+};
79+
80+typedef struct
81+{
82+ int refcount;
83+ char *dir_c;
84+ DBusHashTable *entries;
85+} BusServiceDirectory;
86+
87+typedef struct
88+{
89+ int refcount;
90+ char *name;
91+ char *exec;
92+ char *user;
93+ char *systemd_service;
94+ unsigned long mtime;
95+ BusServiceDirectory *s_dir;
96+ char *filename;
97+} BusActivationEntry;
98+
99+typedef struct BusPendingActivationEntry BusPendingActivationEntry;
100+
101+struct BusPendingActivationEntry
102+{
103+ DBusMessage *activation_message;
104+ DBusConnection *connection;
105+
106+ dbus_bool_t auto_activation;
107+};
108+
109+typedef struct
110+{
111+ int refcount;
112+ BusActivation *activation;
113+ char *service_name;
114+ char *exec;
115+ char *systemd_service;
116+ DBusList *entries;
117+ int n_entries;
118+ DBusBabysitter *babysitter;
119+ DBusTimeout *timeout;
120+ unsigned int timeout_added : 1;
121+} BusPendingActivation;
122+
123+#if 0
124+static BusServiceDirectory *
125+bus_service_directory_ref (BusServiceDirectory *dir)
126+{
127+ _dbus_assert (dir->refcount);
128+
129+ dir->refcount++;
130+
131+ return dir;
132+}
133+#endif
134+
135+static void
136+bus_service_directory_unref (BusServiceDirectory *dir)
137+{
138+ if (dir == NULL)
139+ return;
140+
141+ _dbus_assert (dir->refcount > 0);
142+ dir->refcount--;
143+
144+ if (dir->refcount > 0)
145+ return;
146+
147+ if (dir->entries)
148+ _dbus_hash_table_unref (dir->entries);
149+
150+ dbus_free (dir->dir_c);
151+ dbus_free (dir);
152+}
153+
154+static void
155+bus_pending_activation_entry_free (BusPendingActivationEntry *entry)
156+{
157+ if (entry->activation_message)
158+ dbus_message_unref (entry->activation_message);
159+
160+ if (entry->connection)
161+ dbus_connection_unref (entry->connection);
162+
163+ dbus_free (entry);
164+}
165+
166+static void
167+handle_timeout_callback (DBusTimeout *timeout,
168+ void *data)
169+{
170+ BusPendingActivation *pending_activation = data;
171+
172+ while (!dbus_timeout_handle (pending_activation->timeout))
173+ _dbus_wait_for_memory ();
174+}
175+
176+static BusPendingActivation *
177+bus_pending_activation_ref (BusPendingActivation *pending_activation)
178+{
179+ _dbus_assert (pending_activation->refcount > 0);
180+ pending_activation->refcount += 1;
181+
182+ return pending_activation;
183+}
184+
185+static void
186+bus_pending_activation_unref (BusPendingActivation *pending_activation)
187+{
188+ DBusList *link;
189+
190+ if (pending_activation == NULL) /* hash table requires this */
191+ return;
192+
193+ _dbus_assert (pending_activation->refcount > 0);
194+ pending_activation->refcount -= 1;
195+
196+ if (pending_activation->refcount > 0)
197+ return;
198+
199+ if (pending_activation->timeout_added)
200+ {
201+ _dbus_loop_remove_timeout (bus_context_get_loop (pending_activation->activation->context),
202+ pending_activation->timeout,
203+ handle_timeout_callback, pending_activation);
204+ pending_activation->timeout_added = FALSE;
205+ }
206+
207+ if (pending_activation->timeout)
208+ _dbus_timeout_unref (pending_activation->timeout);
209+
210+ if (pending_activation->babysitter)
211+ {
212+ if (!_dbus_babysitter_set_watch_functions (pending_activation->babysitter,
213+ NULL, NULL, NULL,
214+ pending_activation->babysitter,
215+ NULL))
216+ _dbus_assert_not_reached ("setting watch functions to NULL failed");
217+
218+ _dbus_babysitter_unref (pending_activation->babysitter);
219+ }
220+
221+ dbus_free (pending_activation->service_name);
222+ dbus_free (pending_activation->exec);
223+ dbus_free (pending_activation->systemd_service);
224+
225+ link = _dbus_list_get_first_link (&pending_activation->entries);
226+
227+ while (link != NULL)
228+ {
229+ BusPendingActivationEntry *entry = link->data;
230+
231+ bus_pending_activation_entry_free (entry);
232+
233+ link = _dbus_list_get_next_link (&pending_activation->entries, link);
234+ }
235+ _dbus_list_clear (&pending_activation->entries);
236+
237+ pending_activation->activation->n_pending_activations -=
238+ pending_activation->n_entries;
239+
240+ _dbus_assert (pending_activation->activation->n_pending_activations >= 0);
241+
242+ dbus_free (pending_activation);
243+}
244+
245+static BusActivationEntry *
246+bus_activation_entry_ref (BusActivationEntry *entry)
247+{
248+ _dbus_assert (entry->refcount > 0);
249+ entry->refcount++;
250+
251+ return entry;
252+}
253+
254+static void
255+bus_activation_entry_unref (BusActivationEntry *entry)
256+{
257+ if (entry == NULL) /* hash table requires this */
258+ return;
259+
260+ _dbus_assert (entry->refcount > 0);
261+ entry->refcount--;
262+
263+ if (entry->refcount > 0)
264+ return;
265+
266+ dbus_free (entry->name);
267+ dbus_free (entry->exec);
268+ dbus_free (entry->user);
269+ dbus_free (entry->filename);
270+ dbus_free (entry->systemd_service);
271+
272+ dbus_free (entry);
273+}
274+
275+static dbus_bool_t
276+update_desktop_file_entry (BusActivation *activation,
277+ BusServiceDirectory *s_dir,
278+ DBusString *filename,
279+ BusDesktopFile *desktop_file,
280+ DBusError *error)
281+{
282+ char *name, *exec, *user, *exec_tmp, *systemd_service;
283+ BusActivationEntry *entry;
284+ DBusStat stat_buf;
285+ DBusString file_path;
286+ DBusError tmp_error;
287+
288+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
289+
290+ name = NULL;
291+ exec = NULL;
292+ user = NULL;
293+ exec_tmp = NULL;
294+ entry = NULL;
295+ systemd_service = NULL;
296+
297+ dbus_error_init (&tmp_error);
298+
299+ if (!_dbus_string_init (&file_path))
300+ {
301+ BUS_SET_OOM (error);
302+ return FALSE;
303+ }
304+
305+ if (!_dbus_string_append (&file_path, s_dir->dir_c) ||
306+ !_dbus_concat_dir_and_file (&file_path, filename))
307+ {
308+ BUS_SET_OOM (error);
309+ goto failed;
310+ }
311+
312+ if (!_dbus_stat (&file_path, &stat_buf, NULL))
313+ {
314+ dbus_set_error (error, DBUS_ERROR_FAILED,
315+ "Can't stat the service file\n");
316+ goto failed;
317+ }
318+
319+ if (!bus_desktop_file_get_string (desktop_file,
320+ DBUS_SERVICE_SECTION,
321+ DBUS_SERVICE_NAME,
322+ &name,
323+ error))
324+ goto failed;
325+
326+ if (!bus_desktop_file_get_string (desktop_file,
327+ DBUS_SERVICE_SECTION,
328+ DBUS_SERVICE_EXEC,
329+ &exec_tmp,
330+ error))
331+ goto failed;
332+
333+ /* user is not _required_ unless we are using system activation */
334+ if (!bus_desktop_file_get_string (desktop_file,
335+ DBUS_SERVICE_SECTION,
336+ DBUS_SERVICE_USER,
337+ &user, &tmp_error))
338+ {
339+ _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
340+ /* if we got OOM, then exit */
341+ if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
342+ {
343+ dbus_move_error (&tmp_error, error);
344+ goto failed;
345+ }
346+ else
347+ {
348+ /* if we have error because we didn't find anything then continue */
349+ dbus_error_free (&tmp_error);
350+ dbus_free (user);
351+ user = NULL;
352+ }
353+ }
354+ _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
355+
356+ /* systemd service is never required */
357+ if (!bus_desktop_file_get_string (desktop_file,
358+ DBUS_SERVICE_SECTION,
359+ DBUS_SERVICE_SYSTEMD_SERVICE,
360+ &systemd_service, &tmp_error))
361+ {
362+ _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
363+ /* if we got OOM, then exit */
364+ if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
365+ {
366+ dbus_move_error (&tmp_error, error);
367+ goto failed;
368+ }
369+ else
370+ {
371+ /* if we have error because we didn't find anything then continue */
372+ dbus_error_free (&tmp_error);
373+ dbus_free (systemd_service);
374+ systemd_service = NULL;
375+ }
376+ }
377+
378+ _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
379+
380+ entry = _dbus_hash_table_lookup_string (s_dir->entries,
381+ _dbus_string_get_const_data (filename));
382+
383+ exec = strdup (_dbus_replace_install_prefix (exec_tmp));
384+
385+ if (entry == NULL) /* New file */
386+ {
387+ /* FIXME we need a better-defined algorithm for which service file to
388+ * pick than "whichever one is first in the directory listing"
389+ */
390+ if (_dbus_hash_table_lookup_string (activation->entries, name))
391+ {
392+ dbus_set_error (error, DBUS_ERROR_FAILED,
393+ "Service %s already exists in activation entry list\n", name);
394+ goto failed;
395+ }
396+
397+ entry = dbus_new0 (BusActivationEntry, 1);
398+ if (entry == NULL)
399+ {
400+ BUS_SET_OOM (error);
401+ goto failed;
402+ }
403+
404+ entry->name = name;
405+ entry->exec = exec;
406+ entry->user = user;
407+ entry->systemd_service = systemd_service;
408+ entry->refcount = 1;
409+
410+ entry->s_dir = s_dir;
411+ entry->filename = _dbus_strdup (_dbus_string_get_const_data (filename));
412+ if (!entry->filename)
413+ {
414+ BUS_SET_OOM (error);
415+ goto failed;
416+ }
417+
418+ if (!_dbus_hash_table_insert_string (activation->entries, entry->name, bus_activation_entry_ref (entry)))
419+ {
420+ BUS_SET_OOM (error);
421+ goto failed;
422+ }
423+
424+ if (!_dbus_hash_table_insert_string (s_dir->entries, entry->filename, bus_activation_entry_ref (entry)))
425+ {
426+ /* Revert the insertion in the entries table */
427+ _dbus_hash_table_remove_string (activation->entries, entry->name);
428+ BUS_SET_OOM (error);
429+ goto failed;
430+ }
431+
432+ _dbus_verbose ("Added \"%s\" to list of services\n", entry->name);
433+ }
434+ else /* Just update the entry */
435+ {
436+ bus_activation_entry_ref (entry);
437+ _dbus_hash_table_remove_string (activation->entries, entry->name);
438+
439+ if (_dbus_hash_table_lookup_string (activation->entries, name))
440+ {
441+ _dbus_verbose ("The new service name \"%s\" of service file \"%s\" already in cache, ignoring\n",
442+ name, _dbus_string_get_const_data (&file_path));
443+ goto failed;
444+ }
445+
446+ dbus_free (entry->name);
447+ dbus_free (entry->exec);
448+ dbus_free (entry->user);
449+ dbus_free (entry->systemd_service);
450+ entry->systemd_service = systemd_service;
451+ entry->name = name;
452+ entry->exec = exec;
453+ entry->user = user;
454+ if (!_dbus_hash_table_insert_string (activation->entries,
455+ entry->name, bus_activation_entry_ref(entry)))
456+ {
457+ BUS_SET_OOM (error);
458+ /* Also remove path to entries hash since we want this in sync with
459+ * the entries hash table */
460+ _dbus_hash_table_remove_string (entry->s_dir->entries,
461+ entry->filename);
462+ bus_activation_entry_unref (entry);
463+ return FALSE;
464+ }
465+ }
466+
467+ entry->mtime = stat_buf.mtime;
468+
469+ _dbus_string_free (&file_path);
470+ bus_activation_entry_unref (entry);
471+
472+ return TRUE;
473+
474+failed:
475+ dbus_free (name);
476+ dbus_free (exec_tmp);
477+ dbus_free (user);
478+ dbus_free (systemd_service);
479+ _dbus_string_free (&file_path);
480+
481+ if (entry)
482+ bus_activation_entry_unref (entry);
483+
484+ return FALSE;
485+}
486+
487+static dbus_bool_t
488+check_service_file (BusActivation *activation,
489+ BusActivationEntry *entry,
490+ BusActivationEntry **updated_entry,
491+ DBusError *error)
492+{
493+ DBusStat stat_buf;
494+ dbus_bool_t retval;
495+ BusActivationEntry *tmp_entry;
496+ DBusString file_path;
497+ DBusString filename;
498+
499+ retval = TRUE;
500+ tmp_entry = entry;
501+
502+ _dbus_string_init_const (&filename, entry->filename);
503+
504+ if (!_dbus_string_init (&file_path))
505+ {
506+ BUS_SET_OOM (error);
507+ return FALSE;
508+ }
509+
510+ if (!_dbus_string_append (&file_path, entry->s_dir->dir_c) ||
511+ !_dbus_concat_dir_and_file (&file_path, &filename))
512+ {
513+ BUS_SET_OOM (error);
514+ retval = FALSE;
515+ goto out;
516+ }
517+
518+ if (!_dbus_stat (&file_path, &stat_buf, NULL))
519+ {
520+ _dbus_verbose ("****** Can't stat file \"%s\", removing from cache\n",
521+ _dbus_string_get_const_data (&file_path));
522+
523+ _dbus_hash_table_remove_string (activation->entries, entry->name);
524+ _dbus_hash_table_remove_string (entry->s_dir->entries, entry->filename);
525+
526+ tmp_entry = NULL;
527+ retval = TRUE;
528+ goto out;
529+ }
530+ else
531+ {
532+ if (stat_buf.mtime > entry->mtime)
533+ {
534+ BusDesktopFile *desktop_file;
535+ DBusError tmp_error;
536+
537+ dbus_error_init (&tmp_error);
538+
539+ desktop_file = bus_desktop_file_load (&file_path, &tmp_error);
540+ if (desktop_file == NULL)
541+ {
542+ _dbus_verbose ("Could not load %s: %s\n",
543+ _dbus_string_get_const_data (&file_path),
544+ tmp_error.message);
545+ if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
546+ {
547+ dbus_move_error (&tmp_error, error);
548+ retval = FALSE;
549+ goto out;
550+ }
551+ dbus_error_free (&tmp_error);
552+ retval = TRUE;
553+ goto out;
554+ }
555+
556+ /* @todo We can return OOM or a DBUS_ERROR_FAILED error
557+ * Handle these both better
558+ */
559+ if (!update_desktop_file_entry (activation, entry->s_dir, &filename, desktop_file, &tmp_error))
560+ {
561+ bus_desktop_file_free (desktop_file);
562+ if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
563+ {
564+ dbus_move_error (&tmp_error, error);
565+ retval = FALSE;
566+ goto out;
567+ }
568+ dbus_error_free (&tmp_error);
569+ retval = TRUE;
570+ goto out;
571+ }
572+
573+ bus_desktop_file_free (desktop_file);
574+ retval = TRUE;
575+ }
576+ }
577+
578+out:
579+ _dbus_string_free (&file_path);
580+
581+ if (updated_entry != NULL)
582+ *updated_entry = tmp_entry;
583+ return retval;
584+}
585+
586+
587+/* warning: this doesn't fully "undo" itself on failure, i.e. doesn't strip
588+ * hash entries it already added.
589+ */
590+static dbus_bool_t
591+update_directory (BusActivation *activation,
592+ BusServiceDirectory *s_dir,
593+ DBusError *error)
594+{
595+ DBusDirIter *iter;
596+ DBusString dir, filename;
597+ BusDesktopFile *desktop_file;
598+ DBusError tmp_error;
599+ dbus_bool_t retval;
600+ BusActivationEntry *entry;
601+ DBusString full_path;
602+
603+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
604+
605+ iter = NULL;
606+ desktop_file = NULL;
607+
608+ _dbus_string_init_const (&dir, s_dir->dir_c);
609+
610+ if (!_dbus_string_init (&filename))
611+ {
612+ BUS_SET_OOM (error);
613+ return FALSE;
614+ }
615+
616+ if (!_dbus_string_init (&full_path))
617+ {
618+ BUS_SET_OOM (error);
619+ _dbus_string_free (&filename);
620+ return FALSE;
621+ }
622+
623+ retval = FALSE;
624+
625+ /* from this point it's safe to "goto out" */
626+
627+ iter = _dbus_directory_open (&dir, error);
628+ if (iter == NULL)
629+ {
630+ _dbus_verbose ("Failed to open directory %s: %s\n",
631+ s_dir->dir_c,
632+ error ? error->message : "unknown");
633+ goto out;
634+ }
635+
636+ /* Now read the files */
637+ dbus_error_init (&tmp_error);
638+ while (_dbus_directory_get_next_file (iter, &filename, &tmp_error))
639+ {
640+ _dbus_assert (!dbus_error_is_set (&tmp_error));
641+
642+ _dbus_string_set_length (&full_path, 0);
643+
644+ if (!_dbus_string_ends_with_c_str (&filename, ".service"))
645+ {
646+ _dbus_verbose ("Skipping non-.service file %s\n",
647+ _dbus_string_get_const_data (&filename));
648+ continue;
649+ }
650+
651+ entry = _dbus_hash_table_lookup_string (s_dir->entries, _dbus_string_get_const_data (&filename));
652+ if (entry) /* Already has this service file in the cache */
653+ {
654+ if (!check_service_file (activation, entry, NULL, error))
655+ goto out;
656+
657+ continue;
658+ }
659+
660+ if (!_dbus_string_append (&full_path, s_dir->dir_c) ||
661+ !_dbus_concat_dir_and_file (&full_path, &filename))
662+ {
663+ BUS_SET_OOM (error);
664+ goto out;
665+ }
666+
667+ /* New file */
668+ desktop_file = bus_desktop_file_load (&full_path, &tmp_error);
669+ if (desktop_file == NULL)
670+ {
671+ _dbus_verbose ("Could not load %s: %s\n",
672+ _dbus_string_get_const_data (&full_path),
673+ tmp_error.message);
674+
675+ if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
676+ {
677+ dbus_move_error (&tmp_error, error);
678+ goto out;
679+ }
680+
681+ dbus_error_free (&tmp_error);
682+ continue;
683+ }
684+
685+ /* @todo We can return OOM or a DBUS_ERROR_FAILED error
686+ * Handle these both better
687+ */
688+ if (!update_desktop_file_entry (activation, s_dir, &filename, desktop_file, &tmp_error))
689+ {
690+ bus_desktop_file_free (desktop_file);
691+ desktop_file = NULL;
692+
693+ _dbus_verbose ("Could not add %s to activation entry list: %s\n",
694+ _dbus_string_get_const_data (&full_path), tmp_error.message);
695+
696+ if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
697+ {
698+ dbus_move_error (&tmp_error, error);
699+ goto out;
700+ }
701+
702+ dbus_error_free (&tmp_error);
703+ continue;
704+ }
705+ else
706+ {
707+ bus_desktop_file_free (desktop_file);
708+ desktop_file = NULL;
709+ continue;
710+ }
711+ }
712+
713+ if (dbus_error_is_set (&tmp_error))
714+ {
715+ dbus_move_error (&tmp_error, error);
716+ goto out;
717+ }
718+
719+ retval = TRUE;
720+
721+ out:
722+ if (!retval)
723+ _DBUS_ASSERT_ERROR_IS_SET (error);
724+ else
725+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
726+
727+ if (iter != NULL)
728+ _dbus_directory_close (iter);
729+ _dbus_string_free (&filename);
730+ _dbus_string_free (&full_path);
731+
732+ return retval;
733+}
734+
735+static dbus_bool_t
736+populate_environment (BusActivation *activation)
737+{
738+ DBusString key;
739+ DBusString value;
740+ int i;
741+ char **environment;
742+ dbus_bool_t retval = FALSE;
743+
744+ environment = _dbus_get_environment ();
745+
746+ if (environment == NULL)
747+ return FALSE;
748+
749+ if (!_dbus_string_init (&key))
750+ {
751+ dbus_free_string_array (environment);
752+ return FALSE;
753+ }
754+
755+ if (!_dbus_string_init (&value))
756+ {
757+ _dbus_string_free (&key);
758+ dbus_free_string_array (environment);
759+ return FALSE;
760+ }
761+
762+ for (i = 0; environment[i] != NULL; i++)
763+ {
764+ if (!_dbus_string_append (&key, environment[i]))
765+ break;
766+
767+ if (_dbus_string_split_on_byte (&key, '=', &value))
768+ {
769+ char *hash_key, *hash_value;
770+
771+ if (!_dbus_string_steal_data (&key, &hash_key))
772+ break;
773+
774+ if (!_dbus_string_steal_data (&value, &hash_value))
775+ break;
776+
777+ if (!_dbus_hash_table_insert_string (activation->environment,
778+ hash_key, hash_value))
779+ break;
780+ }
781+ _dbus_string_set_length (&key, 0);
782+ _dbus_string_set_length (&value, 0);
783+ }
784+
785+ if (environment[i] != NULL)
786+ goto out;
787+
788+ retval = TRUE;
789+out:
790+
791+ _dbus_string_free (&key);
792+ _dbus_string_free (&value);
793+ dbus_free_string_array (environment);
794+
795+ return retval;
796+}
797+
798+dbus_bool_t
799+bus_activation_reload (BusActivation *activation,
800+ const DBusString *address,
801+ DBusList **directories,
802+ DBusError *error)
803+{
804+ DBusList *link;
805+ char *dir;
806+
807+ if (activation->server_address != NULL)
808+ dbus_free (activation->server_address);
809+ if (!_dbus_string_copy_data (address, &activation->server_address))
810+ {
811+ BUS_SET_OOM (error);
812+ goto failed;
813+ }
814+
815+ if (activation->entries != NULL)
816+ _dbus_hash_table_unref (activation->entries);
817+ activation->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
818+ (DBusFreeFunction)bus_activation_entry_unref);
819+ if (activation->entries == NULL)
820+ {
821+ BUS_SET_OOM (error);
822+ goto failed;
823+ }
824+
825+ if (activation->directories != NULL)
826+ _dbus_hash_table_unref (activation->directories);
827+ activation->directories = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
828+ (DBusFreeFunction)bus_service_directory_unref);
829+
830+ if (activation->directories == NULL)
831+ {
832+ BUS_SET_OOM (error);
833+ goto failed;
834+ }
835+
836+ link = _dbus_list_get_first_link (directories);
837+ while (link != NULL)
838+ {
839+ BusServiceDirectory *s_dir;
840+
841+ dir = _dbus_strdup ((const char *) link->data);
842+ if (!dir)
843+ {
844+ BUS_SET_OOM (error);
845+ goto failed;
846+ }
847+
848+ s_dir = dbus_new0 (BusServiceDirectory, 1);
849+ if (!s_dir)
850+ {
851+ dbus_free (dir);
852+ BUS_SET_OOM (error);
853+ goto failed;
854+ }
855+
856+ s_dir->refcount = 1;
857+ s_dir->dir_c = dir;
858+
859+ s_dir->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
860+ (DBusFreeFunction)bus_activation_entry_unref);
861+
862+ if (!s_dir->entries)
863+ {
864+ bus_service_directory_unref (s_dir);
865+ BUS_SET_OOM (error);
866+ goto failed;
867+ }
868+
869+ if (!_dbus_hash_table_insert_string (activation->directories, s_dir->dir_c, s_dir))
870+ {
871+ bus_service_directory_unref (s_dir);
872+ BUS_SET_OOM (error);
873+ goto failed;
874+ }
875+
876+ /* only fail on OOM, it is ok if we can't read the directory */
877+ if (!update_directory (activation, s_dir, error))
878+ {
879+ if (dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY))
880+ goto failed;
881+ else
882+ dbus_error_free (error);
883+ }
884+
885+ link = _dbus_list_get_next_link (directories, link);
886+ }
887+
888+ return TRUE;
889+ failed:
890+ return FALSE;
891+}
892+
893+BusActivation*
894+bus_activation_new (BusContext *context,
895+ const DBusString *address,
896+ DBusList **directories,
897+ DBusError *error)
898+{
899+ BusActivation *activation;
900+ DBusList *link;
901+ char *dir;
902+
903+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
904+
905+ activation = dbus_new0 (BusActivation, 1);
906+ if (activation == NULL)
907+ {
908+ BUS_SET_OOM (error);
909+ return NULL;
910+ }
911+
912+ activation->refcount = 1;
913+ activation->context = context;
914+ activation->n_pending_activations = 0;
915+
916+ if (!bus_activation_reload (activation, address, directories, error))
917+ goto failed;
918+
919+ /* Initialize this hash table once, we don't want to lose pending
920+ * activations on reload. */
921+ activation->pending_activations = _dbus_hash_table_new (DBUS_HASH_STRING, NULL,
922+ (DBusFreeFunction)bus_pending_activation_unref);
923+
924+ if (activation->pending_activations == NULL)
925+ {
926+ BUS_SET_OOM (error);
927+ goto failed;
928+ }
929+
930+ activation->environment = _dbus_hash_table_new (DBUS_HASH_STRING,
931+ (DBusFreeFunction) dbus_free,
932+ (DBusFreeFunction) dbus_free);
933+
934+ if (activation->environment == NULL)
935+ {
936+ BUS_SET_OOM (error);
937+ goto failed;
938+ }
939+
940+ if (!populate_environment (activation))
941+ {
942+ BUS_SET_OOM (error);
943+ goto failed;
944+ }
945+
946+ return activation;
947+
948+ failed:
949+ bus_activation_unref (activation);
950+ return NULL;
951+}
952+
953+BusActivation *
954+bus_activation_ref (BusActivation *activation)
955+{
956+ _dbus_assert (activation->refcount > 0);
957+
958+ activation->refcount += 1;
959+
960+ return activation;
961+}
962+
963+void
964+bus_activation_unref (BusActivation *activation)
965+{
966+ _dbus_assert (activation->refcount > 0);
967+
968+ activation->refcount -= 1;
969+
970+ if (activation->refcount > 0)
971+ return;
972+
973+ dbus_free (activation->server_address);
974+ if (activation->entries)
975+ _dbus_hash_table_unref (activation->entries);
976+ if (activation->pending_activations)
977+ _dbus_hash_table_unref (activation->pending_activations);
978+ if (activation->directories)
979+ _dbus_hash_table_unref (activation->directories);
980+ if (activation->environment)
981+ _dbus_hash_table_unref (activation->environment);
982+
983+ dbus_free (activation);
984+}
985+
986+static dbus_bool_t
987+add_bus_environment (BusActivation *activation,
988+ DBusError *error)
989+{
990+ const char *type;
991+
992+ if (!bus_activation_set_environment_variable (activation,
993+ "DBUS_STARTER_ADDRESS",
994+ activation->server_address,
995+ error))
996+ return FALSE;
997+
998+ type = bus_context_get_type (activation->context);
999+ if (type != NULL)
1000+ {
1001+ if (!bus_activation_set_environment_variable (activation,
1002+ "DBUS_STARTER_BUS_TYPE", type,
1003+ error))
1004+ return FALSE;
1005+
1006+ if (strcmp (type, "session") == 0)
1007+ {
1008+ if (!bus_activation_set_environment_variable (activation,
1009+ "DBUS_SESSION_BUS_ADDRESS",
1010+ activation->server_address,
1011+ error))
1012+ return FALSE;
1013+ }
1014+ else if (strcmp (type, "system") == 0)
1015+ {
1016+ if (!bus_activation_set_environment_variable (activation,
1017+ "DBUS_SYSTEM_BUS_ADDRESS",
1018+ activation->server_address,
1019+ error))
1020+ return FALSE;
1021+ }
1022+ }
1023+
1024+ return TRUE;
1025+}
1026+
1027+typedef struct
1028+{
1029+ BusPendingActivation *pending_activation;
1030+ DBusPreallocatedHash *hash_entry;
1031+} RestorePendingData;
1032+
1033+static void
1034+restore_pending (void *data)
1035+{
1036+ RestorePendingData *d = data;
1037+
1038+ _dbus_assert (d->pending_activation != NULL);
1039+ _dbus_assert (d->hash_entry != NULL);
1040+
1041+ _dbus_verbose ("Restoring pending activation for service %s, has timeout = %d\n",
1042+ d->pending_activation->service_name,
1043+ d->pending_activation->timeout_added);
1044+
1045+ _dbus_hash_table_insert_string_preallocated (d->pending_activation->activation->pending_activations,
1046+ d->hash_entry,
1047+ d->pending_activation->service_name, d->pending_activation);
1048+
1049+ bus_pending_activation_ref (d->pending_activation);
1050+
1051+ d->hash_entry = NULL;
1052+}
1053+
1054+static void
1055+free_pending_restore_data (void *data)
1056+{
1057+ RestorePendingData *d = data;
1058+
1059+ if (d->hash_entry)
1060+ _dbus_hash_table_free_preallocated_entry (d->pending_activation->activation->pending_activations,
1061+ d->hash_entry);
1062+
1063+ bus_pending_activation_unref (d->pending_activation);
1064+
1065+ dbus_free (d);
1066+}
1067+
1068+static dbus_bool_t
1069+add_restore_pending_to_transaction (BusTransaction *transaction,
1070+ BusPendingActivation *pending_activation)
1071+{
1072+ RestorePendingData *d;
1073+
1074+ d = dbus_new (RestorePendingData, 1);
1075+ if (d == NULL)
1076+ return FALSE;
1077+
1078+ d->pending_activation = pending_activation;
1079+ d->hash_entry = _dbus_hash_table_preallocate_entry (d->pending_activation->activation->pending_activations);
1080+
1081+ bus_pending_activation_ref (d->pending_activation);
1082+
1083+ if (d->hash_entry == NULL ||
1084+ !bus_transaction_add_cancel_hook (transaction, restore_pending, d,
1085+ free_pending_restore_data))
1086+ {
1087+ free_pending_restore_data (d);
1088+ return FALSE;
1089+ }
1090+
1091+ _dbus_verbose ("Saved pending activation to be restored if the transaction fails\n");
1092+
1093+ return TRUE;
1094+}
1095+
1096+dbus_bool_t
1097+bus_activation_service_created (BusActivation *activation,
1098+ const char *service_name,
1099+ BusTransaction *transaction,
1100+ DBusError *error)
1101+{
1102+ BusPendingActivation *pending_activation;
1103+ DBusMessage *message;
1104+ DBusList *link;
1105+
1106+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1107+
1108+ /* Check if it's a pending activation */
1109+ pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, service_name);
1110+
1111+ if (!pending_activation)
1112+ return TRUE;
1113+
1114+ link = _dbus_list_get_first_link (&pending_activation->entries);
1115+ while (link != NULL)
1116+ {
1117+ BusPendingActivationEntry *entry = link->data;
1118+ DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
1119+
1120+ if (dbus_connection_get_is_connected (entry->connection))
1121+ {
1122+ /* Only send activation replies to regular activation requests. */
1123+ if (!entry->auto_activation)
1124+ {
1125+ dbus_uint32_t result;
1126+
1127+ message = dbus_message_new_method_return (entry->activation_message);
1128+ if (!message)
1129+ {
1130+ BUS_SET_OOM (error);
1131+ goto error;
1132+ }
1133+
1134+ result = DBUS_START_REPLY_SUCCESS;
1135+
1136+ if (!dbus_message_append_args (message,
1137+ DBUS_TYPE_UINT32, &result,
1138+ DBUS_TYPE_INVALID))
1139+ {
1140+ dbus_message_unref (message);
1141+ BUS_SET_OOM (error);
1142+ goto error;
1143+ }
1144+
1145+ if (!bus_transaction_send_from_driver (transaction, entry->connection, message))
1146+ {
1147+ dbus_message_unref (message);
1148+ BUS_SET_OOM (error);
1149+ goto error;
1150+ }
1151+
1152+ dbus_message_unref (message);
1153+ }
1154+ }
1155+
1156+ link = next;
1157+ }
1158+
1159+ return TRUE;
1160+
1161+ error:
1162+ return FALSE;
1163+}
1164+
1165+dbus_bool_t
1166+bus_activation_send_pending_auto_activation_messages (BusActivation *activation,
1167+ BusService *service,
1168+ BusTransaction *transaction,
1169+ DBusError *error)
1170+{
1171+ BusPendingActivation *pending_activation;
1172+ DBusList *link;
1173+
1174+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1175+
1176+ /* Check if it's a pending activation */
1177+ pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations,
1178+ bus_service_get_name (service));
1179+
1180+ if (!pending_activation)
1181+ return TRUE;
1182+
1183+ link = _dbus_list_get_first_link (&pending_activation->entries);
1184+ while (link != NULL)
1185+ {
1186+ BusPendingActivationEntry *entry = link->data;
1187+ DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
1188+
1189+ if (entry->auto_activation && dbus_connection_get_is_connected (entry->connection))
1190+ {
1191+ DBusConnection *addressed_recipient;
1192+
1193+ addressed_recipient = bus_service_get_primary_owners_connection (service);
1194+
1195+ /* Resume dispatching where we left off in bus_dispatch() */
1196+ if (!bus_dispatch_matches (transaction,
1197+ entry->connection,
1198+ addressed_recipient,
1199+ entry->activation_message, error))
1200+ goto error;
1201+ }
1202+
1203+ link = next;
1204+ }
1205+
1206+ if (!add_restore_pending_to_transaction (transaction, pending_activation))
1207+ {
1208+ _dbus_verbose ("Could not add cancel hook to transaction to revert removing pending activation\n");
1209+ BUS_SET_OOM (error);
1210+ goto error;
1211+ }
1212+
1213+ _dbus_hash_table_remove_string (activation->pending_activations, bus_service_get_name (service));
1214+
1215+ return TRUE;
1216+
1217+ error:
1218+ return FALSE;
1219+}
1220+
1221+/**
1222+ * FIXME @todo the error messages here would ideally be preallocated
1223+ * so we don't need to allocate memory to send them.
1224+ * Using the usual tactic, prealloc an OOM message, then
1225+ * if we can't alloc the real error send the OOM error instead.
1226+ */
1227+static dbus_bool_t
1228+try_send_activation_failure (BusPendingActivation *pending_activation,
1229+ const DBusError *how)
1230+{
1231+ BusActivation *activation;
1232+ DBusList *link;
1233+ BusTransaction *transaction;
1234+
1235+ activation = pending_activation->activation;
1236+
1237+ transaction = bus_transaction_new (activation->context);
1238+ if (transaction == NULL)
1239+ return FALSE;
1240+
1241+ link = _dbus_list_get_first_link (&pending_activation->entries);
1242+ while (link != NULL)
1243+ {
1244+ BusPendingActivationEntry *entry = link->data;
1245+ DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
1246+
1247+ if (dbus_connection_get_is_connected (entry->connection))
1248+ {
1249+ if (!bus_transaction_send_error_reply (transaction,
1250+ entry->connection,
1251+ how,
1252+ entry->activation_message))
1253+ goto error;
1254+ }
1255+
1256+ link = next;
1257+ }
1258+
1259+ bus_transaction_execute_and_free (transaction);
1260+
1261+ return TRUE;
1262+
1263+ error:
1264+ if (transaction)
1265+ bus_transaction_cancel_and_free (transaction);
1266+ return FALSE;
1267+}
1268+
1269+/**
1270+ * Free the pending activation and send an error message to all the
1271+ * connections that were waiting for it.
1272+ */
1273+static void
1274+pending_activation_failed (BusPendingActivation *pending_activation,
1275+ const DBusError *how)
1276+{
1277+ /* FIXME use preallocated OOM messages instead of bus_wait_for_memory() */
1278+ while (!try_send_activation_failure (pending_activation, how))
1279+ _dbus_wait_for_memory ();
1280+
1281+ /* Destroy this pending activation */
1282+ _dbus_hash_table_remove_string (pending_activation->activation->pending_activations,
1283+ pending_activation->service_name);
1284+}
1285+
1286+/**
1287+ * Depending on the exit code of the helper, set the error accordingly
1288+ */
1289+static void
1290+handle_servicehelper_exit_error (int exit_code,
1291+ DBusError *error)
1292+{
1293+ switch (exit_code)
1294+ {
1295+ case BUS_SPAWN_EXIT_CODE_NO_MEMORY:
1296+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
1297+ "Launcher could not run (out of memory)");
1298+ break;
1299+ case BUS_SPAWN_EXIT_CODE_SETUP_FAILED:
1300+ dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED,
1301+ "Failed to setup environment correctly");
1302+ break;
1303+ case BUS_SPAWN_EXIT_CODE_NAME_INVALID:
1304+ dbus_set_error (error, DBUS_ERROR_SPAWN_SERVICE_INVALID,
1305+ "Bus name is not valid or missing");
1306+ break;
1307+ case BUS_SPAWN_EXIT_CODE_SERVICE_NOT_FOUND:
1308+ dbus_set_error (error, DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND,
1309+ "Bus name not found in system service directory");
1310+ break;
1311+ case BUS_SPAWN_EXIT_CODE_PERMISSIONS_INVALID:
1312+ dbus_set_error (error, DBUS_ERROR_SPAWN_PERMISSIONS_INVALID,
1313+ "The permission of the setuid helper is not correct");
1314+ break;
1315+ case BUS_SPAWN_EXIT_CODE_FILE_INVALID:
1316+ dbus_set_error (error, DBUS_ERROR_SPAWN_PERMISSIONS_INVALID,
1317+ "The service file is incorrect or does not have all required attributes");
1318+ break;
1319+ case BUS_SPAWN_EXIT_CODE_EXEC_FAILED:
1320+ dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
1321+ "Cannot launch daemon, file not found or permissions invalid");
1322+ break;
1323+ case BUS_SPAWN_EXIT_CODE_INVALID_ARGS:
1324+ dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1325+ "Invalid arguments to command line");
1326+ break;
1327+ case BUS_SPAWN_EXIT_CODE_CHILD_SIGNALED:
1328+ dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_SIGNALED,
1329+ "Launched child was signaled, it probably crashed");
1330+ break;
1331+ default:
1332+ dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
1333+ "Launch helper exited with unknown return code %i", exit_code);
1334+ break;
1335+ }
1336+}
1337+
1338+static dbus_bool_t
1339+babysitter_watch_callback (DBusWatch *watch,
1340+ unsigned int condition,
1341+ void *data)
1342+{
1343+ BusPendingActivation *pending_activation = data;
1344+ dbus_bool_t retval;
1345+ DBusBabysitter *babysitter;
1346+ dbus_bool_t uses_servicehelper;
1347+
1348+ babysitter = pending_activation->babysitter;
1349+
1350+ _dbus_babysitter_ref (babysitter);
1351+
1352+ retval = dbus_watch_handle (watch, condition);
1353+
1354+ /* There are two major cases here; are we the system bus or the session? Here this
1355+ * is distinguished by whether or not we use a setuid helper launcher. With the launch helper,
1356+ * some process exit codes are meaningful, processed by handle_servicehelper_exit_error.
1357+ *
1358+ * In both cases though, just ignore when a process exits with status 0; it's possible for
1359+ * a program to (misguidedly) "daemonize", and that appears to us as an exit. This closes a race
1360+ * condition between this code and the child process claiming the bus name.
1361+ */
1362+ uses_servicehelper = bus_context_get_servicehelper (pending_activation->activation->context) != NULL;
1363+
1364+ /* FIXME this is broken in the same way that
1365+ * connection watches used to be; there should be
1366+ * a separate callback for status change, instead
1367+ * of doing "if we handled a watch status might
1368+ * have changed"
1369+ *
1370+ * Fixing this lets us move dbus_watch_handle
1371+ * calls into dbus-mainloop.c
1372+ */
1373+ if (_dbus_babysitter_get_child_exited (babysitter))
1374+ {
1375+ DBusError error;
1376+ DBusHashIter iter;
1377+ dbus_bool_t activation_failed;
1378+ int exit_code = 0;
1379+
1380+ dbus_error_init (&error);
1381+
1382+ _dbus_babysitter_set_child_exit_error (babysitter, &error);
1383+
1384+ /* Explicitly check for SPAWN_CHILD_EXITED to avoid overwriting an
1385+ * exec error */
1386+ if (dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)
1387+ && _dbus_babysitter_get_child_exit_status (babysitter, &exit_code))
1388+ {
1389+ activation_failed = exit_code != 0;
1390+
1391+ dbus_error_free(&error);
1392+
1393+ if (activation_failed)
1394+ {
1395+ if (uses_servicehelper)
1396+ handle_servicehelper_exit_error (exit_code, &error);
1397+ else
1398+ _dbus_babysitter_set_child_exit_error (babysitter, &error);
1399+ }
1400+ }
1401+ else
1402+ {
1403+ activation_failed = TRUE;
1404+ }
1405+
1406+ if (activation_failed)
1407+ {
1408+ /* Destroy all pending activations with the same exec */
1409+ _dbus_hash_iter_init (pending_activation->activation->pending_activations,
1410+ &iter);
1411+ while (_dbus_hash_iter_next (&iter))
1412+ {
1413+ BusPendingActivation *p = _dbus_hash_iter_get_value (&iter);
1414+
1415+ if (p != pending_activation && strcmp (p->exec, pending_activation->exec) == 0)
1416+ pending_activation_failed (p, &error);
1417+ }
1418+
1419+ /* Destroys the pending activation */
1420+ pending_activation_failed (pending_activation, &error);
1421+
1422+ dbus_error_free (&error);
1423+ }
1424+ }
1425+
1426+ _dbus_babysitter_unref (babysitter);
1427+
1428+ return retval;
1429+}
1430+
1431+static dbus_bool_t
1432+add_babysitter_watch (DBusWatch *watch,
1433+ void *data)
1434+{
1435+ BusPendingActivation *pending_activation = data;
1436+
1437+ return _dbus_loop_add_watch (bus_context_get_loop (pending_activation->activation->context),
1438+ watch, babysitter_watch_callback, pending_activation,
1439+ NULL);
1440+}
1441+
1442+static void
1443+remove_babysitter_watch (DBusWatch *watch,
1444+ void *data)
1445+{
1446+ BusPendingActivation *pending_activation = data;
1447+
1448+ _dbus_loop_remove_watch (bus_context_get_loop (pending_activation->activation->context),
1449+ watch, babysitter_watch_callback, pending_activation);
1450+}
1451+
1452+static dbus_bool_t
1453+pending_activation_timed_out (void *data)
1454+{
1455+ BusPendingActivation *pending_activation = data;
1456+ DBusError error;
1457+
1458+ /* Kill the spawned process, since it sucks
1459+ * (not sure this is what we want to do, but
1460+ * may as well try it for now)
1461+ */
1462+ if (pending_activation->babysitter)
1463+ _dbus_babysitter_kill_child (pending_activation->babysitter);
1464+
1465+ dbus_error_init (&error);
1466+
1467+ dbus_set_error (&error, DBUS_ERROR_TIMED_OUT,
1468+ "Activation of %s timed out",
1469+ pending_activation->service_name);
1470+
1471+ pending_activation_failed (pending_activation, &error);
1472+
1473+ dbus_error_free (&error);
1474+
1475+ return TRUE;
1476+}
1477+
1478+static void
1479+cancel_pending (void *data)
1480+{
1481+ BusPendingActivation *pending_activation = data;
1482+
1483+ _dbus_verbose ("Canceling pending activation of %s\n",
1484+ pending_activation->service_name);
1485+
1486+ if (pending_activation->babysitter)
1487+ _dbus_babysitter_kill_child (pending_activation->babysitter);
1488+
1489+ _dbus_hash_table_remove_string (pending_activation->activation->pending_activations,
1490+ pending_activation->service_name);
1491+}
1492+
1493+static void
1494+free_pending_cancel_data (void *data)
1495+{
1496+ BusPendingActivation *pending_activation = data;
1497+
1498+ bus_pending_activation_unref (pending_activation);
1499+}
1500+
1501+static dbus_bool_t
1502+add_cancel_pending_to_transaction (BusTransaction *transaction,
1503+ BusPendingActivation *pending_activation)
1504+{
1505+ if (!bus_transaction_add_cancel_hook (transaction, cancel_pending,
1506+ pending_activation,
1507+ free_pending_cancel_data))
1508+ return FALSE;
1509+
1510+ bus_pending_activation_ref (pending_activation);
1511+
1512+ _dbus_verbose ("Saved pending activation to be canceled if the transaction fails\n");
1513+
1514+ return TRUE;
1515+}
1516+
1517+static dbus_bool_t
1518+update_service_cache (BusActivation *activation, DBusError *error)
1519+{
1520+ DBusHashIter iter;
1521+
1522+ _dbus_hash_iter_init (activation->directories, &iter);
1523+ while (_dbus_hash_iter_next (&iter))
1524+ {
1525+ DBusError tmp_error;
1526+ BusServiceDirectory *s_dir;
1527+
1528+ s_dir = _dbus_hash_iter_get_value (&iter);
1529+
1530+ dbus_error_init (&tmp_error);
1531+ if (!update_directory (activation, s_dir, &tmp_error))
1532+ {
1533+ if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY))
1534+ {
1535+ dbus_move_error (&tmp_error, error);
1536+ return FALSE;
1537+ }
1538+
1539+ dbus_error_free (&tmp_error);
1540+ continue;
1541+ }
1542+ }
1543+
1544+ return TRUE;
1545+}
1546+
1547+static BusActivationEntry *
1548+activation_find_entry (BusActivation *activation,
1549+ const char *service_name,
1550+ DBusError *error)
1551+{
1552+ BusActivationEntry *entry;
1553+
1554+ entry = _dbus_hash_table_lookup_string (activation->entries, service_name);
1555+ if (!entry)
1556+ {
1557+ if (!update_service_cache (activation, error))
1558+ return NULL;
1559+
1560+ entry = _dbus_hash_table_lookup_string (activation->entries,
1561+ service_name);
1562+ }
1563+ else
1564+ {
1565+ BusActivationEntry *updated_entry;
1566+
1567+ if (!check_service_file (activation, entry, &updated_entry, error))
1568+ return NULL;
1569+
1570+ entry = updated_entry;
1571+ }
1572+
1573+ if (!entry)
1574+ {
1575+ dbus_set_error (error, DBUS_ERROR_SERVICE_UNKNOWN,
1576+ "The name %s was not provided by any .service files",
1577+ service_name);
1578+ return NULL;
1579+ }
1580+
1581+ return entry;
1582+}
1583+
1584+static char **
1585+bus_activation_get_environment (BusActivation *activation)
1586+{
1587+ char **environment;
1588+ int i, length;
1589+ DBusString entry;
1590+ DBusHashIter iter;
1591+
1592+ length = _dbus_hash_table_get_n_entries (activation->environment);
1593+
1594+ environment = dbus_new0 (char *, length + 1);
1595+
1596+ if (environment == NULL)
1597+ return NULL;
1598+
1599+ i = 0;
1600+ _dbus_hash_iter_init (activation->environment, &iter);
1601+
1602+ if (!_dbus_string_init (&entry))
1603+ {
1604+ dbus_free_string_array (environment);
1605+ return NULL;
1606+ }
1607+
1608+ while (_dbus_hash_iter_next (&iter))
1609+ {
1610+ const char *key, *value;
1611+
1612+ key = (const char *) _dbus_hash_iter_get_string_key (&iter);
1613+ value = (const char *) _dbus_hash_iter_get_value (&iter);
1614+
1615+ if (!_dbus_string_append_printf (&entry, "%s=%s", key, value))
1616+ break;
1617+
1618+ if (!_dbus_string_steal_data (&entry, environment + i))
1619+ break;
1620+ i++;
1621+ }
1622+
1623+ _dbus_string_free (&entry);
1624+
1625+ if (i != length)
1626+ {
1627+ dbus_free_string_array (environment);
1628+ environment = NULL;
1629+ }
1630+
1631+ return environment;
1632+}
1633+
1634+dbus_bool_t
1635+bus_activation_set_environment_variable (BusActivation *activation,
1636+ const char *key,
1637+ const char *value,
1638+ DBusError *error)
1639+{
1640+ char *hash_key;
1641+ char *hash_value;
1642+ dbus_bool_t retval;
1643+
1644+ retval = FALSE;
1645+ hash_key = NULL;
1646+ hash_value = NULL;
1647+ hash_key = _dbus_strdup (key);
1648+
1649+ if (hash_key == NULL)
1650+ goto out;
1651+
1652+ hash_value = _dbus_strdup (value);
1653+
1654+ if (hash_value == NULL)
1655+ goto out;
1656+
1657+ if (!_dbus_hash_table_insert_string (activation->environment,
1658+ hash_key, hash_value))
1659+ goto out;
1660+
1661+ retval = TRUE;
1662+out:
1663+ if (retval == FALSE)
1664+ {
1665+ dbus_free (hash_key);
1666+ dbus_free (hash_value);
1667+ BUS_SET_OOM (error);
1668+ }
1669+
1670+ return retval;
1671+}
1672+
1673+dbus_bool_t
1674+bus_activation_activate_service (BusActivation *activation,
1675+ DBusConnection *connection,
1676+ BusTransaction *transaction,
1677+ dbus_bool_t auto_activation,
1678+ DBusMessage *activation_message,
1679+ const char *service_name,
1680+ DBusError *error)
1681+{
1682+ BusActivationEntry *entry;
1683+ BusPendingActivation *pending_activation;
1684+ BusPendingActivationEntry *pending_activation_entry;
1685+ DBusMessage *message;
1686+ DBusString service_str;
1687+ const char *servicehelper;
1688+ char **argv;
1689+ char **envp = NULL;
1690+ int argc;
1691+ dbus_bool_t retval;
1692+ DBusHashIter iter;
1693+ dbus_bool_t activated;
1694+ DBusString command;
1695+
1696+ activated = TRUE;
1697+
1698+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1699+
1700+ if (activation->n_pending_activations >=
1701+ bus_context_get_max_pending_activations (activation->context))
1702+ {
1703+ dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
1704+ "The maximum number of pending activations has been reached, activation of %s failed",
1705+ service_name);
1706+ return FALSE;
1707+ }
1708+
1709+ entry = activation_find_entry (activation, service_name, error);
1710+ if (!entry)
1711+ return FALSE;
1712+
1713+ /* Bypass the registry lookup if we're auto-activating, bus_dispatch would not
1714+ * call us if the service is already active.
1715+ */
1716+ if (!auto_activation)
1717+ {
1718+ /* Check if the service is active */
1719+ _dbus_string_init_const (&service_str, service_name);
1720+ if (bus_registry_lookup (bus_context_get_registry (activation->context), &service_str) != NULL)
1721+ {
1722+ dbus_uint32_t result;
1723+
1724+ _dbus_verbose ("Service \"%s\" is already active\n", service_name);
1725+
1726+ message = dbus_message_new_method_return (activation_message);
1727+
1728+ if (!message)
1729+ {
1730+ _dbus_verbose ("No memory to create reply to activate message\n");
1731+ BUS_SET_OOM (error);
1732+ return FALSE;
1733+ }
1734+
1735+ result = DBUS_START_REPLY_ALREADY_RUNNING;
1736+
1737+ if (!dbus_message_append_args (message,
1738+ DBUS_TYPE_UINT32, &result,
1739+ DBUS_TYPE_INVALID))
1740+ {
1741+ _dbus_verbose ("No memory to set args of reply to activate message\n");
1742+ BUS_SET_OOM (error);
1743+ dbus_message_unref (message);
1744+ return FALSE;
1745+ }
1746+
1747+ retval = bus_transaction_send_from_driver (transaction, connection, message);
1748+ dbus_message_unref (message);
1749+ if (!retval)
1750+ {
1751+ _dbus_verbose ("Failed to send reply\n");
1752+ BUS_SET_OOM (error);
1753+ }
1754+
1755+ return retval;
1756+ }
1757+ }
1758+
1759+ pending_activation_entry = dbus_new0 (BusPendingActivationEntry, 1);
1760+ if (!pending_activation_entry)
1761+ {
1762+ _dbus_verbose ("Failed to create pending activation entry\n");
1763+ BUS_SET_OOM (error);
1764+ return FALSE;
1765+ }
1766+
1767+ pending_activation_entry->auto_activation = auto_activation;
1768+
1769+ pending_activation_entry->activation_message = activation_message;
1770+ dbus_message_ref (activation_message);
1771+ pending_activation_entry->connection = connection;
1772+ dbus_connection_ref (connection);
1773+
1774+ /* Check if the service is being activated */
1775+ pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, service_name);
1776+ if (pending_activation)
1777+ {
1778+ if (!_dbus_list_append (&pending_activation->entries, pending_activation_entry))
1779+ {
1780+ _dbus_verbose ("Failed to append a new entry to pending activation\n");
1781+
1782+ BUS_SET_OOM (error);
1783+ bus_pending_activation_entry_free (pending_activation_entry);
1784+ return FALSE;
1785+ }
1786+
1787+ pending_activation->n_entries += 1;
1788+ pending_activation->activation->n_pending_activations += 1;
1789+ }
1790+ else
1791+ {
1792+ pending_activation = dbus_new0 (BusPendingActivation, 1);
1793+ if (!pending_activation)
1794+ {
1795+ _dbus_verbose ("Failed to create pending activation\n");
1796+
1797+ BUS_SET_OOM (error);
1798+ bus_pending_activation_entry_free (pending_activation_entry);
1799+ return FALSE;
1800+ }
1801+
1802+ pending_activation->activation = activation;
1803+ pending_activation->refcount = 1;
1804+
1805+ pending_activation->service_name = _dbus_strdup (service_name);
1806+ if (!pending_activation->service_name)
1807+ {
1808+ _dbus_verbose ("Failed to copy service name for pending activation\n");
1809+
1810+ BUS_SET_OOM (error);
1811+ bus_pending_activation_unref (pending_activation);
1812+ bus_pending_activation_entry_free (pending_activation_entry);
1813+ return FALSE;
1814+ }
1815+
1816+ pending_activation->exec = _dbus_strdup (entry->exec);
1817+ if (!pending_activation->exec)
1818+ {
1819+ _dbus_verbose ("Failed to copy service exec for pending activation\n");
1820+ BUS_SET_OOM (error);
1821+ bus_pending_activation_unref (pending_activation);
1822+ bus_pending_activation_entry_free (pending_activation_entry);
1823+ return FALSE;
1824+ }
1825+
1826+ if (entry->systemd_service)
1827+ {
1828+ pending_activation->systemd_service = _dbus_strdup (entry->systemd_service);
1829+ if (!pending_activation->systemd_service)
1830+ {
1831+ _dbus_verbose ("Failed to copy systemd service for pending activation\n");
1832+ BUS_SET_OOM (error);
1833+ bus_pending_activation_unref (pending_activation);
1834+ bus_pending_activation_entry_free (pending_activation_entry);
1835+ return FALSE;
1836+ }
1837+ }
1838+
1839+ pending_activation->timeout =
1840+ _dbus_timeout_new (bus_context_get_activation_timeout (activation->context),
1841+ pending_activation_timed_out,
1842+ pending_activation,
1843+ NULL);
1844+ if (!pending_activation->timeout)
1845+ {
1846+ _dbus_verbose ("Failed to create timeout for pending activation\n");
1847+
1848+ BUS_SET_OOM (error);
1849+ bus_pending_activation_unref (pending_activation);
1850+ bus_pending_activation_entry_free (pending_activation_entry);
1851+ return FALSE;
1852+ }
1853+
1854+ if (!_dbus_loop_add_timeout (bus_context_get_loop (activation->context),
1855+ pending_activation->timeout,
1856+ handle_timeout_callback,
1857+ pending_activation,
1858+ NULL))
1859+ {
1860+ _dbus_verbose ("Failed to add timeout for pending activation\n");
1861+
1862+ BUS_SET_OOM (error);
1863+ bus_pending_activation_unref (pending_activation);
1864+ bus_pending_activation_entry_free (pending_activation_entry);
1865+ return FALSE;
1866+ }
1867+
1868+ pending_activation->timeout_added = TRUE;
1869+
1870+ if (!_dbus_list_append (&pending_activation->entries, pending_activation_entry))
1871+ {
1872+ _dbus_verbose ("Failed to add entry to just-created pending activation\n");
1873+
1874+ BUS_SET_OOM (error);
1875+ bus_pending_activation_unref (pending_activation);
1876+ bus_pending_activation_entry_free (pending_activation_entry);
1877+ return FALSE;
1878+ }
1879+
1880+ pending_activation->n_entries += 1;
1881+ pending_activation->activation->n_pending_activations += 1;
1882+
1883+ activated = FALSE;
1884+ _dbus_hash_iter_init (activation->pending_activations, &iter);
1885+ while (_dbus_hash_iter_next (&iter))
1886+ {
1887+ BusPendingActivation *p = _dbus_hash_iter_get_value (&iter);
1888+
1889+ if (strcmp (p->exec, entry->exec) == 0)
1890+ {
1891+ activated = TRUE;
1892+ break;
1893+ }
1894+ }
1895+
1896+ if (!_dbus_hash_table_insert_string (activation->pending_activations,
1897+ pending_activation->service_name,
1898+ pending_activation))
1899+ {
1900+ _dbus_verbose ("Failed to put pending activation in hash table\n");
1901+
1902+ BUS_SET_OOM (error);
1903+ bus_pending_activation_unref (pending_activation);
1904+ return FALSE;
1905+ }
1906+ }
1907+
1908+ if (!add_cancel_pending_to_transaction (transaction, pending_activation))
1909+ {
1910+ _dbus_verbose ("Failed to add pending activation cancel hook to transaction\n");
1911+ BUS_SET_OOM (error);
1912+ _dbus_hash_table_remove_string (activation->pending_activations,
1913+ pending_activation->service_name);
1914+
1915+ return FALSE;
1916+ }
1917+
1918+ if (activated)
1919+ return TRUE;
1920+
1921+ if (bus_context_get_systemd_activation (activation->context))
1922+ {
1923+ if (strcmp (service_name, "org.freedesktop.systemd1") == 0)
1924+ /* systemd itself is missing apparently. That can happen
1925+ only during early startup. Let's just wait until systemd
1926+ connects to us and do nothing. */
1927+ return TRUE;
1928+
1929+ if (entry->systemd_service)
1930+ {
1931+ BusTransaction *activation_transaction;
1932+ DBusString service_string;
1933+ BusService *service;
1934+ BusRegistry *registry;
1935+
1936+ /* OK, we have a systemd service configured for this entry,
1937+ hence let's enqueue an activation request message. This
1938+ is implemented as a directed signal, not a method call,
1939+ for three reasons: 1) we don't expect a response on
1940+ success, where we just expect a name appearing on the
1941+ bus; 2) at this time the systemd service might not yet
1942+ have connected, so we wouldn't know the message serial at
1943+ this point to set up a pending call; 3) it is ugly if the
1944+ bus suddenly becomes the caller of a remote method. */
1945+
1946+ message = dbus_message_new_signal (DBUS_PATH_DBUS,
1947+ "org.freedesktop.systemd1.Activator",
1948+ "ActivationRequest");
1949+ if (!message)
1950+ {
1951+ _dbus_verbose ("No memory to create activation message\n");
1952+ BUS_SET_OOM (error);
1953+ return FALSE;
1954+ }
1955+
1956+ if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS) ||
1957+ !dbus_message_set_destination (message, "org.freedesktop.systemd1") ||
1958+ !dbus_message_append_args (message,
1959+ DBUS_TYPE_STRING, &entry->systemd_service,
1960+ DBUS_TYPE_INVALID))
1961+ {
1962+ _dbus_verbose ("No memory to set args of activation message\n");
1963+ dbus_message_unref (message);
1964+ BUS_SET_OOM (error);
1965+ return FALSE;
1966+ }
1967+
1968+ /* Create our transaction */
1969+ activation_transaction = bus_transaction_new (activation->context);
1970+ if (activation_transaction == NULL)
1971+ {
1972+ _dbus_verbose ("No memory to create activation transaction\n");
1973+ dbus_message_unref (message);
1974+ BUS_SET_OOM (error);
1975+ return FALSE;
1976+ }
1977+
1978+ /* Check whether systemd is already connected */
1979+ registry = bus_connection_get_registry (connection);
1980+ _dbus_string_init_const (&service_string, "org.freedesktop.systemd1");
1981+ service = bus_registry_lookup (registry, &service_string);
1982+
1983+ if (service != NULL)
1984+ /* Wonderful, systemd is connected, let's just send the msg */
1985+ retval = bus_dispatch_matches (activation_transaction, NULL, bus_service_get_primary_owners_connection (service),
1986+ message, error);
1987+ else
1988+ /* systemd is not around, let's "activate" it. */
1989+ retval = bus_activation_activate_service (activation, connection, activation_transaction, TRUE,
1990+ message, "org.freedesktop.systemd1", error);
1991+
1992+ dbus_message_unref (message);
1993+
1994+ if (!retval)
1995+ {
1996+ _DBUS_ASSERT_ERROR_IS_SET (error);
1997+ _dbus_verbose ("failed to send activation message: %s\n", error->name);
1998+ bus_transaction_cancel_and_free (activation_transaction);
1999+ return FALSE;
2000+ }
2001+
2002+ bus_transaction_execute_and_free (activation_transaction);
2003+ return TRUE;
2004+ }
2005+
2006+ /* OK, we have no configured systemd service, hence let's
2007+ proceed with traditional activation. */
2008+ }
2009+
2010+ /* use command as system and session different */
2011+ if (!_dbus_string_init (&command))
2012+ {
2013+ BUS_SET_OOM (error);
2014+ return FALSE;
2015+ }
2016+
2017+ /* does the bus use a helper? */
2018+ servicehelper = bus_context_get_servicehelper (activation->context);
2019+ if (servicehelper != NULL)
2020+ {
2021+ if (entry->user == NULL)
2022+ {
2023+ _dbus_string_free (&command);
2024+ dbus_set_error (error, DBUS_ERROR_SPAWN_FILE_INVALID,
2025+ "Cannot do system-bus activation with no user\n");
2026+ return FALSE;
2027+ }
2028+
2029+ /* join the helper path and the service name */
2030+ if (!_dbus_string_append (&command, servicehelper))
2031+ {
2032+ _dbus_string_free (&command);
2033+ BUS_SET_OOM (error);
2034+ return FALSE;
2035+ }
2036+ if (!_dbus_string_append (&command, " "))
2037+ {
2038+ _dbus_string_free (&command);
2039+ BUS_SET_OOM (error);
2040+ return FALSE;
2041+ }
2042+ if (!_dbus_string_append (&command, service_name))
2043+ {
2044+ _dbus_string_free (&command);
2045+ BUS_SET_OOM (error);
2046+ return FALSE;
2047+ }
2048+ }
2049+ else
2050+ {
2051+ /* the bus does not use a helper, so we can append arguments with the exec line */
2052+ if (!_dbus_string_append (&command, entry->exec))
2053+ {
2054+ _dbus_string_free (&command);
2055+ BUS_SET_OOM (error);
2056+ return FALSE;
2057+ }
2058+ }
2059+
2060+ /* convert command into arguments */
2061+ if (!_dbus_shell_parse_argv (_dbus_string_get_const_data (&command), &argc, &argv, error))
2062+ {
2063+ _dbus_verbose ("Failed to parse command line: %s\n", entry->exec);
2064+ _DBUS_ASSERT_ERROR_IS_SET (error);
2065+
2066+ _dbus_hash_table_remove_string (activation->pending_activations,
2067+ pending_activation->service_name);
2068+
2069+ _dbus_string_free (&command);
2070+ return FALSE;
2071+ }
2072+ _dbus_string_free (&command);
2073+
2074+ if (!add_bus_environment (activation, error))
2075+ {
2076+ _DBUS_ASSERT_ERROR_IS_SET (error);
2077+ dbus_free_string_array (argv);
2078+ return FALSE;
2079+ }
2080+
2081+ envp = bus_activation_get_environment (activation);
2082+
2083+ if (envp == NULL)
2084+ {
2085+ BUS_SET_OOM (error);
2086+ dbus_free_string_array (argv);
2087+ return FALSE;
2088+ }
2089+
2090+ _dbus_verbose ("Spawning %s ...\n", argv[0]);
2091+ if (!_dbus_spawn_async_with_babysitter (&pending_activation->babysitter, argv,
2092+ envp,
2093+ NULL, activation,
2094+ error))
2095+ {
2096+ _dbus_verbose ("Failed to spawn child\n");
2097+ _DBUS_ASSERT_ERROR_IS_SET (error);
2098+ dbus_free_string_array (argv);
2099+ dbus_free_string_array (envp);
2100+
2101+ return FALSE;
2102+ }
2103+
2104+ dbus_free_string_array (argv);
2105+ envp = NULL;
2106+
2107+ _dbus_assert (pending_activation->babysitter != NULL);
2108+
2109+ if (!_dbus_babysitter_set_watch_functions (pending_activation->babysitter,
2110+ add_babysitter_watch,
2111+ remove_babysitter_watch,
2112+ NULL,
2113+ pending_activation,
2114+ NULL))
2115+ {
2116+ BUS_SET_OOM (error);
2117+ _dbus_verbose ("Failed to set babysitter watch functions\n");
2118+ return FALSE;
2119+ }
2120+
2121+ return TRUE;
2122+}
2123+
2124+dbus_bool_t
2125+bus_activation_list_services (BusActivation *activation,
2126+ char ***listp,
2127+ int *array_len)
2128+{
2129+ int i, j, len;
2130+ char **retval;
2131+ DBusHashIter iter;
2132+
2133+ len = _dbus_hash_table_get_n_entries (activation->entries);
2134+ retval = dbus_new (char *, len + 1);
2135+
2136+ if (retval == NULL)
2137+ return FALSE;
2138+
2139+ _dbus_hash_iter_init (activation->entries, &iter);
2140+ i = 0;
2141+ while (_dbus_hash_iter_next (&iter))
2142+ {
2143+ BusActivationEntry *entry = _dbus_hash_iter_get_value (&iter);
2144+
2145+ retval[i] = _dbus_strdup (entry->name);
2146+ if (retval[i] == NULL)
2147+ goto error;
2148+
2149+ i++;
2150+ }
2151+
2152+ retval[i] = NULL;
2153+
2154+ if (array_len)
2155+ *array_len = len;
2156+
2157+ *listp = retval;
2158+ return TRUE;
2159+
2160+ error:
2161+ for (j = 0; j < i; j++)
2162+ dbus_free (retval[i]);
2163+ dbus_free (retval);
2164+
2165+ return FALSE;
2166+}
2167+
2168+dbus_bool_t
2169+dbus_activation_systemd_failure (BusActivation *activation,
2170+ DBusMessage *message)
2171+{
2172+ DBusError error;
2173+ const char *code, *str, *unit = NULL;
2174+
2175+ dbus_error_init(&error);
2176+
2177+ /* This is called whenever the systemd activator sent us a
2178+ response. We'll invalidate all pending activations that match the
2179+ unit name. */
2180+
2181+ if (dbus_message_get_args (message, &error,
2182+ DBUS_TYPE_STRING, &unit,
2183+ DBUS_TYPE_STRING, &code,
2184+ DBUS_TYPE_STRING, &str,
2185+ DBUS_TYPE_INVALID))
2186+ dbus_set_error(&error, code, str);
2187+
2188+ if (unit)
2189+ {
2190+ DBusHashIter iter;
2191+
2192+ _dbus_hash_iter_init (activation->pending_activations,
2193+ &iter);
2194+
2195+ while (_dbus_hash_iter_next (&iter))
2196+ {
2197+ BusPendingActivation *p = _dbus_hash_iter_get_value (&iter);
2198+
2199+ if (p->systemd_service && strcmp (p->systemd_service, unit) == 0)
2200+ pending_activation_failed(p, &error);
2201+ }
2202+ }
2203+
2204+ dbus_error_free(&error);
2205+
2206+ return TRUE;
2207+}
2208+
2209+#ifdef DBUS_BUILD_TESTS
2210+
2211+#include <stdio.h>
2212+
2213+#define SERVICE_NAME_1 "MyService1"
2214+#define SERVICE_NAME_2 "MyService2"
2215+#define SERVICE_NAME_3 "MyService3"
2216+
2217+#define SERVICE_FILE_1 "service-1.service"
2218+#define SERVICE_FILE_2 "service-2.service"
2219+#define SERVICE_FILE_3 "service-3.service"
2220+
2221+static dbus_bool_t
2222+test_create_service_file (DBusString *dir,
2223+ const char *filename,
2224+ const char *name,
2225+ const char *exec)
2226+{
2227+ DBusString file_name, full_path;
2228+ FILE *file;
2229+ dbus_bool_t ret_val;
2230+
2231+ ret_val = TRUE;
2232+ _dbus_string_init_const (&file_name, filename);
2233+
2234+ if (!_dbus_string_init (&full_path))
2235+ return FALSE;
2236+
2237+ if (!_dbus_string_append (&full_path, _dbus_string_get_const_data (dir)) ||
2238+ !_dbus_concat_dir_and_file (&full_path, &file_name))
2239+ {
2240+ ret_val = FALSE;
2241+ goto out;
2242+ }
2243+
2244+ file = fopen (_dbus_string_get_const_data (&full_path), "w");
2245+ if (!file)
2246+ {
2247+ ret_val = FALSE;
2248+ goto out;
2249+ }
2250+
2251+ fprintf (file, "[D-BUS Service]\nName=%s\nExec=%s\n", name, exec);
2252+ fclose (file);
2253+
2254+out:
2255+ _dbus_string_free (&full_path);
2256+ return ret_val;
2257+}
2258+
2259+static dbus_bool_t
2260+test_remove_service_file (DBusString *dir, const char *filename)
2261+{
2262+ DBusString file_name, full_path;
2263+ dbus_bool_t ret_val;
2264+
2265+ ret_val = TRUE;
2266+
2267+ _dbus_string_init_const (&file_name, filename);
2268+
2269+ if (!_dbus_string_init (&full_path))
2270+ return FALSE;
2271+
2272+ if (!_dbus_string_append (&full_path, _dbus_string_get_const_data (dir)) ||
2273+ !_dbus_concat_dir_and_file (&full_path, &file_name))
2274+ {
2275+ ret_val = FALSE;
2276+ goto out;
2277+ }
2278+
2279+ if (!_dbus_delete_file (&full_path, NULL))
2280+ {
2281+ ret_val = FALSE;
2282+ goto out;
2283+ }
2284+
2285+out:
2286+ _dbus_string_free (&full_path);
2287+ return ret_val;
2288+}
2289+
2290+static dbus_bool_t
2291+test_remove_directory (DBusString *dir)
2292+{
2293+ DBusDirIter *iter;
2294+ DBusString filename, full_path;
2295+ dbus_bool_t ret_val;
2296+
2297+ ret_val = TRUE;
2298+
2299+ if (!_dbus_string_init (&filename))
2300+ return FALSE;
2301+
2302+ if (!_dbus_string_init (&full_path))
2303+ {
2304+ _dbus_string_free (&filename);
2305+ return FALSE;
2306+ }
2307+
2308+ iter = _dbus_directory_open (dir, NULL);
2309+ if (iter == NULL)
2310+ {
2311+ ret_val = FALSE;
2312+ goto out;
2313+ }
2314+
2315+ while (_dbus_directory_get_next_file (iter, &filename, NULL))
2316+ {
2317+ if (!test_remove_service_file (dir, _dbus_string_get_const_data (&filename)))
2318+ {
2319+ ret_val = FALSE;
2320+ goto out;
2321+ }
2322+ }
2323+ _dbus_directory_close (iter);
2324+
2325+ if (!_dbus_delete_directory (dir, NULL))
2326+ {
2327+ ret_val = FALSE;
2328+ goto out;
2329+ }
2330+
2331+out:
2332+ _dbus_string_free (&filename);
2333+ _dbus_string_free (&full_path);
2334+
2335+ return ret_val;
2336+}
2337+
2338+static dbus_bool_t
2339+init_service_reload_test (DBusString *dir)
2340+{
2341+ DBusStat stat_buf;
2342+
2343+ if (!_dbus_stat (dir, &stat_buf, NULL))
2344+ {
2345+ if (!_dbus_create_directory (dir, NULL))
2346+ return FALSE;
2347+ }
2348+ else
2349+ {
2350+ if (!test_remove_directory (dir))
2351+ return FALSE;
2352+
2353+ if (!_dbus_create_directory (dir, NULL))
2354+ return FALSE;
2355+ }
2356+
2357+ /* Create one initial file */
2358+ if (!test_create_service_file (dir, SERVICE_FILE_1, SERVICE_NAME_1, "exec-1"))
2359+ return FALSE;
2360+
2361+ return TRUE;
2362+}
2363+
2364+static dbus_bool_t
2365+cleanup_service_reload_test (DBusString *dir)
2366+{
2367+ if (!test_remove_directory (dir))
2368+ return FALSE;
2369+
2370+ return TRUE;
2371+}
2372+
2373+typedef struct
2374+{
2375+ BusActivation *activation;
2376+ const char *service_name;
2377+ dbus_bool_t expecting_find;
2378+} CheckData;
2379+
2380+static dbus_bool_t
2381+check_func (void *data)
2382+{
2383+ CheckData *d;
2384+ BusActivationEntry *entry;
2385+ DBusError error;
2386+ dbus_bool_t ret_val;
2387+
2388+ ret_val = TRUE;
2389+ d = data;
2390+
2391+ dbus_error_init (&error);
2392+
2393+ entry = activation_find_entry (d->activation, d->service_name, &error);
2394+ if (entry == NULL)
2395+ {
2396+ if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
2397+ {
2398+ ret_val = TRUE;
2399+ }
2400+ else
2401+ {
2402+ if (d->expecting_find)
2403+ ret_val = FALSE;
2404+ }
2405+
2406+ dbus_error_free (&error);
2407+ }
2408+ else
2409+ {
2410+ if (!d->expecting_find)
2411+ ret_val = FALSE;
2412+ }
2413+
2414+ return ret_val;
2415+}
2416+
2417+static dbus_bool_t
2418+do_test (const char *description, dbus_bool_t oom_test, CheckData *data)
2419+{
2420+ dbus_bool_t err;
2421+
2422+ if (oom_test)
2423+ err = !_dbus_test_oom_handling (description, check_func, data);
2424+ else
2425+ err = !check_func (data);
2426+
2427+ if (err)
2428+ _dbus_assert_not_reached ("Test failed");
2429+
2430+ return TRUE;
2431+}
2432+
2433+static dbus_bool_t
2434+do_service_reload_test (DBusString *dir, dbus_bool_t oom_test)
2435+{
2436+ BusActivation *activation;
2437+ DBusString address;
2438+ DBusList *directories;
2439+ CheckData d;
2440+
2441+ directories = NULL;
2442+ _dbus_string_init_const (&address, "");
2443+
2444+ if (!_dbus_list_append (&directories, _dbus_string_get_data (dir)))
2445+ return FALSE;
2446+
2447+ activation = bus_activation_new (NULL, &address, &directories, NULL);
2448+ if (!activation)
2449+ return FALSE;
2450+
2451+ d.activation = activation;
2452+
2453+ /* Check for existing service file */
2454+ d.expecting_find = TRUE;
2455+ d.service_name = SERVICE_NAME_1;
2456+
2457+ if (!do_test ("Existing service file", oom_test, &d))
2458+ return FALSE;
2459+
2460+ /* Check for non-existing service file */
2461+ d.expecting_find = FALSE;
2462+ d.service_name = SERVICE_NAME_3;
2463+
2464+ if (!do_test ("Nonexisting service file", oom_test, &d))
2465+ return FALSE;
2466+
2467+ /* Check for added service file */
2468+ if (!test_create_service_file (dir, SERVICE_FILE_2, SERVICE_NAME_2, "exec-2"))
2469+ return FALSE;
2470+
2471+ d.expecting_find = TRUE;
2472+ d.service_name = SERVICE_NAME_2;
2473+
2474+ if (!do_test ("Added service file", oom_test, &d))
2475+ return FALSE;
2476+
2477+ /* Check for removed service file */
2478+ if (!test_remove_service_file (dir, SERVICE_FILE_2))
2479+ return FALSE;
2480+
2481+ d.expecting_find = FALSE;
2482+ d.service_name = SERVICE_FILE_2;
2483+
2484+ if (!do_test ("Removed service file", oom_test, &d))
2485+ return FALSE;
2486+
2487+ /* Check for updated service file */
2488+
2489+ _dbus_sleep_milliseconds (1000); /* Sleep a second to make sure the mtime is updated */
2490+
2491+ if (!test_create_service_file (dir, SERVICE_FILE_1, SERVICE_NAME_3, "exec-3"))
2492+ return FALSE;
2493+
2494+ d.expecting_find = TRUE;
2495+ d.service_name = SERVICE_NAME_3;
2496+
2497+ if (!do_test ("Updated service file, part 1", oom_test, &d))
2498+ return FALSE;
2499+
2500+ d.expecting_find = FALSE;
2501+ d.service_name = SERVICE_NAME_1;
2502+
2503+ if (!do_test ("Updated service file, part 2", oom_test, &d))
2504+ return FALSE;
2505+
2506+ bus_activation_unref (activation);
2507+ _dbus_list_clear (&directories);
2508+
2509+ return TRUE;
2510+}
2511+
2512+dbus_bool_t
2513+bus_activation_service_reload_test (const DBusString *test_data_dir)
2514+{
2515+ DBusString directory;
2516+
2517+ if (!_dbus_string_init (&directory))
2518+ return FALSE;
2519+
2520+ if (!_dbus_string_append (&directory, _dbus_get_tmpdir()))
2521+ return FALSE;
2522+
2523+ if (!_dbus_string_append (&directory, "/dbus-reload-test-") ||
2524+ !_dbus_generate_random_ascii (&directory, 6))
2525+ {
2526+ return FALSE;
2527+ }
2528+
2529+ /* Do normal 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, FALSE))
2534+ ; /* Do nothing? */
2535+
2536+ /* Do OOM tests */
2537+ if (!init_service_reload_test (&directory))
2538+ _dbus_assert_not_reached ("could not initiate service reload test");
2539+
2540+ if (!do_service_reload_test (&directory, TRUE))
2541+ ; /* Do nothing? */
2542+
2543+ /* Cleanup test directory */
2544+ if (!cleanup_service_reload_test (&directory))
2545+ return FALSE;
2546+
2547+ _dbus_string_free (&directory);
2548+
2549+ return TRUE;
2550+}
2551+
2552+#endif /* DBUS_BUILD_TESTS */
2553
2554=== added file '.pc/0001-activation-allow-for-more-variation-than-just-system.patch/bus/bus.c'
2555--- .pc/0001-activation-allow-for-more-variation-than-just-system.patch/bus/bus.c 1970-01-01 00:00:00 +0000
2556+++ .pc/0001-activation-allow-for-more-variation-than-just-system.patch/bus/bus.c 2011-03-28 07:17:28 +0000
2557@@ -0,0 +1,1638 @@
2558+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2559+/* bus.c message bus context object
2560+ *
2561+ * Copyright (C) 2003, 2004 Red Hat, Inc.
2562+ *
2563+ * Licensed under the Academic Free License version 2.1
2564+ *
2565+ * This program is free software; you can redistribute it and/or modify
2566+ * it under the terms of the GNU General Public License as published by
2567+ * the Free Software Foundation; either version 2 of the License, or
2568+ * (at your option) any later version.
2569+ *
2570+ * This program is distributed in the hope that it will be useful,
2571+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2572+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2573+ * GNU General Public License for more details.
2574+ *
2575+ * You should have received a copy of the GNU General Public License
2576+ * along with this program; if not, write to the Free Software
2577+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2578+ *
2579+ */
2580+
2581+#include <config.h>
2582+#include "bus.h"
2583+#include "activation.h"
2584+#include "connection.h"
2585+#include "services.h"
2586+#include "utils.h"
2587+#include "policy.h"
2588+#include "config-parser.h"
2589+#include "signals.h"
2590+#include "selinux.h"
2591+#include "dir-watch.h"
2592+#include <dbus/dbus-list.h>
2593+#include <dbus/dbus-hash.h>
2594+#include <dbus/dbus-credentials.h>
2595+#include <dbus/dbus-internals.h>
2596+#ifdef DBUS_CYGWIN
2597+#include <signal.h>
2598+#endif
2599+
2600+struct BusContext
2601+{
2602+ int refcount;
2603+ DBusGUID uuid;
2604+ char *config_file;
2605+ char *type;
2606+ char *servicehelper;
2607+ char *address;
2608+ char *pidfile;
2609+ char *user;
2610+ char *log_prefix;
2611+ DBusLoop *loop;
2612+ DBusList *servers;
2613+ BusConnections *connections;
2614+ BusActivation *activation;
2615+ BusRegistry *registry;
2616+ BusPolicy *policy;
2617+ BusMatchmaker *matchmaker;
2618+ BusLimits limits;
2619+ unsigned int fork : 1;
2620+ unsigned int syslog : 1;
2621+ unsigned int keep_umask : 1;
2622+ unsigned int allow_anonymous : 1;
2623+ unsigned int systemd_activation : 1;
2624+};
2625+
2626+static dbus_int32_t server_data_slot = -1;
2627+
2628+typedef struct
2629+{
2630+ BusContext *context;
2631+} BusServerData;
2632+
2633+#define BUS_SERVER_DATA(server) (dbus_server_get_data ((server), server_data_slot))
2634+
2635+static BusContext*
2636+server_get_context (DBusServer *server)
2637+{
2638+ BusContext *context;
2639+ BusServerData *bd;
2640+
2641+ if (!dbus_server_allocate_data_slot (&server_data_slot))
2642+ return NULL;
2643+
2644+ bd = BUS_SERVER_DATA (server);
2645+ if (bd == NULL)
2646+ {
2647+ dbus_server_free_data_slot (&server_data_slot);
2648+ return NULL;
2649+ }
2650+
2651+ context = bd->context;
2652+
2653+ dbus_server_free_data_slot (&server_data_slot);
2654+
2655+ return context;
2656+}
2657+
2658+static dbus_bool_t
2659+server_watch_callback (DBusWatch *watch,
2660+ unsigned int condition,
2661+ void *data)
2662+{
2663+ /* FIXME this can be done in dbus-mainloop.c
2664+ * if the code in activation.c for the babysitter
2665+ * watch handler is fixed.
2666+ */
2667+
2668+ return dbus_watch_handle (watch, condition);
2669+}
2670+
2671+static dbus_bool_t
2672+add_server_watch (DBusWatch *watch,
2673+ void *data)
2674+{
2675+ DBusServer *server = data;
2676+ BusContext *context;
2677+
2678+ context = server_get_context (server);
2679+
2680+ return _dbus_loop_add_watch (context->loop,
2681+ watch, server_watch_callback, server,
2682+ NULL);
2683+}
2684+
2685+static void
2686+remove_server_watch (DBusWatch *watch,
2687+ void *data)
2688+{
2689+ DBusServer *server = data;
2690+ BusContext *context;
2691+
2692+ context = server_get_context (server);
2693+
2694+ _dbus_loop_remove_watch (context->loop,
2695+ watch, server_watch_callback, server);
2696+}
2697+
2698+
2699+static void
2700+server_timeout_callback (DBusTimeout *timeout,
2701+ void *data)
2702+{
2703+ /* can return FALSE on OOM but we just let it fire again later */
2704+ dbus_timeout_handle (timeout);
2705+}
2706+
2707+static dbus_bool_t
2708+add_server_timeout (DBusTimeout *timeout,
2709+ void *data)
2710+{
2711+ DBusServer *server = data;
2712+ BusContext *context;
2713+
2714+ context = server_get_context (server);
2715+
2716+ return _dbus_loop_add_timeout (context->loop,
2717+ timeout, server_timeout_callback, server, NULL);
2718+}
2719+
2720+static void
2721+remove_server_timeout (DBusTimeout *timeout,
2722+ void *data)
2723+{
2724+ DBusServer *server = data;
2725+ BusContext *context;
2726+
2727+ context = server_get_context (server);
2728+
2729+ _dbus_loop_remove_timeout (context->loop,
2730+ timeout, server_timeout_callback, server);
2731+}
2732+
2733+static void
2734+new_connection_callback (DBusServer *server,
2735+ DBusConnection *new_connection,
2736+ void *data)
2737+{
2738+ BusContext *context = data;
2739+
2740+ if (!bus_connections_setup_connection (context->connections, new_connection))
2741+ {
2742+ _dbus_verbose ("No memory to setup new connection\n");
2743+
2744+ /* if we don't do this, it will get unref'd without
2745+ * being disconnected... kind of strange really
2746+ * that we have to do this, people won't get it right
2747+ * in general.
2748+ */
2749+ dbus_connection_close (new_connection);
2750+ }
2751+
2752+ dbus_connection_set_max_received_size (new_connection,
2753+ context->limits.max_incoming_bytes);
2754+
2755+ dbus_connection_set_max_message_size (new_connection,
2756+ context->limits.max_message_size);
2757+
2758+ dbus_connection_set_max_received_unix_fds (new_connection,
2759+ context->limits.max_incoming_unix_fds);
2760+
2761+ dbus_connection_set_max_message_unix_fds (new_connection,
2762+ context->limits.max_message_unix_fds);
2763+
2764+ dbus_connection_set_allow_anonymous (new_connection,
2765+ context->allow_anonymous);
2766+
2767+ /* on OOM, we won't have ref'd the connection so it will die. */
2768+}
2769+
2770+static void
2771+free_server_data (void *data)
2772+{
2773+ BusServerData *bd = data;
2774+
2775+ dbus_free (bd);
2776+}
2777+
2778+static dbus_bool_t
2779+setup_server (BusContext *context,
2780+ DBusServer *server,
2781+ char **auth_mechanisms,
2782+ DBusError *error)
2783+{
2784+ BusServerData *bd;
2785+
2786+ bd = dbus_new0 (BusServerData, 1);
2787+ if (bd == NULL || !dbus_server_set_data (server,
2788+ server_data_slot,
2789+ bd, free_server_data))
2790+ {
2791+ dbus_free (bd);
2792+ BUS_SET_OOM (error);
2793+ return FALSE;
2794+ }
2795+
2796+ bd->context = context;
2797+
2798+ if (!dbus_server_set_auth_mechanisms (server, (const char**) auth_mechanisms))
2799+ {
2800+ BUS_SET_OOM (error);
2801+ return FALSE;
2802+ }
2803+
2804+ dbus_server_set_new_connection_function (server,
2805+ new_connection_callback,
2806+ context, NULL);
2807+
2808+ if (!dbus_server_set_watch_functions (server,
2809+ add_server_watch,
2810+ remove_server_watch,
2811+ NULL,
2812+ server,
2813+ NULL))
2814+ {
2815+ BUS_SET_OOM (error);
2816+ return FALSE;
2817+ }
2818+
2819+ if (!dbus_server_set_timeout_functions (server,
2820+ add_server_timeout,
2821+ remove_server_timeout,
2822+ NULL,
2823+ server, NULL))
2824+ {
2825+ BUS_SET_OOM (error);
2826+ return FALSE;
2827+ }
2828+
2829+ return TRUE;
2830+}
2831+
2832+/* This code only gets executed the first time the
2833+ * config files are parsed. It is not executed
2834+ * when config files are reloaded.
2835+ */
2836+static dbus_bool_t
2837+process_config_first_time_only (BusContext *context,
2838+ BusConfigParser *parser,
2839+ const DBusString *address,
2840+ dbus_bool_t systemd_activation,
2841+ DBusError *error)
2842+{
2843+ DBusString log_prefix;
2844+ DBusList *link;
2845+ DBusList **addresses;
2846+ const char *user, *pidfile;
2847+ char **auth_mechanisms;
2848+ DBusList **auth_mechanisms_list;
2849+ int len;
2850+ dbus_bool_t retval;
2851+
2852+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2853+
2854+ retval = FALSE;
2855+ auth_mechanisms = NULL;
2856+
2857+ context->systemd_activation = systemd_activation;
2858+
2859+ /* Check for an existing pid file. Of course this is a race;
2860+ * we'd have to use fcntl() locks on the pid file to
2861+ * avoid that. But we want to check for the pid file
2862+ * before overwriting any existing sockets, etc.
2863+ */
2864+ pidfile = bus_config_parser_get_pidfile (parser);
2865+ if (pidfile != NULL)
2866+ {
2867+ DBusString u;
2868+ DBusStat stbuf;
2869+
2870+ _dbus_string_init_const (&u, pidfile);
2871+
2872+ if (_dbus_stat (&u, &stbuf, NULL))
2873+ {
2874+#ifdef DBUS_CYGWIN
2875+ DBusString p;
2876+ long /* int */ pid;
2877+
2878+ _dbus_string_init (&p);
2879+ _dbus_file_get_contents(&p, &u, NULL);
2880+ _dbus_string_parse_int(&p, 0, &pid, NULL);
2881+ _dbus_string_free(&p);
2882+
2883+ if ((kill((int)pid, 0))) {
2884+ dbus_set_error(NULL, DBUS_ERROR_FILE_EXISTS,
2885+ "pid %ld not running, removing stale pid file\n",
2886+ pid);
2887+ _dbus_delete_file(&u, NULL);
2888+ } else {
2889+#endif
2890+ dbus_set_error (error, DBUS_ERROR_FAILED,
2891+ "The pid file \"%s\" exists, if the message bus is not running, remove this file",
2892+ pidfile);
2893+ goto failed;
2894+#ifdef DBUS_CYGWIN
2895+ }
2896+#endif
2897+ }
2898+ }
2899+
2900+ /* keep around the pid filename so we can delete it later */
2901+ context->pidfile = _dbus_strdup (pidfile);
2902+
2903+ /* note that type may be NULL */
2904+ context->type = _dbus_strdup (bus_config_parser_get_type (parser));
2905+ if (bus_config_parser_get_type (parser) != NULL && context->type == NULL)
2906+ goto oom;
2907+
2908+ user = bus_config_parser_get_user (parser);
2909+ if (user != NULL)
2910+ {
2911+ context->user = _dbus_strdup (user);
2912+ if (context->user == NULL)
2913+ goto oom;
2914+ }
2915+
2916+ /* Set up the prefix for syslog messages */
2917+ if (!_dbus_string_init (&log_prefix))
2918+ goto oom;
2919+ if (context->type && !strcmp (context->type, "system"))
2920+ {
2921+ if (!_dbus_string_append (&log_prefix, "[system] "))
2922+ goto oom;
2923+ }
2924+ else if (context->type && !strcmp (context->type, "session"))
2925+ {
2926+ DBusCredentials *credentials;
2927+
2928+ credentials = _dbus_credentials_new_from_current_process ();
2929+ if (!credentials)
2930+ goto oom;
2931+ if (!_dbus_string_append (&log_prefix, "[session "))
2932+ goto oom;
2933+ if (!_dbus_credentials_to_string_append (credentials, &log_prefix))
2934+ goto oom;
2935+ if (!_dbus_string_append (&log_prefix, "] "))
2936+ goto oom;
2937+ _dbus_credentials_unref (credentials);
2938+ }
2939+ if (!_dbus_string_steal_data (&log_prefix, &context->log_prefix))
2940+ goto oom;
2941+ _dbus_string_free (&log_prefix);
2942+
2943+ /* Build an array of auth mechanisms */
2944+
2945+ auth_mechanisms_list = bus_config_parser_get_mechanisms (parser);
2946+ len = _dbus_list_get_length (auth_mechanisms_list);
2947+
2948+ if (len > 0)
2949+ {
2950+ int i;
2951+
2952+ auth_mechanisms = dbus_new0 (char*, len + 1);
2953+ if (auth_mechanisms == NULL)
2954+ goto oom;
2955+
2956+ i = 0;
2957+ link = _dbus_list_get_first_link (auth_mechanisms_list);
2958+ while (link != NULL)
2959+ {
2960+ auth_mechanisms[i] = _dbus_strdup (link->data);
2961+ if (auth_mechanisms[i] == NULL)
2962+ goto oom;
2963+ link = _dbus_list_get_next_link (auth_mechanisms_list, link);
2964+ }
2965+ }
2966+ else
2967+ {
2968+ auth_mechanisms = NULL;
2969+ }
2970+
2971+ /* Listen on our addresses */
2972+
2973+ if (address)
2974+ {
2975+ DBusServer *server;
2976+
2977+ server = dbus_server_listen (_dbus_string_get_const_data(address), error);
2978+ if (server == NULL)
2979+ {
2980+ _DBUS_ASSERT_ERROR_IS_SET (error);
2981+ goto failed;
2982+ }
2983+ else if (!setup_server (context, server, auth_mechanisms, error))
2984+ {
2985+ _DBUS_ASSERT_ERROR_IS_SET (error);
2986+ goto failed;
2987+ }
2988+
2989+ if (!_dbus_list_append (&context->servers, server))
2990+ goto oom;
2991+ }
2992+ else
2993+ {
2994+ addresses = bus_config_parser_get_addresses (parser);
2995+
2996+ link = _dbus_list_get_first_link (addresses);
2997+ while (link != NULL)
2998+ {
2999+ DBusServer *server;
3000+
3001+ server = dbus_server_listen (link->data, error);
3002+ if (server == NULL)
3003+ {
3004+ _DBUS_ASSERT_ERROR_IS_SET (error);
3005+ goto failed;
3006+ }
3007+ else if (!setup_server (context, server, auth_mechanisms, error))
3008+ {
3009+ _DBUS_ASSERT_ERROR_IS_SET (error);
3010+ goto failed;
3011+ }
3012+
3013+ if (!_dbus_list_append (&context->servers, server))
3014+ goto oom;
3015+
3016+ link = _dbus_list_get_next_link (addresses, link);
3017+ }
3018+ }
3019+
3020+ context->fork = bus_config_parser_get_fork (parser);
3021+ context->syslog = bus_config_parser_get_syslog (parser);
3022+ context->keep_umask = bus_config_parser_get_keep_umask (parser);
3023+ context->allow_anonymous = bus_config_parser_get_allow_anonymous (parser);
3024+
3025+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3026+ retval = TRUE;
3027+
3028+ failed:
3029+ dbus_free_string_array (auth_mechanisms);
3030+ return retval;
3031+
3032+ oom:
3033+ BUS_SET_OOM (error);
3034+ dbus_free_string_array (auth_mechanisms);
3035+ return FALSE;
3036+}
3037+
3038+/* This code gets executed every time the config files
3039+ * are parsed: both during BusContext construction
3040+ * and on reloads. This function is slightly screwy
3041+ * since it can do a "half reload" in out-of-memory
3042+ * situations. Realistically, unlikely to ever matter.
3043+ */
3044+static dbus_bool_t
3045+process_config_every_time (BusContext *context,
3046+ BusConfigParser *parser,
3047+ dbus_bool_t is_reload,
3048+ DBusError *error)
3049+{
3050+ DBusString full_address;
3051+ DBusList *link;
3052+ DBusList **dirs;
3053+ BusActivation *new_activation;
3054+ char *addr;
3055+ const char *servicehelper;
3056+ char *s;
3057+
3058+ dbus_bool_t retval;
3059+
3060+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3061+
3062+ addr = NULL;
3063+ retval = FALSE;
3064+
3065+ if (!_dbus_string_init (&full_address))
3066+ {
3067+ BUS_SET_OOM (error);
3068+ return FALSE;
3069+ }
3070+
3071+ /* get our limits and timeout lengths */
3072+ bus_config_parser_get_limits (parser, &context->limits);
3073+
3074+ if (context->policy)
3075+ bus_policy_unref (context->policy);
3076+ context->policy = bus_config_parser_steal_policy (parser);
3077+ _dbus_assert (context->policy != NULL);
3078+
3079+ /* We have to build the address backward, so that
3080+ * <listen> later in the config file have priority
3081+ */
3082+ link = _dbus_list_get_last_link (&context->servers);
3083+ while (link != NULL)
3084+ {
3085+ addr = dbus_server_get_address (link->data);
3086+ if (addr == NULL)
3087+ {
3088+ BUS_SET_OOM (error);
3089+ goto failed;
3090+ }
3091+
3092+ if (_dbus_string_get_length (&full_address) > 0)
3093+ {
3094+ if (!_dbus_string_append (&full_address, ";"))
3095+ {
3096+ BUS_SET_OOM (error);
3097+ goto failed;
3098+ }
3099+ }
3100+
3101+ if (!_dbus_string_append (&full_address, addr))
3102+ {
3103+ BUS_SET_OOM (error);
3104+ goto failed;
3105+ }
3106+
3107+ dbus_free (addr);
3108+ addr = NULL;
3109+
3110+ link = _dbus_list_get_prev_link (&context->servers, link);
3111+ }
3112+
3113+ if (is_reload)
3114+ dbus_free (context->address);
3115+
3116+ if (!_dbus_string_copy_data (&full_address, &context->address))
3117+ {
3118+ BUS_SET_OOM (error);
3119+ goto failed;
3120+ }
3121+
3122+ /* get the service directories */
3123+ dirs = bus_config_parser_get_service_dirs (parser);
3124+
3125+ /* and the service helper */
3126+ servicehelper = bus_config_parser_get_servicehelper (parser);
3127+
3128+ s = _dbus_strdup(servicehelper);
3129+ if (s == NULL && servicehelper != NULL)
3130+ {
3131+ BUS_SET_OOM (error);
3132+ goto failed;
3133+ }
3134+ else
3135+ {
3136+ dbus_free(context->servicehelper);
3137+ context->servicehelper = s;
3138+ }
3139+
3140+ /* Create activation subsystem */
3141+ if (context->activation)
3142+ {
3143+ if (!bus_activation_reload (context->activation, &full_address, dirs, error))
3144+ goto failed;
3145+ }
3146+ else
3147+ {
3148+ context->activation = bus_activation_new (context, &full_address, dirs, error);
3149+ }
3150+
3151+ if (context->activation == NULL)
3152+ {
3153+ _DBUS_ASSERT_ERROR_IS_SET (error);
3154+ goto failed;
3155+ }
3156+
3157+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3158+ retval = TRUE;
3159+
3160+ failed:
3161+ _dbus_string_free (&full_address);
3162+
3163+ if (addr)
3164+ dbus_free (addr);
3165+
3166+ return retval;
3167+}
3168+
3169+static dbus_bool_t
3170+list_concat_new (DBusList **a,
3171+ DBusList **b,
3172+ DBusList **result)
3173+{
3174+ DBusList *link;
3175+
3176+ *result = NULL;
3177+
3178+ link = _dbus_list_get_first_link (a);
3179+ for (link = _dbus_list_get_first_link (a); link; link = _dbus_list_get_next_link (a, link))
3180+ {
3181+ if (!_dbus_list_append (result, link->data))
3182+ goto oom;
3183+ }
3184+ for (link = _dbus_list_get_first_link (b); link; link = _dbus_list_get_next_link (b, link))
3185+ {
3186+ if (!_dbus_list_append (result, link->data))
3187+ goto oom;
3188+ }
3189+
3190+ return TRUE;
3191+oom:
3192+ _dbus_list_clear (result);
3193+ return FALSE;
3194+}
3195+
3196+static dbus_bool_t
3197+process_config_postinit (BusContext *context,
3198+ BusConfigParser *parser,
3199+ DBusError *error)
3200+{
3201+ DBusHashTable *service_context_table;
3202+ DBusList *watched_dirs = NULL;
3203+
3204+ service_context_table = bus_config_parser_steal_service_context_table (parser);
3205+ if (!bus_registry_set_service_context_table (context->registry,
3206+ service_context_table))
3207+ {
3208+ BUS_SET_OOM (error);
3209+ return FALSE;
3210+ }
3211+
3212+ _dbus_hash_table_unref (service_context_table);
3213+
3214+ /* We need to monitor both the configuration directories and directories
3215+ * containing .service files.
3216+ */
3217+ if (!list_concat_new (bus_config_parser_get_conf_dirs (parser),
3218+ bus_config_parser_get_service_dirs (parser),
3219+ &watched_dirs))
3220+ {
3221+ BUS_SET_OOM (error);
3222+ return FALSE;
3223+ }
3224+
3225+ bus_set_watched_dirs (context, &watched_dirs);
3226+
3227+ _dbus_list_clear (&watched_dirs);
3228+
3229+ return TRUE;
3230+}
3231+
3232+BusContext*
3233+bus_context_new (const DBusString *config_file,
3234+ ForceForkSetting force_fork,
3235+ DBusPipe *print_addr_pipe,
3236+ DBusPipe *print_pid_pipe,
3237+ const DBusString *address,
3238+ dbus_bool_t systemd_activation,
3239+ DBusError *error)
3240+{
3241+ DBusString log_prefix;
3242+ BusContext *context;
3243+ BusConfigParser *parser;
3244+
3245+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3246+
3247+ context = NULL;
3248+ parser = NULL;
3249+
3250+ if (!dbus_server_allocate_data_slot (&server_data_slot))
3251+ {
3252+ BUS_SET_OOM (error);
3253+ return NULL;
3254+ }
3255+
3256+ context = dbus_new0 (BusContext, 1);
3257+ if (context == NULL)
3258+ {
3259+ BUS_SET_OOM (error);
3260+ goto failed;
3261+ }
3262+ context->refcount = 1;
3263+
3264+ _dbus_generate_uuid (&context->uuid);
3265+
3266+ if (!_dbus_string_copy_data (config_file, &context->config_file))
3267+ {
3268+ BUS_SET_OOM (error);
3269+ goto failed;
3270+ }
3271+
3272+ context->loop = _dbus_loop_new ();
3273+ if (context->loop == NULL)
3274+ {
3275+ BUS_SET_OOM (error);
3276+ goto failed;
3277+ }
3278+
3279+ context->registry = bus_registry_new (context);
3280+ if (context->registry == NULL)
3281+ {
3282+ BUS_SET_OOM (error);
3283+ goto failed;
3284+ }
3285+
3286+ parser = bus_config_load (config_file, TRUE, NULL, error);
3287+ if (parser == NULL)
3288+ {
3289+ _DBUS_ASSERT_ERROR_IS_SET (error);
3290+ goto failed;
3291+ }
3292+
3293+ if (!process_config_first_time_only (context, parser, address, systemd_activation, error))
3294+ {
3295+ _DBUS_ASSERT_ERROR_IS_SET (error);
3296+ goto failed;
3297+ }
3298+ if (!process_config_every_time (context, parser, FALSE, error))
3299+ {
3300+ _DBUS_ASSERT_ERROR_IS_SET (error);
3301+ goto failed;
3302+ }
3303+
3304+ /* we need another ref of the server data slot for the context
3305+ * to own
3306+ */
3307+ if (!dbus_server_allocate_data_slot (&server_data_slot))
3308+ _dbus_assert_not_reached ("second ref of server data slot failed");
3309+
3310+ /* Note that we don't know whether the print_addr_pipe is
3311+ * one of the sockets we're using to listen on, or some
3312+ * other random thing. But I think the answer is "don't do
3313+ * that then"
3314+ */
3315+ if (print_addr_pipe != NULL && _dbus_pipe_is_valid (print_addr_pipe))
3316+ {
3317+ DBusString addr;
3318+ const char *a = bus_context_get_address (context);
3319+ int bytes;
3320+
3321+ _dbus_assert (a != NULL);
3322+ if (!_dbus_string_init (&addr))
3323+ {
3324+ BUS_SET_OOM (error);
3325+ goto failed;
3326+ }
3327+
3328+ if (!_dbus_string_append (&addr, a) ||
3329+ !_dbus_string_append (&addr, "\n"))
3330+ {
3331+ _dbus_string_free (&addr);
3332+ BUS_SET_OOM (error);
3333+ goto failed;
3334+ }
3335+
3336+ bytes = _dbus_string_get_length (&addr);
3337+ if (_dbus_pipe_write (print_addr_pipe, &addr, 0, bytes, error) != bytes)
3338+ {
3339+ /* pipe write returns an error on failure but not short write */
3340+ if (error != NULL && !dbus_error_is_set (error))
3341+ {
3342+ dbus_set_error (error, DBUS_ERROR_FAILED,
3343+ "Printing message bus address: did not write all bytes\n");
3344+ }
3345+ _dbus_string_free (&addr);
3346+ goto failed;
3347+ }
3348+
3349+ if (!_dbus_pipe_is_stdout_or_stderr (print_addr_pipe))
3350+ _dbus_pipe_close (print_addr_pipe, NULL);
3351+
3352+ _dbus_string_free (&addr);
3353+ }
3354+
3355+ context->connections = bus_connections_new (context);
3356+ if (context->connections == NULL)
3357+ {
3358+ BUS_SET_OOM (error);
3359+ goto failed;
3360+ }
3361+
3362+ context->matchmaker = bus_matchmaker_new ();
3363+ if (context->matchmaker == NULL)
3364+ {
3365+ BUS_SET_OOM (error);
3366+ goto failed;
3367+ }
3368+
3369+ /* check user before we fork */
3370+ if (context->user != NULL)
3371+ {
3372+ if (!_dbus_verify_daemon_user (context->user))
3373+ {
3374+ dbus_set_error (error, DBUS_ERROR_FAILED,
3375+ "Could not get UID and GID for username \"%s\"",
3376+ context->user);
3377+ goto failed;
3378+ }
3379+ }
3380+
3381+ /* Now become a daemon if appropriate and write out pid file in any case */
3382+ {
3383+ DBusString u;
3384+
3385+ if (context->pidfile)
3386+ _dbus_string_init_const (&u, context->pidfile);
3387+
3388+ if ((force_fork != FORK_NEVER && context->fork) || force_fork == FORK_ALWAYS)
3389+ {
3390+ _dbus_verbose ("Forking and becoming daemon\n");
3391+
3392+ if (!_dbus_become_daemon (context->pidfile ? &u : NULL,
3393+ print_pid_pipe,
3394+ error,
3395+ context->keep_umask))
3396+ {
3397+ _DBUS_ASSERT_ERROR_IS_SET (error);
3398+ goto failed;
3399+ }
3400+ }
3401+ else
3402+ {
3403+ _dbus_verbose ("Fork not requested\n");
3404+
3405+ /* Need to write PID file and to PID pipe for ourselves,
3406+ * not for the child process. This is a no-op if the pidfile
3407+ * is NULL and print_pid_pipe is NULL.
3408+ */
3409+ if (!_dbus_write_pid_to_file_and_pipe (context->pidfile ? &u : NULL,
3410+ print_pid_pipe,
3411+ _dbus_getpid (),
3412+ error))
3413+ {
3414+ _DBUS_ASSERT_ERROR_IS_SET (error);
3415+ goto failed;
3416+ }
3417+ }
3418+ }
3419+
3420+ if (print_pid_pipe && _dbus_pipe_is_valid (print_pid_pipe) &&
3421+ !_dbus_pipe_is_stdout_or_stderr (print_pid_pipe))
3422+ _dbus_pipe_close (print_pid_pipe, NULL);
3423+
3424+ if (!bus_selinux_full_init ())
3425+ {
3426+ bus_context_log (context, DBUS_SYSTEM_LOG_FATAL, "SELinux enabled but AVC initialization failed; check system log\n");
3427+ }
3428+
3429+ if (!process_config_postinit (context, parser, error))
3430+ {
3431+ _DBUS_ASSERT_ERROR_IS_SET (error);
3432+ goto failed;
3433+ }
3434+
3435+ if (parser != NULL)
3436+ {
3437+ bus_config_parser_unref (parser);
3438+ parser = NULL;
3439+ }
3440+
3441+ /* Here we change our credentials if required,
3442+ * as soon as we've set up our sockets and pidfile
3443+ */
3444+ if (context->user != NULL)
3445+ {
3446+ if (!_dbus_change_to_daemon_user (context->user, error))
3447+ {
3448+ _DBUS_ASSERT_ERROR_IS_SET (error);
3449+ goto failed;
3450+ }
3451+
3452+#ifdef HAVE_SELINUX
3453+ /* FIXME - why not just put this in full_init() below? */
3454+ bus_selinux_audit_init ();
3455+#endif
3456+ }
3457+
3458+ dbus_server_free_data_slot (&server_data_slot);
3459+
3460+ return context;
3461+
3462+ failed:
3463+ if (parser != NULL)
3464+ bus_config_parser_unref (parser);
3465+ if (context != NULL)
3466+ bus_context_unref (context);
3467+
3468+ if (server_data_slot >= 0)
3469+ dbus_server_free_data_slot (&server_data_slot);
3470+
3471+ return NULL;
3472+}
3473+
3474+dbus_bool_t
3475+bus_context_get_id (BusContext *context,
3476+ DBusString *uuid)
3477+{
3478+ return _dbus_uuid_encode (&context->uuid, uuid);
3479+}
3480+
3481+dbus_bool_t
3482+bus_context_reload_config (BusContext *context,
3483+ DBusError *error)
3484+{
3485+ BusConfigParser *parser;
3486+ DBusString config_file;
3487+ dbus_bool_t ret;
3488+
3489+ /* Flush the user database cache */
3490+ _dbus_flush_caches ();
3491+
3492+ ret = FALSE;
3493+ _dbus_string_init_const (&config_file, context->config_file);
3494+ parser = bus_config_load (&config_file, TRUE, NULL, error);
3495+ if (parser == NULL)
3496+ {
3497+ _DBUS_ASSERT_ERROR_IS_SET (error);
3498+ goto failed;
3499+ }
3500+
3501+ if (!process_config_every_time (context, parser, TRUE, error))
3502+ {
3503+ _DBUS_ASSERT_ERROR_IS_SET (error);
3504+ goto failed;
3505+ }
3506+ if (!process_config_postinit (context, parser, error))
3507+ {
3508+ _DBUS_ASSERT_ERROR_IS_SET (error);
3509+ goto failed;
3510+ }
3511+ ret = TRUE;
3512+
3513+ bus_context_log (context, DBUS_SYSTEM_LOG_INFO, "Reloaded configuration");
3514+ failed:
3515+ if (!ret)
3516+ bus_context_log (context, DBUS_SYSTEM_LOG_INFO, "Unable to reload configuration: %s", error->message);
3517+ if (parser != NULL)
3518+ bus_config_parser_unref (parser);
3519+ return ret;
3520+}
3521+
3522+static void
3523+shutdown_server (BusContext *context,
3524+ DBusServer *server)
3525+{
3526+ if (server == NULL ||
3527+ !dbus_server_get_is_connected (server))
3528+ return;
3529+
3530+ if (!dbus_server_set_watch_functions (server,
3531+ NULL, NULL, NULL,
3532+ context,
3533+ NULL))
3534+ _dbus_assert_not_reached ("setting watch functions to NULL failed");
3535+
3536+ if (!dbus_server_set_timeout_functions (server,
3537+ NULL, NULL, NULL,
3538+ context,
3539+ NULL))
3540+ _dbus_assert_not_reached ("setting timeout functions to NULL failed");
3541+
3542+ dbus_server_disconnect (server);
3543+}
3544+
3545+void
3546+bus_context_shutdown (BusContext *context)
3547+{
3548+ DBusList *link;
3549+
3550+ link = _dbus_list_get_first_link (&context->servers);
3551+ while (link != NULL)
3552+ {
3553+ shutdown_server (context, link->data);
3554+
3555+ link = _dbus_list_get_next_link (&context->servers, link);
3556+ }
3557+}
3558+
3559+BusContext *
3560+bus_context_ref (BusContext *context)
3561+{
3562+ _dbus_assert (context->refcount > 0);
3563+ context->refcount += 1;
3564+
3565+ return context;
3566+}
3567+
3568+void
3569+bus_context_unref (BusContext *context)
3570+{
3571+ _dbus_assert (context->refcount > 0);
3572+ context->refcount -= 1;
3573+
3574+ if (context->refcount == 0)
3575+ {
3576+ DBusList *link;
3577+
3578+ _dbus_verbose ("Finalizing bus context %p\n", context);
3579+
3580+ bus_context_shutdown (context);
3581+
3582+ if (context->connections)
3583+ {
3584+ bus_connections_unref (context->connections);
3585+ context->connections = NULL;
3586+ }
3587+
3588+ if (context->registry)
3589+ {
3590+ bus_registry_unref (context->registry);
3591+ context->registry = NULL;
3592+ }
3593+
3594+ if (context->activation)
3595+ {
3596+ bus_activation_unref (context->activation);
3597+ context->activation = NULL;
3598+ }
3599+
3600+ link = _dbus_list_get_first_link (&context->servers);
3601+ while (link != NULL)
3602+ {
3603+ dbus_server_unref (link->data);
3604+
3605+ link = _dbus_list_get_next_link (&context->servers, link);
3606+ }
3607+ _dbus_list_clear (&context->servers);
3608+
3609+ if (context->policy)
3610+ {
3611+ bus_policy_unref (context->policy);
3612+ context->policy = NULL;
3613+ }
3614+
3615+ if (context->loop)
3616+ {
3617+ _dbus_loop_unref (context->loop);
3618+ context->loop = NULL;
3619+ }
3620+
3621+ if (context->matchmaker)
3622+ {
3623+ bus_matchmaker_unref (context->matchmaker);
3624+ context->matchmaker = NULL;
3625+ }
3626+
3627+ dbus_free (context->config_file);
3628+ dbus_free (context->log_prefix);
3629+ dbus_free (context->type);
3630+ dbus_free (context->address);
3631+ dbus_free (context->user);
3632+ dbus_free (context->servicehelper);
3633+
3634+ if (context->pidfile)
3635+ {
3636+ DBusString u;
3637+ _dbus_string_init_const (&u, context->pidfile);
3638+
3639+ /* Deliberately ignore errors here, since there's not much
3640+ * we can do about it, and we're exiting anyways.
3641+ */
3642+ _dbus_delete_file (&u, NULL);
3643+
3644+ dbus_free (context->pidfile);
3645+ }
3646+ dbus_free (context);
3647+
3648+ dbus_server_free_data_slot (&server_data_slot);
3649+ }
3650+}
3651+
3652+/* type may be NULL */
3653+const char*
3654+bus_context_get_type (BusContext *context)
3655+{
3656+ return context->type;
3657+}
3658+
3659+const char*
3660+bus_context_get_address (BusContext *context)
3661+{
3662+ return context->address;
3663+}
3664+
3665+const char*
3666+bus_context_get_servicehelper (BusContext *context)
3667+{
3668+ return context->servicehelper;
3669+}
3670+
3671+dbus_bool_t
3672+bus_context_get_systemd_activation (BusContext *context)
3673+{
3674+ return context->systemd_activation;
3675+}
3676+
3677+BusRegistry*
3678+bus_context_get_registry (BusContext *context)
3679+{
3680+ return context->registry;
3681+}
3682+
3683+BusConnections*
3684+bus_context_get_connections (BusContext *context)
3685+{
3686+ return context->connections;
3687+}
3688+
3689+BusActivation*
3690+bus_context_get_activation (BusContext *context)
3691+{
3692+ return context->activation;
3693+}
3694+
3695+BusMatchmaker*
3696+bus_context_get_matchmaker (BusContext *context)
3697+{
3698+ return context->matchmaker;
3699+}
3700+
3701+DBusLoop*
3702+bus_context_get_loop (BusContext *context)
3703+{
3704+ return context->loop;
3705+}
3706+
3707+dbus_bool_t
3708+bus_context_allow_unix_user (BusContext *context,
3709+ unsigned long uid)
3710+{
3711+ return bus_policy_allow_unix_user (context->policy,
3712+ uid);
3713+}
3714+
3715+/* For now this is never actually called because the default
3716+ * DBusConnection behavior of 'same user that owns the bus can connect'
3717+ * is all it would do.
3718+ */
3719+dbus_bool_t
3720+bus_context_allow_windows_user (BusContext *context,
3721+ const char *windows_sid)
3722+{
3723+ return bus_policy_allow_windows_user (context->policy,
3724+ windows_sid);
3725+}
3726+
3727+BusPolicy *
3728+bus_context_get_policy (BusContext *context)
3729+{
3730+ return context->policy;
3731+}
3732+
3733+BusClientPolicy*
3734+bus_context_create_client_policy (BusContext *context,
3735+ DBusConnection *connection,
3736+ DBusError *error)
3737+{
3738+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
3739+ return bus_policy_create_client_policy (context->policy, connection,
3740+ error);
3741+}
3742+
3743+int
3744+bus_context_get_activation_timeout (BusContext *context)
3745+{
3746+
3747+ return context->limits.activation_timeout;
3748+}
3749+
3750+int
3751+bus_context_get_auth_timeout (BusContext *context)
3752+{
3753+ return context->limits.auth_timeout;
3754+}
3755+
3756+int
3757+bus_context_get_max_completed_connections (BusContext *context)
3758+{
3759+ return context->limits.max_completed_connections;
3760+}
3761+
3762+int
3763+bus_context_get_max_incomplete_connections (BusContext *context)
3764+{
3765+ return context->limits.max_incomplete_connections;
3766+}
3767+
3768+int
3769+bus_context_get_max_connections_per_user (BusContext *context)
3770+{
3771+ return context->limits.max_connections_per_user;
3772+}
3773+
3774+int
3775+bus_context_get_max_pending_activations (BusContext *context)
3776+{
3777+ return context->limits.max_pending_activations;
3778+}
3779+
3780+int
3781+bus_context_get_max_services_per_connection (BusContext *context)
3782+{
3783+ return context->limits.max_services_per_connection;
3784+}
3785+
3786+int
3787+bus_context_get_max_match_rules_per_connection (BusContext *context)
3788+{
3789+ return context->limits.max_match_rules_per_connection;
3790+}
3791+
3792+int
3793+bus_context_get_max_replies_per_connection (BusContext *context)
3794+{
3795+ return context->limits.max_replies_per_connection;
3796+}
3797+
3798+int
3799+bus_context_get_reply_timeout (BusContext *context)
3800+{
3801+ return context->limits.reply_timeout;
3802+}
3803+
3804+void
3805+bus_context_log (BusContext *context, DBusSystemLogSeverity severity, const char *msg, ...) _DBUS_GNUC_PRINTF (3, 4);
3806+
3807+void
3808+bus_context_log (BusContext *context, DBusSystemLogSeverity severity, const char *msg, ...)
3809+{
3810+ va_list args;
3811+
3812+ if (!context->syslog)
3813+ return;
3814+
3815+ va_start (args, msg);
3816+
3817+ if (context->log_prefix)
3818+ {
3819+ DBusString full_msg;
3820+
3821+ if (!_dbus_string_init (&full_msg))
3822+ goto out;
3823+ if (!_dbus_string_append (&full_msg, context->log_prefix))
3824+ goto oom_out;
3825+ if (!_dbus_string_append_printf_valist (&full_msg, msg, args))
3826+ goto oom_out;
3827+
3828+ _dbus_system_log (severity, "%s", _dbus_string_get_const_data (&full_msg));
3829+ oom_out:
3830+ _dbus_string_free (&full_msg);
3831+ }
3832+ else
3833+ _dbus_system_logv (severity, msg, args);
3834+
3835+out:
3836+ va_end (args);
3837+}
3838+
3839+/*
3840+ * addressed_recipient is the recipient specified in the message.
3841+ *
3842+ * proposed_recipient is the recipient we're considering sending
3843+ * to right this second, and may be an eavesdropper.
3844+ *
3845+ * sender is the sender of the message.
3846+ *
3847+ * NULL for proposed_recipient or sender definitely means the bus driver.
3848+ *
3849+ * NULL for addressed_recipient may mean the bus driver, or may mean
3850+ * no destination was specified in the message (e.g. a signal).
3851+ */
3852+dbus_bool_t
3853+bus_context_check_security_policy (BusContext *context,
3854+ BusTransaction *transaction,
3855+ DBusConnection *sender,
3856+ DBusConnection *addressed_recipient,
3857+ DBusConnection *proposed_recipient,
3858+ DBusMessage *message,
3859+ DBusError *error)
3860+{
3861+ const char *dest;
3862+ BusClientPolicy *sender_policy;
3863+ BusClientPolicy *recipient_policy;
3864+ dbus_int32_t toggles;
3865+ dbus_bool_t log;
3866+ int type;
3867+ dbus_bool_t requested_reply;
3868+ const char *sender_name;
3869+ const char *sender_loginfo;
3870+ const char *proposed_recipient_loginfo;
3871+
3872+ type = dbus_message_get_type (message);
3873+ dest = dbus_message_get_destination (message);
3874+
3875+ /* dispatch.c was supposed to ensure these invariants */
3876+ _dbus_assert (dest != NULL ||
3877+ type == DBUS_MESSAGE_TYPE_SIGNAL ||
3878+ (sender == NULL && !bus_connection_is_active (proposed_recipient)));
3879+ _dbus_assert (type == DBUS_MESSAGE_TYPE_SIGNAL ||
3880+ addressed_recipient != NULL ||
3881+ strcmp (dest, DBUS_SERVICE_DBUS) == 0);
3882+
3883+ /* Used in logging below */
3884+ if (sender != NULL)
3885+ {
3886+ sender_name = bus_connection_get_name (sender);
3887+ sender_loginfo = bus_connection_get_loginfo (sender);
3888+ }
3889+ else
3890+ {
3891+ sender_name = NULL;
3892+ sender_loginfo = "(bus)";
3893+ }
3894+
3895+ if (proposed_recipient != NULL)
3896+ proposed_recipient_loginfo = bus_connection_get_loginfo (proposed_recipient);
3897+ else
3898+ proposed_recipient_loginfo = "bus";
3899+
3900+ switch (type)
3901+ {
3902+ case DBUS_MESSAGE_TYPE_METHOD_CALL:
3903+ case DBUS_MESSAGE_TYPE_SIGNAL:
3904+ case DBUS_MESSAGE_TYPE_METHOD_RETURN:
3905+ case DBUS_MESSAGE_TYPE_ERROR:
3906+ break;
3907+
3908+ default:
3909+ _dbus_verbose ("security check disallowing message of unknown type %d\n",
3910+ type);
3911+
3912+ dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
3913+ "Message bus will not accept messages of unknown type\n");
3914+
3915+ return FALSE;
3916+ }
3917+
3918+ requested_reply = FALSE;
3919+
3920+ if (sender != NULL)
3921+ {
3922+ /* First verify the SELinux access controls. If allowed then
3923+ * go on with the standard checks.
3924+ */
3925+ if (!bus_selinux_allows_send (sender, proposed_recipient,
3926+ dbus_message_type_to_string (dbus_message_get_type (message)),
3927+ dbus_message_get_interface (message),
3928+ dbus_message_get_member (message),
3929+ dbus_message_get_error_name (message),
3930+ dest ? dest : DBUS_SERVICE_DBUS, error))
3931+ {
3932+ if (error != NULL && !dbus_error_is_set (error))
3933+ {
3934+ dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
3935+ "An SELinux policy prevents this sender "
3936+ "from sending this message to this recipient "
3937+ "(rejected message had sender \"%s\" interface \"%s\" "
3938+ "member \"%s\" error name \"%s\" destination \"%s\")",
3939+ sender_name ? sender_name : "(unset)",
3940+ dbus_message_get_interface (message) ?
3941+ dbus_message_get_interface (message) : "(unset)",
3942+ dbus_message_get_member (message) ?
3943+ dbus_message_get_member (message) : "(unset)",
3944+ dbus_message_get_error_name (message) ?
3945+ dbus_message_get_error_name (message) : "(unset)",
3946+ dest ? dest : DBUS_SERVICE_DBUS);
3947+ _dbus_verbose ("SELinux security check denying send to service\n");
3948+ }
3949+
3950+ return FALSE;
3951+ }
3952+
3953+ if (bus_connection_is_active (sender))
3954+ {
3955+ sender_policy = bus_connection_get_policy (sender);
3956+ _dbus_assert (sender_policy != NULL);
3957+
3958+ /* Fill in requested_reply variable with TRUE if this is a
3959+ * reply and the reply was pending.
3960+ */
3961+ if (dbus_message_get_reply_serial (message) != 0)
3962+ {
3963+ if (proposed_recipient != NULL /* not to the bus driver */ &&
3964+ addressed_recipient == proposed_recipient /* not eavesdropping */)
3965+ {
3966+ DBusError error2;
3967+
3968+ dbus_error_init (&error2);
3969+ requested_reply = bus_connections_check_reply (bus_connection_get_connections (sender),
3970+ transaction,
3971+ sender, addressed_recipient, message,
3972+ &error2);
3973+ if (dbus_error_is_set (&error2))
3974+ {
3975+ dbus_move_error (&error2, error);
3976+ return FALSE;
3977+ }
3978+ }
3979+ }
3980+ }
3981+ else
3982+ {
3983+ /* Policy for inactive connections is that they can only send
3984+ * the hello message to the bus driver
3985+ */
3986+ if (proposed_recipient == NULL &&
3987+ dbus_message_is_method_call (message,
3988+ DBUS_INTERFACE_DBUS,
3989+ "Hello"))
3990+ {
3991+ _dbus_verbose ("security check allowing %s message\n",
3992+ "Hello");
3993+ return TRUE;
3994+ }
3995+ else
3996+ {
3997+ _dbus_verbose ("security check disallowing non-%s message\n",
3998+ "Hello");
3999+
4000+ dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
4001+ "Client tried to send a message other than %s without being registered",
4002+ "Hello");
4003+
4004+ return FALSE;
4005+ }
4006+ }
4007+ }
4008+ else
4009+ {
4010+ sender_policy = NULL;
4011+
4012+ /* If the sender is the bus driver, we assume any reply was a
4013+ * requested reply as bus driver won't send bogus ones
4014+ */
4015+ if (addressed_recipient == proposed_recipient /* not eavesdropping */ &&
4016+ dbus_message_get_reply_serial (message) != 0)
4017+ requested_reply = TRUE;
4018+ }
4019+
4020+ _dbus_assert ((sender != NULL && sender_policy != NULL) ||
4021+ (sender == NULL && sender_policy == NULL));
4022+
4023+ if (proposed_recipient != NULL)
4024+ {
4025+ /* only the bus driver can send to an inactive recipient (as it
4026+ * owns no services, so other apps can't address it). Inactive
4027+ * recipients can receive any message.
4028+ */
4029+ if (bus_connection_is_active (proposed_recipient))
4030+ {
4031+ recipient_policy = bus_connection_get_policy (proposed_recipient);
4032+ _dbus_assert (recipient_policy != NULL);
4033+ }
4034+ else if (sender == NULL)
4035+ {
4036+ _dbus_verbose ("security check using NULL recipient policy for message from bus\n");
4037+ recipient_policy = NULL;
4038+ }
4039+ else
4040+ {
4041+ _dbus_assert_not_reached ("a message was somehow sent to an inactive recipient from a source other than the message bus\n");
4042+ recipient_policy = NULL;
4043+ }
4044+ }
4045+ else
4046+ recipient_policy = NULL;
4047+
4048+ _dbus_assert ((proposed_recipient != NULL && recipient_policy != NULL) ||
4049+ (proposed_recipient != NULL && sender == NULL && recipient_policy == NULL) ||
4050+ (proposed_recipient == NULL && recipient_policy == NULL));
4051+
4052+ log = FALSE;
4053+ if (sender_policy &&
4054+ !bus_client_policy_check_can_send (sender_policy,
4055+ context->registry,
4056+ requested_reply,
4057+ proposed_recipient,
4058+ message, &toggles, &log))
4059+ {
4060+ const char *msg = "Rejected send message, %d matched rules; "
4061+ "type=\"%s\", sender=\"%s\" (%s) interface=\"%s\" member=\"%s\" error name=\"%s\" requested_reply=%d destination=\"%s\" (%s))";
4062+
4063+ dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, msg,
4064+ toggles,
4065+ dbus_message_type_to_string (dbus_message_get_type (message)),
4066+ sender_name ? sender_name : "(unset)",
4067+ sender_loginfo,
4068+ dbus_message_get_interface (message) ?
4069+ dbus_message_get_interface (message) : "(unset)",
4070+ dbus_message_get_member (message) ?
4071+ dbus_message_get_member (message) : "(unset)",
4072+ dbus_message_get_error_name (message) ?
4073+ dbus_message_get_error_name (message) : "(unset)",
4074+ requested_reply,
4075+ dest ? dest : DBUS_SERVICE_DBUS,
4076+ proposed_recipient_loginfo);
4077+ /* Needs to be duplicated to avoid calling malloc and having to handle OOM */
4078+ if (addressed_recipient == proposed_recipient)
4079+ bus_context_log (context, DBUS_SYSTEM_LOG_SECURITY, msg,
4080+ toggles,
4081+ dbus_message_type_to_string (dbus_message_get_type (message)),
4082+ sender_name ? sender_name : "(unset)",
4083+ sender_loginfo,
4084+ dbus_message_get_interface (message) ?
4085+ dbus_message_get_interface (message) : "(unset)",
4086+ dbus_message_get_member (message) ?
4087+ dbus_message_get_member (message) : "(unset)",
4088+ dbus_message_get_error_name (message) ?
4089+ dbus_message_get_error_name (message) : "(unset)",
4090+ requested_reply,
4091+ dest ? dest : DBUS_SERVICE_DBUS,
4092+ proposed_recipient_loginfo);
4093+ _dbus_verbose ("security policy disallowing message due to sender policy\n");
4094+ return FALSE;
4095+ }
4096+
4097+ if (log)
4098+ bus_context_log (context, DBUS_SYSTEM_LOG_SECURITY,
4099+ "Would reject message, %d matched rules; "
4100+ "type=\"%s\", sender=\"%s\" (%s) interface=\"%s\" member=\"%s\" error name=\"%s\" requested_reply=%d destination=\"%s\" (%s))",
4101+ toggles,
4102+ dbus_message_type_to_string (dbus_message_get_type (message)),
4103+ sender_name ? sender_name : "(unset)",
4104+ sender_loginfo,
4105+ dbus_message_get_interface (message) ?
4106+ dbus_message_get_interface (message) : "(unset)",
4107+ dbus_message_get_member (message) ?
4108+ dbus_message_get_member (message) : "(unset)",
4109+ dbus_message_get_error_name (message) ?
4110+ dbus_message_get_error_name (message) : "(unset)",
4111+ requested_reply,
4112+ dest ? dest : DBUS_SERVICE_DBUS,
4113+ proposed_recipient_loginfo);
4114+
4115+ if (recipient_policy &&
4116+ !bus_client_policy_check_can_receive (recipient_policy,
4117+ context->registry,
4118+ requested_reply,
4119+ sender,
4120+ addressed_recipient, proposed_recipient,
4121+ message, &toggles))
4122+ {
4123+ const char *msg = "Rejected receive message, %d matched rules; "
4124+ "type=\"%s\" sender=\"%s\" (%s) interface=\"%s\" member=\"%s\" error name=\"%s\" reply serial=%u requested_reply=%d destination=\"%s\" (%s))";
4125+
4126+ dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, msg,
4127+ toggles,
4128+ dbus_message_type_to_string (dbus_message_get_type (message)),
4129+ sender_name ? sender_name : "(unset)",
4130+ sender_loginfo,
4131+ dbus_message_get_interface (message) ?
4132+ dbus_message_get_interface (message) : "(unset)",
4133+ dbus_message_get_member (message) ?
4134+ dbus_message_get_member (message) : "(unset)",
4135+ dbus_message_get_error_name (message) ?
4136+ dbus_message_get_error_name (message) : "(unset)",
4137+ dbus_message_get_reply_serial (message),
4138+ requested_reply,
4139+ dest ? dest : DBUS_SERVICE_DBUS,
4140+ proposed_recipient_loginfo);
4141+ /* Needs to be duplicated to avoid calling malloc and having to handle OOM */
4142+ if (addressed_recipient == proposed_recipient)
4143+ bus_context_log (context, DBUS_SYSTEM_LOG_SECURITY, msg,
4144+ toggles,
4145+ dbus_message_type_to_string (dbus_message_get_type (message)),
4146+ sender_name ? sender_name : "(unset)",
4147+ sender_loginfo,
4148+ dbus_message_get_interface (message) ?
4149+ dbus_message_get_interface (message) : "(unset)",
4150+ dbus_message_get_member (message) ?
4151+ dbus_message_get_member (message) : "(unset)",
4152+ dbus_message_get_error_name (message) ?
4153+ dbus_message_get_error_name (message) : "(unset)",
4154+ dbus_message_get_reply_serial (message),
4155+ requested_reply,
4156+ dest ? dest : DBUS_SERVICE_DBUS,
4157+ proposed_recipient_loginfo);
4158+ _dbus_verbose ("security policy disallowing message due to recipient policy\n");
4159+ return FALSE;
4160+ }
4161+
4162+ /* See if limits on size have been exceeded */
4163+ if (proposed_recipient &&
4164+ ((dbus_connection_get_outgoing_size (proposed_recipient) > context->limits.max_outgoing_bytes) ||
4165+ (dbus_connection_get_outgoing_unix_fds (proposed_recipient) > context->limits.max_outgoing_unix_fds)))
4166+ {
4167+ dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
4168+ "The destination service \"%s\" has a full message queue",
4169+ dest ? dest : (proposed_recipient ?
4170+ bus_connection_get_name (proposed_recipient) :
4171+ DBUS_SERVICE_DBUS));
4172+ _dbus_verbose ("security policy disallowing message due to full message queue\n");
4173+ return FALSE;
4174+ }
4175+
4176+ /* Record that we will allow a reply here in the future (don't
4177+ * bother if the recipient is the bus or this is an eavesdropping
4178+ * connection). Only the addressed recipient may reply.
4179+ */
4180+ if (type == DBUS_MESSAGE_TYPE_METHOD_CALL &&
4181+ sender &&
4182+ addressed_recipient &&
4183+ addressed_recipient == proposed_recipient && /* not eavesdropping */
4184+ !bus_connections_expect_reply (bus_connection_get_connections (sender),
4185+ transaction,
4186+ sender, addressed_recipient,
4187+ message, error))
4188+ {
4189+ _dbus_verbose ("Failed to record reply expectation or problem with the message expecting a reply\n");
4190+ return FALSE;
4191+ }
4192+
4193+ _dbus_verbose ("security policy allowing message\n");
4194+ return TRUE;
4195+}
4196
4197=== added file '.pc/0001-activation-allow-for-more-variation-than-just-system.patch/bus/bus.h'
4198--- .pc/0001-activation-allow-for-more-variation-than-just-system.patch/bus/bus.h 1970-01-01 00:00:00 +0000
4199+++ .pc/0001-activation-allow-for-more-variation-than-just-system.patch/bus/bus.h 2011-03-28 07:17:28 +0000
4200@@ -0,0 +1,128 @@
4201+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
4202+/* bus.h message bus context object
4203+ *
4204+ * Copyright (C) 2003 Red Hat, Inc.
4205+ *
4206+ * Licensed under the Academic Free License version 2.1
4207+ *
4208+ * This program is free software; you can redistribute it and/or modify
4209+ * it under the terms of the GNU General Public License as published by
4210+ * the Free Software Foundation; either version 2 of the License, or
4211+ * (at your option) any later version.
4212+ *
4213+ * This program is distributed in the hope that it will be useful,
4214+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4215+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4216+ * GNU General Public License for more details.
4217+ *
4218+ * You should have received a copy of the GNU General Public License
4219+ * along with this program; if not, write to the Free Software
4220+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
4221+ *
4222+ */
4223+
4224+#ifndef BUS_BUS_H
4225+#define BUS_BUS_H
4226+
4227+#include <dbus/dbus.h>
4228+#include <dbus/dbus-string.h>
4229+#include <dbus/dbus-mainloop.h>
4230+#include <dbus/dbus-pipe.h>
4231+#include <dbus/dbus-sysdeps.h>
4232+
4233+typedef struct BusActivation BusActivation;
4234+typedef struct BusConnections BusConnections;
4235+typedef struct BusContext BusContext;
4236+typedef struct BusPolicy BusPolicy;
4237+typedef struct BusClientPolicy BusClientPolicy;
4238+typedef struct BusPolicyRule BusPolicyRule;
4239+typedef struct BusRegistry BusRegistry;
4240+typedef struct BusSELinuxID BusSELinuxID;
4241+typedef struct BusService BusService;
4242+typedef struct BusOwner BusOwner;
4243+typedef struct BusTransaction BusTransaction;
4244+typedef struct BusMatchmaker BusMatchmaker;
4245+typedef struct BusMatchRule BusMatchRule;
4246+
4247+typedef struct
4248+{
4249+ long max_incoming_bytes; /**< How many incoming message bytes for a single connection */
4250+ long max_incoming_unix_fds; /**< How many incoming message unix fds for a single connection */
4251+ long max_outgoing_bytes; /**< How many outgoing bytes can be queued for a single connection */
4252+ long max_outgoing_unix_fds; /**< How many outgoing unix fds can be queued for a single connection */
4253+ long max_message_size; /**< Max size of a single message in bytes */
4254+ long max_message_unix_fds; /**< Max number of unix fds of a single message*/
4255+ int activation_timeout; /**< How long to wait for an activation to time out */
4256+ int auth_timeout; /**< How long to wait for an authentication to time out */
4257+ int max_completed_connections; /**< Max number of authorized connections */
4258+ int max_incomplete_connections; /**< Max number of incomplete connections */
4259+ int max_connections_per_user; /**< Max number of connections auth'd as same user */
4260+ int max_pending_activations; /**< Max number of pending activations for the entire bus */
4261+ int max_services_per_connection; /**< Max number of owned services for a single connection */
4262+ int max_match_rules_per_connection; /**< Max number of match rules for a single connection */
4263+ int max_replies_per_connection; /**< Max number of replies that can be pending for each connection */
4264+ int reply_timeout; /**< How long to wait before timing out a reply */
4265+} BusLimits;
4266+
4267+typedef enum
4268+{
4269+ FORK_FOLLOW_CONFIG_FILE,
4270+ FORK_ALWAYS,
4271+ FORK_NEVER
4272+} ForceForkSetting;
4273+
4274+BusContext* bus_context_new (const DBusString *config_file,
4275+ ForceForkSetting force_fork,
4276+ DBusPipe *print_addr_pipe,
4277+ DBusPipe *print_pid_pipe,
4278+ const DBusString *address,
4279+ dbus_bool_t systemd_activation,
4280+ DBusError *error);
4281+dbus_bool_t bus_context_reload_config (BusContext *context,
4282+ DBusError *error);
4283+void bus_context_shutdown (BusContext *context);
4284+BusContext* bus_context_ref (BusContext *context);
4285+void bus_context_unref (BusContext *context);
4286+dbus_bool_t bus_context_get_id (BusContext *context,
4287+ DBusString *uuid);
4288+const char* bus_context_get_type (BusContext *context);
4289+const char* bus_context_get_address (BusContext *context);
4290+const char* bus_context_get_servicehelper (BusContext *context);
4291+dbus_bool_t bus_context_get_systemd_activation (BusContext *context);
4292+BusRegistry* bus_context_get_registry (BusContext *context);
4293+BusConnections* bus_context_get_connections (BusContext *context);
4294+BusActivation* bus_context_get_activation (BusContext *context);
4295+BusMatchmaker* bus_context_get_matchmaker (BusContext *context);
4296+DBusLoop* bus_context_get_loop (BusContext *context);
4297+dbus_bool_t bus_context_allow_unix_user (BusContext *context,
4298+ unsigned long uid);
4299+dbus_bool_t bus_context_allow_windows_user (BusContext *context,
4300+ const char *windows_sid);
4301+BusPolicy* bus_context_get_policy (BusContext *context);
4302+
4303+BusClientPolicy* bus_context_create_client_policy (BusContext *context,
4304+ DBusConnection *connection,
4305+ DBusError *error);
4306+int bus_context_get_activation_timeout (BusContext *context);
4307+int bus_context_get_auth_timeout (BusContext *context);
4308+int bus_context_get_max_completed_connections (BusContext *context);
4309+int bus_context_get_max_incomplete_connections (BusContext *context);
4310+int bus_context_get_max_connections_per_user (BusContext *context);
4311+int bus_context_get_max_pending_activations (BusContext *context);
4312+int bus_context_get_max_services_per_connection (BusContext *context);
4313+int bus_context_get_max_match_rules_per_connection (BusContext *context);
4314+int bus_context_get_max_replies_per_connection (BusContext *context);
4315+int bus_context_get_reply_timeout (BusContext *context);
4316+void bus_context_log (BusContext *context,
4317+ DBusSystemLogSeverity severity,
4318+ const char *msg,
4319+ ...);
4320+dbus_bool_t bus_context_check_security_policy (BusContext *context,
4321+ BusTransaction *transaction,
4322+ DBusConnection *sender,
4323+ DBusConnection *addressed_recipient,
4324+ DBusConnection *proposed_recipient,
4325+ DBusMessage *message,
4326+ DBusError *error);
4327+
4328+#endif /* BUS_BUS_H */
4329
4330=== added file '.pc/0001-activation-allow-for-more-variation-than-just-system.patch/bus/main.c'
4331--- .pc/0001-activation-allow-for-more-variation-than-just-system.patch/bus/main.c 1970-01-01 00:00:00 +0000
4332+++ .pc/0001-activation-allow-for-more-variation-than-just-system.patch/bus/main.c 2011-03-28 07:17:28 +0000
4333@@ -0,0 +1,527 @@
4334+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
4335+/* main.c main() for message bus
4336+ *
4337+ * Copyright (C) 2003 Red Hat, Inc.
4338+ *
4339+ * Licensed under the Academic Free License version 2.1
4340+ *
4341+ * This program is free software; you can redistribute it and/or modify
4342+ * it under the terms of the GNU General Public License as published by
4343+ * the Free Software Foundation; either version 2 of the License, or
4344+ * (at your option) any later version.
4345+ *
4346+ * This program is distributed in the hope that it will be useful,
4347+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4348+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4349+ * GNU General Public License for more details.
4350+ *
4351+ * You should have received a copy of the GNU General Public License
4352+ * along with this program; if not, write to the Free Software
4353+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
4354+ *
4355+ */
4356+
4357+#include <config.h>
4358+#include "bus.h"
4359+#include "driver.h"
4360+#include <dbus/dbus-internals.h>
4361+#include <dbus/dbus-watch.h>
4362+#include <stdio.h>
4363+#include <stdlib.h>
4364+#include <string.h>
4365+#ifdef HAVE_SIGNAL_H
4366+#include <signal.h>
4367+#endif
4368+#ifdef HAVE_ERRNO_H
4369+#include <errno.h>
4370+#endif
4371+#include "selinux.h"
4372+
4373+static BusContext *context;
4374+
4375+static int reload_pipe[2];
4376+#define RELOAD_READ_END 0
4377+#define RELOAD_WRITE_END 1
4378+
4379+static void close_reload_pipe (void);
4380+
4381+static void
4382+signal_handler (int sig)
4383+{
4384+
4385+ switch (sig)
4386+ {
4387+#ifdef DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX
4388+ case SIGIO:
4389+ /* explicit fall-through */
4390+#endif /* DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX */
4391+#ifdef SIGHUP
4392+ case SIGHUP:
4393+ {
4394+ DBusString str;
4395+ _dbus_string_init_const (&str, "foo");
4396+ if ((reload_pipe[RELOAD_WRITE_END] > 0) &&
4397+ !_dbus_write_socket (reload_pipe[RELOAD_WRITE_END], &str, 0, 1))
4398+ {
4399+ _dbus_warn ("Unable to write to reload pipe.\n");
4400+ close_reload_pipe ();
4401+ }
4402+ }
4403+ break;
4404+#endif
4405+ }
4406+}
4407+
4408+static void
4409+usage (void)
4410+{
4411+ fprintf (stderr, DBUS_DAEMON_NAME " [--version] [--session] [--system] [--config-file=FILE] [--print-address[=DESCRIPTOR]] [--print-pid[=DESCRIPTOR]] [--fork] [--nofork] [--introspect] [--address=ADDRESS] [--systemd-activation]\n");
4412+ exit (1);
4413+}
4414+
4415+static void
4416+version (void)
4417+{
4418+ printf ("D-Bus Message Bus Daemon %s\n"
4419+ "Copyright (C) 2002, 2003 Red Hat, Inc., CodeFactory AB, and others\n"
4420+ "This is free software; see the source for copying conditions.\n"
4421+ "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
4422+ DBUS_VERSION_STRING);
4423+ exit (0);
4424+}
4425+
4426+static void
4427+introspect (void)
4428+{
4429+ DBusString xml;
4430+ const char *v_STRING;
4431+
4432+ if (!_dbus_string_init (&xml))
4433+ goto oom;
4434+
4435+ if (!bus_driver_generate_introspect_string (&xml))
4436+ {
4437+ _dbus_string_free (&xml);
4438+ goto oom;
4439+ }
4440+
4441+ v_STRING = _dbus_string_get_const_data (&xml);
4442+ printf ("%s\n", v_STRING);
4443+
4444+ exit (0);
4445+
4446+ oom:
4447+ _dbus_warn ("Can not introspect - Out of memory\n");
4448+ exit (1);
4449+}
4450+
4451+static void
4452+check_two_config_files (const DBusString *config_file,
4453+ const char *extra_arg)
4454+{
4455+ if (_dbus_string_get_length (config_file) > 0)
4456+ {
4457+ fprintf (stderr, "--%s specified but configuration file %s already requested\n",
4458+ extra_arg, _dbus_string_get_const_data (config_file));
4459+ exit (1);
4460+ }
4461+}
4462+
4463+static void
4464+check_two_addresses (const DBusString *address,
4465+ const char *extra_arg)
4466+{
4467+ if (_dbus_string_get_length (address) > 0)
4468+ {
4469+ fprintf (stderr, "--%s specified but address %s already requested\n",
4470+ extra_arg, _dbus_string_get_const_data (address));
4471+ exit (1);
4472+ }
4473+}
4474+
4475+static void
4476+check_two_addr_descriptors (const DBusString *addr_fd,
4477+ const char *extra_arg)
4478+{
4479+ if (_dbus_string_get_length (addr_fd) > 0)
4480+ {
4481+ fprintf (stderr, "--%s specified but printing address to %s already requested\n",
4482+ extra_arg, _dbus_string_get_const_data (addr_fd));
4483+ exit (1);
4484+ }
4485+}
4486+
4487+static void
4488+check_two_pid_descriptors (const DBusString *pid_fd,
4489+ const char *extra_arg)
4490+{
4491+ if (_dbus_string_get_length (pid_fd) > 0)
4492+ {
4493+ fprintf (stderr, "--%s specified but printing pid to %s already requested\n",
4494+ extra_arg, _dbus_string_get_const_data (pid_fd));
4495+ exit (1);
4496+ }
4497+}
4498+
4499+static dbus_bool_t
4500+handle_reload_watch (DBusWatch *watch,
4501+ unsigned int flags,
4502+ void *data)
4503+{
4504+ DBusError error;
4505+ DBusString str;
4506+
4507+ while (!_dbus_string_init (&str))
4508+ _dbus_wait_for_memory ();
4509+
4510+ if ((reload_pipe[RELOAD_READ_END] > 0) &&
4511+ _dbus_read_socket (reload_pipe[RELOAD_READ_END], &str, 1) != 1)
4512+ {
4513+ _dbus_warn ("Couldn't read from reload pipe.\n");
4514+ close_reload_pipe ();
4515+ return TRUE;
4516+ }
4517+ _dbus_string_free (&str);
4518+
4519+ /* this can only fail if we don't understand the config file
4520+ * or OOM. Either way we should just stick with the currently
4521+ * loaded config.
4522+ */
4523+ dbus_error_init (&error);
4524+ if (! bus_context_reload_config (context, &error))
4525+ {
4526+ _DBUS_ASSERT_ERROR_IS_SET (&error);
4527+ _dbus_assert (dbus_error_has_name (&error, DBUS_ERROR_FAILED) ||
4528+ dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY));
4529+ _dbus_warn ("Unable to reload configuration: %s\n",
4530+ error.message);
4531+ dbus_error_free (&error);
4532+ }
4533+ return TRUE;
4534+}
4535+
4536+static dbus_bool_t
4537+reload_watch_callback (DBusWatch *watch,
4538+ unsigned int condition,
4539+ void *data)
4540+{
4541+ return dbus_watch_handle (watch, condition);
4542+}
4543+
4544+static void
4545+setup_reload_pipe (DBusLoop *loop)
4546+{
4547+ DBusError error;
4548+ DBusWatch *watch;
4549+
4550+ dbus_error_init (&error);
4551+
4552+ if (!_dbus_full_duplex_pipe (&reload_pipe[0], &reload_pipe[1],
4553+ TRUE, &error))
4554+ {
4555+ _dbus_warn ("Unable to create reload pipe: %s\n",
4556+ error.message);
4557+ dbus_error_free (&error);
4558+ exit (1);
4559+ }
4560+
4561+ watch = _dbus_watch_new (reload_pipe[RELOAD_READ_END],
4562+ DBUS_WATCH_READABLE, TRUE,
4563+ handle_reload_watch, NULL, NULL);
4564+
4565+ if (watch == NULL)
4566+ {
4567+ _dbus_warn ("Unable to create reload watch: %s\n",
4568+ error.message);
4569+ dbus_error_free (&error);
4570+ exit (1);
4571+ }
4572+
4573+ if (!_dbus_loop_add_watch (loop, watch, reload_watch_callback,
4574+ NULL, NULL))
4575+ {
4576+ _dbus_warn ("Unable to add reload watch to main loop: %s\n",
4577+ error.message);
4578+ dbus_error_free (&error);
4579+ exit (1);
4580+ }
4581+
4582+}
4583+
4584+static void
4585+close_reload_pipe (void)
4586+{
4587+ _dbus_close_socket (reload_pipe[RELOAD_READ_END], NULL);
4588+ reload_pipe[RELOAD_READ_END] = -1;
4589+
4590+ _dbus_close_socket (reload_pipe[RELOAD_WRITE_END], NULL);
4591+ reload_pipe[RELOAD_WRITE_END] = -1;
4592+}
4593+
4594+int
4595+main (int argc, char **argv)
4596+{
4597+ DBusError error;
4598+ DBusString config_file;
4599+ DBusString address;
4600+ DBusString addr_fd;
4601+ DBusString pid_fd;
4602+ const char *prev_arg;
4603+ DBusPipe print_addr_pipe;
4604+ DBusPipe print_pid_pipe;
4605+ int i;
4606+ dbus_bool_t print_address;
4607+ dbus_bool_t print_pid;
4608+ dbus_bool_t is_session_bus;
4609+ int force_fork;
4610+ dbus_bool_t systemd_activation;
4611+
4612+ if (!_dbus_string_init (&config_file))
4613+ return 1;
4614+
4615+ if (!_dbus_string_init (&address))
4616+ return 1;
4617+
4618+ if (!_dbus_string_init (&addr_fd))
4619+ return 1;
4620+
4621+ if (!_dbus_string_init (&pid_fd))
4622+ return 1;
4623+
4624+ print_address = FALSE;
4625+ print_pid = FALSE;
4626+ is_session_bus = FALSE;
4627+ force_fork = FORK_FOLLOW_CONFIG_FILE;
4628+ systemd_activation = FALSE;
4629+
4630+ prev_arg = NULL;
4631+ i = 1;
4632+ while (i < argc)
4633+ {
4634+ const char *arg = argv[i];
4635+
4636+ if (strcmp (arg, "--help") == 0 ||
4637+ strcmp (arg, "-h") == 0 ||
4638+ strcmp (arg, "-?") == 0)
4639+ usage ();
4640+ else if (strcmp (arg, "--version") == 0)
4641+ version ();
4642+ else if (strcmp (arg, "--introspect") == 0)
4643+ introspect ();
4644+ else if (strcmp (arg, "--nofork") == 0)
4645+ force_fork = FORK_NEVER;
4646+ else if (strcmp (arg, "--fork") == 0)
4647+ force_fork = FORK_ALWAYS;
4648+ else if (strcmp (arg, "--systemd-activation") == 0)
4649+ systemd_activation = TRUE;
4650+ else if (strcmp (arg, "--system") == 0)
4651+ {
4652+ check_two_config_files (&config_file, "system");
4653+
4654+ if (!_dbus_append_system_config_file (&config_file))
4655+ exit (1);
4656+ }
4657+ else if (strcmp (arg, "--session") == 0)
4658+ {
4659+ check_two_config_files (&config_file, "session");
4660+
4661+ if (!_dbus_append_session_config_file (&config_file))
4662+ exit (1);
4663+ }
4664+ else if (strstr (arg, "--config-file=") == arg)
4665+ {
4666+ const char *file;
4667+
4668+ check_two_config_files (&config_file, "config-file");
4669+
4670+ file = strchr (arg, '=');
4671+ ++file;
4672+
4673+ if (!_dbus_string_append (&config_file, file))
4674+ exit (1);
4675+ }
4676+ else if (prev_arg &&
4677+ strcmp (prev_arg, "--config-file") == 0)
4678+ {
4679+ check_two_config_files (&config_file, "config-file");
4680+
4681+ if (!_dbus_string_append (&config_file, arg))
4682+ exit (1);
4683+ }
4684+ else if (strcmp (arg, "--config-file") == 0)
4685+ ; /* wait for next arg */
4686+ else if (strstr (arg, "--address=") == arg)
4687+ {
4688+ const char *file;
4689+
4690+ check_two_addresses (&address, "address");
4691+
4692+ file = strchr (arg, '=');
4693+ ++file;
4694+
4695+ if (!_dbus_string_append (&address, file))
4696+ exit (1);
4697+ }
4698+ else if (prev_arg &&
4699+ strcmp (prev_arg, "--address") == 0)
4700+ {
4701+ check_two_addresses (&address, "address");
4702+
4703+ if (!_dbus_string_append (&address, arg))
4704+ exit (1);
4705+ }
4706+ else if (strcmp (arg, "--address") == 0)
4707+ ; /* wait for next arg */
4708+ else if (strstr (arg, "--print-address=") == arg)
4709+ {
4710+ const char *desc;
4711+
4712+ check_two_addr_descriptors (&addr_fd, "print-address");
4713+
4714+ desc = strchr (arg, '=');
4715+ ++desc;
4716+
4717+ if (!_dbus_string_append (&addr_fd, desc))
4718+ exit (1);
4719+
4720+ print_address = TRUE;
4721+ }
4722+ else if (prev_arg &&
4723+ strcmp (prev_arg, "--print-address") == 0)
4724+ {
4725+ check_two_addr_descriptors (&addr_fd, "print-address");
4726+
4727+ if (!_dbus_string_append (&addr_fd, arg))
4728+ exit (1);
4729+
4730+ print_address = TRUE;
4731+ }
4732+ else if (strcmp (arg, "--print-address") == 0)
4733+ print_address = TRUE; /* and we'll get the next arg if appropriate */
4734+ else if (strstr (arg, "--print-pid=") == arg)
4735+ {
4736+ const char *desc;
4737+
4738+ check_two_pid_descriptors (&pid_fd, "print-pid");
4739+
4740+ desc = strchr (arg, '=');
4741+ ++desc;
4742+
4743+ if (!_dbus_string_append (&pid_fd, desc))
4744+ exit (1);
4745+
4746+ print_pid = TRUE;
4747+ }
4748+ else if (prev_arg &&
4749+ strcmp (prev_arg, "--print-pid") == 0)
4750+ {
4751+ check_two_pid_descriptors (&pid_fd, "print-pid");
4752+
4753+ if (!_dbus_string_append (&pid_fd, arg))
4754+ exit (1);
4755+
4756+ print_pid = TRUE;
4757+ }
4758+ else if (strcmp (arg, "--print-pid") == 0)
4759+ print_pid = TRUE; /* and we'll get the next arg if appropriate */
4760+ else
4761+ usage ();
4762+
4763+ prev_arg = arg;
4764+
4765+ ++i;
4766+ }
4767+
4768+ if (_dbus_string_get_length (&config_file) == 0)
4769+ {
4770+ fprintf (stderr, "No configuration file specified.\n");
4771+ usage ();
4772+ }
4773+
4774+ _dbus_pipe_invalidate (&print_addr_pipe);
4775+ if (print_address)
4776+ {
4777+ _dbus_pipe_init_stdout (&print_addr_pipe);
4778+ if (_dbus_string_get_length (&addr_fd) > 0)
4779+ {
4780+ long val;
4781+ int end;
4782+ if (!_dbus_string_parse_int (&addr_fd, 0, &val, &end) ||
4783+ end != _dbus_string_get_length (&addr_fd) ||
4784+ val < 0 || val > _DBUS_INT_MAX)
4785+ {
4786+ fprintf (stderr, "Invalid file descriptor: \"%s\"\n",
4787+ _dbus_string_get_const_data (&addr_fd));
4788+ exit (1);
4789+ }
4790+
4791+ _dbus_pipe_init (&print_addr_pipe, val);
4792+ }
4793+ }
4794+ _dbus_string_free (&addr_fd);
4795+
4796+ _dbus_pipe_invalidate (&print_pid_pipe);
4797+ if (print_pid)
4798+ {
4799+ _dbus_pipe_init_stdout (&print_pid_pipe);
4800+ if (_dbus_string_get_length (&pid_fd) > 0)
4801+ {
4802+ long val;
4803+ int end;
4804+ if (!_dbus_string_parse_int (&pid_fd, 0, &val, &end) ||
4805+ end != _dbus_string_get_length (&pid_fd) ||
4806+ val < 0 || val > _DBUS_INT_MAX)
4807+ {
4808+ fprintf (stderr, "Invalid file descriptor: \"%s\"\n",
4809+ _dbus_string_get_const_data (&pid_fd));
4810+ exit (1);
4811+ }
4812+
4813+ _dbus_pipe_init (&print_pid_pipe, val);
4814+ }
4815+ }
4816+ _dbus_string_free (&pid_fd);
4817+
4818+ if (!bus_selinux_pre_init ())
4819+ {
4820+ _dbus_warn ("SELinux pre-initialization failed\n");
4821+ exit (1);
4822+ }
4823+
4824+ dbus_error_init (&error);
4825+ context = bus_context_new (&config_file, force_fork,
4826+ &print_addr_pipe, &print_pid_pipe,
4827+ _dbus_string_get_length(&address) > 0 ? &address : NULL,
4828+ systemd_activation,
4829+ &error);
4830+ _dbus_string_free (&config_file);
4831+ if (context == NULL)
4832+ {
4833+ _dbus_warn ("Failed to start message bus: %s\n",
4834+ error.message);
4835+ dbus_error_free (&error);
4836+ exit (1);
4837+ }
4838+
4839+ /* bus_context_new() closes the print_addr_pipe and
4840+ * print_pid_pipe
4841+ */
4842+
4843+ setup_reload_pipe (bus_context_get_loop (context));
4844+
4845+#ifdef SIGHUP
4846+ _dbus_set_signal_handler (SIGHUP, signal_handler);
4847+#endif
4848+#ifdef DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX
4849+ _dbus_set_signal_handler (SIGIO, signal_handler);
4850+#endif /* DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX */
4851+
4852+ _dbus_verbose ("We are on D-Bus...\n");
4853+ _dbus_loop_run (bus_context_get_loop (context));
4854+
4855+ bus_context_shutdown (context);
4856+ bus_context_unref (context);
4857+ bus_selinux_shutdown ();
4858+
4859+ return 0;
4860+}
4861
4862=== added directory '.pc/0002-bus-change-systemd-activation-to-activation-systemd.patch'
4863=== renamed directory '.pc/0002-bus-change-systemd-activation-to-activation-systemd.patch' => '.pc/0002-bus-change-systemd-activation-to-activation-systemd.patch.moved'
4864=== added file '.pc/0002-bus-change-systemd-activation-to-activation-systemd.patch/.timestamp'
4865=== added directory '.pc/0002-bus-change-systemd-activation-to-activation-systemd.patch/bus'
4866=== added file '.pc/0002-bus-change-systemd-activation-to-activation-systemd.patch/bus/dbus.service.in'
4867--- .pc/0002-bus-change-systemd-activation-to-activation-systemd.patch/bus/dbus.service.in 1970-01-01 00:00:00 +0000
4868+++ .pc/0002-bus-change-systemd-activation-to-activation-systemd.patch/bus/dbus.service.in 2011-03-28 07:17:28 +0000
4869@@ -0,0 +1,10 @@
4870+[Unit]
4871+Description=D-Bus System Message Bus
4872+Requires=dbus.socket
4873+After=syslog.target
4874+
4875+[Service]
4876+ExecStartPre=@EXPANDED_BINDIR@/dbus-uuidgen --ensure
4877+ExecStartPre=-/bin/rm -f @DBUS_SYSTEM_PID_FILE@
4878+ExecStart=@EXPANDED_BINDIR@/dbus-daemon --system --address=systemd: --nofork --systemd-activation
4879+ExecReload=@EXPANDED_BINDIR@/dbus-send --print-reply --system --type=method_call --dest=org.freedesktop.DBus / org.freedesktop.DBus.ReloadConfig
4880
4881=== added file '.pc/0002-bus-change-systemd-activation-to-activation-systemd.patch/bus/main.c'
4882--- .pc/0002-bus-change-systemd-activation-to-activation-systemd.patch/bus/main.c 1970-01-01 00:00:00 +0000
4883+++ .pc/0002-bus-change-systemd-activation-to-activation-systemd.patch/bus/main.c 2011-03-28 07:17:28 +0000
4884@@ -0,0 +1,527 @@
4885+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
4886+/* main.c main() for message bus
4887+ *
4888+ * Copyright (C) 2003 Red Hat, Inc.
4889+ *
4890+ * Licensed under the Academic Free License version 2.1
4891+ *
4892+ * This program is free software; you can redistribute it and/or modify
4893+ * it under the terms of the GNU General Public License as published by
4894+ * the Free Software Foundation; either version 2 of the License, or
4895+ * (at your option) any later version.
4896+ *
4897+ * This program is distributed in the hope that it will be useful,
4898+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4899+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4900+ * GNU General Public License for more details.
4901+ *
4902+ * You should have received a copy of the GNU General Public License
4903+ * along with this program; if not, write to the Free Software
4904+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
4905+ *
4906+ */
4907+
4908+#include <config.h>
4909+#include "bus.h"
4910+#include "driver.h"
4911+#include <dbus/dbus-internals.h>
4912+#include <dbus/dbus-watch.h>
4913+#include <stdio.h>
4914+#include <stdlib.h>
4915+#include <string.h>
4916+#ifdef HAVE_SIGNAL_H
4917+#include <signal.h>
4918+#endif
4919+#ifdef HAVE_ERRNO_H
4920+#include <errno.h>
4921+#endif
4922+#include "selinux.h"
4923+
4924+static BusContext *context;
4925+
4926+static int reload_pipe[2];
4927+#define RELOAD_READ_END 0
4928+#define RELOAD_WRITE_END 1
4929+
4930+static void close_reload_pipe (void);
4931+
4932+static void
4933+signal_handler (int sig)
4934+{
4935+
4936+ switch (sig)
4937+ {
4938+#ifdef DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX
4939+ case SIGIO:
4940+ /* explicit fall-through */
4941+#endif /* DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX */
4942+#ifdef SIGHUP
4943+ case SIGHUP:
4944+ {
4945+ DBusString str;
4946+ _dbus_string_init_const (&str, "foo");
4947+ if ((reload_pipe[RELOAD_WRITE_END] > 0) &&
4948+ !_dbus_write_socket (reload_pipe[RELOAD_WRITE_END], &str, 0, 1))
4949+ {
4950+ _dbus_warn ("Unable to write to reload pipe.\n");
4951+ close_reload_pipe ();
4952+ }
4953+ }
4954+ break;
4955+#endif
4956+ }
4957+}
4958+
4959+static void
4960+usage (void)
4961+{
4962+ fprintf (stderr, DBUS_DAEMON_NAME " [--version] [--session] [--system] [--config-file=FILE] [--print-address[=DESCRIPTOR]] [--print-pid[=DESCRIPTOR]] [--fork] [--nofork] [--introspect] [--address=ADDRESS] [--systemd-activation]\n");
4963+ exit (1);
4964+}
4965+
4966+static void
4967+version (void)
4968+{
4969+ printf ("D-Bus Message Bus Daemon %s\n"
4970+ "Copyright (C) 2002, 2003 Red Hat, Inc., CodeFactory AB, and others\n"
4971+ "This is free software; see the source for copying conditions.\n"
4972+ "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
4973+ DBUS_VERSION_STRING);
4974+ exit (0);
4975+}
4976+
4977+static void
4978+introspect (void)
4979+{
4980+ DBusString xml;
4981+ const char *v_STRING;
4982+
4983+ if (!_dbus_string_init (&xml))
4984+ goto oom;
4985+
4986+ if (!bus_driver_generate_introspect_string (&xml))
4987+ {
4988+ _dbus_string_free (&xml);
4989+ goto oom;
4990+ }
4991+
4992+ v_STRING = _dbus_string_get_const_data (&xml);
4993+ printf ("%s\n", v_STRING);
4994+
4995+ exit (0);
4996+
4997+ oom:
4998+ _dbus_warn ("Can not introspect - Out of memory\n");
4999+ exit (1);
5000+}
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: