]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus.c
sd-bus: synthesize a description for user/system bus if otherwise unset
[thirdparty/systemd.git] / src / core / dbus.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
a7334b09
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2010 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
a7334b09
LP
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 15 Lesser General Public License for more details.
a7334b09 16
5430f7f2 17 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
ea430986 21#include <errno.h>
07630cea 22#include <sys/epoll.h>
ea430986
LP
23#include <unistd.h>
24
718db961 25#include "sd-bus.h"
07630cea 26
b5efdb8a 27#include "alloc-util.h"
07630cea
LP
28#include "bus-common-errors.h"
29#include "bus-error.h"
30#include "bus-internal.h"
31#include "bus-util.h"
32#include "dbus-cgroup.h"
718db961 33#include "dbus-execute.h"
07630cea 34#include "dbus-job.h"
718db961 35#include "dbus-kill.h"
07630cea
LP
36#include "dbus-manager.h"
37#include "dbus-unit.h"
3ffd4af2
LP
38#include "dbus.h"
39#include "fd-util.h"
5b5e6dea 40#include "fs-util.h"
07630cea
LP
41#include "log.h"
42#include "missing.h"
43#include "mkdir.h"
dccca82b 44#include "process-util.h"
07630cea 45#include "selinux-access.h"
8f6df3fa 46#include "special.h"
07630cea
LP
47#include "string-util.h"
48#include "strv.h"
718db961 49#include "strxcpyx.h"
ee104e11 50#include "user-util.h"
4288f619 51
cbecf9bf 52#define CONNECTIONS_MAX 4096
5e8d1c9a 53
718db961
LP
54static void destroy_bus(Manager *m, sd_bus **bus);
55
56int bus_send_queued_message(Manager *m) {
57 int r;
8e274523 58
8e274523 59 assert(m);
2e317f52 60
718db961
LP
61 if (!m->queued_message)
62 return 0;
8e274523 63
718db961
LP
64 /* If we cannot get rid of this message we won't dispatch any
65 * D-Bus messages, so that we won't end up wanting to queue
66 * another message. */
ea430986 67
8f88ecf6 68 r = sd_bus_send(NULL, m->queued_message, NULL);
718db961 69 if (r < 0)
da927ba9 70 log_warning_errno(r, "Failed to send queued message: %m");
ea430986 71
718db961 72 m->queued_message = sd_bus_message_unref(m->queued_message);
ea430986 73
718db961 74 return 0;
ea430986
LP
75}
76
d8fdc620
LP
77int bus_forward_agent_released(Manager *m, const char *path) {
78 int r;
79
80 assert(m);
81 assert(path);
82
83 if (!MANAGER_IS_SYSTEM(m))
84 return 0;
85
86 if (!m->system_bus)
87 return 0;
88
89 /* If we are running a system instance we forward the agent message on the system bus, so that the user
90 * instances get notified about this, too */
91
92 r = sd_bus_emit_signal(m->system_bus,
93 "/org/freedesktop/systemd1/agent",
94 "org.freedesktop.systemd1.Agent",
95 "Released",
96 "s", path);
97 if (r < 0)
d5f15326 98 return log_debug_errno(r, "Failed to propagate agent release message: %m");
d8fdc620
LP
99
100 return 1;
101}
102
19070062 103static int signal_agent_released(sd_bus_message *message, void *userdata, sd_bus_error *error) {
4afd3348 104 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
718db961 105 Manager *m = userdata;
d8fdc620 106 const char *cgroup;
0a069ce6 107 uid_t sender_uid;
718db961 108 int r;
ea430986 109
718db961 110 assert(message);
ea430986
LP
111 assert(m);
112
0a069ce6
DH
113 /* only accept org.freedesktop.systemd1.Agent from UID=0 */
114 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
115 if (r < 0)
116 return r;
117
118 r = sd_bus_creds_get_euid(creds, &sender_uid);
119 if (r < 0 || sender_uid != 0)
120 return 0;
121
122 /* parse 'cgroup-empty' notification */
718db961
LP
123 r = sd_bus_message_read(message, "s", &cgroup);
124 if (r < 0) {
125 bus_log_parse_error(r);
126 return 0;
127 }
ea430986 128
718db961 129 manager_notify_cgroup_empty(m, cgroup);
718db961
LP
130 return 0;
131}
ea430986 132
19070062 133static int signal_disconnected(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 134 Manager *m = userdata;
19070062 135 sd_bus *bus;
ea430986 136
718db961
LP
137 assert(message);
138 assert(m);
19070062 139 assert_se(bus = sd_bus_message_get_bus(message));
ea430986 140
718db961 141 if (bus == m->api_bus)
4502c403 142 bus_done_api(m);
718db961 143 if (bus == m->system_bus)
4502c403
LP
144 bus_done_system(m);
145
718db961
LP
146 if (set_remove(m->private_buses, bus)) {
147 log_debug("Got disconnect on private connection.");
148 destroy_bus(m, &bus);
ea430986
LP
149 }
150
718db961 151 return 0;
ea430986
LP
152}
153
19070062 154static int signal_activation_request(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
4afd3348
LP
155 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
156 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
718db961
LP
157 Manager *m = userdata;
158 const char *name;
159 Unit *u;
160 int r;
ea430986 161
718db961 162 assert(message);
ea430986
LP
163 assert(m);
164
718db961
LP
165 r = sd_bus_message_read(message, "s", &name);
166 if (r < 0) {
167 bus_log_parse_error(r);
168 return 0;
169 }
ea430986 170
718db961
LP
171 if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) ||
172 manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) {
173 r = sd_bus_error_setf(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
174 goto failed;
175 }
ea430986 176
718db961
LP
177 r = manager_load_unit(m, name, NULL, &error, &u);
178 if (r < 0)
179 goto failed;
ea430986 180
718db961 181 if (u->refuse_manual_start) {
7e974e85 182 r = sd_bus_error_setf(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, %s may be requested by dependency only (it is configured to refuse manual start/stop).", u->id);
718db961 183 goto failed;
ea430986
LP
184 }
185
4bd29fe5 186 r = manager_add_job(m, JOB_START, u, JOB_REPLACE, &error, NULL);
718db961
LP
187 if (r < 0)
188 goto failed;
ea430986 189
718db961 190 /* Successfully queued, that's it for us */
ea430986 191 return 0;
ea430986 192
718db961
LP
193failed:
194 if (!sd_bus_error_is_set(&error))
195 sd_bus_error_set_errno(&error, r);
ea430986 196
718db961 197 log_debug("D-Bus activation failed for %s: %s", name, bus_error_message(&error, r));
ea430986 198
966c66e3 199 r = sd_bus_message_new_signal(sd_bus_message_get_bus(message), &reply, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure");
718db961
LP
200 if (r < 0) {
201 bus_log_create_error(r);
202 return 0;
203 }
204
fa0fed49 205 r = sd_bus_message_append(reply, "sss", name, error.name, error.message);
718db961
LP
206 if (r < 0) {
207 bus_log_create_error(r);
208 return 0;
209 }
210
966c66e3 211 r = sd_bus_send_to(NULL, reply, "org.freedesktop.DBus", NULL);
23bbb0de
MS
212 if (r < 0)
213 return log_error_errno(r, "Failed to respond with to bus activation request: %m");
ea430986 214
718db961 215 return 0;
ea430986
LP
216}
217
349cc4a5 218#if HAVE_SELINUX
19070062 219static int mac_selinux_filter(sd_bus_message *message, void *userdata, sd_bus_error *error) {
969987ea
LP
220 Manager *m = userdata;
221 const char *verb, *path;
222 Unit *u = NULL;
223 Job *j;
224 int r;
225
969987ea
LP
226 assert(message);
227
228 /* Our own method calls are all protected individually with
229 * selinux checks, but the built-in interfaces need to be
230 * protected too. */
231
232 if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set"))
233 verb = "reload";
234 else if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", NULL) ||
235 sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", NULL) ||
236 sd_bus_message_is_method_call(message, "org.freedesktop.DBus.ObjectManager", NULL) ||
237 sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Peer", NULL))
238 verb = "status";
239 else
240 return 0;
241
242 path = sd_bus_message_get_path(message);
243
244 if (object_path_startswith("/org/freedesktop/systemd1", path)) {
245
8a188de9 246 r = mac_selinux_access_check(message, verb, error);
969987ea
LP
247 if (r < 0)
248 return r;
249
250 return 0;
251 }
252
253 if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
4afd3348 254 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
969987ea
LP
255 pid_t pid;
256
5b12334d
LP
257 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
258 if (r < 0)
259 return 0;
260
261 r = sd_bus_creds_get_pid(creds, &pid);
969987ea
LP
262 if (r < 0)
263 return 0;
264
265 u = manager_get_unit_by_pid(m, pid);
266 } else {
267 r = manager_get_job_from_dbus_path(m, path, &j);
268 if (r >= 0)
269 u = j->unit;
270 else
271 manager_load_unit_from_dbus_path(m, path, NULL, &u);
272 }
273
274 if (!u)
275 return 0;
276
8a188de9 277 r = mac_selinux_unit_access_check(u, message, verb, error);
969987ea
LP
278 if (r < 0)
279 return r;
280
281 return 0;
282}
ad5b215d 283#endif
969987ea 284
f00c3121 285static int bus_job_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
718db961
LP
286 Manager *m = userdata;
287 Job *j;
288 int r;
ea430986 289
718db961
LP
290 assert(bus);
291 assert(path);
292 assert(interface);
293 assert(found);
ea430986
LP
294 assert(m);
295
718db961
LP
296 r = manager_get_job_from_dbus_path(m, path, &j);
297 if (r < 0)
298 return 0;
ea430986 299
718db961
LP
300 *found = j;
301 return 1;
302}
ea430986 303
f00c3121 304static int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_bus_error *error) {
a8cfb1b3 305 Unit *u = NULL; /* just to appease gcc, initialization is not really necessary */
718db961 306 int r;
ea430986 307
718db961
LP
308 assert(m);
309 assert(bus);
310 assert(path);
ea430986 311
718db961 312 if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) {
4afd3348 313 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
718db961
LP
314 sd_bus_message *message;
315 pid_t pid;
ea430986 316
19befb2d 317 message = sd_bus_get_current_message(bus);
718db961 318 if (!message)
f00c3121 319 return 0;
ea430986 320
5b12334d 321 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
718db961 322 if (r < 0)
5b12334d
LP
323 return r;
324
325 r = sd_bus_creds_get_pid(creds, &pid);
326 if (r < 0)
327 return r;
ea430986 328
718db961 329 u = manager_get_unit_by_pid(m, pid);
a8cfb1b3
ZJS
330 if (!u)
331 return 0;
718db961 332 } else {
f00c3121 333 r = manager_load_unit_from_dbus_path(m, path, error, &u);
718db961 334 if (r < 0)
f00c3121 335 return 0;
a8cfb1b3 336 assert(u);
718db961 337 }
ea430986 338
f00c3121
LP
339 *unit = u;
340 return 1;
ea430986
LP
341}
342
f00c3121 343static int bus_unit_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
718db961 344 Manager *m = userdata;
ea430986 345
718db961
LP
346 assert(bus);
347 assert(path);
348 assert(interface);
349 assert(found);
ea430986
LP
350 assert(m);
351
f00c3121 352 return find_unit(m, bus, path, (Unit**) found, error);
ea430986
LP
353}
354
f00c3121 355static int bus_unit_interface_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
718db961
LP
356 Manager *m = userdata;
357 Unit *u;
f00c3121 358 int r;
ea430986 359
718db961
LP
360 assert(bus);
361 assert(path);
362 assert(interface);
363 assert(found);
ea430986
LP
364 assert(m);
365
f00c3121
LP
366 r = find_unit(m, bus, path, &u, error);
367 if (r <= 0)
368 return r;
3df5bf61 369
21b735e7 370 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
718db961 371 return 0;
ea430986 372
718db961
LP
373 *found = u;
374 return 1;
ea430986
LP
375}
376
f00c3121 377static int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
718db961
LP
378 Manager *m = userdata;
379 Unit *u;
f00c3121 380 int r;
c1e1601e 381
718db961
LP
382 assert(bus);
383 assert(path);
384 assert(interface);
385 assert(found);
c1e1601e
LP
386 assert(m);
387
f00c3121
LP
388 r = find_unit(m, bus, path, &u, error);
389 if (r <= 0)
390 return r;
05e343b7 391
21b735e7 392 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
718db961 393 return 0;
05e343b7 394
35b7ff80 395 if (!UNIT_HAS_CGROUP_CONTEXT(u))
718db961 396 return 0;
0034c15c 397
718db961
LP
398 *found = u;
399 return 1;
400}
0034c15c 401
f00c3121 402static int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
718db961
LP
403 Manager *m = userdata;
404 CGroupContext *c;
405 Unit *u;
f00c3121 406 int r;
af25ec12 407
718db961
LP
408 assert(bus);
409 assert(path);
410 assert(interface);
411 assert(found);
412 assert(m);
0034c15c 413
f00c3121
LP
414 r = find_unit(m, bus, path, &u, error);
415 if (r <= 0)
416 return r;
0034c15c 417
21b735e7 418 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
718db961 419 return 0;
0034c15c 420
718db961
LP
421 c = unit_get_cgroup_context(u);
422 if (!c)
423 return 0;
c1e1601e 424
718db961
LP
425 *found = c;
426 return 1;
427}
0034c15c 428
f00c3121 429static int bus_exec_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
718db961
LP
430 Manager *m = userdata;
431 ExecContext *c;
432 Unit *u;
f00c3121 433 int r;
0034c15c 434
718db961
LP
435 assert(bus);
436 assert(path);
437 assert(interface);
438 assert(found);
439 assert(m);
0034c15c 440
f00c3121
LP
441 r = find_unit(m, bus, path, &u, error);
442 if (r <= 0)
443 return r;
0034c15c 444
21b735e7 445 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
718db961 446 return 0;
0034c15c 447
718db961
LP
448 c = unit_get_exec_context(u);
449 if (!c)
450 return 0;
0034c15c 451
718db961
LP
452 *found = c;
453 return 1;
c1e1601e
LP
454}
455
f00c3121 456static int bus_kill_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
718db961
LP
457 Manager *m = userdata;
458 KillContext *c;
459 Unit *u;
f00c3121 460 int r;
8e274523 461
718db961
LP
462 assert(bus);
463 assert(path);
464 assert(interface);
465 assert(found);
8e274523
LP
466 assert(m);
467
f00c3121
LP
468 r = find_unit(m, bus, path, &u, error);
469 if (r <= 0)
470 return r;
8e274523 471
21b735e7 472 if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
718db961 473 return 0;
8e274523 474
718db961
LP
475 c = unit_get_kill_context(u);
476 if (!c)
477 return 0;
53c6a358 478
718db961
LP
479 *found = c;
480 return 1;
481}
8e274523 482
f00c3121 483static int bus_job_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
f0c03de8 484 _cleanup_strv_free_ char **l = NULL;
718db961
LP
485 Manager *m = userdata;
486 unsigned k = 0;
487 Iterator i;
488 Job *j;
8e274523 489
718db961
LP
490 l = new0(char*, hashmap_size(m->jobs)+1);
491 if (!l)
492 return -ENOMEM;
8e274523 493
718db961
LP
494 HASHMAP_FOREACH(j, m->jobs, i) {
495 l[k] = job_dbus_path(j);
496 if (!l[k])
497 return -ENOMEM;
5e8d1c9a 498
718db961
LP
499 k++;
500 }
5e8d1c9a 501
718db961 502 assert(hashmap_size(m->jobs) == k);
3c661fad 503
718db961
LP
504 *nodes = l;
505 l = NULL;
5e8d1c9a 506
718db961
LP
507 return k;
508}
53c6a358 509
f00c3121 510static int bus_unit_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
f0c03de8 511 _cleanup_strv_free_ char **l = NULL;
718db961
LP
512 Manager *m = userdata;
513 unsigned k = 0;
514 Iterator i;
515 Unit *u;
3c661fad 516
718db961
LP
517 l = new0(char*, hashmap_size(m->units)+1);
518 if (!l)
519 return -ENOMEM;
53c6a358 520
718db961
LP
521 HASHMAP_FOREACH(u, m->units, i) {
522 l[k] = unit_dbus_path(u);
523 if (!l[k])
524 return -ENOMEM;
53c6a358 525
718db961 526 k++;
3c661fad
LP
527 }
528
718db961
LP
529 *nodes = l;
530 l = NULL;
5e8d1c9a 531
718db961 532 return k;
5e8d1c9a
LP
533}
534
718db961
LP
535static int bus_setup_api_vtables(Manager *m, sd_bus *bus) {
536 UnitType t;
537 int r;
5e8d1c9a 538
ea430986 539 assert(m);
718db961 540 assert(bus);
ea430986 541
349cc4a5 542#if HAVE_SELINUX
8a188de9 543 r = sd_bus_add_filter(bus, NULL, mac_selinux_filter, m);
23bbb0de
MS
544 if (r < 0)
545 return log_error_errno(r, "Failed to add SELinux access filter: %m");
ad5b215d 546#endif
969987ea 547
19befb2d 548 r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m);
23bbb0de
MS
549 if (r < 0)
550 return log_error_errno(r, "Failed to register Manager vtable: %m");
a16e1123 551
19befb2d 552 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m);
23bbb0de
MS
553 if (r < 0)
554 return log_error_errno(r, "Failed to register Job vtable: %m");
c1e1601e 555
19befb2d 556 r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/job", bus_job_enumerate, m);
23bbb0de
MS
557 if (r < 0)
558 return log_error_errno(r, "Failed to add job enumerator: %m");
61902ea3 559
19befb2d 560 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m);
23bbb0de
MS
561 if (r < 0)
562 return log_error_errno(r, "Failed to register Unit vtable: %m");
61902ea3 563
19befb2d 564 r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/unit", bus_unit_enumerate, m);
23bbb0de
MS
565 if (r < 0)
566 return log_error_errno(r, "Failed to add job enumerator: %m");
61902ea3 567
718db961 568 for (t = 0; t < _UNIT_TYPE_MAX; t++) {
21b735e7
LP
569 const char *interface;
570
571 assert_se(interface = unit_dbus_interface_from_type(t));
572
573 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, unit_vtable[t]->bus_vtable, bus_unit_interface_find, m);
23bbb0de 574 if (r < 0)
21b735e7 575 return log_error_errno(r, "Failed to register type specific vtable for %s: %m", interface);
61902ea3 576
718db961 577 if (unit_vtable[t]->cgroup_context_offset > 0) {
21b735e7 578 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_unit_cgroup_vtable, bus_unit_cgroup_find, m);
23bbb0de 579 if (r < 0)
21b735e7 580 return log_error_errno(r, "Failed to register control group unit vtable for %s: %m", interface);
61902ea3 581
21b735e7 582 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_cgroup_vtable, bus_cgroup_context_find, m);
23bbb0de 583 if (r < 0)
21b735e7 584 return log_error_errno(r, "Failed to register control group vtable for %s: %m", interface);
61902ea3
LP
585 }
586
718db961 587 if (unit_vtable[t]->exec_context_offset > 0) {
21b735e7 588 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_exec_vtable, bus_exec_context_find, m);
23bbb0de 589 if (r < 0)
21b735e7 590 return log_error_errno(r, "Failed to register execute vtable for %s: %m", interface);
718db961 591 }
61902ea3 592
718db961 593 if (unit_vtable[t]->kill_context_offset > 0) {
21b735e7 594 r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", interface, bus_kill_vtable, bus_kill_context_find, m);
23bbb0de 595 if (r < 0)
21b735e7 596 return log_error_errno(r, "Failed to register kill vtable for %s: %m", interface);
718db961 597 }
61902ea3
LP
598 }
599
718db961 600 return 0;
61902ea3
LP
601}
602
718db961
LP
603static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) {
604 int r;
61902ea3 605
718db961
LP
606 assert(m);
607 assert(bus);
61902ea3 608
75152a4d 609 r = sd_bus_match_signal_async(
718db961 610 bus,
19befb2d 611 NULL,
75152a4d
LP
612 "org.freedesktop.DBus.Local",
613 "/org/freedesktop/DBus/Local",
614 "org.freedesktop.DBus.Local",
615 "Disconnected",
616 signal_disconnected, NULL, m);
23bbb0de 617 if (r < 0)
75152a4d 618 return log_error_errno(r, "Failed to request match for Disconnected message: %m");
05e343b7 619
718db961 620 return 0;
ea430986
LP
621}
622
718db961 623static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
4afd3348 624 _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
718db961 625 _cleanup_close_ int nfd = -1;
6dded4c7 626 Manager *m = userdata;
718db961
LP
627 sd_id128_t id;
628 int r;
6dded4c7 629
718db961 630 assert(s);
6dded4c7
LP
631 assert(m);
632
718db961
LP
633 nfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
634 if (nfd < 0) {
56f64d95 635 log_warning_errno(errno, "Failed to accept private connection, ignoring: %m");
718db961
LP
636 return 0;
637 }
6dded4c7 638
718db961
LP
639 if (set_size(m->private_buses) >= CONNECTIONS_MAX) {
640 log_warning("Too many concurrent connections, refusing");
641 return 0;
642 }
6dded4c7 643
d5099efc 644 r = set_ensure_allocated(&m->private_buses, NULL);
718db961
LP
645 if (r < 0) {
646 log_oom();
647 return 0;
648 }
6dded4c7 649
718db961
LP
650 r = sd_bus_new(&bus);
651 if (r < 0) {
da927ba9 652 log_warning_errno(r, "Failed to allocate new private connection bus: %m");
718db961
LP
653 return 0;
654 }
6dded4c7 655
718db961
LP
656 r = sd_bus_set_fd(bus, nfd, nfd);
657 if (r < 0) {
da927ba9 658 log_warning_errno(r, "Failed to set fd on new connection bus: %m");
718db961
LP
659 return 0;
660 }
6dded4c7 661
718db961 662 nfd = -1;
6dded4c7 663
718db961
LP
664 r = bus_check_peercred(bus);
665 if (r < 0) {
da927ba9 666 log_warning_errno(r, "Incoming private connection from unprivileged client, refusing: %m");
718db961
LP
667 return 0;
668 }
6dded4c7 669
718db961 670 assert_se(sd_id128_randomize(&id) >= 0);
6dded4c7 671
718db961
LP
672 r = sd_bus_set_server(bus, 1, id);
673 if (r < 0) {
da927ba9 674 log_warning_errno(r, "Failed to enable server support for new connection bus: %m");
718db961
LP
675 return 0;
676 }
6dded4c7 677
0674bbea
LP
678 r = sd_bus_negotiate_creds(bus, 1,
679 SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|
680 SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS|
681 SD_BUS_CREDS_SELINUX_CONTEXT);
682 if (r < 0) {
683 log_warning_errno(r, "Failed to enable credentials for new connection: %m");
684 return 0;
685 }
686
a5ea30b7
LP
687 r = sd_bus_set_sender(bus, "org.freedesktop.systemd1");
688 if (r < 0) {
689 log_warning_errno(r, "Failed to set direct connection sender: %m");
690 return 0;
691 }
692
718db961
LP
693 r = sd_bus_start(bus);
694 if (r < 0) {
da927ba9 695 log_warning_errno(r, "Failed to start new connection bus: %m");
718db961 696 return 0;
6dded4c7
LP
697 }
698
718db961
LP
699 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
700 if (r < 0) {
da927ba9 701 log_warning_errno(r, "Failed to attach new connection bus to event loop: %m");
718db961 702 return 0;
6dded4c7
LP
703 }
704
718db961
LP
705 r = bus_setup_disconnected_match(m, bus);
706 if (r < 0)
707 return 0;
6dded4c7 708
718db961
LP
709 r = bus_setup_api_vtables(m, bus);
710 if (r < 0) {
da927ba9 711 log_warning_errno(r, "Failed to set up API vtables on new connection bus: %m");
718db961
LP
712 return 0;
713 }
6dded4c7 714
718db961
LP
715 r = set_put(m->private_buses, bus);
716 if (r < 0) {
05a08cb6 717 log_warning_errno(r, "Failed to add new connection bus to set: %m");
718db961 718 return 0;
6dded4c7
LP
719 }
720
718db961 721 bus = NULL;
6dded4c7 722
718db961 723 log_debug("Accepted new private connection.");
6dded4c7 724
8e274523
LP
725 return 0;
726}
727
8936a5e3 728int manager_sync_bus_names(Manager *m, sd_bus *bus) {
0e7be129 729 _cleanup_strv_free_ char **names = NULL;
d8ccf5fd
DM
730 const char *name;
731 Iterator i;
732 Unit *u;
718db961 733 int r;
5e8d1c9a
LP
734
735 assert(m);
718db961 736 assert(bus);
5e8d1c9a 737
0e7be129 738 r = sd_bus_list_names(bus, &names, NULL);
23bbb0de
MS
739 if (r < 0)
740 return log_error_errno(r, "Failed to get initial list of names: %m");
5e8d1c9a 741
d8ccf5fd
DM
742 /* We have to synchronize the current bus names with the
743 * list of active services. To do this, walk the list of
744 * all units with bus names. */
745 HASHMAP_FOREACH_KEY(u, name, m->watch_bus, i) {
746 Service *s = SERVICE(u);
747
748 assert(s);
bbc29086 749
d8ccf5fd
DM
750 if (!streq_ptr(s->bus_name, name)) {
751 log_unit_warning(u, "Bus name has changed from %s → %s, ignoring.", s->bus_name, name);
752 continue;
753 }
754
755 /* Check if a service's bus name is in the list of currently
756 * active names */
757 if (strv_contains(names, name)) {
758 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
759 const char *unique;
760
761 /* If it is, determine its current owner */
762 r = sd_bus_get_name_creds(bus, name, SD_BUS_CREDS_UNIQUE_NAME, &creds);
763 if (r < 0) {
ddbf0d4b 764 log_full_errno(r == -ENXIO ? LOG_DEBUG : LOG_ERR, r, "Failed to get bus name owner %s: %m", name);
d8ccf5fd
DM
765 continue;
766 }
767
768 r = sd_bus_creds_get_unique_name(creds, &unique);
769 if (r < 0) {
ddbf0d4b 770 log_full_errno(r == -ENXIO ? LOG_DEBUG : LOG_ERR, r, "Failed to get unique name for %s: %m", name);
d8ccf5fd
DM
771 continue;
772 }
773
774 /* Now, let's compare that to the previous bus owner, and
775 * if it's still the same, all is fine, so just don't
776 * bother the service. Otherwise, the name has apparently
777 * changed, so synthesize a name owner changed signal. */
778
779 if (!streq_ptr(unique, s->bus_name_owner))
780 UNIT_VTABLE(u)->bus_name_owner_change(u, name, s->bus_name_owner, unique);
781 } else {
782 /* So, the name we're watching is not on the bus.
783 * This either means it simply hasn't appeared yet,
784 * or it was lost during the daemon reload.
785 * Check if the service has a stored name owner,
786 * and synthesize a name loss signal in this case. */
787
788 if (s->bus_name_owner)
789 UNIT_VTABLE(u)->bus_name_owner_change(u, name, s->bus_name_owner, NULL);
790 }
bbc29086 791 }
5e8d1c9a 792
718db961 793 return 0;
5e8d1c9a
LP
794}
795
718db961 796static int bus_setup_api(Manager *m, sd_bus *bus) {
bbc29086
DM
797 Iterator i;
798 char *name;
799 Unit *u;
718db961 800 int r;
f278026d 801
718db961
LP
802 assert(m);
803 assert(bus);
c1e1601e 804
8fd00193
LP
805 /* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
806 r = sd_bus_negotiate_creds(bus, 1,
807 SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|
808 SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS|
809 SD_BUS_CREDS_SELINUX_CONTEXT);
810 if (r < 0)
da927ba9 811 log_warning_errno(r, "Failed to enable credential passing, ignoring: %m");
8fd00193 812
718db961
LP
813 r = bus_setup_api_vtables(m, bus);
814 if (r < 0)
815 return r;
cbd37330 816
bbc29086 817 HASHMAP_FOREACH_KEY(u, name, m->watch_bus, i) {
9806e87d 818 r = unit_install_bus_match(u, bus, name);
bbc29086 819 if (r < 0)
8ea823b6 820 log_error_errno(r, "Failed to subscribe to NameOwnerChanged signal for '%s': %m", name);
bbc29086 821 }
718db961 822
75152a4d 823 r = sd_bus_match_signal_async(
718db961 824 bus,
19befb2d 825 NULL,
75152a4d
LP
826 "org.freedesktop.DBus",
827 "/org/freedesktop/DBus",
828 "org.freedesktop.systemd1.Activator",
829 "ActivationRequest",
830 signal_activation_request, NULL, m);
718db961 831 if (r < 0)
da927ba9 832 log_warning_errno(r, "Failed to subscribe to activation signal: %m");
cbd37330 833
0c0b9306
LP
834 /* Allow replacing of our name, to ease implementation of reexecution, where we keep the old connection open
835 * until after the new connection is set up and the name installed to allow clients to synchronously wait for
836 * reexecution to finish */
837 r = sd_bus_request_name_async(bus, NULL, "org.freedesktop.systemd1", SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_ALLOW_REPLACEMENT, NULL, NULL);
23bbb0de 838 if (r < 0)
0c0b9306 839 return log_error_errno(r, "Failed to request name: %m");
53c6a358 840
8936a5e3 841 r = manager_sync_bus_names(m, bus);
d8ccf5fd
DM
842 if (r < 0)
843 return r;
f278026d 844
718db961 845 log_debug("Successfully connected to API bus.");
f278026d
LP
846 return 0;
847}
848
8559b3b7 849int bus_init_api(Manager *m) {
4afd3348 850 _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
f278026d
LP
851 int r;
852
718db961
LP
853 if (m->api_bus)
854 return 0;
cbd37330 855
718db961 856 /* The API and system bus is the same if we are running in system mode */
463d0d15 857 if (MANAGER_IS_SYSTEM(m) && m->system_bus)
718db961
LP
858 bus = sd_bus_ref(m->system_bus);
859 else {
463d0d15 860 if (MANAGER_IS_SYSTEM(m))
718db961
LP
861 r = sd_bus_open_system(&bus);
862 else
863 r = sd_bus_open_user(&bus);
dc7118ba
MS
864 if (r < 0)
865 return log_error_errno(r, "Failed to connect to API bus: %m");
cbd37330 866
718db961 867 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
dc7118ba
MS
868 if (r < 0)
869 return log_error_errno(r, "Failed to attach API bus to event loop: %m");
cbd37330 870
718db961
LP
871 r = bus_setup_disconnected_match(m, bus);
872 if (r < 0)
dc7118ba 873 return r;
cbd37330
MS
874 }
875
718db961 876 r = bus_setup_api(m, bus);
dc7118ba
MS
877 if (r < 0)
878 return log_error_errno(r, "Failed to set up API bus: %m");
cbd37330 879
718db961
LP
880 m->api_bus = bus;
881 bus = NULL;
cbd37330
MS
882
883 return 0;
cbd37330
MS
884}
885
718db961
LP
886static int bus_setup_system(Manager *m, sd_bus *bus) {
887 int r;
cbd37330 888
718db961
LP
889 assert(m);
890 assert(bus);
cbd37330 891
d8fdc620
LP
892 /* if we are a user instance we get the Released message via the system bus */
893 if (MANAGER_IS_USER(m)) {
75152a4d 894 r = sd_bus_match_signal_async(
f5b51ea7
DH
895 bus,
896 NULL,
75152a4d
LP
897 NULL,
898 "/org/freedesktop/systemd1/agent",
899 "org.freedesktop.systemd1.Agent",
900 "Released",
901 signal_agent_released, NULL, m);
f5b51ea7 902 if (r < 0)
75152a4d 903 log_warning_errno(r, "Failed to request Released match on system bus: %m");
f5b51ea7 904 }
718db961
LP
905
906 log_debug("Successfully connected to system bus.");
907 return 0;
cbd37330
MS
908}
909
8559b3b7 910int bus_init_system(Manager *m) {
4afd3348 911 _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
cbd37330
MS
912 int r;
913
914 if (m->system_bus)
915 return 0;
916
718db961 917 /* The API and system bus is the same if we are running in system mode */
463d0d15 918 if (MANAGER_IS_SYSTEM(m) && m->api_bus) {
718db961
LP
919 m->system_bus = sd_bus_ref(m->api_bus);
920 return 0;
9014a8bd 921 }
8e274523 922
718db961 923 r = sd_bus_open_system(&bus);
dc7118ba
MS
924 if (r < 0)
925 return log_error_errno(r, "Failed to connect to system bus: %m");
cbd37330 926
718db961 927 r = bus_setup_disconnected_match(m, bus);
cbd37330 928 if (r < 0)
dc7118ba 929 return r;
cbd37330 930
718db961 931 r = sd_bus_attach_event(bus, m->event, SD_EVENT_PRIORITY_NORMAL);
dc7118ba
MS
932 if (r < 0)
933 return log_error_errno(r, "Failed to attach system bus to event loop: %m");
cbd37330 934
718db961 935 r = bus_setup_system(m, bus);
dc7118ba
MS
936 if (r < 0)
937 return log_error_errno(r, "Failed to set up system bus: %m");
cbd37330 938
718db961
LP
939 m->system_bus = bus;
940 bus = NULL;
cbd37330
MS
941
942 return 0;
5e8d1c9a
LP
943}
944
8559b3b7 945int bus_init_private(Manager *m) {
718db961
LP
946 _cleanup_close_ int fd = -1;
947 union sockaddr_union sa = {
948 .un.sun_family = AF_UNIX
5e8d1c9a 949 };
718db961
LP
950 sd_event_source *s;
951 socklen_t salen;
952 int r;
5e8d1c9a
LP
953
954 assert(m);
955
718db961 956 if (m->private_listen_fd >= 0)
5e8d1c9a
LP
957 return 0;
958
463d0d15 959 if (MANAGER_IS_SYSTEM(m)) {
be81bfc4
LP
960
961 /* We want the private bus only when running as init */
df0ff127 962 if (getpid_cached() != 1)
be81bfc4
LP
963 return 0;
964
718db961 965 strcpy(sa.un.sun_path, "/run/systemd/private");
fc2fffe7 966 salen = SOCKADDR_UN_LEN(sa.un);
be81bfc4 967 } else {
718db961
LP
968 size_t left = sizeof(sa.un.sun_path);
969 char *p = sa.un.sun_path;
be81bfc4 970 const char *e;
be81bfc4 971
4db17f29 972 e = secure_getenv("XDG_RUNTIME_DIR");
718db961
LP
973 if (!e) {
974 log_error("Failed to determine XDG_RUNTIME_DIR");
975 return -EHOSTDOWN;
be81bfc4
LP
976 }
977
718db961
LP
978 left = strpcpy(&p, left, e);
979 left = strpcpy(&p, left, "/systemd/private");
92f30349 980
718db961 981 salen = sizeof(sa.un) - left;
be81bfc4 982 }
5e8d1c9a 983
f0e62e89
LP
984 (void) mkdir_parents_label(sa.un.sun_path, 0755);
985 (void) unlink(sa.un.sun_path);
718db961
LP
986
987 fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
4a62c710
MS
988 if (fd < 0)
989 return log_error_errno(errno, "Failed to allocate private socket: %m");
5e8d1c9a 990
718db961 991 r = bind(fd, &sa.sa, salen);
4a62c710
MS
992 if (r < 0)
993 return log_error_errno(errno, "Failed to bind private socket: %m");
5e8d1c9a 994
718db961 995 r = listen(fd, SOMAXCONN);
4a62c710
MS
996 if (r < 0)
997 return log_error_errno(errno, "Failed to make private socket listening: %m");
5e8d1c9a 998
5b5e6dea
LP
999 /* Generate an inotify event in case somebody waits for this socket to appear using inotify() */
1000 (void) touch(sa.un.sun_path);
1001
151b9b96 1002 r = sd_event_add_io(m->event, &s, fd, EPOLLIN, bus_on_connection, m);
23bbb0de
MS
1003 if (r < 0)
1004 return log_error_errno(r, "Failed to allocate event source: %m");
5e8d1c9a 1005
7dfbe2e3
TG
1006 (void) sd_event_source_set_description(s, "bus-connection");
1007
718db961
LP
1008 m->private_listen_fd = fd;
1009 m->private_listen_event_source = s;
1010 fd = -1;
5e8d1c9a 1011
718db961 1012 log_debug("Successfully created private D-Bus server.");
5e8d1c9a 1013
718db961 1014 return 0;
5e8d1c9a
LP
1015}
1016
718db961 1017static void destroy_bus(Manager *m, sd_bus **bus) {
a567261a 1018 Iterator i;
8367fea5 1019 Unit *u;
718db961 1020 Job *j;
a567261a 1021
718db961
LP
1022 assert(m);
1023 assert(bus);
5e8d1c9a 1024
718db961 1025 if (!*bus)
cbd37330 1026 return;
f278026d 1027
8367fea5
LP
1028 /* Make sure all bus slots watching names are released. */
1029 HASHMAP_FOREACH(u, m->watch_bus, i) {
1030 if (!u->match_bus_slot)
1031 continue;
1032
1033 if (sd_bus_slot_get_bus(u->match_bus_slot) != *bus)
1034 continue;
1035
1036 u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot);
1037 }
1038
718db961 1039 /* Get rid of tracked clients on this bus */
8f8f05a9
LP
1040 if (m->subscribed && sd_bus_track_get_bus(m->subscribed) == *bus)
1041 m->subscribed = sd_bus_track_unref(m->subscribed);
1042
718db961 1043 HASHMAP_FOREACH(j, m->jobs, i)
1a465207
LP
1044 if (j->bus_track && sd_bus_track_get_bus(j->bus_track) == *bus)
1045 j->bus_track = sd_bus_track_unref(j->bus_track);
c1e1601e 1046
718db961 1047 /* Get rid of queued message on this bus */
8f88ecf6
LP
1048 if (m->queued_message && sd_bus_message_get_bus(m->queued_message) == *bus)
1049 m->queued_message = sd_bus_message_unref(m->queued_message);
f278026d 1050
718db961
LP
1051 /* Possibly flush unwritten data, but only if we are
1052 * unprivileged, since we don't want to sync here */
463d0d15 1053 if (!MANAGER_IS_SYSTEM(m))
718db961 1054 sd_bus_flush(*bus);
5e8d1c9a 1055
718db961
LP
1056 /* And destroy the object */
1057 sd_bus_close(*bus);
1058 *bus = sd_bus_unref(*bus);
5e8d1c9a
LP
1059}
1060
4502c403 1061void bus_done_api(Manager *m) {
05e343b7 1062 assert(m);
05e343b7 1063
718db961
LP
1064 if (m->api_bus)
1065 destroy_bus(m, &m->api_bus);
4502c403
LP
1066}
1067
1068void bus_done_system(Manager *m) {
1069 assert(m);
1070
718db961
LP
1071 if (m->system_bus)
1072 destroy_bus(m, &m->system_bus);
4502c403
LP
1073}
1074
1075void bus_done_private(Manager *m) {
1076 sd_bus *b;
1077
1078 assert(m);
1079
718db961
LP
1080 while ((b = set_steal_first(m->private_buses)))
1081 destroy_bus(m, &b);
05e343b7 1082
525d3cc7 1083 m->private_buses = set_free(m->private_buses);
8f8f05a9 1084
4502c403
LP
1085 m->private_listen_event_source = sd_event_source_unref(m->private_listen_event_source);
1086 m->private_listen_fd = safe_close(m->private_listen_fd);
1087}
1088
1089void bus_done(Manager *m) {
1090 assert(m);
05e343b7 1091
4502c403
LP
1092 bus_done_api(m);
1093 bus_done_system(m);
1094 bus_done_private(m);
05e343b7 1095
4502c403 1096 assert(!m->subscribed);
283868e1 1097
4502c403 1098 m->deserialized_subscribed = strv_free(m->deserialized_subscribed);
283868e1 1099 bus_verify_polkit_async_registry_free(m->polkit_registry);
a567261a 1100}
b23de6af
LP
1101
1102int bus_fdset_add_all(Manager *m, FDSet *fds) {
1103 Iterator i;
718db961
LP
1104 sd_bus *b;
1105 int fd;
b23de6af
LP
1106
1107 assert(m);
1108 assert(fds);
1109
1110 /* When we are about to reexecute we add all D-Bus fds to the
1111 * set to pass over to the newly executed systemd. They won't
718db961 1112 * be used there however, except thatt they are closed at the
b23de6af 1113 * very end of deserialization, those making it possible for
44143309 1114 * clients to synchronously wait for systemd to reexec by
b23de6af
LP
1115 * simply waiting for disconnection */
1116
718db961
LP
1117 if (m->api_bus) {
1118 fd = sd_bus_get_fd(m->api_bus);
1119 if (fd >= 0) {
b23de6af 1120 fd = fdset_put_dup(fds, fd);
b23de6af
LP
1121 if (fd < 0)
1122 return fd;
1123 }
1124 }
1125
718db961
LP
1126 SET_FOREACH(b, m->private_buses, i) {
1127 fd = sd_bus_get_fd(b);
1128 if (fd >= 0) {
b23de6af 1129 fd = fdset_put_dup(fds, fd);
b23de6af
LP
1130 if (fd < 0)
1131 return fd;
1132 }
1133 }
1134
718db961
LP
1135 /* We don't offer any APIs on the system bus (well, unless it
1136 * is the same as the API bus) hence we don't bother with it
1137 * here */
6fa48533 1138
718db961 1139 return 0;
6fa48533
LP
1140}
1141
8f8f05a9
LP
1142int bus_foreach_bus(
1143 Manager *m,
1144 sd_bus_track *subscribed2,
1145 int (*send_message)(sd_bus *bus, void *userdata),
1146 void *userdata) {
1147
1148 Iterator i;
1149 sd_bus *b;
1150 int r, ret = 0;
1151
ff9b60f3 1152 /* Send to all direct buses, unconditionally */
8f8f05a9
LP
1153 SET_FOREACH(b, m->private_buses, i) {
1154 r = send_message(b, userdata);
1155 if (r < 0)
1156 ret = r;
1157 }
1158
1159 /* Send to API bus, but only if somebody is subscribed */
1160 if (sd_bus_track_count(m->subscribed) > 0 ||
1161 sd_bus_track_count(subscribed2) > 0) {
1162 r = send_message(m->api_bus, userdata);
1163 if (r < 0)
1164 ret = r;
1165 }
1166
1167 return ret;
1168}
1169
05a98afd 1170void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix) {
8f8f05a9
LP
1171 const char *n;
1172
6fa48533 1173 assert(f);
05a98afd 1174 assert(prefix);
6fa48533 1175
05a98afd
LP
1176 for (n = sd_bus_track_first(t); n; n = sd_bus_track_next(t)) {
1177 int c, j;
230314d7 1178
05a98afd 1179 c = sd_bus_track_count_name(t, n);
8f8f05a9 1180
05a98afd
LP
1181 for (j = 0; j < c; j++) {
1182 fputs(prefix, f);
1183 fputc('=', f);
1184 fputs(n, f);
1185 fputc('\n', f);
1186 }
1187 }
8f8f05a9
LP
1188}
1189
05a98afd 1190int bus_track_coldplug(Manager *m, sd_bus_track **t, bool recursive, char **l) {
8f8f05a9
LP
1191 int r = 0;
1192
1193 assert(m);
1194 assert(t);
8f8f05a9 1195
05a98afd
LP
1196 if (strv_isempty(l))
1197 return 0;
8f8f05a9 1198
05a98afd
LP
1199 if (!m->api_bus)
1200 return 0;
8f8f05a9 1201
05a98afd
LP
1202 if (!*t) {
1203 r = sd_bus_track_new(m->api_bus, t, NULL, NULL);
1204 if (r < 0)
1205 return r;
8f8f05a9
LP
1206 }
1207
05a98afd
LP
1208 r = sd_bus_track_set_recursive(*t, recursive);
1209 if (r < 0)
1210 return r;
1211
984794ba 1212 return bus_track_add_name_many(*t, l);
6fa48533 1213}
283868e1 1214
1d22e906 1215int bus_verify_manage_units_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
403ed0e5 1216 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-units", NULL, false, UID_INVALID, &m->polkit_registry, error);
283868e1
SW
1217}
1218
283868e1 1219int bus_verify_manage_unit_files_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
403ed0e5 1220 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.manage-unit-files", NULL, false, UID_INVALID, &m->polkit_registry, error);
283868e1
SW
1221}
1222
1223int bus_verify_reload_daemon_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
403ed0e5 1224 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.reload-daemon", NULL, false, UID_INVALID, &m->polkit_registry, error);
283868e1 1225}
1d22e906
LP
1226
1227int bus_verify_set_environment_async(Manager *m, sd_bus_message *call, sd_bus_error *error) {
403ed0e5 1228 return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.set-environment", NULL, false, UID_INVALID, &m->polkit_registry, error);
1d22e906 1229}