]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-manager.c
core: fix serialization of client tracker
[thirdparty/systemd.git] / src / core / dbus-manager.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
ea430986 2
a7334b09
LP
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
a7334b09
LP
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
a7334b09 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
ea430986 22#include <errno.h>
871c44a7 23#include <unistd.h>
ea430986 24
ea430986 25#include "log.h"
1137a57c 26#include "strv.h"
09bde77f 27#include "build.h"
c0576cd6 28#include "install.h"
e2417e41 29#include "selinux-access.h"
c757a65b 30#include "watchdog.h"
bbc98d32 31#include "hwclock.h"
664f88a7 32#include "path-util.h"
dfae3488 33#include "virt.h"
4d1a6904 34#include "env-util.h"
718db961
LP
35#include "dbus.h"
36#include "dbus-manager.h"
37#include "dbus-unit.h"
38#include "dbus-snapshot.h"
39#include "dbus-client-track.h"
40#include "dbus-execute.h"
41#include "bus-errors.h"
ea430986 42
718db961
LP
43static int property_get_version(
44 sd_bus *bus,
45 const char *path,
46 const char *interface,
47 const char *property,
48 sd_bus_message *reply,
ebcf1f97
LP
49 void *userdata,
50 sd_bus_error *error) {
718db961
LP
51
52 assert(bus);
53 assert(reply);
54
55 return sd_bus_message_append(reply, "s", PACKAGE_VERSION);
56}
c5d34390 57
718db961
LP
58static int property_get_features(
59 sd_bus *bus,
60 const char *path,
61 const char *interface,
62 const char *property,
63 sd_bus_message *reply,
ebcf1f97
LP
64 void *userdata,
65 sd_bus_error *error) {
718db961
LP
66
67 assert(bus);
68 assert(reply);
69
70 return sd_bus_message_append(reply, "s", SYSTEMD_FEATURES);
71}
72
73static int property_get_virtualization(
74 sd_bus *bus,
75 const char *path,
76 const char *interface,
77 const char *property,
78 sd_bus_message *reply,
ebcf1f97
LP
79 void *userdata,
80 sd_bus_error *error) {
718db961
LP
81
82 const char *id = NULL;
83
84 assert(bus);
85 assert(reply);
86
87 detect_virtualization(&id);
88
89 return sd_bus_message_append(reply, "s", id);
90}
91
92static int property_get_tainted(
93 sd_bus *bus,
94 const char *path,
95 const char *interface,
96 const char *property,
97 sd_bus_message *reply,
ebcf1f97
LP
98 void *userdata,
99 sd_bus_error *error) {
718db961 100
ebcf1f97 101 char buf[sizeof("split-usr:mtab-not-symlink:cgroups-missing:local-hwclock:")] = "", *e = buf;
718db961
LP
102 _cleanup_free_ char *p = NULL;
103 Manager *m = userdata;
104
105 assert(bus);
106 assert(reply);
bfebab7f 107 assert(m);
c5d34390 108
72bc8d00 109 if (m->taint_usr)
e677bf7e 110 e = stpcpy(e, "split-usr:");
c5d34390 111
871c44a7 112 if (readlink_malloc("/etc/mtab", &p) < 0)
e677bf7e 113 e = stpcpy(e, "mtab-not-symlink:");
c5d34390 114
871c44a7 115 if (access("/proc/cgroups", F_OK) < 0)
1ebf0cb7 116 e = stpcpy(e, "cgroups-missing:");
871c44a7 117
e677bf7e 118 if (hwclock_is_localtime() > 0)
1ebf0cb7 119 e = stpcpy(e, "local-hwclock:");
e677bf7e 120
1ebf0cb7
MS
121 /* remove the last ':' */
122 if (e != buf)
123 e[-1] = 0;
e677bf7e 124
718db961 125 return sd_bus_message_append(reply, "s", buf);
c5d34390
LP
126}
127
718db961
LP
128static int property_get_log_target(
129 sd_bus *bus,
130 const char *path,
131 const char *interface,
132 const char *property,
133 sd_bus_message *reply,
ebcf1f97
LP
134 void *userdata,
135 sd_bus_error *error) {
1adf1049 136
718db961
LP
137 assert(bus);
138 assert(reply);
1adf1049 139
718db961 140 return sd_bus_message_append(reply, "s", log_target_to_string(log_get_target()));
1adf1049
LP
141}
142
718db961
LP
143static int property_set_log_target(
144 sd_bus *bus,
145 const char *path,
146 const char *interface,
147 const char *property,
148 sd_bus_message *value,
ebcf1f97
LP
149 void *userdata,
150 sd_bus_error *error) {
718db961 151
c826cda4 152 const char *t;
718db961 153 int r;
c826cda4 154
718db961
LP
155 assert(bus);
156 assert(value);
c826cda4 157
718db961
LP
158 r = sd_bus_message_read(value, "s", &t);
159 if (r < 0)
160 return r;
c826cda4
AB
161
162 return log_set_target_from_string(t);
163}
164
718db961
LP
165static int property_get_log_level(
166 sd_bus *bus,
167 const char *path,
168 const char *interface,
169 const char *property,
170 sd_bus_message *reply,
ebcf1f97
LP
171 void *userdata,
172 sd_bus_error *error) {
718db961 173
68eda4bd 174 _cleanup_free_ char *t = NULL;
f8b69d1d 175 int r;
1adf1049 176
718db961
LP
177 assert(bus);
178 assert(reply);
1adf1049 179
f8b69d1d
MS
180 r = log_level_to_string_alloc(log_get_max_level(), &t);
181 if (r < 0)
182 return r;
1adf1049 183
718db961 184 return sd_bus_message_append(reply, "s", t);
1adf1049
LP
185}
186
718db961
LP
187static int property_set_log_level(
188 sd_bus *bus,
189 const char *path,
190 const char *interface,
191 const char *property,
192 sd_bus_message *value,
ebcf1f97
LP
193 void *userdata,
194 sd_bus_error *error) {
718db961 195
c826cda4 196 const char *t;
718db961 197 int r;
c826cda4 198
718db961
LP
199 assert(bus);
200 assert(value);
c826cda4 201
718db961
LP
202 r = sd_bus_message_read(value, "s", &t);
203 if (r < 0)
204 return r;
c826cda4
AB
205
206 return log_set_max_level_from_string(t);
207}
208
718db961
LP
209static int property_get_n_names(
210 sd_bus *bus,
211 const char *path,
212 const char *interface,
213 const char *property,
214 sd_bus_message *reply,
ebcf1f97
LP
215 void *userdata,
216 sd_bus_error *error) {
4f0f902f 217
718db961 218 Manager *m = userdata;
4f0f902f 219
718db961
LP
220 assert(bus);
221 assert(reply);
222 assert(m);
4f0f902f 223
718db961 224 return sd_bus_message_append(reply, "u", (uint32_t) hashmap_size(m->units));
4f0f902f
LP
225}
226
718db961
LP
227static int property_get_n_jobs(
228 sd_bus *bus,
229 const char *path,
230 const char *interface,
231 const char *property,
232 sd_bus_message *reply,
ebcf1f97
LP
233 void *userdata,
234 sd_bus_error *error) {
4f0f902f 235
718db961 236 Manager *m = userdata;
4f0f902f 237
718db961
LP
238 assert(bus);
239 assert(reply);
240 assert(m);
4f0f902f 241
718db961 242 return sd_bus_message_append(reply, "u", (uint32_t) hashmap_size(m->jobs));
4f0f902f
LP
243}
244
718db961
LP
245static int property_get_progress(
246 sd_bus *bus,
247 const char *path,
248 const char *interface,
249 const char *property,
250 sd_bus_message *reply,
ebcf1f97
LP
251 void *userdata,
252 sd_bus_error *error) {
718db961
LP
253
254 Manager *m = userdata;
05d6a3b6
LP
255 double d;
256
718db961
LP
257 assert(bus);
258 assert(reply);
bfebab7f 259 assert(m);
05d6a3b6
LP
260
261 if (dual_timestamp_is_set(&m->finish_timestamp))
262 d = 1.0;
263 else
264 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
265
718db961
LP
266 return sd_bus_message_append(reply, "d", d);
267}
268
269static int property_set_runtime_watchdog(
270 sd_bus *bus,
271 const char *path,
272 const char *interface,
273 const char *property,
274 sd_bus_message *value,
ebcf1f97
LP
275 void *userdata,
276 sd_bus_error *error) {
05d6a3b6 277
718db961
LP
278 usec_t *t = userdata;
279 int r;
280
281 assert(bus);
282 assert(value);
283
284 assert_cc(sizeof(usec_t) == sizeof(uint64_t));
285
286 r = sd_bus_message_read(value, "t", t);
287 if (r < 0)
288 return r;
289
290 return watchdog_set_timeout(t);
05d6a3b6
LP
291}
292
ebcf1f97 293static int method_get_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
294 _cleanup_free_ char *path = NULL;
295 Manager *m = userdata;
296 const char *name;
297 Unit *u;
298 int r;
dfae3488 299
718db961
LP
300 assert(bus);
301 assert(message);
dfae3488
LP
302 assert(m);
303
718db961
LP
304 r = sd_bus_message_read(message, "s", &name);
305 if (r < 0)
ebcf1f97 306 return r;
dfae3488 307
718db961
LP
308 u = manager_get_unit(m, name);
309 if (!u)
ebcf1f97 310 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", name);
dfae3488 311
ebcf1f97
LP
312 r = selinux_unit_access_check(u, bus, message, "status", error);
313 if (r < 0)
314 return r;
dfae3488 315
718db961
LP
316 path = unit_dbus_path(u);
317 if (!path)
ebcf1f97 318 return -ENOMEM;
729e3769 319
df2d202e 320 return sd_bus_reply_method_return(message, "o", path);
718db961 321}
c0576cd6 322
ebcf1f97 323static int method_get_unit_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
324 _cleanup_free_ char *path = NULL;
325 Manager *m = userdata;
326 pid_t pid;
327 Unit *u;
328 int r;
c0576cd6 329
718db961
LP
330 assert(bus);
331 assert(message);
332 assert(m);
c0576cd6 333
718db961 334 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
729e3769 335
718db961
LP
336 r = sd_bus_message_read(message, "u", &pid);
337 if (r < 0)
ebcf1f97 338 return r;
718db961
LP
339
340 if (pid == 0) {
341 r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), &pid);
342 if (r < 0)
ebcf1f97 343 return r;
729e3769
LP
344 }
345
718db961
LP
346 u = manager_get_unit_by_pid(m, pid);
347 if (!u)
ebcf1f97 348 return sd_bus_error_setf(error, BUS_ERROR_NO_UNIT_FOR_PID, "PID %u does not belong to any loaded unit.", pid);
c0576cd6 349
ebcf1f97
LP
350 r = selinux_unit_access_check(u, bus, message, "status", error);
351 if (r < 0)
352 return r;
718db961
LP
353
354 path = unit_dbus_path(u);
355 if (!path)
ebcf1f97 356 return -ENOMEM;
718db961 357
df2d202e 358 return sd_bus_reply_method_return(message, "o", path);
718db961
LP
359}
360
ebcf1f97 361static int method_load_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
362 _cleanup_free_ char *path = NULL;
363 Manager *m = userdata;
364 const char *name;
365 Unit *u;
366 int r;
c0576cd6 367
718db961
LP
368 assert(bus);
369 assert(message);
370 assert(m);
371
372 r = sd_bus_message_read(message, "s", &name);
373 if (r < 0)
ebcf1f97 374 return r;
c0576cd6 375
ebcf1f97 376 r = manager_load_unit(m, name, NULL, error, &u);
718db961 377 if (r < 0)
ebcf1f97 378 return r;
718db961 379
ebcf1f97
LP
380 r = selinux_unit_access_check(u, bus, message, "status", error);
381 if (r < 0)
382 return r;
c0576cd6 383
718db961
LP
384 path = unit_dbus_path(u);
385 if (!path)
ebcf1f97 386 return -ENOMEM;
718db961 387
df2d202e 388 return sd_bus_reply_method_return(message, "o", path);
c0576cd6
LP
389}
390
ebcf1f97 391static int method_start_unit_generic(sd_bus *bus, sd_bus_message *message, Manager *m, JobType job_type, bool reload_if_possible, sd_bus_error *error) {
718db961
LP
392 const char *name;
393 Unit *u;
c0576cd6
LP
394 int r;
395
718db961
LP
396 assert(bus);
397 assert(message);
398 assert(m);
c0576cd6 399
718db961
LP
400 r = sd_bus_message_read(message, "s", &name);
401 if (r < 0)
ebcf1f97 402 return r;
c0576cd6 403
ebcf1f97 404 r = manager_load_unit(m, name, NULL, error, &u);
718db961 405 if (r < 0)
ebcf1f97 406 return r;
718db961 407
ebcf1f97 408 return bus_unit_method_start_generic(bus, message, u, job_type, reload_if_possible, error);
c0576cd6
LP
409}
410
ebcf1f97
LP
411static int method_start_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
412 return method_start_unit_generic(bus, message, userdata, JOB_START, false, error);
718db961 413}
c757a65b 414
ebcf1f97
LP
415static int method_stop_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
416 return method_start_unit_generic(bus, message, userdata, JOB_STOP, false, error);
718db961 417}
c757a65b 418
ebcf1f97
LP
419static int method_reload_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
420 return method_start_unit_generic(bus, message, userdata, JOB_RELOAD, false, error);
718db961 421}
c757a65b 422
ebcf1f97
LP
423static int method_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
424 return method_start_unit_generic(bus, message, userdata, JOB_RESTART, false, error);
c757a65b
LP
425}
426
ebcf1f97
LP
427static int method_try_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
428 return method_start_unit_generic(bus, message, userdata, JOB_TRY_RESTART, false, error);
718db961 429}
d200735e 430
ebcf1f97
LP
431static int method_reload_or_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
432 return method_start_unit_generic(bus, message, userdata, JOB_RESTART, true, error);
718db961 433}
d200735e 434
ebcf1f97
LP
435static int method_reload_or_try_restart_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
436 return method_start_unit_generic(bus, message, userdata, JOB_TRY_RESTART, true, error);
718db961 437}
d200735e 438
ebcf1f97 439static int method_start_unit_replace(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
440 Manager *m = userdata;
441 const char *old_name;
442 Unit *u;
1adf1049 443 int r;
ea430986 444
718db961 445 assert(bus);
ea430986
LP
446 assert(message);
447 assert(m);
448
718db961
LP
449 r = sd_bus_message_read(message, "s", &old_name);
450 if (r < 0)
ebcf1f97 451 return r;
ea430986 452
718db961
LP
453 u = manager_get_unit(m, old_name);
454 if (!u || !u->job || u->job->type != JOB_START)
ebcf1f97 455 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
c0576cd6 456
ebcf1f97 457 return method_start_unit_generic(bus, message, m, JOB_START, false, error);
718db961 458}
ea430986 459
ebcf1f97 460static int method_kill_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
461 Manager *m = userdata;
462 const char *name;
463 Unit *u;
464 int r;
ea430986 465
718db961
LP
466 assert(bus);
467 assert(message);
468 assert(m);
ea430986 469
718db961
LP
470 r = sd_bus_message_read(message, "s", &name);
471 if (r < 0)
ebcf1f97 472 return r;
598b557b 473
718db961
LP
474 u = manager_get_unit(m, name);
475 if (!u)
ebcf1f97 476 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
0a524ba7 477
ebcf1f97 478 return bus_unit_method_kill(bus, message, u, error);
718db961 479}
8a0867d6 480
ebcf1f97 481static int method_reset_failed_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
482 Manager *m = userdata;
483 const char *name;
484 Unit *u;
485 int r;
8a0867d6 486
718db961
LP
487 assert(bus);
488 assert(message);
489 assert(m);
cad45ba1 490
718db961
LP
491 r = sd_bus_message_read(message, "s", &name);
492 if (r < 0)
ebcf1f97 493 return r;
ea430986 494
718db961
LP
495 u = manager_get_unit(m, name);
496 if (!u)
ebcf1f97 497 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
5dd9014f 498
ebcf1f97 499 return bus_unit_method_reset_failed(bus, message, u, error);
718db961 500}
5dd9014f 501
ebcf1f97 502static int method_set_unit_properties(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
503 Manager *m = userdata;
504 const char *name;
505 Unit *u;
506 int r;
5dd9014f 507
718db961
LP
508 assert(bus);
509 assert(message);
510 assert(m);
511
512 r = sd_bus_message_read(message, "s", &name);
513 if (r < 0)
ebcf1f97 514 return r;
718db961
LP
515
516 u = manager_get_unit(m, name);
517 if (!u)
ebcf1f97 518 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
ea430986 519
ebcf1f97 520 return bus_unit_method_set_properties(bus, message, u, error);
718db961
LP
521}
522
ebcf1f97 523static int method_start_transient_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
524 const char *name, *smode;
525 Manager *m = userdata;
526 JobMode mode;
527 UnitType t;
528 Unit *u;
529 int r;
ea430986 530
718db961
LP
531 assert(bus);
532 assert(message);
533 assert(m);
ea430986 534
718db961
LP
535 r = sd_bus_message_read(message, "ss", &name, &smode);
536 if (r < 0)
ebcf1f97 537 return r;
5632e374 538
718db961
LP
539 t = unit_name_to_type(name);
540 if (t < 0)
ebcf1f97 541 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit type.");
cad45ba1 542
718db961 543 if (!unit_vtable[t]->can_transient)
ebcf1f97 544 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit type %s does not support transient units.");
5632e374 545
718db961
LP
546 mode = job_mode_from_string(smode);
547 if (mode < 0)
ebcf1f97 548 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s is invalid.", smode);
5632e374 549
6ce270b1 550 r = selinux_access_check(bus, message, "start", error);
718db961 551 if (r < 0)
ebcf1f97 552 return r;
5632e374 553
6ce270b1 554 r = manager_load_unit(m, name, NULL, error, &u);
ebcf1f97
LP
555 if (r < 0)
556 return r;
5632e374 557
718db961 558 if (u->load_state != UNIT_NOT_FOUND || set_size(u->dependencies[UNIT_REFERENCED_BY]) > 0)
ebcf1f97 559 return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit %s already exists.", name);
5632e374 560
718db961
LP
561 /* OK, the unit failed to load and is unreferenced, now let's
562 * fill in the transient data instead */
563 r = unit_make_transient(u);
564 if (r < 0)
ebcf1f97 565 return r;
ea430986 566
718db961 567 /* Set our properties */
ebcf1f97 568 r = bus_unit_set_properties(u, message, UNIT_RUNTIME, false, error);
718db961 569 if (r < 0)
ebcf1f97 570 return r;
ea430986 571
718db961
LP
572 /* And load this stub fully */
573 r = unit_load(u);
574 if (r < 0)
ebcf1f97 575 return r;
ea430986 576
718db961 577 manager_dispatch_load_queue(m);
cad45ba1 578
718db961 579 /* Finally, start it */
ebcf1f97 580 return bus_unit_queue_job(bus, message, u, JOB_START, mode, false, error);
718db961 581}
ea430986 582
ebcf1f97 583static int method_get_job(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
584 _cleanup_free_ char *path = NULL;
585 Manager *m = userdata;
586 uint32_t id;
587 Job *j;
588 int r;
ea430986 589
718db961
LP
590 assert(bus);
591 assert(message);
592 assert(m);
ea430986 593
718db961
LP
594 r = sd_bus_message_read(message, "u", &id);
595 if (r < 0)
ebcf1f97 596 return r;
ea430986 597
718db961
LP
598 j = manager_get_job(m, id);
599 if (!j)
ebcf1f97 600 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
ea430986 601
ebcf1f97
LP
602 r = selinux_unit_access_check(j->unit, bus, message, "status", error);
603 if (r < 0)
604 return r;
ea430986 605
718db961
LP
606 path = job_dbus_path(j);
607 if (!path)
ebcf1f97 608 return -ENOMEM;
ea430986 609
df2d202e 610 return sd_bus_reply_method_return(message, "o", path);
718db961 611}
ea430986 612
ebcf1f97 613static int method_cancel_job(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
614 Manager *m = userdata;
615 uint32_t id;
616 Job *j;
617 int r;
ea430986 618
718db961
LP
619 assert(bus);
620 assert(message);
621 assert(m);
ea430986 622
718db961
LP
623 r = sd_bus_message_read(message, "u", &id);
624 if (r < 0)
ebcf1f97 625 return r;
ea430986 626
718db961
LP
627 j = manager_get_job(m, id);
628 if (!j)
ebcf1f97 629 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
ea430986 630
ebcf1f97
LP
631 r = selinux_unit_access_check(j->unit, bus, message, "stop", error);
632 if (r < 0)
633 return r;
a567261a 634
718db961 635 job_finish_and_invalidate(j, JOB_CANCELED, true);
cad45ba1 636
df2d202e 637 return sd_bus_reply_method_return(message, NULL);
718db961 638}
c1e1601e 639
ebcf1f97 640static int method_clear_jobs(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 641 Manager *m = userdata;
ebcf1f97 642 int r;
c1e1601e 643
718db961
LP
644 assert(bus);
645 assert(message);
646 assert(m);
c1e1601e 647
ebcf1f97
LP
648 r = selinux_access_check(bus, message, "reboot", error);
649 if (r < 0)
650 return r;
651
718db961 652 manager_clear_jobs(m);
c1e1601e 653
df2d202e 654 return sd_bus_reply_method_return(message, NULL);
718db961 655}
c1e1601e 656
ebcf1f97 657static int method_reset_failed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 658 Manager *m = userdata;
ebcf1f97 659 int r;
cad45ba1 660
718db961
LP
661 assert(bus);
662 assert(message);
663 assert(m);
664
ebcf1f97
LP
665 r = selinux_access_check(bus, message, "reload", error);
666 if (r < 0)
667 return r;
668
718db961 669 manager_reset_failed(m);
c1e1601e 670
df2d202e 671 return sd_bus_reply_method_return(message, NULL);
718db961 672}
c1e1601e 673
ebcf1f97 674static int method_list_units(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
675 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
676 Manager *m = userdata;
677 const char *k;
678 Iterator i;
679 Unit *u;
680 int r;
c1e1601e 681
718db961
LP
682 assert(bus);
683 assert(message);
684 assert(m);
b152adec 685
ebcf1f97
LP
686 r = selinux_access_check(bus, message, "status", error);
687 if (r < 0)
688 return r;
cad45ba1 689
df2d202e 690 r = sd_bus_message_new_method_return(message, &reply);
718db961 691 if (r < 0)
ebcf1f97 692 return r;
b152adec 693
718db961
LP
694 r = sd_bus_message_open_container(reply, 'a', "(ssssssouso)");
695 if (r < 0)
ebcf1f97 696 return r;
b152adec 697
718db961
LP
698 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
699 _cleanup_free_ char *unit_path = NULL, *job_path = NULL;
700 Unit *following;
b152adec 701
718db961
LP
702 if (k != u->id)
703 continue;
b152adec 704
718db961 705 following = unit_following(u);
b152adec 706
718db961
LP
707 unit_path = unit_dbus_path(u);
708 if (!unit_path)
ebcf1f97 709 return -ENOMEM;
718db961
LP
710
711 if (u->job) {
712 job_path = job_dbus_path(u->job);
713 if (!job_path)
ebcf1f97 714 return -ENOMEM;
b152adec
LP
715 }
716
718db961
LP
717 r = sd_bus_message_append(
718 reply, "(ssssssouso)",
719 u->id,
720 unit_description(u),
721 unit_load_state_to_string(u->load_state),
722 unit_active_state_to_string(unit_active_state(u)),
723 unit_sub_state_to_string(u),
724 following ? following->id : "",
725 unit_path,
726 u->job ? u->job->id : 0,
727 u->job ? job_type_to_string(u->job->type) : "",
728 job_path ? job_path : "/");
729 if (r < 0)
ebcf1f97 730 return r;
718db961 731 }
4139c1b2 732
718db961
LP
733 r = sd_bus_message_close_container(reply);
734 if (r < 0)
ebcf1f97 735 return r;
cad45ba1 736
718db961
LP
737 return sd_bus_send(bus, reply, NULL);
738}
4139c1b2 739
ebcf1f97 740static int method_list_jobs(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
741 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
742 Manager *m = userdata;
743 Iterator i;
744 Job *j;
745 int r;
4139c1b2 746
718db961
LP
747 assert(bus);
748 assert(message);
749 assert(m);
750
ebcf1f97
LP
751 r = selinux_access_check(bus, message, "status", error);
752 if (r < 0)
753 return r;
718db961 754
df2d202e 755 r = sd_bus_message_new_method_return(message, &reply);
718db961 756 if (r < 0)
ebcf1f97 757 return r;
718db961
LP
758
759 r = sd_bus_message_open_container(reply, 'a', "(usssoo)");
760 if (r < 0)
ebcf1f97 761 return r;
718db961
LP
762
763 HASHMAP_FOREACH(j, m->jobs, i) {
764 _cleanup_free_ char *unit_path = NULL, *job_path = NULL;
765
766 job_path = job_dbus_path(j);
767 if (!job_path)
ebcf1f97 768 return -ENOMEM;
718db961
LP
769
770 unit_path = unit_dbus_path(j->unit);
771 if (!unit_path)
ebcf1f97 772 return -ENOMEM;
718db961
LP
773
774 r = sd_bus_message_append(
775 reply, "(usssoo)",
776 j->id,
777 job_state_to_string(j->state),
778 job_type_to_string(j->type),
779 job_path,
780 unit_path);
cad45ba1 781 if (r < 0)
ebcf1f97 782 return r;
718db961 783 }
5dd9014f 784
718db961
LP
785 r = sd_bus_message_close_container(reply);
786 if (r < 0)
ebcf1f97 787 return r;
5dd9014f 788
718db961
LP
789 return sd_bus_send(bus, reply, NULL);
790}
5dd9014f 791
ebcf1f97 792static int method_subscribe(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
793 Manager *m = userdata;
794 int r;
5dd9014f 795
718db961
LP
796 assert(bus);
797 assert(message);
798 assert(m);
ea430986 799
ebcf1f97
LP
800 r = selinux_access_check(bus, message, "status", error);
801 if (r < 0)
802 return r;
cad45ba1 803
718db961
LP
804 r = bus_client_track(&m->subscribed, bus, sd_bus_message_get_sender(message));
805 if (r < 0)
ebcf1f97 806 return r;
718db961 807 if (r == 0)
ebcf1f97 808 return sd_bus_error_setf(error, BUS_ERROR_ALREADY_SUBSCRIBED, "Client is already subscribed.");
ea430986 809
df2d202e 810 return sd_bus_reply_method_return(message, NULL);
718db961 811}
ea430986 812
ebcf1f97 813static int method_unsubscribe(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
814 Manager *m = userdata;
815 int r;
ea430986 816
718db961
LP
817 assert(bus);
818 assert(message);
819 assert(m);
ea430986 820
ebcf1f97
LP
821 r = selinux_access_check(bus, message, "status", error);
822 if (r < 0)
823 return r;
ea430986 824
718db961
LP
825 r = bus_client_untrack(m->subscribed, bus, sd_bus_message_get_sender(message));
826 if (r < 0)
ebcf1f97 827 return r;
718db961 828 if (r == 0)
ebcf1f97 829 return sd_bus_error_setf(error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
ea430986 830
df2d202e 831 return sd_bus_reply_method_return(message, NULL);
718db961 832}
ea430986 833
ebcf1f97 834static int method_dump(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
835 _cleanup_free_ char *dump = NULL;
836 _cleanup_fclose_ FILE *f = NULL;
837 Manager *m = userdata;
838 size_t size;
ebcf1f97 839 int r;
ea430986 840
718db961
LP
841 assert(bus);
842 assert(message);
843 assert(m);
ea430986 844
ebcf1f97
LP
845 r = selinux_access_check(bus, message, "status", error);
846 if (r < 0)
847 return r;
ea430986 848
718db961
LP
849 f = open_memstream(&dump, &size);
850 if (!f)
ebcf1f97 851 return -ENOMEM;
ea430986 852
718db961
LP
853 manager_dump_units(m, f, NULL);
854 manager_dump_jobs(m, f, NULL);
ea430986 855
718db961 856 fflush(f);
ea430986 857
718db961 858 if (ferror(f))
ebcf1f97 859 return -ENOMEM;
a16e1123 860
df2d202e 861 return sd_bus_reply_method_return(message, "s", dump);
718db961 862}
cad45ba1 863
ebcf1f97 864static int method_create_snapshot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
865 _cleanup_free_ char *path = NULL;
866 Manager *m = userdata;
867 const char *name;
868 int cleanup;
869 Snapshot *s;
870 int r;
a16e1123 871
718db961
LP
872 assert(bus);
873 assert(message);
874 assert(m);
a16e1123 875
ebcf1f97
LP
876 r = selinux_access_check(bus, message, "start", error);
877 if (r < 0)
878 return r;
a16e1123 879
718db961
LP
880 r = sd_bus_message_read(message, "sb", &name, &cleanup);
881 if (r < 0)
ebcf1f97 882 return r;
a16e1123 883
718db961
LP
884 if (isempty(name))
885 name = NULL;
a16e1123 886
ebcf1f97 887 r = snapshot_create(m, name, cleanup, error, &s);
718db961 888 if (r < 0)
ebcf1f97 889 return r;
cad45ba1 890
718db961
LP
891 path = unit_dbus_path(UNIT(s));
892 if (!path)
ebcf1f97 893 return -ENOMEM;
a16e1123 894
df2d202e 895 return sd_bus_reply_method_return(message, "o", path);
718db961 896}
a16e1123 897
ebcf1f97 898static int method_remove_snapshot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
899 Manager *m = userdata;
900 const char *name;
901 Unit *u;
902 int r;
a16e1123 903
718db961
LP
904 assert(bus);
905 assert(message);
906 assert(m);
cad45ba1 907
ebcf1f97
LP
908 r = selinux_access_check(bus, message, "stop", error);
909 if (r < 0)
910 return r;
a16e1123 911
718db961
LP
912 r = sd_bus_message_read(message, "s", &name);
913 if (r < 0)
ebcf1f97 914 return r;
a16e1123 915
718db961
LP
916 u = manager_get_unit(m, name);
917 if (!u)
ebcf1f97 918 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s does not exist.", name);
a16e1123 919
718db961 920 if (u->type != UNIT_SNAPSHOT)
ebcf1f97 921 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not a snapshot", name);
6652a2b9 922
ebcf1f97 923 return bus_snapshot_method_remove(bus, message, u, error);
718db961 924}
cad45ba1 925
ebcf1f97 926static int method_reload(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
927 Manager *m = userdata;
928 int r;
6652a2b9 929
718db961
LP
930 assert(bus);
931 assert(message);
932 assert(m);
6652a2b9 933
ebcf1f97
LP
934 r = selinux_access_check(bus, message, "reload", error);
935 if (r < 0)
936 return r;
6652a2b9 937
718db961
LP
938 /* Instead of sending the reply back right away, we just
939 * remember that we need to and then send it after the reload
940 * is finished. That way the caller knows when the reload
941 * finished. */
6652a2b9 942
718db961 943 assert(!m->queued_message);
df2d202e 944 r = sd_bus_message_new_method_return(message, &m->queued_message);
718db961 945 if (r < 0)
ebcf1f97 946 return r;
cad45ba1 947
718db961
LP
948 m->queued_message_bus = sd_bus_ref(bus);
949 m->exit_code = MANAGER_RELOAD;
6652a2b9 950
718db961
LP
951 return 1;
952}
6652a2b9 953
ebcf1f97 954static int method_reexecute(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 955 Manager *m = userdata;
ebcf1f97 956 int r;
6652a2b9 957
718db961
LP
958 assert(bus);
959 assert(message);
960 assert(m);
6652a2b9 961
ebcf1f97
LP
962 r = selinux_access_check(bus, message, "reload", error);
963 if (r < 0)
964 return r;
cad45ba1 965
718db961
LP
966 /* We don't send a reply back here, the client should
967 * just wait for us disconnecting. */
6652a2b9 968
718db961
LP
969 m->exit_code = MANAGER_REEXECUTE;
970 return 1;
971}
6652a2b9 972
ebcf1f97 973static int method_exit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 974 Manager *m = userdata;
ebcf1f97 975 int r;
6652a2b9 976
718db961
LP
977 assert(bus);
978 assert(message);
979 assert(m);
6652a2b9 980
ebcf1f97
LP
981 r = selinux_access_check(bus, message, "halt", error);
982 if (r < 0)
983 return r;
cad45ba1 984
718db961 985 if (m->running_as == SYSTEMD_SYSTEM)
ebcf1f97 986 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
6652a2b9 987
718db961 988 m->exit_code = MANAGER_EXIT;
6652a2b9 989
df2d202e 990 return sd_bus_reply_method_return(message, NULL);
718db961 991}
6652a2b9 992
ebcf1f97 993static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 994 Manager *m = userdata;
ebcf1f97 995 int r;
664f88a7 996
718db961
LP
997 assert(bus);
998 assert(message);
999 assert(m);
cad45ba1 1000
ebcf1f97
LP
1001 r = selinux_access_check(bus, message, "reboot", error);
1002 if (r < 0)
1003 return r;
664f88a7 1004
718db961 1005 if (m->running_as != SYSTEMD_SYSTEM)
ebcf1f97 1006 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
664f88a7 1007
718db961 1008 m->exit_code = MANAGER_REBOOT;
664f88a7 1009
df2d202e 1010 return sd_bus_reply_method_return(message, NULL);
718db961 1011}
664f88a7 1012
50913bc0 1013
ebcf1f97 1014static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 1015 Manager *m = userdata;
ebcf1f97 1016 int r;
50913bc0 1017
718db961
LP
1018 assert(bus);
1019 assert(message);
1020 assert(m);
1137a57c 1021
ebcf1f97
LP
1022 r = selinux_access_check(bus, message, "halt", error);
1023 if (r < 0)
1024 return r;
1137a57c 1025
718db961 1026 if (m->running_as != SYSTEMD_SYSTEM)
ebcf1f97 1027 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1137a57c 1028
718db961 1029 m->exit_code = MANAGER_POWEROFF;
1137a57c 1030
df2d202e 1031 return sd_bus_reply_method_return(message, NULL);
718db961 1032}
1137a57c 1033
ebcf1f97 1034static int method_halt(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 1035 Manager *m = userdata;
ebcf1f97 1036 int r;
1137a57c 1037
718db961
LP
1038 assert(bus);
1039 assert(message);
1040 assert(m);
8d0e38a2 1041
ebcf1f97
LP
1042 r = selinux_access_check(bus, message, "halt", error);
1043 if (r < 0)
1044 return r;
cad45ba1 1045
718db961 1046 if (m->running_as != SYSTEMD_SYSTEM)
ebcf1f97 1047 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Halt is only supported for system managers.");
8d0e38a2 1048
718db961 1049 m->exit_code = MANAGER_HALT;
8d0e38a2 1050
df2d202e 1051 return sd_bus_reply_method_return(message, NULL);
718db961 1052}
8d0e38a2 1053
ebcf1f97 1054static int method_kexec(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 1055 Manager *m = userdata;
ebcf1f97 1056 int r;
8d0e38a2 1057
718db961
LP
1058 assert(bus);
1059 assert(message);
1060 assert(m);
c0576cd6 1061
ebcf1f97
LP
1062 r = selinux_access_check(bus, message, "reboot", error);
1063 if (r < 0)
1064 return r;
cad45ba1 1065
718db961 1066 if (m->running_as != SYSTEMD_SYSTEM)
ebcf1f97 1067 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "KExec is only supported for system managers.");
c0576cd6 1068
718db961 1069 m->exit_code = MANAGER_KEXEC;
c0576cd6 1070
df2d202e 1071 return sd_bus_reply_method_return(message, NULL);
718db961 1072}
c0576cd6 1073
ebcf1f97 1074static int method_switch_root(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1075 char *ri = NULL, *rt = NULL;
1076 const char *root, *init;
1077 Manager *m = userdata;
1078 int r;
c0576cd6 1079
718db961
LP
1080 assert(bus);
1081 assert(message);
1082 assert(m);
c0576cd6 1083
ebcf1f97
LP
1084 r = selinux_access_check(bus, message, "reboot", error);
1085 if (r < 0)
1086 return r;
c0576cd6 1087
718db961 1088 if (m->running_as != SYSTEMD_SYSTEM)
ebcf1f97 1089 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "KExec is only supported for system managers.");
c0576cd6 1090
718db961
LP
1091 r = sd_bus_message_read(message, "ss", &root, &init);
1092 if (r < 0)
ebcf1f97 1093 return r;
c0576cd6 1094
718db961 1095 if (path_equal(root, "/") || !path_is_absolute(root))
ebcf1f97 1096 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid switch root path %s", root);
c0576cd6 1097
718db961
LP
1098 /* Safety check */
1099 if (isempty(init)) {
1100 if (! path_is_os_tree(root))
ebcf1f97 1101 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified switch root path %s does not seem to be an OS tree. /etc/os-release is missing.", root);
718db961
LP
1102 } else {
1103 _cleanup_free_ char *p = NULL;
c0576cd6 1104
718db961 1105 if (!path_is_absolute(init))
ebcf1f97 1106 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid init path %s", init);
c0576cd6 1107
718db961
LP
1108 p = strappend(root, init);
1109 if (!p)
ebcf1f97 1110 return -ENOMEM;
c0576cd6 1111
718db961 1112 if (access(p, X_OK) < 0)
ebcf1f97 1113 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified init binary %s does not exist.", p);
718db961
LP
1114 }
1115
1116 rt = strdup(root);
1117 if (!rt)
ebcf1f97 1118 return -ENOMEM;
718db961
LP
1119
1120 if (!isempty(init)) {
1121 ri = strdup(init);
1122 if (!ri) {
1123 free(ri);
ebcf1f97 1124 return -ENOMEM;
c0576cd6 1125 }
718db961 1126 }
c0576cd6 1127
718db961
LP
1128 free(m->switch_root);
1129 m->switch_root = rt;
c0576cd6 1130
718db961
LP
1131 free(m->switch_root_init);
1132 m->switch_root_init = ri;
c0576cd6 1133
df2d202e 1134 return sd_bus_reply_method_return(message, NULL);
718db961 1135}
c0576cd6 1136
ebcf1f97 1137static int method_set_environment(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1138 _cleanup_strv_free_ char **plus = NULL;
1139 Manager *m = userdata;
1140 int r;
c0576cd6 1141
718db961
LP
1142 assert(bus);
1143 assert(message);
1144 assert(m);
cad45ba1 1145
ebcf1f97
LP
1146 r = selinux_access_check(bus, message, "reload", error);
1147 if (r < 0)
1148 return r;
c0576cd6 1149
718db961
LP
1150 r = sd_bus_message_read_strv(message, &plus);
1151 if (r < 0)
ebcf1f97 1152 return r;
718db961 1153 if (!strv_env_is_valid(plus))
ebcf1f97 1154 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
c0576cd6 1155
718db961
LP
1156 r = manager_environment_add(m, NULL, plus);
1157 if (r < 0)
ebcf1f97 1158 return r;
c0576cd6 1159
df2d202e 1160 return sd_bus_reply_method_return(message, NULL);
718db961
LP
1161}
1162
ebcf1f97 1163static int method_unset_environment(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1164 _cleanup_strv_free_ char **minus = NULL;
1165 Manager *m = userdata;
1166 int r;
1167
1168 assert(bus);
1169 assert(message);
1170 assert(m);
1171
ebcf1f97
LP
1172 r = selinux_access_check(bus, message, "reload", error);
1173 if (r < 0)
1174 return r;
c0576cd6 1175
718db961
LP
1176 r = sd_bus_message_read_strv(message, &minus);
1177 if (r < 0)
ebcf1f97 1178 return r;
718db961
LP
1179
1180 if (!strv_env_name_or_assignment_is_valid(minus))
ebcf1f97 1181 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
718db961
LP
1182
1183 r = manager_environment_add(m, minus, NULL);
1184 if (r < 0)
ebcf1f97 1185 return r;
718db961 1186
df2d202e 1187 return sd_bus_reply_method_return(message, NULL);
718db961
LP
1188}
1189
ebcf1f97 1190static int method_unset_and_set_environment(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1191 _cleanup_strv_free_ char **minus = NULL, **plus = NULL;
1192 Manager *m = userdata;
1193 int r;
1194
1195 assert(bus);
1196 assert(message);
1197 assert(m);
1198
ebcf1f97
LP
1199 r = selinux_access_check(bus, message, "reload", error);
1200 if (r < 0)
1201 return r;
718db961
LP
1202
1203 r = sd_bus_message_read_strv(message, &plus);
1204 if (r < 0)
ebcf1f97 1205 return r;
718db961
LP
1206
1207 r = sd_bus_message_read_strv(message, &minus);
1208 if (r < 0)
ebcf1f97 1209 return r;
718db961
LP
1210
1211 if (!strv_env_is_valid(plus))
ebcf1f97 1212 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
718db961 1213 if (!strv_env_name_or_assignment_is_valid(minus))
ebcf1f97 1214 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
718db961
LP
1215
1216 r = manager_environment_add(m, minus, plus);
1217 if (r < 0)
ebcf1f97 1218 return r;
718db961 1219
df2d202e 1220 return sd_bus_reply_method_return(message, NULL);
718db961
LP
1221}
1222
ebcf1f97 1223static int method_list_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1224 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1225 Manager *m = userdata;
1226 UnitFileList *item;
1227 Hashmap *h;
1228 Iterator i;
1229 int r;
1230
1231 assert(bus);
1232 assert(message);
1233 assert(m);
1234
ebcf1f97
LP
1235 r = selinux_access_check(bus, message, "status", error);
1236 if (r < 0)
1237 return r;
718db961 1238
df2d202e 1239 r = sd_bus_message_new_method_return(message, &reply);
718db961 1240 if (r < 0)
ebcf1f97 1241 return r;
c0576cd6 1242
718db961
LP
1243 h = hashmap_new(string_hash_func, string_compare_func);
1244 if (!h)
ebcf1f97 1245 return -ENOMEM;
c0576cd6 1246
718db961 1247 r = unit_file_get_list(m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
ebcf1f97 1248 if (r < 0)
718db961 1249 goto fail;
718db961
LP
1250
1251 r = sd_bus_message_open_container(reply, 'a', "(ss)");
ebcf1f97 1252 if (r < 0)
718db961 1253 goto fail;
718db961
LP
1254
1255 HASHMAP_FOREACH(item, h, i) {
1256
1257 r = sd_bus_message_append(reply, "(ss)", item->path, unit_file_state_to_string(item->state));
ebcf1f97 1258 if (r < 0)
718db961 1259 goto fail;
718db961 1260 }
c0576cd6 1261
718db961 1262 unit_file_list_free(h);
c0576cd6 1263
718db961
LP
1264 r = sd_bus_message_close_container(reply);
1265 if (r < 0)
ebcf1f97 1266 return r;
8d0e38a2 1267
718db961 1268 return sd_bus_send(bus, reply, NULL);
99504dd4 1269
718db961
LP
1270fail:
1271 unit_file_list_free(h);
1272 return r;
1273}
99504dd4 1274
ebcf1f97 1275static int method_get_unit_file_state(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1276 Manager *m = userdata;
1277 const char *name;
1278 UnitFileState state;
1279 UnitFileScope scope;
1280 int r;
99504dd4 1281
718db961
LP
1282 assert(bus);
1283 assert(message);
1284 assert(m);
8e2af478 1285
ebcf1f97
LP
1286 r = selinux_access_check(bus, message, "status", error);
1287 if (r < 0)
1288 return r;
8e2af478 1289
718db961
LP
1290 r = sd_bus_message_read(message, "s", &name);
1291 if (r < 0)
ebcf1f97 1292 return r;
8e2af478 1293
718db961 1294 scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
8e2af478 1295
718db961
LP
1296 state = unit_file_get_state(scope, NULL, name);
1297 if (state < 0)
ebcf1f97 1298 return state;
8e2af478 1299
df2d202e 1300 return sd_bus_reply_method_return(message, "s", unit_file_state_to_string(state));
718db961 1301}
8e2af478 1302
ebcf1f97 1303static int method_get_default_target(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1304 _cleanup_free_ char *default_target = NULL;
1305 Manager *m = userdata;
1306 UnitFileScope scope;
1307 int r;
c2756a68 1308
718db961
LP
1309 assert(bus);
1310 assert(message);
1311 assert(m);
c2756a68 1312
ebcf1f97
LP
1313 r = selinux_access_check(bus, message, "status", error);
1314 if (r < 0)
1315 return r;
c2756a68 1316
718db961 1317 scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
c2756a68 1318
718db961
LP
1319 r = unit_file_get_default(scope, NULL, &default_target);
1320 if (r < 0)
ebcf1f97 1321 return r;
c2756a68 1322
df2d202e 1323 return sd_bus_reply_method_return(message, "s", default_target);
718db961 1324}
c2756a68 1325
718db961
LP
1326static int send_unit_files_changed(sd_bus *bus, const char *destination, void *userdata) {
1327 _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
1328 int r;
1329
1330 assert(bus);
1331
1332 r = sd_bus_message_new_signal(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged", &message);
1333 if (r < 0)
1334 return r;
1335
1336 return sd_bus_send_to(bus, message, destination, NULL);
1337}
1338
1339static int reply_unit_file_changes_and_free(
1340 Manager *m,
1341 sd_bus *bus,
1342 sd_bus_message *message,
1343 int carries_install_info,
1344 UnitFileChange *changes,
1345 unsigned n_changes) {
1346
1347 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1348 unsigned i;
1349 int r;
1350
1351 if (n_changes > 0)
1352 bus_manager_foreach_client(m, send_unit_files_changed, NULL);
1353
df2d202e 1354 r = sd_bus_message_new_method_return(message, &reply);
718db961
LP
1355 if (r < 0)
1356 goto fail;
1357
1358 if (carries_install_info >= 0) {
1359 r = sd_bus_message_append(reply, "b", carries_install_info);
c2756a68 1360 if (r < 0)
718db961
LP
1361 goto fail;
1362 }
1363
1364 r = sd_bus_message_open_container(reply, 'a', "(sss)");
1365 if (r < 0)
1366 goto fail;
c2756a68 1367
718db961
LP
1368 for (i = 0; i < n_changes; i++) {
1369 r = sd_bus_message_append(
21586b77 1370 reply, "(sss)",
718db961
LP
1371 unit_file_change_type_to_string(changes[i].type),
1372 changes[i].path,
1373 changes[i].source);
c2756a68 1374 if (r < 0)
718db961
LP
1375 goto fail;
1376 }
c2756a68 1377
718db961
LP
1378 r = sd_bus_message_close_container(reply);
1379 if (r < 0)
1380 goto fail;
c2756a68 1381
21586b77 1382 return sd_bus_send(bus, reply, NULL);
c2756a68 1383
718db961
LP
1384fail:
1385 unit_file_changes_free(changes, n_changes);
ebcf1f97 1386 return r;
718db961 1387}
cad45ba1 1388
718db961
LP
1389static int method_enable_unit_files_generic(
1390 sd_bus *bus,
1391 sd_bus_message *message,
1392 Manager *m, const
1393 char *verb,
1394 int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes),
ebcf1f97
LP
1395 bool carries_install_info,
1396 sd_bus_error *error) {
718db961
LP
1397
1398 _cleanup_strv_free_ char **l = NULL;
1399 UnitFileChange *changes = NULL;
1400 unsigned n_changes = 0;
1401 UnitFileScope scope;
1402 int runtime, force, r;
1403
1404 assert(bus);
1405 assert(message);
1406 assert(m);
cad45ba1 1407
ebcf1f97
LP
1408 r = selinux_access_check(bus, message, verb, error);
1409 if (r < 0)
1410 return r;
ea430986 1411
718db961
LP
1412 r = sd_bus_message_read_strv(message, &l);
1413 if (r < 0)
ebcf1f97 1414 return r;
90bb85e1 1415
718db961
LP
1416 r = sd_bus_message_read(message, "bb", &runtime, &force);
1417 if (r < 0)
ebcf1f97 1418 return r;
c87eba54 1419
718db961 1420 scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
c87eba54 1421
718db961
LP
1422 r = call(scope, runtime, NULL, l, force, &changes, &n_changes);
1423 if (r < 0)
ebcf1f97 1424 return r;
718db961
LP
1425
1426 return reply_unit_file_changes_and_free(m, bus, message, carries_install_info ? r : -1, changes, n_changes);
1427}
c87eba54 1428
ebcf1f97
LP
1429static int method_enable_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1430 return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_enable, true, error);
718db961 1431}
ea430986 1432
ebcf1f97
LP
1433static int method_reenable_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1434 return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_reenable, true, error);
718db961
LP
1435}
1436
ebcf1f97
LP
1437static int method_link_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1438 return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_link, false, error);
718db961
LP
1439}
1440
ebcf1f97
LP
1441static int method_preset_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1442 return method_enable_unit_files_generic(bus, message, userdata, "enable", unit_file_preset, true, error);
718db961
LP
1443}
1444
ebcf1f97
LP
1445static int method_mask_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1446 return method_enable_unit_files_generic(bus, message, userdata, "disable", unit_file_mask, false, error);
718db961 1447}
ea430986 1448
718db961
LP
1449static int method_disable_unit_files_generic(
1450 sd_bus *bus,
1451 sd_bus_message *message,
1452 Manager *m, const
1453 char *verb,
ebcf1f97
LP
1454 int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes),
1455 sd_bus_error *error) {
718db961
LP
1456
1457 _cleanup_strv_free_ char **l = NULL;
1458 UnitFileChange *changes = NULL;
1459 unsigned n_changes = 0;
1460 UnitFileScope scope;
1461 int r, runtime;
1462
1463 assert(bus);
1464 assert(message);
1465 assert(m);
1466
ebcf1f97
LP
1467 r = selinux_access_check(bus, message, verb, error);
1468 if (r < 0)
1469 return r;
718db961
LP
1470
1471 r = sd_bus_message_read_strv(message, &l);
1472 if (r < 0)
ebcf1f97 1473 return r;
718db961
LP
1474
1475 r = sd_bus_message_read(message, "b", &runtime);
1476 if (r < 0)
ebcf1f97 1477 return r;
718db961
LP
1478
1479 scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1480
1481 r = call(scope, runtime, NULL, l, &changes, &n_changes);
1482 if (r < 0)
ebcf1f97 1483 return r;
718db961
LP
1484
1485 return reply_unit_file_changes_and_free(m, bus, message, -1, changes, n_changes);
1486}
ea430986 1487
ebcf1f97
LP
1488static int method_disable_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1489 return method_disable_unit_files_generic(bus, message, userdata, "disable", unit_file_disable, error);
ea430986
LP
1490}
1491
ebcf1f97
LP
1492static int method_unmask_unit_files(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1493 return method_disable_unit_files_generic(bus, message, userdata, "enable", unit_file_unmask, error);
718db961
LP
1494}
1495
ebcf1f97 1496static int method_set_default_target(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1497 UnitFileChange *changes = NULL;
1498 unsigned n_changes = 0;
1499 Manager *m = userdata;
1500 UnitFileScope scope;
1501 const char *name;
1502 int force, r;
1503
1504 assert(bus);
1505 assert(message);
1506 assert(m);
1507
ebcf1f97
LP
1508 r = selinux_access_check(bus, message, "enable", error);
1509 if (r < 0)
1510 return r;
718db961
LP
1511
1512 r = sd_bus_message_read(message, "sb", &name, &force);
1513 if (r < 0)
ebcf1f97 1514 return r;
718db961
LP
1515
1516 scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
1517
1518 r = unit_file_set_default(scope, NULL, name, force, &changes, &n_changes);
1519 if (r < 0)
ebcf1f97 1520 return r;
718db961
LP
1521
1522 return reply_unit_file_changes_and_free(m, bus, message, -1, changes, n_changes);
1523}
1524
1525const sd_bus_vtable bus_manager_vtable[] = {
1526 SD_BUS_VTABLE_START(0),
1527
1528 SD_BUS_PROPERTY("Version", "s", property_get_version, 0, 0),
1529 SD_BUS_PROPERTY("Features", "s", property_get_features, 0, 0),
1530 SD_BUS_PROPERTY("Virtualization", "s", property_get_virtualization, 0, 0),
1531 SD_BUS_PROPERTY("Tainted", "s", property_get_tainted, 0, 0),
1532 BUS_PROPERTY_DUAL_TIMESTAMP("FirmwareTimestamp", offsetof(Manager, firmware_timestamp), 0),
1533 BUS_PROPERTY_DUAL_TIMESTAMP("LoaderTimestamp", offsetof(Manager, loader_timestamp), 0),
1534 BUS_PROPERTY_DUAL_TIMESTAMP("KernelTimestamp", offsetof(Manager, firmware_timestamp), 0),
1535 BUS_PROPERTY_DUAL_TIMESTAMP("InitRDTimestamp", offsetof(Manager, initrd_timestamp), 0),
1536 BUS_PROPERTY_DUAL_TIMESTAMP("UserspaceTimestamp", offsetof(Manager, userspace_timestamp), 0),
1537 BUS_PROPERTY_DUAL_TIMESTAMP("FinishTimestamp", offsetof(Manager, finish_timestamp), 0),
1538 BUS_PROPERTY_DUAL_TIMESTAMP("SecurityStartTimestamp", offsetof(Manager, security_start_timestamp), 0),
1539 BUS_PROPERTY_DUAL_TIMESTAMP("SecurityFinishTimestamp", offsetof(Manager, security_finish_timestamp), 0),
1540 BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsStartTimestamp", offsetof(Manager, generators_start_timestamp), 0),
1541 BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsFinishTimestamp", offsetof(Manager, generators_finish_timestamp), 0),
1542 BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadStartTimestamp", offsetof(Manager, units_load_start_timestamp), 0),
1543 BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadFinishTimestamp", offsetof(Manager, units_load_finish_timestamp), 0),
1544 SD_BUS_WRITABLE_PROPERTY("LogLevel", "s", property_get_log_level, property_set_log_level, 0, 0),
1545 SD_BUS_WRITABLE_PROPERTY("LogTarget", "s", property_get_log_target, property_set_log_target, 0, 0),
1546 SD_BUS_PROPERTY("NNames", "u", property_get_n_names, 0, 0),
1547 SD_BUS_PROPERTY("NJobs", "u", property_get_n_jobs, 0, 0),
1548 SD_BUS_PROPERTY("NInstalledJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_installed_jobs), 0),
1549 SD_BUS_PROPERTY("NFailedJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_failed_jobs), 0),
1550 SD_BUS_PROPERTY("Progress", "d", property_get_progress, 0, 0),
1551 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(Manager, environment), 0),
1552 SD_BUS_PROPERTY("ConfirmSpawn", "b", bus_property_get_bool, offsetof(Manager, confirm_spawn), 0),
1553 SD_BUS_PROPERTY("ShowStatus", "b", bus_property_get_bool, offsetof(Manager, show_status), 0),
1554 SD_BUS_PROPERTY("UnitPath", "as", NULL, offsetof(Manager, lookup_paths.unit_path), 0),
1555 SD_BUS_PROPERTY("DefaultStandardOutput", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), 0),
1556 SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), 0),
1557 SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", bus_property_get_usec, property_set_runtime_watchdog, offsetof(Manager, runtime_watchdog), 0),
1558 SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, shutdown_watchdog), 0),
1559
1560 SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, 0),
1561 SD_BUS_METHOD("GetUnitByPID", "u", "o", method_get_unit_by_pid, 0),
1562 SD_BUS_METHOD("LoadUnit", "s", "o", method_load_unit, 0),
1563 SD_BUS_METHOD("StartUnit", "ss", "o", method_start_unit, 0),
1564 SD_BUS_METHOD("StartUnitReplace", "sss", "o", method_start_unit_replace, 0),
1565 SD_BUS_METHOD("StopUnit", "ss", "o", method_stop_unit, 0),
1566 SD_BUS_METHOD("ReloadUnit", "ss", "o", method_reload_unit, 0),
1567 SD_BUS_METHOD("RestartUnit", "ss", "o", method_restart_unit, 0),
1568 SD_BUS_METHOD("TryRestartUnit", "ss", "o", method_try_restart_unit, 0),
1569 SD_BUS_METHOD("ReloadOrRestartUnit", "ss", "o", method_reload_or_restart_unit, 0),
1570 SD_BUS_METHOD("ReloadOrTryRestartUnit", "ss", "o", method_reload_or_try_restart_unit, 0),
1571 SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, 0),
1572 SD_BUS_METHOD("ResetFailedUnit", "s", NULL, method_reset_failed_unit, 0),
1573 SD_BUS_METHOD("SetUnitProperties", "sb", "a(sv)", method_set_unit_properties, 0),
1574 SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit, 0),
1575 SD_BUS_METHOD("GetJob", "u", "o", method_get_job, 0),
1576 SD_BUS_METHOD("CancelJob", "u", NULL, method_cancel_job, 0),
1577 SD_BUS_METHOD("ClearJobs", NULL, NULL, method_clear_jobs, 0),
1578 SD_BUS_METHOD("ResetFailed", NULL, NULL, method_reset_failed, 0),
1579 SD_BUS_METHOD("ListUnits", NULL, "a(ssssssouso)", method_list_units, 0),
1580 SD_BUS_METHOD("ListJobs", NULL, "a(usssoo)", method_list_jobs, 0),
1581 SD_BUS_METHOD("Subscribe", NULL, NULL, method_subscribe, 0),
1582 SD_BUS_METHOD("Unsubscribe", NULL, NULL, method_unsubscribe, 0),
1583 SD_BUS_METHOD("Dump", NULL, "s", method_dump, 0),
1584 SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_create_snapshot, 0),
1585 SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_remove_snapshot, 0),
1586 SD_BUS_METHOD("Reload", NULL, NULL, method_reload, 0),
1587 SD_BUS_METHOD("Reexecute", NULL, NULL, method_reexecute, 0),
1588 SD_BUS_METHOD("Exit", NULL, NULL, method_exit, 0),
1589 SD_BUS_METHOD("Reboot", NULL, NULL, method_reboot, 0),
1590 SD_BUS_METHOD("PowerOff", NULL, NULL, method_poweroff, 0),
1591 SD_BUS_METHOD("Halt", NULL, NULL, method_halt, 0),
1592 SD_BUS_METHOD("KExec", NULL, NULL, method_kexec, 0),
1593 SD_BUS_METHOD("SwitchRoot", "ss", NULL, method_switch_root, 0),
1594 SD_BUS_METHOD("SetEnvironment", "as", NULL, method_set_environment, 0),
1595 SD_BUS_METHOD("UnsetEnvironment", "as", NULL, method_unset_environment, 0),
1596 SD_BUS_METHOD("UnsetAndSetEnvironment", "asas", NULL, method_unset_and_set_environment, 0),
1597 SD_BUS_METHOD("ListUnitFiles", NULL, "a(ss)", method_list_unit_files, 0),
1598 SD_BUS_METHOD("GetUnitFileState", "s", "s", method_get_unit_file_state, 0),
1599 SD_BUS_METHOD("EnableUnitFiles", "asbb", "ba(sss)", method_enable_unit_files, 0),
1600 SD_BUS_METHOD("DisableUnitFiles", "asb", "a(sss)", method_disable_unit_files, 0),
1601 SD_BUS_METHOD("ReenableUnitFiles", "asbb", "ba(sss)", method_reenable_unit_files, 0),
1602 SD_BUS_METHOD("LinkUnitFiles", "asbb", "a(sss)", method_link_unit_files, 0),
1603 SD_BUS_METHOD("PresetUnitFiles", "asbb", "ba(sss)", method_preset_unit_files, 0),
1604 SD_BUS_METHOD("MaskUnitFiles", "asbb", "a(sss)", method_mask_unit_files, 0),
1605 SD_BUS_METHOD("UnmaskUnitFiles", "asb", "a(sss)", method_unmask_unit_files, 0),
1606 SD_BUS_METHOD("SetDefaultTarget", "sb", "a(sss)", method_set_default_target, 0),
1607 SD_BUS_METHOD("GetDefaultTarget", NULL, "s", method_get_default_target, 0),
1608
1609 SD_BUS_SIGNAL("UnitNew", "so", 0),
1610 SD_BUS_SIGNAL("UnitRemoved", "so", 0),
1611 SD_BUS_SIGNAL("JobNew", "uos", 0),
1612 SD_BUS_SIGNAL("JobRemoved", "uoss", 0),
1613 SD_BUS_SIGNAL("StartupFinished", "tttttt", 0),
1614 SD_BUS_SIGNAL("UnitFilesChanged", NULL, 0),
1615 SD_BUS_SIGNAL("Reloading", "b", 0),
1616
1617 SD_BUS_VTABLE_END
ea430986 1618};
718db961
LP
1619
1620int bus_manager_foreach_client(Manager *m, int (*send_message)(sd_bus *bus, const char *destination, void *userdata), void *userdata) {
1621 Iterator i;
1622 sd_bus *b;
1623 unsigned n;
1624 int r;
1625
1626 n = set_size(m->subscribed);
1627 if (n <= 0)
1628 return 0;
1629 if (n == 1) {
1630 BusTrackedClient *d;
1631
1632 assert_se(d = set_first(m->subscribed));
1633 return send_message(d->bus, isempty(d->name) ? NULL : d->name, userdata);
1634 }
1635
1636 /* Send to everybody */
1637 SET_FOREACH(b, m->private_buses, i) {
1638 r = send_message(b, NULL, userdata);
1639 if (r < 0)
1640 return r;
1641 }
1642
1643 if (m->api_bus)
1644 return send_message(m->api_bus, NULL, userdata);
1645
1646 return 0;
1647}
1648
1649static int send_finished(sd_bus *bus, const char *destination, void *userdata) {
1650 _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
1651 usec_t *times = userdata;
1652 int r;
1653
1654 assert(bus);
1655 assert(times);
1656
1657 r = sd_bus_message_new_signal(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished", &message);
1658 if (r < 0)
1659 return r;
1660
1661 r = sd_bus_message_append(message, "tttttt", times[0], times[1], times[2], times[3], times[4], times[5]);
1662 if (r < 0)
1663 return r;
1664
1665 return sd_bus_send_to(bus, message, destination, NULL);
1666}
1667
1668int bus_manager_send_finished(
1669 Manager *m,
1670 usec_t firmware_usec,
1671 usec_t loader_usec,
1672 usec_t kernel_usec,
1673 usec_t initrd_usec,
1674 usec_t userspace_usec,
1675 usec_t total_usec) {
1676
1677 assert(m);
1678
1679 return bus_manager_foreach_client(m, send_finished,
1680 (usec_t[6]) { firmware_usec, loader_usec, kernel_usec, initrd_usec, userspace_usec, total_usec });
1681}
1682
1683static int send_reloading(sd_bus *bus, const char *destination, void *userdata) {
1684 _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
1685 int r;
1686
1687 assert(bus);
1688
1689 r = sd_bus_message_new_signal(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reloading", &message);
1690 if (r < 0)
1691 return r;
1692
1693 r = sd_bus_message_append(message, "b", PTR_TO_INT(userdata));
1694 if (r < 0)
1695 return r;
1696
1697 return sd_bus_send_to(bus, message, destination, NULL);
1698}
1699
1700int bus_manager_send_reloading(Manager *m, bool active) {
1701 assert(m);
1702
1703 return bus_manager_foreach_client(m, send_reloading, INT_TO_PTR(active));
1704}