Merge lp:~ubuntu-branches/ubuntu/natty/dbus/natty-201103250227 into lp:ubuntu/natty/dbus
- Natty (11.04)
- natty-201103250227
- Merge into natty
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu branches | Pending | ||
Review via email: mp+55073@code.launchpad.net |
Commit message
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.