]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-manager.c
Merge pull request #1574 from evverx/run-timer-slack-nsec
[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"
24efb112 31#include "clock-util.h"
664f88a7 32#include "path-util.h"
dfae3488 33#include "virt.h"
7452394e 34#include "architecture.h"
4d1a6904 35#include "env-util.h"
718db961 36#include "dbus.h"
2ea31e5b 37#include "dbus-job.h"
718db961
LP
38#include "dbus-manager.h"
39#include "dbus-unit.h"
40#include "dbus-snapshot.h"
718db961 41#include "dbus-execute.h"
96aad8d1 42#include "bus-common-errors.h"
6482f626 43#include "formats-util.h"
ea430986 44
718db961
LP
45static int property_get_version(
46 sd_bus *bus,
47 const char *path,
48 const char *interface,
49 const char *property,
50 sd_bus_message *reply,
ebcf1f97
LP
51 void *userdata,
52 sd_bus_error *error) {
718db961
LP
53
54 assert(bus);
55 assert(reply);
56
57 return sd_bus_message_append(reply, "s", PACKAGE_VERSION);
58}
c5d34390 59
718db961
LP
60static int property_get_features(
61 sd_bus *bus,
62 const char *path,
63 const char *interface,
64 const char *property,
65 sd_bus_message *reply,
ebcf1f97
LP
66 void *userdata,
67 sd_bus_error *error) {
718db961
LP
68
69 assert(bus);
70 assert(reply);
71
72 return sd_bus_message_append(reply, "s", SYSTEMD_FEATURES);
73}
74
75static int property_get_virtualization(
76 sd_bus *bus,
77 const char *path,
78 const char *interface,
79 const char *property,
80 sd_bus_message *reply,
ebcf1f97
LP
81 void *userdata,
82 sd_bus_error *error) {
718db961 83
5c22925a
LP
84 int v;
85
718db961
LP
86 assert(bus);
87 assert(reply);
88
5c22925a
LP
89 v = detect_virtualization();
90
91 /* Make sure to return the empty string when we detect no virtualization, as that is the API.
92 *
93 * https://github.com/systemd/systemd/issues/1423
94 */
95
96 return sd_bus_message_append(
97 reply, "s",
98 v == VIRTUALIZATION_NONE ? "" : virtualization_to_string(v));
718db961
LP
99}
100
7452394e
LP
101static int property_get_architecture(
102 sd_bus *bus,
103 const char *path,
104 const char *interface,
105 const char *property,
106 sd_bus_message *reply,
107 void *userdata,
108 sd_bus_error *error) {
109
110 assert(bus);
111 assert(reply);
112
113 return sd_bus_message_append(reply, "s", architecture_to_string(uname_architecture()));
114}
115
718db961
LP
116static int property_get_tainted(
117 sd_bus *bus,
118 const char *path,
119 const char *interface,
120 const char *property,
121 sd_bus_message *reply,
ebcf1f97
LP
122 void *userdata,
123 sd_bus_error *error) {
718db961 124
b492ce8a 125 char buf[sizeof("split-usr:cgroups-missing:local-hwclock:")] = "", *e = buf;
718db961
LP
126 Manager *m = userdata;
127
128 assert(bus);
129 assert(reply);
bfebab7f 130 assert(m);
c5d34390 131
72bc8d00 132 if (m->taint_usr)
e677bf7e 133 e = stpcpy(e, "split-usr:");
c5d34390 134
871c44a7 135 if (access("/proc/cgroups", F_OK) < 0)
1ebf0cb7 136 e = stpcpy(e, "cgroups-missing:");
871c44a7 137
24efb112 138 if (clock_is_localtime() > 0)
1ebf0cb7 139 e = stpcpy(e, "local-hwclock:");
e677bf7e 140
1ebf0cb7
MS
141 /* remove the last ':' */
142 if (e != buf)
143 e[-1] = 0;
e677bf7e 144
718db961 145 return sd_bus_message_append(reply, "s", buf);
c5d34390
LP
146}
147
718db961
LP
148static int property_get_log_target(
149 sd_bus *bus,
150 const char *path,
151 const char *interface,
152 const char *property,
153 sd_bus_message *reply,
ebcf1f97
LP
154 void *userdata,
155 sd_bus_error *error) {
1adf1049 156
718db961
LP
157 assert(bus);
158 assert(reply);
1adf1049 159
718db961 160 return sd_bus_message_append(reply, "s", log_target_to_string(log_get_target()));
1adf1049
LP
161}
162
718db961
LP
163static int property_set_log_target(
164 sd_bus *bus,
165 const char *path,
166 const char *interface,
167 const char *property,
168 sd_bus_message *value,
ebcf1f97
LP
169 void *userdata,
170 sd_bus_error *error) {
718db961 171
c826cda4 172 const char *t;
718db961 173 int r;
c826cda4 174
718db961
LP
175 assert(bus);
176 assert(value);
c826cda4 177
718db961
LP
178 r = sd_bus_message_read(value, "s", &t);
179 if (r < 0)
180 return r;
c826cda4
AB
181
182 return log_set_target_from_string(t);
183}
184
718db961
LP
185static int property_get_log_level(
186 sd_bus *bus,
187 const char *path,
188 const char *interface,
189 const char *property,
190 sd_bus_message *reply,
ebcf1f97
LP
191 void *userdata,
192 sd_bus_error *error) {
718db961 193
68eda4bd 194 _cleanup_free_ char *t = NULL;
f8b69d1d 195 int r;
1adf1049 196
718db961
LP
197 assert(bus);
198 assert(reply);
1adf1049 199
f8b69d1d
MS
200 r = log_level_to_string_alloc(log_get_max_level(), &t);
201 if (r < 0)
202 return r;
1adf1049 203
718db961 204 return sd_bus_message_append(reply, "s", t);
1adf1049
LP
205}
206
718db961
LP
207static int property_set_log_level(
208 sd_bus *bus,
209 const char *path,
210 const char *interface,
211 const char *property,
212 sd_bus_message *value,
ebcf1f97
LP
213 void *userdata,
214 sd_bus_error *error) {
718db961 215
c826cda4 216 const char *t;
718db961 217 int r;
c826cda4 218
718db961
LP
219 assert(bus);
220 assert(value);
c826cda4 221
718db961
LP
222 r = sd_bus_message_read(value, "s", &t);
223 if (r < 0)
224 return r;
c826cda4
AB
225
226 return log_set_max_level_from_string(t);
227}
228
718db961
LP
229static int property_get_n_names(
230 sd_bus *bus,
231 const char *path,
232 const char *interface,
233 const char *property,
234 sd_bus_message *reply,
ebcf1f97
LP
235 void *userdata,
236 sd_bus_error *error) {
4f0f902f 237
718db961 238 Manager *m = userdata;
4f0f902f 239
718db961
LP
240 assert(bus);
241 assert(reply);
242 assert(m);
4f0f902f 243
718db961 244 return sd_bus_message_append(reply, "u", (uint32_t) hashmap_size(m->units));
4f0f902f
LP
245}
246
f755e3b7
LP
247static int property_get_n_failed_units(
248 sd_bus *bus,
249 const char *path,
250 const char *interface,
251 const char *property,
252 sd_bus_message *reply,
253 void *userdata,
254 sd_bus_error *error) {
255
256 Manager *m = userdata;
257
258 assert(bus);
259 assert(reply);
260 assert(m);
261
262 return sd_bus_message_append(reply, "u", (uint32_t) set_size(m->failed_units));
263}
264
718db961
LP
265static int property_get_n_jobs(
266 sd_bus *bus,
267 const char *path,
268 const char *interface,
269 const char *property,
270 sd_bus_message *reply,
ebcf1f97
LP
271 void *userdata,
272 sd_bus_error *error) {
4f0f902f 273
718db961 274 Manager *m = userdata;
4f0f902f 275
718db961
LP
276 assert(bus);
277 assert(reply);
278 assert(m);
4f0f902f 279
718db961 280 return sd_bus_message_append(reply, "u", (uint32_t) hashmap_size(m->jobs));
4f0f902f
LP
281}
282
718db961
LP
283static int property_get_progress(
284 sd_bus *bus,
285 const char *path,
286 const char *interface,
287 const char *property,
288 sd_bus_message *reply,
ebcf1f97
LP
289 void *userdata,
290 sd_bus_error *error) {
718db961
LP
291
292 Manager *m = userdata;
05d6a3b6
LP
293 double d;
294
718db961
LP
295 assert(bus);
296 assert(reply);
bfebab7f 297 assert(m);
05d6a3b6
LP
298
299 if (dual_timestamp_is_set(&m->finish_timestamp))
300 d = 1.0;
301 else
302 d = 1.0 - ((double) hashmap_size(m->jobs) / (double) m->n_installed_jobs);
303
718db961
LP
304 return sd_bus_message_append(reply, "d", d);
305}
306
f755e3b7
LP
307static int property_get_system_state(
308 sd_bus *bus,
309 const char *path,
310 const char *interface,
311 const char *property,
312 sd_bus_message *reply,
313 void *userdata,
314 sd_bus_error *error) {
315
316 Manager *m = userdata;
317
318 assert(bus);
319 assert(reply);
320 assert(m);
321
322 return sd_bus_message_append(reply, "s", manager_state_to_string(manager_state(m)));
323}
324
718db961
LP
325static int property_set_runtime_watchdog(
326 sd_bus *bus,
327 const char *path,
328 const char *interface,
329 const char *property,
330 sd_bus_message *value,
ebcf1f97
LP
331 void *userdata,
332 sd_bus_error *error) {
05d6a3b6 333
718db961
LP
334 usec_t *t = userdata;
335 int r;
336
337 assert(bus);
338 assert(value);
339
340 assert_cc(sizeof(usec_t) == sizeof(uint64_t));
341
342 r = sd_bus_message_read(value, "t", t);
343 if (r < 0)
344 return r;
345
346 return watchdog_set_timeout(t);
05d6a3b6
LP
347}
348
19070062 349static int method_get_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
350 _cleanup_free_ char *path = NULL;
351 Manager *m = userdata;
352 const char *name;
353 Unit *u;
354 int r;
dfae3488 355
718db961 356 assert(message);
dfae3488
LP
357 assert(m);
358
283868e1
SW
359 /* Anyone can call this method */
360
718db961
LP
361 r = sd_bus_message_read(message, "s", &name);
362 if (r < 0)
ebcf1f97 363 return r;
dfae3488 364
1d22e906
LP
365 if (isempty(name)) {
366 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
367 pid_t pid;
368
369 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
370 if (r < 0)
371 return r;
372
373 r = sd_bus_creds_get_pid(creds, &pid);
374 if (r < 0)
375 return r;
376
377 u = manager_get_unit_by_pid(m, pid);
378 if (!u)
379 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Client not member of any unit.");
380 } else {
381 u = manager_get_unit(m, name);
382 if (!u)
383 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", name);
384 }
dfae3488 385
8a188de9 386 r = mac_selinux_unit_access_check(u, message, "status", error);
ebcf1f97
LP
387 if (r < 0)
388 return r;
dfae3488 389
718db961
LP
390 path = unit_dbus_path(u);
391 if (!path)
ebcf1f97 392 return -ENOMEM;
729e3769 393
df2d202e 394 return sd_bus_reply_method_return(message, "o", path);
718db961 395}
c0576cd6 396
19070062 397static int method_get_unit_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
398 _cleanup_free_ char *path = NULL;
399 Manager *m = userdata;
400 pid_t pid;
401 Unit *u;
402 int r;
c0576cd6 403
718db961
LP
404 assert(message);
405 assert(m);
c0576cd6 406
718db961 407 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
729e3769 408
283868e1
SW
409 /* Anyone can call this method */
410
718db961
LP
411 r = sd_bus_message_read(message, "u", &pid);
412 if (r < 0)
ebcf1f97 413 return r;
1d22e906
LP
414 if (pid < 0)
415 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PID " PID_FMT, pid);
718db961
LP
416
417 if (pid == 0) {
5b12334d
LP
418 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
419
420 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
421 if (r < 0)
422 return r;
423
424 r = sd_bus_creds_get_pid(creds, &pid);
718db961 425 if (r < 0)
ebcf1f97 426 return r;
729e3769
LP
427 }
428
718db961
LP
429 u = manager_get_unit_by_pid(m, pid);
430 if (!u)
1fa2f38f 431 return sd_bus_error_setf(error, BUS_ERROR_NO_UNIT_FOR_PID, "PID "PID_FMT" does not belong to any loaded unit.", pid);
c0576cd6 432
8a188de9 433 r = mac_selinux_unit_access_check(u, message, "status", error);
ebcf1f97
LP
434 if (r < 0)
435 return r;
718db961
LP
436
437 path = unit_dbus_path(u);
438 if (!path)
ebcf1f97 439 return -ENOMEM;
718db961 440
df2d202e 441 return sd_bus_reply_method_return(message, "o", path);
718db961
LP
442}
443
19070062 444static int method_load_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
445 _cleanup_free_ char *path = NULL;
446 Manager *m = userdata;
447 const char *name;
448 Unit *u;
449 int r;
c0576cd6 450
718db961
LP
451 assert(message);
452 assert(m);
453
283868e1
SW
454 /* Anyone can call this method */
455
718db961
LP
456 r = sd_bus_message_read(message, "s", &name);
457 if (r < 0)
ebcf1f97 458 return r;
c0576cd6 459
1d22e906
LP
460 if (isempty(name)) {
461 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
462 pid_t pid;
463
464 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
465 if (r < 0)
466 return r;
467
468 r = sd_bus_creds_get_pid(creds, &pid);
469 if (r < 0)
470 return r;
471
472 u = manager_get_unit_by_pid(m, pid);
473 if (!u)
474 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Client not member of any unit.");
475 } else {
476 r = manager_load_unit(m, name, NULL, error, &u);
477 if (r < 0)
478 return r;
479 }
718db961 480
8a188de9 481 r = mac_selinux_unit_access_check(u, message, "status", error);
ebcf1f97
LP
482 if (r < 0)
483 return r;
c0576cd6 484
718db961
LP
485 path = unit_dbus_path(u);
486 if (!path)
ebcf1f97 487 return -ENOMEM;
718db961 488
df2d202e 489 return sd_bus_reply_method_return(message, "o", path);
c0576cd6
LP
490}
491
19070062 492static int method_start_unit_generic(sd_bus_message *message, Manager *m, JobType job_type, bool reload_if_possible, sd_bus_error *error) {
718db961
LP
493 const char *name;
494 Unit *u;
c0576cd6
LP
495 int r;
496
718db961
LP
497 assert(message);
498 assert(m);
c0576cd6 499
718db961
LP
500 r = sd_bus_message_read(message, "s", &name);
501 if (r < 0)
ebcf1f97 502 return r;
c0576cd6 503
ebcf1f97 504 r = manager_load_unit(m, name, NULL, error, &u);
718db961 505 if (r < 0)
ebcf1f97 506 return r;
718db961 507
19070062 508 return bus_unit_method_start_generic(message, u, job_type, reload_if_possible, error);
c0576cd6
LP
509}
510
19070062
LP
511static int method_start_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
512 return method_start_unit_generic(message, userdata, JOB_START, false, error);
718db961 513}
c757a65b 514
19070062
LP
515static int method_stop_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
516 return method_start_unit_generic(message, userdata, JOB_STOP, false, error);
718db961 517}
c757a65b 518
19070062
LP
519static int method_reload_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
520 return method_start_unit_generic(message, userdata, JOB_RELOAD, false, error);
718db961 521}
c757a65b 522
19070062
LP
523static int method_restart_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
524 return method_start_unit_generic(message, userdata, JOB_RESTART, false, error);
c757a65b
LP
525}
526
19070062
LP
527static int method_try_restart_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
528 return method_start_unit_generic(message, userdata, JOB_TRY_RESTART, false, error);
718db961 529}
d200735e 530
19070062
LP
531static int method_reload_or_restart_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
532 return method_start_unit_generic(message, userdata, JOB_RESTART, true, error);
718db961 533}
d200735e 534
19070062
LP
535static int method_reload_or_try_restart_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
536 return method_start_unit_generic(message, userdata, JOB_TRY_RESTART, true, error);
718db961 537}
d200735e 538
19070062 539static int method_start_unit_replace(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
540 Manager *m = userdata;
541 const char *old_name;
542 Unit *u;
1adf1049 543 int r;
ea430986 544
ea430986
LP
545 assert(message);
546 assert(m);
547
718db961
LP
548 r = sd_bus_message_read(message, "s", &old_name);
549 if (r < 0)
ebcf1f97 550 return r;
ea430986 551
718db961
LP
552 u = manager_get_unit(m, old_name);
553 if (!u || !u->job || u->job->type != JOB_START)
ebcf1f97 554 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
c0576cd6 555
19070062 556 return method_start_unit_generic(message, m, JOB_START, false, error);
718db961 557}
ea430986 558
19070062 559static int method_kill_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
560 Manager *m = userdata;
561 const char *name;
562 Unit *u;
563 int r;
ea430986 564
718db961
LP
565 assert(message);
566 assert(m);
ea430986 567
718db961
LP
568 r = sd_bus_message_read(message, "s", &name);
569 if (r < 0)
ebcf1f97 570 return r;
598b557b 571
718db961
LP
572 u = manager_get_unit(m, name);
573 if (!u)
ebcf1f97 574 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
0a524ba7 575
19070062 576 return bus_unit_method_kill(message, u, error);
718db961 577}
8a0867d6 578
19070062 579static int method_reset_failed_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
580 Manager *m = userdata;
581 const char *name;
582 Unit *u;
583 int r;
8a0867d6 584
718db961
LP
585 assert(message);
586 assert(m);
cad45ba1 587
718db961
LP
588 r = sd_bus_message_read(message, "s", &name);
589 if (r < 0)
ebcf1f97 590 return r;
ea430986 591
718db961
LP
592 u = manager_get_unit(m, name);
593 if (!u)
ebcf1f97 594 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
5dd9014f 595
19070062 596 return bus_unit_method_reset_failed(message, u, error);
718db961 597}
5dd9014f 598
19070062 599static int method_set_unit_properties(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
600 Manager *m = userdata;
601 const char *name;
602 Unit *u;
603 int r;
5dd9014f 604
718db961
LP
605 assert(message);
606 assert(m);
607
608 r = sd_bus_message_read(message, "s", &name);
609 if (r < 0)
ebcf1f97 610 return r;
718db961
LP
611
612 u = manager_get_unit(m, name);
613 if (!u)
ebcf1f97 614 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
ea430986 615
19070062 616 return bus_unit_method_set_properties(message, u, error);
718db961
LP
617}
618
ab31f6b8
WC
619static int transient_unit_from_message(
620 Manager *m,
621 sd_bus_message *message,
622 const char *name,
623 Unit **unit,
624 sd_bus_error *error) {
625
626 Unit *u;
627 int r;
628
629 assert(m);
630 assert(message);
631 assert(name);
632
633 r = manager_load_unit(m, name, NULL, error, &u);
634 if (r < 0)
635 return r;
636
637 if (u->load_state != UNIT_NOT_FOUND ||
638 set_size(u->dependencies[UNIT_REFERENCED_BY]) > 0)
639 return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit %s already exists.", name);
640
641 /* OK, the unit failed to load and is unreferenced, now let's
642 * fill in the transient data instead */
643 r = unit_make_transient(u);
644 if (r < 0)
645 return r;
646
647 /* Set our properties */
648 r = bus_unit_set_properties(u, message, UNIT_RUNTIME, false, error);
649 if (r < 0)
650 return r;
651
652 *unit = u;
653
654 return 0;
655}
656
657static int transient_aux_units_from_message(
658 Manager *m,
659 sd_bus_message *message,
660 sd_bus_error *error) {
661
662 Unit *u;
663 char *name = NULL;
664 int r;
665
666 assert(m);
667 assert(message);
668
669 r = sd_bus_message_enter_container(message, 'a', "(sa(sv))");
670 if (r < 0)
671 return r;
672
673 while ((r = sd_bus_message_enter_container(message, 'r', "sa(sv)")) > 0) {
ab31f6b8
WC
674 r = sd_bus_message_read(message, "s", &name);
675 if (r < 0)
676 return r;
677
678 r = transient_unit_from_message(m, message, name, &u, error);
679 if (r < 0 && r != -EEXIST)
680 return r;
681
4c213d6c
WC
682 if (r != -EEXIST) {
683 r = unit_load(u);
684 if (r < 0)
685 return r;
686 }
ab31f6b8
WC
687
688 r = sd_bus_message_exit_container(message);
689 if (r < 0)
690 return r;
691 }
692 if (r < 0)
693 return r;
694
695 r = sd_bus_message_exit_container(message);
696 if (r < 0)
697 return r;
698
699 return 0;
700}
701
19070062 702static int method_start_transient_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
703 const char *name, *smode;
704 Manager *m = userdata;
705 JobMode mode;
706 UnitType t;
707 Unit *u;
708 int r;
ea430986 709
718db961
LP
710 assert(message);
711 assert(m);
ea430986 712
1d22e906 713 r = mac_selinux_access_check(message, "start", error);
283868e1
SW
714 if (r < 0)
715 return r;
283868e1 716
718db961
LP
717 r = sd_bus_message_read(message, "ss", &name, &smode);
718 if (r < 0)
ebcf1f97 719 return r;
5632e374 720
718db961
LP
721 t = unit_name_to_type(name);
722 if (t < 0)
ebcf1f97 723 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit type.");
cad45ba1 724
718db961 725 if (!unit_vtable[t]->can_transient)
d14ab08b 726 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit type %s does not support transient units.", unit_type_to_string(t));
5632e374 727
718db961
LP
728 mode = job_mode_from_string(smode);
729 if (mode < 0)
ebcf1f97 730 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s is invalid.", smode);
5632e374 731
1d22e906 732 r = bus_verify_manage_units_async(m, message, error);
718db961 733 if (r < 0)
ebcf1f97 734 return r;
1d22e906
LP
735 if (r == 0)
736 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
5632e374 737
ab31f6b8 738 r = transient_unit_from_message(m, message, name, &u, error);
ebcf1f97
LP
739 if (r < 0)
740 return r;
5632e374 741
ab31f6b8 742 r = transient_aux_units_from_message(m, message, error);
718db961 743 if (r < 0)
ebcf1f97 744 return r;
ea430986 745
718db961
LP
746 /* And load this stub fully */
747 r = unit_load(u);
748 if (r < 0)
ebcf1f97 749 return r;
ea430986 750
718db961 751 manager_dispatch_load_queue(m);
cad45ba1 752
718db961 753 /* Finally, start it */
19070062 754 return bus_unit_queue_job(message, u, JOB_START, mode, false, error);
718db961 755}
ea430986 756
19070062 757static int method_get_job(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
758 _cleanup_free_ char *path = NULL;
759 Manager *m = userdata;
760 uint32_t id;
761 Job *j;
762 int r;
ea430986 763
718db961
LP
764 assert(message);
765 assert(m);
ea430986 766
283868e1
SW
767 /* Anyone can call this method */
768
718db961
LP
769 r = sd_bus_message_read(message, "u", &id);
770 if (r < 0)
ebcf1f97 771 return r;
ea430986 772
718db961
LP
773 j = manager_get_job(m, id);
774 if (!j)
ebcf1f97 775 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
ea430986 776
8a188de9 777 r = mac_selinux_unit_access_check(j->unit, message, "status", error);
ebcf1f97
LP
778 if (r < 0)
779 return r;
ea430986 780
718db961
LP
781 path = job_dbus_path(j);
782 if (!path)
ebcf1f97 783 return -ENOMEM;
ea430986 784
df2d202e 785 return sd_bus_reply_method_return(message, "o", path);
718db961 786}
ea430986 787
19070062 788static int method_cancel_job(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
789 Manager *m = userdata;
790 uint32_t id;
791 Job *j;
792 int r;
ea430986 793
718db961
LP
794 assert(message);
795 assert(m);
ea430986 796
718db961
LP
797 r = sd_bus_message_read(message, "u", &id);
798 if (r < 0)
ebcf1f97 799 return r;
ea430986 800
718db961
LP
801 j = manager_get_job(m, id);
802 if (!j)
ebcf1f97 803 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
ea430986 804
19070062 805 return bus_job_method_cancel(message, j, error);
718db961 806}
c1e1601e 807
19070062 808static int method_clear_jobs(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 809 Manager *m = userdata;
ebcf1f97 810 int r;
c1e1601e 811
718db961
LP
812 assert(message);
813 assert(m);
c1e1601e 814
1d22e906 815 r = mac_selinux_access_check(message, "reload", error);
ebcf1f97
LP
816 if (r < 0)
817 return r;
818
1d22e906
LP
819 r = bus_verify_manage_units_async(m, message, error);
820 if (r < 0)
821 return r;
822 if (r == 0)
823 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
824
718db961 825 manager_clear_jobs(m);
c1e1601e 826
df2d202e 827 return sd_bus_reply_method_return(message, NULL);
718db961 828}
c1e1601e 829
19070062 830static int method_reset_failed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 831 Manager *m = userdata;
ebcf1f97 832 int r;
cad45ba1 833
718db961
LP
834 assert(message);
835 assert(m);
836
8a188de9 837 r = mac_selinux_access_check(message, "reload", error);
ebcf1f97
LP
838 if (r < 0)
839 return r;
840
1d22e906
LP
841 r = bus_verify_manage_units_async(m, message, error);
842 if (r < 0)
843 return r;
844 if (r == 0)
845 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
846
718db961 847 manager_reset_failed(m);
c1e1601e 848
df2d202e 849 return sd_bus_reply_method_return(message, NULL);
718db961 850}
c1e1601e 851
19070062 852static int list_units_filtered(sd_bus_message *message, void *userdata, sd_bus_error *error, char **states) {
718db961
LP
853 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
854 Manager *m = userdata;
855 const char *k;
856 Iterator i;
857 Unit *u;
858 int r;
c1e1601e 859
718db961
LP
860 assert(message);
861 assert(m);
b152adec 862
283868e1
SW
863 /* Anyone can call this method */
864
8a188de9 865 r = mac_selinux_access_check(message, "status", error);
ebcf1f97
LP
866 if (r < 0)
867 return r;
cad45ba1 868
df2d202e 869 r = sd_bus_message_new_method_return(message, &reply);
718db961 870 if (r < 0)
ebcf1f97 871 return r;
b152adec 872
718db961
LP
873 r = sd_bus_message_open_container(reply, 'a', "(ssssssouso)");
874 if (r < 0)
ebcf1f97 875 return r;
b152adec 876
718db961
LP
877 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
878 _cleanup_free_ char *unit_path = NULL, *job_path = NULL;
879 Unit *following;
b152adec 880
718db961
LP
881 if (k != u->id)
882 continue;
b152adec 883
718db961 884 following = unit_following(u);
b152adec 885
cdc06ed7
DS
886 if (!strv_isempty(states) &&
887 !strv_contains(states, unit_load_state_to_string(u->load_state)) &&
888 !strv_contains(states, unit_active_state_to_string(unit_active_state(u))) &&
889 !strv_contains(states, unit_sub_state_to_string(u)))
890 continue;
891
718db961
LP
892 unit_path = unit_dbus_path(u);
893 if (!unit_path)
ebcf1f97 894 return -ENOMEM;
718db961
LP
895
896 if (u->job) {
897 job_path = job_dbus_path(u->job);
898 if (!job_path)
ebcf1f97 899 return -ENOMEM;
b152adec
LP
900 }
901
718db961
LP
902 r = sd_bus_message_append(
903 reply, "(ssssssouso)",
904 u->id,
905 unit_description(u),
906 unit_load_state_to_string(u->load_state),
907 unit_active_state_to_string(unit_active_state(u)),
908 unit_sub_state_to_string(u),
909 following ? following->id : "",
910 unit_path,
911 u->job ? u->job->id : 0,
912 u->job ? job_type_to_string(u->job->type) : "",
913 job_path ? job_path : "/");
914 if (r < 0)
ebcf1f97 915 return r;
718db961 916 }
4139c1b2 917
718db961
LP
918 r = sd_bus_message_close_container(reply);
919 if (r < 0)
ebcf1f97 920 return r;
cad45ba1 921
9030ca46 922 return sd_bus_send(NULL, reply, NULL);
718db961 923}
4139c1b2 924
19070062
LP
925static int method_list_units(sd_bus_message *message, void *userdata, sd_bus_error *error) {
926 return list_units_filtered(message, userdata, error, NULL);
cdc06ed7
DS
927}
928
19070062 929static int method_list_units_filtered(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cdc06ed7
DS
930 _cleanup_strv_free_ char **states = NULL;
931 int r;
932
933 r = sd_bus_message_read_strv(message, &states);
934 if (r < 0)
935 return r;
936
19070062 937 return list_units_filtered(message, userdata, error, states);
cdc06ed7
DS
938}
939
19070062 940static int method_list_jobs(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
941 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
942 Manager *m = userdata;
943 Iterator i;
944 Job *j;
945 int r;
4139c1b2 946
718db961
LP
947 assert(message);
948 assert(m);
949
283868e1
SW
950 /* Anyone can call this method */
951
8a188de9 952 r = mac_selinux_access_check(message, "status", error);
ebcf1f97
LP
953 if (r < 0)
954 return r;
718db961 955
df2d202e 956 r = sd_bus_message_new_method_return(message, &reply);
718db961 957 if (r < 0)
ebcf1f97 958 return r;
718db961
LP
959
960 r = sd_bus_message_open_container(reply, 'a', "(usssoo)");
961 if (r < 0)
ebcf1f97 962 return r;
718db961
LP
963
964 HASHMAP_FOREACH(j, m->jobs, i) {
965 _cleanup_free_ char *unit_path = NULL, *job_path = NULL;
966
967 job_path = job_dbus_path(j);
968 if (!job_path)
ebcf1f97 969 return -ENOMEM;
718db961
LP
970
971 unit_path = unit_dbus_path(j->unit);
972 if (!unit_path)
ebcf1f97 973 return -ENOMEM;
718db961
LP
974
975 r = sd_bus_message_append(
976 reply, "(usssoo)",
977 j->id,
1302759d 978 j->unit->id,
718db961 979 job_type_to_string(j->type),
1302759d 980 job_state_to_string(j->state),
718db961
LP
981 job_path,
982 unit_path);
cad45ba1 983 if (r < 0)
ebcf1f97 984 return r;
718db961 985 }
5dd9014f 986
718db961
LP
987 r = sd_bus_message_close_container(reply);
988 if (r < 0)
ebcf1f97 989 return r;
5dd9014f 990
9030ca46 991 return sd_bus_send(NULL, reply, NULL);
718db961 992}
5dd9014f 993
19070062 994static int method_subscribe(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
995 Manager *m = userdata;
996 int r;
5dd9014f 997
718db961
LP
998 assert(message);
999 assert(m);
ea430986 1000
283868e1
SW
1001 /* Anyone can call this method */
1002
8a188de9 1003 r = mac_selinux_access_check(message, "status", error);
ebcf1f97
LP
1004 if (r < 0)
1005 return r;
cad45ba1 1006
19070062 1007 if (sd_bus_message_get_bus(message) == m->api_bus) {
8f8f05a9
LP
1008
1009 /* Note that direct bus connection subscribe by
1010 * default, we only track peers on the API bus here */
1011
1012 if (!m->subscribed) {
19070062 1013 r = sd_bus_track_new(sd_bus_message_get_bus(message), &m->subscribed, NULL, NULL);
8f8f05a9
LP
1014 if (r < 0)
1015 return r;
1016 }
1017
1018 r = sd_bus_track_add_sender(m->subscribed, message);
1019 if (r < 0)
1020 return r;
1021 if (r == 0)
1022 return sd_bus_error_setf(error, BUS_ERROR_ALREADY_SUBSCRIBED, "Client is already subscribed.");
1023 }
ea430986 1024
df2d202e 1025 return sd_bus_reply_method_return(message, NULL);
718db961 1026}
ea430986 1027
19070062 1028static int method_unsubscribe(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1029 Manager *m = userdata;
1030 int r;
ea430986 1031
718db961
LP
1032 assert(message);
1033 assert(m);
ea430986 1034
283868e1
SW
1035 /* Anyone can call this method */
1036
8a188de9 1037 r = mac_selinux_access_check(message, "status", error);
ebcf1f97
LP
1038 if (r < 0)
1039 return r;
ea430986 1040
19070062 1041 if (sd_bus_message_get_bus(message) == m->api_bus) {
8f8f05a9
LP
1042 r = sd_bus_track_remove_sender(m->subscribed, message);
1043 if (r < 0)
1044 return r;
1045 if (r == 0)
1046 return sd_bus_error_setf(error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
1047 }
ea430986 1048
df2d202e 1049 return sd_bus_reply_method_return(message, NULL);
718db961 1050}
ea430986 1051
19070062 1052static int method_dump(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1053 _cleanup_free_ char *dump = NULL;
1054 _cleanup_fclose_ FILE *f = NULL;
1055 Manager *m = userdata;
1056 size_t size;
ebcf1f97 1057 int r;
ea430986 1058
718db961
LP
1059 assert(message);
1060 assert(m);
ea430986 1061
283868e1
SW
1062 /* Anyone can call this method */
1063
8a188de9 1064 r = mac_selinux_access_check(message, "status", error);
ebcf1f97
LP
1065 if (r < 0)
1066 return r;
ea430986 1067
718db961
LP
1068 f = open_memstream(&dump, &size);
1069 if (!f)
ebcf1f97 1070 return -ENOMEM;
ea430986 1071
718db961
LP
1072 manager_dump_units(m, f, NULL);
1073 manager_dump_jobs(m, f, NULL);
ea430986 1074
dacd6cee
LP
1075 r = fflush_and_check(f);
1076 if (r < 0)
1077 return r;
a16e1123 1078
df2d202e 1079 return sd_bus_reply_method_return(message, "s", dump);
718db961 1080}
cad45ba1 1081
19070062 1082static int method_create_snapshot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1083 _cleanup_free_ char *path = NULL;
1084 Manager *m = userdata;
1085 const char *name;
1086 int cleanup;
39883f62 1087 Snapshot *s = NULL;
718db961 1088 int r;
a16e1123 1089
718db961
LP
1090 assert(message);
1091 assert(m);
a16e1123 1092
8a188de9 1093 r = mac_selinux_access_check(message, "start", error);
ebcf1f97
LP
1094 if (r < 0)
1095 return r;
a16e1123 1096
718db961
LP
1097 r = sd_bus_message_read(message, "sb", &name, &cleanup);
1098 if (r < 0)
ebcf1f97 1099 return r;
a16e1123 1100
718db961
LP
1101 if (isempty(name))
1102 name = NULL;
a16e1123 1103
1d22e906
LP
1104 r = bus_verify_manage_units_async(m, message, error);
1105 if (r < 0)
1106 return r;
1107 if (r == 0)
1108 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1109
ebcf1f97 1110 r = snapshot_create(m, name, cleanup, error, &s);
718db961 1111 if (r < 0)
ebcf1f97 1112 return r;
cad45ba1 1113
718db961
LP
1114 path = unit_dbus_path(UNIT(s));
1115 if (!path)
ebcf1f97 1116 return -ENOMEM;
a16e1123 1117
df2d202e 1118 return sd_bus_reply_method_return(message, "o", path);
718db961 1119}
a16e1123 1120
19070062 1121static int method_remove_snapshot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1122 Manager *m = userdata;
1123 const char *name;
1124 Unit *u;
1125 int r;
a16e1123 1126
718db961
LP
1127 assert(message);
1128 assert(m);
cad45ba1 1129
718db961
LP
1130 r = sd_bus_message_read(message, "s", &name);
1131 if (r < 0)
ebcf1f97 1132 return r;
a16e1123 1133
718db961
LP
1134 u = manager_get_unit(m, name);
1135 if (!u)
ebcf1f97 1136 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s does not exist.", name);
a16e1123 1137
718db961 1138 if (u->type != UNIT_SNAPSHOT)
ebcf1f97 1139 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not a snapshot", name);
6652a2b9 1140
19070062 1141 return bus_snapshot_method_remove(message, u, error);
718db961 1142}
cad45ba1 1143
19070062 1144static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1145 Manager *m = userdata;
1146 int r;
6652a2b9 1147
718db961
LP
1148 assert(message);
1149 assert(m);
6652a2b9 1150
1d22e906 1151 r = mac_selinux_access_check(message, "reload", error);
283868e1
SW
1152 if (r < 0)
1153 return r;
283868e1 1154
1d22e906 1155 r = bus_verify_reload_daemon_async(m, message, error);
ebcf1f97
LP
1156 if (r < 0)
1157 return r;
1d22e906
LP
1158 if (r == 0)
1159 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
6652a2b9 1160
718db961
LP
1161 /* Instead of sending the reply back right away, we just
1162 * remember that we need to and then send it after the reload
1163 * is finished. That way the caller knows when the reload
1164 * finished. */
6652a2b9 1165
718db961 1166 assert(!m->queued_message);
df2d202e 1167 r = sd_bus_message_new_method_return(message, &m->queued_message);
718db961 1168 if (r < 0)
ebcf1f97 1169 return r;
cad45ba1 1170
718db961 1171 m->exit_code = MANAGER_RELOAD;
6652a2b9 1172
718db961
LP
1173 return 1;
1174}
6652a2b9 1175
19070062 1176static int method_reexecute(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 1177 Manager *m = userdata;
ebcf1f97 1178 int r;
6652a2b9 1179
718db961
LP
1180 assert(message);
1181 assert(m);
6652a2b9 1182
1d22e906 1183 r = mac_selinux_access_check(message, "reload", error);
283868e1
SW
1184 if (r < 0)
1185 return r;
283868e1 1186
1d22e906 1187 r = bus_verify_reload_daemon_async(m, message, error);
ebcf1f97
LP
1188 if (r < 0)
1189 return r;
1d22e906
LP
1190 if (r == 0)
1191 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
cad45ba1 1192
718db961
LP
1193 /* We don't send a reply back here, the client should
1194 * just wait for us disconnecting. */
6652a2b9 1195
718db961
LP
1196 m->exit_code = MANAGER_REEXECUTE;
1197 return 1;
1198}
6652a2b9 1199
19070062 1200static int method_exit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 1201 Manager *m = userdata;
ebcf1f97 1202 int r;
6652a2b9 1203
718db961
LP
1204 assert(message);
1205 assert(m);
6652a2b9 1206
8a188de9 1207 r = mac_selinux_access_check(message, "halt", error);
ebcf1f97
LP
1208 if (r < 0)
1209 return r;
cad45ba1 1210
287419c1
AC
1211 /* Exit() (in contrast to SetExitCode()) is actually allowed even if
1212 * we are running on the host. It will fall back on reboot() in
1213 * systemd-shutdown if it cannot do the exit() because it isn't a
1214 * container. */
6652a2b9 1215
718db961 1216 m->exit_code = MANAGER_EXIT;
6652a2b9 1217
df2d202e 1218 return sd_bus_reply_method_return(message, NULL);
718db961 1219}
6652a2b9 1220
19070062 1221static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 1222 Manager *m = userdata;
ebcf1f97 1223 int r;
664f88a7 1224
718db961
LP
1225 assert(message);
1226 assert(m);
cad45ba1 1227
8a188de9 1228 r = mac_selinux_access_check(message, "reboot", error);
ebcf1f97
LP
1229 if (r < 0)
1230 return r;
664f88a7 1231
b2c23da8 1232 if (m->running_as != MANAGER_SYSTEM)
ebcf1f97 1233 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
664f88a7 1234
718db961 1235 m->exit_code = MANAGER_REBOOT;
664f88a7 1236
df2d202e 1237 return sd_bus_reply_method_return(message, NULL);
718db961 1238}
664f88a7 1239
19070062 1240static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 1241 Manager *m = userdata;
ebcf1f97 1242 int r;
50913bc0 1243
718db961
LP
1244 assert(message);
1245 assert(m);
1137a57c 1246
8a188de9 1247 r = mac_selinux_access_check(message, "halt", error);
ebcf1f97
LP
1248 if (r < 0)
1249 return r;
1137a57c 1250
b2c23da8 1251 if (m->running_as != MANAGER_SYSTEM)
ebcf1f97 1252 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
1137a57c 1253
718db961 1254 m->exit_code = MANAGER_POWEROFF;
1137a57c 1255
df2d202e 1256 return sd_bus_reply_method_return(message, NULL);
718db961 1257}
1137a57c 1258
19070062 1259static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 1260 Manager *m = userdata;
ebcf1f97 1261 int r;
1137a57c 1262
718db961
LP
1263 assert(message);
1264 assert(m);
8d0e38a2 1265
8a188de9 1266 r = mac_selinux_access_check(message, "halt", error);
ebcf1f97
LP
1267 if (r < 0)
1268 return r;
cad45ba1 1269
b2c23da8 1270 if (m->running_as != MANAGER_SYSTEM)
ebcf1f97 1271 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Halt is only supported for system managers.");
8d0e38a2 1272
718db961 1273 m->exit_code = MANAGER_HALT;
8d0e38a2 1274
df2d202e 1275 return sd_bus_reply_method_return(message, NULL);
718db961 1276}
8d0e38a2 1277
19070062 1278static int method_kexec(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961 1279 Manager *m = userdata;
ebcf1f97 1280 int r;
8d0e38a2 1281
718db961
LP
1282 assert(message);
1283 assert(m);
c0576cd6 1284
8a188de9 1285 r = mac_selinux_access_check(message, "reboot", error);
ebcf1f97
LP
1286 if (r < 0)
1287 return r;
cad45ba1 1288
b2c23da8 1289 if (m->running_as != MANAGER_SYSTEM)
ebcf1f97 1290 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "KExec is only supported for system managers.");
c0576cd6 1291
718db961 1292 m->exit_code = MANAGER_KEXEC;
c0576cd6 1293
df2d202e 1294 return sd_bus_reply_method_return(message, NULL);
718db961 1295}
c0576cd6 1296
19070062 1297static int method_switch_root(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1298 char *ri = NULL, *rt = NULL;
1299 const char *root, *init;
1300 Manager *m = userdata;
1301 int r;
c0576cd6 1302
718db961
LP
1303 assert(message);
1304 assert(m);
c0576cd6 1305
8a188de9 1306 r = mac_selinux_access_check(message, "reboot", error);
ebcf1f97
LP
1307 if (r < 0)
1308 return r;
c0576cd6 1309
b2c23da8 1310 if (m->running_as != MANAGER_SYSTEM)
6ad3b2b6 1311 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Root switching is only supported by system manager.");
c0576cd6 1312
718db961
LP
1313 r = sd_bus_message_read(message, "ss", &root, &init);
1314 if (r < 0)
ebcf1f97 1315 return r;
c0576cd6 1316
718db961 1317 if (path_equal(root, "/") || !path_is_absolute(root))
ebcf1f97 1318 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid switch root path %s", root);
c0576cd6 1319
718db961
LP
1320 /* Safety check */
1321 if (isempty(init)) {
6ad3b2b6 1322 if (!path_is_os_tree(root))
5ae4d543 1323 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified switch root path %s does not seem to be an OS tree. os-release file is missing.", root);
718db961
LP
1324 } else {
1325 _cleanup_free_ char *p = NULL;
c0576cd6 1326
718db961 1327 if (!path_is_absolute(init))
ebcf1f97 1328 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid init path %s", init);
c0576cd6 1329
718db961
LP
1330 p = strappend(root, init);
1331 if (!p)
ebcf1f97 1332 return -ENOMEM;
c0576cd6 1333
718db961 1334 if (access(p, X_OK) < 0)
ebcf1f97 1335 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified init binary %s does not exist.", p);
718db961
LP
1336 }
1337
1338 rt = strdup(root);
1339 if (!rt)
ebcf1f97 1340 return -ENOMEM;
718db961
LP
1341
1342 if (!isempty(init)) {
1343 ri = strdup(init);
1344 if (!ri) {
92b315df 1345 free(rt);
ebcf1f97 1346 return -ENOMEM;
c0576cd6 1347 }
718db961 1348 }
c0576cd6 1349
718db961
LP
1350 free(m->switch_root);
1351 m->switch_root = rt;
c0576cd6 1352
718db961
LP
1353 free(m->switch_root_init);
1354 m->switch_root_init = ri;
c0576cd6 1355
92b315df
LP
1356 m->exit_code = MANAGER_SWITCH_ROOT;
1357
df2d202e 1358 return sd_bus_reply_method_return(message, NULL);
718db961 1359}
c0576cd6 1360
19070062 1361static int method_set_environment(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1362 _cleanup_strv_free_ char **plus = NULL;
1363 Manager *m = userdata;
1364 int r;
c0576cd6 1365
718db961
LP
1366 assert(message);
1367 assert(m);
cad45ba1 1368
8a188de9 1369 r = mac_selinux_access_check(message, "reload", error);
ebcf1f97
LP
1370 if (r < 0)
1371 return r;
c0576cd6 1372
718db961
LP
1373 r = sd_bus_message_read_strv(message, &plus);
1374 if (r < 0)
ebcf1f97 1375 return r;
718db961 1376 if (!strv_env_is_valid(plus))
ebcf1f97 1377 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
c0576cd6 1378
1d22e906
LP
1379 r = bus_verify_set_environment_async(m, message, error);
1380 if (r < 0)
1381 return r;
1382 if (r == 0)
1383 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1384
718db961
LP
1385 r = manager_environment_add(m, NULL, plus);
1386 if (r < 0)
ebcf1f97 1387 return r;
c0576cd6 1388
df2d202e 1389 return sd_bus_reply_method_return(message, NULL);
718db961
LP
1390}
1391
19070062 1392static int method_unset_environment(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1393 _cleanup_strv_free_ char **minus = NULL;
1394 Manager *m = userdata;
1395 int r;
1396
718db961
LP
1397 assert(message);
1398 assert(m);
1399
8a188de9 1400 r = mac_selinux_access_check(message, "reload", error);
ebcf1f97
LP
1401 if (r < 0)
1402 return r;
c0576cd6 1403
718db961
LP
1404 r = sd_bus_message_read_strv(message, &minus);
1405 if (r < 0)
ebcf1f97 1406 return r;
718db961
LP
1407
1408 if (!strv_env_name_or_assignment_is_valid(minus))
ebcf1f97 1409 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
718db961 1410
1d22e906
LP
1411 r = bus_verify_set_environment_async(m, message, error);
1412 if (r < 0)
1413 return r;
1414 if (r == 0)
1415 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1416
718db961
LP
1417 r = manager_environment_add(m, minus, NULL);
1418 if (r < 0)
ebcf1f97 1419 return r;
718db961 1420
df2d202e 1421 return sd_bus_reply_method_return(message, NULL);
718db961
LP
1422}
1423
19070062 1424static int method_unset_and_set_environment(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1425 _cleanup_strv_free_ char **minus = NULL, **plus = NULL;
1426 Manager *m = userdata;
1427 int r;
1428
718db961
LP
1429 assert(message);
1430 assert(m);
1431
8a188de9 1432 r = mac_selinux_access_check(message, "reload", error);
ebcf1f97
LP
1433 if (r < 0)
1434 return r;
718db961 1435
eb6c7d20 1436 r = sd_bus_message_read_strv(message, &minus);
718db961 1437 if (r < 0)
ebcf1f97 1438 return r;
718db961 1439
eb6c7d20 1440 r = sd_bus_message_read_strv(message, &plus);
718db961 1441 if (r < 0)
ebcf1f97 1442 return r;
718db961 1443
718db961 1444 if (!strv_env_name_or_assignment_is_valid(minus))
ebcf1f97 1445 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment variable names or assignments");
eb6c7d20
ZJS
1446 if (!strv_env_is_valid(plus))
1447 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
718db961 1448
1d22e906
LP
1449 r = bus_verify_set_environment_async(m, message, error);
1450 if (r < 0)
1451 return r;
1452 if (r == 0)
1453 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1454
718db961
LP
1455 r = manager_environment_add(m, minus, plus);
1456 if (r < 0)
ebcf1f97 1457 return r;
718db961 1458
df2d202e 1459 return sd_bus_reply_method_return(message, NULL);
718db961
LP
1460}
1461
287419c1
AC
1462static int method_set_exit_code(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1463 uint8_t code;
1464 Manager *m = userdata;
1465 int r;
1466
1467 assert(message);
1468 assert(m);
1469
1470 r = mac_selinux_access_check(message, "exit", error);
1471 if (r < 0)
1472 return r;
1473
1474 r = sd_bus_message_read_basic(message, 'y', &code);
1475 if (r < 0)
1476 return r;
1477
1478 if (m->running_as == MANAGER_SYSTEM && detect_container() <= 0)
1479 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "ExitCode can only be set for user service managers or in containers.");
1480
1481 m->return_value = code;
1482
1483 return sd_bus_reply_method_return(message, NULL);
1484}
1485
19070062 1486static int method_list_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1487 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1488 Manager *m = userdata;
1489 UnitFileList *item;
1490 Hashmap *h;
1491 Iterator i;
1492 int r;
1493
718db961
LP
1494 assert(message);
1495 assert(m);
1496
283868e1
SW
1497 /* Anyone can call this method */
1498
8a188de9 1499 r = mac_selinux_access_check(message, "status", error);
ebcf1f97
LP
1500 if (r < 0)
1501 return r;
718db961 1502
df2d202e 1503 r = sd_bus_message_new_method_return(message, &reply);
718db961 1504 if (r < 0)
ebcf1f97 1505 return r;
c0576cd6 1506
d5099efc 1507 h = hashmap_new(&string_hash_ops);
718db961 1508 if (!h)
ebcf1f97 1509 return -ENOMEM;
c0576cd6 1510
b2c23da8 1511 r = unit_file_get_list(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
ebcf1f97 1512 if (r < 0)
718db961 1513 goto fail;
718db961
LP
1514
1515 r = sd_bus_message_open_container(reply, 'a', "(ss)");
ebcf1f97 1516 if (r < 0)
718db961 1517 goto fail;
718db961
LP
1518
1519 HASHMAP_FOREACH(item, h, i) {
1520
1521 r = sd_bus_message_append(reply, "(ss)", item->path, unit_file_state_to_string(item->state));
ebcf1f97 1522 if (r < 0)
718db961 1523 goto fail;
718db961 1524 }
c0576cd6 1525
718db961 1526 unit_file_list_free(h);
c0576cd6 1527
718db961
LP
1528 r = sd_bus_message_close_container(reply);
1529 if (r < 0)
ebcf1f97 1530 return r;
8d0e38a2 1531
9030ca46 1532 return sd_bus_send(NULL, reply, NULL);
99504dd4 1533
718db961
LP
1534fail:
1535 unit_file_list_free(h);
1536 return r;
1537}
99504dd4 1538
19070062 1539static int method_get_unit_file_state(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1540 Manager *m = userdata;
1541 const char *name;
1542 UnitFileState state;
1543 UnitFileScope scope;
1544 int r;
99504dd4 1545
718db961
LP
1546 assert(message);
1547 assert(m);
8e2af478 1548
283868e1
SW
1549 /* Anyone can call this method */
1550
8a188de9 1551 r = mac_selinux_access_check(message, "status", error);
ebcf1f97
LP
1552 if (r < 0)
1553 return r;
8e2af478 1554
718db961
LP
1555 r = sd_bus_message_read(message, "s", &name);
1556 if (r < 0)
ebcf1f97 1557 return r;
8e2af478 1558
b2c23da8 1559 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
8e2af478 1560
718db961
LP
1561 state = unit_file_get_state(scope, NULL, name);
1562 if (state < 0)
ebcf1f97 1563 return state;
8e2af478 1564
df2d202e 1565 return sd_bus_reply_method_return(message, "s", unit_file_state_to_string(state));
718db961 1566}
8e2af478 1567
19070062 1568static int method_get_default_target(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1569 _cleanup_free_ char *default_target = NULL;
1570 Manager *m = userdata;
1571 UnitFileScope scope;
1572 int r;
c2756a68 1573
718db961
LP
1574 assert(message);
1575 assert(m);
c2756a68 1576
283868e1
SW
1577 /* Anyone can call this method */
1578
8a188de9 1579 r = mac_selinux_access_check(message, "status", error);
ebcf1f97
LP
1580 if (r < 0)
1581 return r;
c2756a68 1582
b2c23da8 1583 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
c2756a68 1584
718db961
LP
1585 r = unit_file_get_default(scope, NULL, &default_target);
1586 if (r < 0)
ebcf1f97 1587 return r;
c2756a68 1588
df2d202e 1589 return sd_bus_reply_method_return(message, "s", default_target);
718db961 1590}
c2756a68 1591
8f8f05a9 1592static int send_unit_files_changed(sd_bus *bus, void *userdata) {
718db961
LP
1593 _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
1594 int r;
1595
1596 assert(bus);
1597
151b9b96 1598 r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
718db961
LP
1599 if (r < 0)
1600 return r;
1601
8f8f05a9 1602 return sd_bus_send(bus, message, NULL);
718db961
LP
1603}
1604
1605static int reply_unit_file_changes_and_free(
1606 Manager *m,
718db961
LP
1607 sd_bus_message *message,
1608 int carries_install_info,
1609 UnitFileChange *changes,
1610 unsigned n_changes) {
1611
1612 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1613 unsigned i;
1614 int r;
1615
fe7f06f1
LP
1616 if (n_changes > 0) {
1617 r = bus_foreach_bus(m, NULL, send_unit_files_changed, NULL);
1618 if (r < 0)
da927ba9 1619 log_debug_errno(r, "Failed to send UnitFilesChanged signal: %m");
fe7f06f1 1620 }
718db961 1621
df2d202e 1622 r = sd_bus_message_new_method_return(message, &reply);
718db961
LP
1623 if (r < 0)
1624 goto fail;
1625
1626 if (carries_install_info >= 0) {
1627 r = sd_bus_message_append(reply, "b", carries_install_info);
c2756a68 1628 if (r < 0)
718db961
LP
1629 goto fail;
1630 }
1631
1632 r = sd_bus_message_open_container(reply, 'a', "(sss)");
1633 if (r < 0)
1634 goto fail;
c2756a68 1635
718db961
LP
1636 for (i = 0; i < n_changes; i++) {
1637 r = sd_bus_message_append(
21586b77 1638 reply, "(sss)",
718db961
LP
1639 unit_file_change_type_to_string(changes[i].type),
1640 changes[i].path,
1641 changes[i].source);
c2756a68 1642 if (r < 0)
718db961
LP
1643 goto fail;
1644 }
c2756a68 1645
718db961
LP
1646 r = sd_bus_message_close_container(reply);
1647 if (r < 0)
1648 goto fail;
c2756a68 1649
9030ca46 1650 return sd_bus_send(NULL, reply, NULL);
c2756a68 1651
718db961
LP
1652fail:
1653 unit_file_changes_free(changes, n_changes);
ebcf1f97 1654 return r;
718db961 1655}
cad45ba1 1656
718db961 1657static int method_enable_unit_files_generic(
718db961 1658 sd_bus_message *message,
d309c1c3
LP
1659 Manager *m,
1660 const char *verb,
718db961 1661 int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes),
ebcf1f97
LP
1662 bool carries_install_info,
1663 sd_bus_error *error) {
718db961
LP
1664
1665 _cleanup_strv_free_ char **l = NULL;
1666 UnitFileChange *changes = NULL;
1667 unsigned n_changes = 0;
1668 UnitFileScope scope;
1669 int runtime, force, r;
1670
718db961
LP
1671 assert(message);
1672 assert(m);
cad45ba1 1673
718db961
LP
1674 r = sd_bus_message_read_strv(message, &l);
1675 if (r < 0)
ebcf1f97 1676 return r;
90bb85e1 1677
d309c1c3
LP
1678 r = sd_bus_message_read(message, "bb", &runtime, &force);
1679 if (r < 0)
1680 return r;
1681
1d22e906
LP
1682 r = bus_verify_manage_unit_files_async(m, message, error);
1683 if (r < 0)
1684 return r;
1685 if (r == 0)
1686 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1687
b2c23da8 1688 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
c87eba54 1689
718db961
LP
1690 r = call(scope, runtime, NULL, l, force, &changes, &n_changes);
1691 if (r < 0)
ebcf1f97 1692 return r;
718db961 1693
19070062 1694 return reply_unit_file_changes_and_free(m, message, carries_install_info ? r : -1, changes, n_changes);
718db961 1695}
c87eba54 1696
19070062
LP
1697static int method_enable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1698 return method_enable_unit_files_generic(message, userdata, "enable", unit_file_enable, true, error);
718db961 1699}
ea430986 1700
19070062
LP
1701static int method_reenable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1702 return method_enable_unit_files_generic(message, userdata, "enable", unit_file_reenable, true, error);
718db961
LP
1703}
1704
19070062
LP
1705static int method_link_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1706 return method_enable_unit_files_generic(message, userdata, "enable", unit_file_link, false, error);
718db961
LP
1707}
1708
d309c1c3
LP
1709static int unit_file_preset_without_mode(UnitFileScope scope, bool runtime, const char *root_dir, char **files, bool force, UnitFileChange **changes, unsigned *n_changes) {
1710 return unit_file_preset(scope, runtime, root_dir, files, UNIT_FILE_PRESET_FULL, force, changes, n_changes);
1711}
1712
19070062
LP
1713static int method_preset_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1714 return method_enable_unit_files_generic(message, userdata, "enable", unit_file_preset_without_mode, true, error);
718db961
LP
1715}
1716
19070062
LP
1717static int method_mask_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1718 return method_enable_unit_files_generic(message, userdata, "disable", unit_file_mask, false, error);
718db961 1719}
ea430986 1720
19070062 1721static int method_preset_unit_files_with_mode(sd_bus_message *message, void *userdata, sd_bus_error *error) {
d309c1c3
LP
1722
1723 _cleanup_strv_free_ char **l = NULL;
d309c1c3
LP
1724 UnitFileChange *changes = NULL;
1725 unsigned n_changes = 0;
1726 Manager *m = userdata;
1727 UnitFilePresetMode mm;
1728 UnitFileScope scope;
1729 int runtime, force, r;
1730 const char *mode;
1731
d309c1c3
LP
1732 assert(message);
1733 assert(m);
1734
1735 r = sd_bus_message_read_strv(message, &l);
1736 if (r < 0)
1737 return r;
1738
1739 r = sd_bus_message_read(message, "sbb", &mode, &runtime, &force);
1740 if (r < 0)
1741 return r;
1742
1743 if (isempty(mode))
1744 mm = UNIT_FILE_PRESET_FULL;
1745 else {
1746 mm = unit_file_preset_mode_from_string(mode);
1747 if (mm < 0)
1748 return -EINVAL;
1749 }
1750
1d22e906
LP
1751 r = bus_verify_manage_unit_files_async(m, message, error);
1752 if (r < 0)
1753 return r;
1754 if (r == 0)
1755 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1756
b2c23da8 1757 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
d309c1c3
LP
1758
1759 r = unit_file_preset(scope, runtime, NULL, l, mm, force, &changes, &n_changes);
1760 if (r < 0)
1761 return r;
1762
19070062 1763 return reply_unit_file_changes_and_free(m, message, r, changes, n_changes);
d309c1c3
LP
1764}
1765
718db961 1766static int method_disable_unit_files_generic(
718db961
LP
1767 sd_bus_message *message,
1768 Manager *m, const
1769 char *verb,
ebcf1f97
LP
1770 int (*call)(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes),
1771 sd_bus_error *error) {
718db961
LP
1772
1773 _cleanup_strv_free_ char **l = NULL;
1774 UnitFileChange *changes = NULL;
1775 unsigned n_changes = 0;
1776 UnitFileScope scope;
1777 int r, runtime;
1778
718db961
LP
1779 assert(message);
1780 assert(m);
1781
df823e23 1782 r = sd_bus_message_read_strv(message, &l);
ebcf1f97
LP
1783 if (r < 0)
1784 return r;
718db961 1785
df823e23 1786 r = sd_bus_message_read(message, "b", &runtime);
718db961 1787 if (r < 0)
ebcf1f97 1788 return r;
718db961 1789
b2c23da8 1790 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
718db961 1791
1d22e906
LP
1792 r = bus_verify_manage_unit_files_async(m, message, error);
1793 if (r < 0)
1794 return r;
1795 if (r == 0)
1796 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1797
718db961
LP
1798 r = call(scope, runtime, NULL, l, &changes, &n_changes);
1799 if (r < 0)
ebcf1f97 1800 return r;
718db961 1801
19070062 1802 return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes);
718db961 1803}
ea430986 1804
19070062
LP
1805static int method_disable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1806 return method_disable_unit_files_generic(message, userdata, "disable", unit_file_disable, error);
ea430986
LP
1807}
1808
19070062
LP
1809static int method_unmask_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1810 return method_disable_unit_files_generic(message, userdata, "enable", unit_file_unmask, error);
718db961
LP
1811}
1812
19070062 1813static int method_set_default_target(sd_bus_message *message, void *userdata, sd_bus_error *error) {
718db961
LP
1814 UnitFileChange *changes = NULL;
1815 unsigned n_changes = 0;
1816 Manager *m = userdata;
1817 UnitFileScope scope;
1818 const char *name;
1819 int force, r;
1820
718db961
LP
1821 assert(message);
1822 assert(m);
1823
1d22e906 1824 r = mac_selinux_access_check(message, "enable", error);
283868e1
SW
1825 if (r < 0)
1826 return r;
283868e1 1827
1d22e906 1828 r = sd_bus_message_read(message, "sb", &name, &force);
ebcf1f97
LP
1829 if (r < 0)
1830 return r;
718db961 1831
1d22e906 1832 r = bus_verify_manage_unit_files_async(m, message, error);
718db961 1833 if (r < 0)
ebcf1f97 1834 return r;
1d22e906
LP
1835 if (r == 0)
1836 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
718db961 1837
b2c23da8 1838 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
718db961
LP
1839
1840 r = unit_file_set_default(scope, NULL, name, force, &changes, &n_changes);
1841 if (r < 0)
ebcf1f97 1842 return r;
718db961 1843
19070062 1844 return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes);
718db961
LP
1845}
1846
19070062 1847static int method_preset_all_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
d309c1c3
LP
1848 UnitFileChange *changes = NULL;
1849 unsigned n_changes = 0;
1850 Manager *m = userdata;
1851 UnitFilePresetMode mm;
1852 UnitFileScope scope;
1853 const char *mode;
1854 int force, runtime, r;
1855
d309c1c3
LP
1856 assert(message);
1857 assert(m);
1858
8a188de9 1859 r = mac_selinux_access_check(message, "enable", error);
d309c1c3
LP
1860 if (r < 0)
1861 return r;
1862
1863 r = sd_bus_message_read(message, "sbb", &mode, &runtime, &force);
1864 if (r < 0)
1865 return r;
1866
1867 if (isempty(mode))
1868 mm = UNIT_FILE_PRESET_FULL;
1869 else {
1870 mm = unit_file_preset_mode_from_string(mode);
1871 if (mm < 0)
1872 return -EINVAL;
1873 }
1874
1d22e906
LP
1875 r = bus_verify_manage_unit_files_async(m, message, error);
1876 if (r < 0)
1877 return r;
1878 if (r == 0)
1879 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1880
b2c23da8 1881 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
d309c1c3
LP
1882
1883 r = unit_file_preset_all(scope, runtime, NULL, mm, force, &changes, &n_changes);
1884 if (r < 0)
1885 return r;
1886
19070062 1887 return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes);
d309c1c3
LP
1888}
1889
19070062 1890static int method_add_dependency_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
e94937df
LN
1891 _cleanup_strv_free_ char **l = NULL;
1892 Manager *m = userdata;
1893 UnitFileChange *changes = NULL;
1894 unsigned n_changes = 0;
1895 UnitFileScope scope;
1896 int runtime, force, r;
1897 char *target;
1898 char *type;
1899 UnitDependency dep;
1900
e94937df
LN
1901 assert(message);
1902 assert(m);
1903
1904 r = bus_verify_manage_unit_files_async(m, message, error);
1905 if (r < 0)
1906 return r;
1907 if (r == 0)
1908 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1909
1910 r = sd_bus_message_read_strv(message, &l);
1911 if (r < 0)
1912 return r;
1913
1914 r = sd_bus_message_read(message, "ssbb", &target, &type, &runtime, &force);
1915 if (r < 0)
1916 return r;
1917
1918 dep = unit_dependency_from_string(type);
1919 if (dep < 0)
1920 return -EINVAL;
1921
b2c23da8 1922 scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
e94937df
LN
1923
1924 r = unit_file_add_dependency(scope, runtime, NULL, l, target, dep, force, &changes, &n_changes);
1925 if (r < 0)
1926 return r;
1927
19070062 1928 return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes);
e94937df
LN
1929}
1930
718db961
LP
1931const sd_bus_vtable bus_manager_vtable[] = {
1932 SD_BUS_VTABLE_START(0),
1933
556089dc
LP
1934 SD_BUS_PROPERTY("Version", "s", property_get_version, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1935 SD_BUS_PROPERTY("Features", "s", property_get_features, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1936 SD_BUS_PROPERTY("Virtualization", "s", property_get_virtualization, 0, SD_BUS_VTABLE_PROPERTY_CONST),
7452394e 1937 SD_BUS_PROPERTY("Architecture", "s", property_get_architecture, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
1938 SD_BUS_PROPERTY("Tainted", "s", property_get_tainted, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1939 BUS_PROPERTY_DUAL_TIMESTAMP("FirmwareTimestamp", offsetof(Manager, firmware_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1940 BUS_PROPERTY_DUAL_TIMESTAMP("LoaderTimestamp", offsetof(Manager, loader_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1941 BUS_PROPERTY_DUAL_TIMESTAMP("KernelTimestamp", offsetof(Manager, kernel_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1942 BUS_PROPERTY_DUAL_TIMESTAMP("InitRDTimestamp", offsetof(Manager, initrd_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1943 BUS_PROPERTY_DUAL_TIMESTAMP("UserspaceTimestamp", offsetof(Manager, userspace_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1944 BUS_PROPERTY_DUAL_TIMESTAMP("FinishTimestamp", offsetof(Manager, finish_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1945 BUS_PROPERTY_DUAL_TIMESTAMP("SecurityStartTimestamp", offsetof(Manager, security_start_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1946 BUS_PROPERTY_DUAL_TIMESTAMP("SecurityFinishTimestamp", offsetof(Manager, security_finish_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1947 BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsStartTimestamp", offsetof(Manager, generators_start_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1948 BUS_PROPERTY_DUAL_TIMESTAMP("GeneratorsFinishTimestamp", offsetof(Manager, generators_finish_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1949 BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadStartTimestamp", offsetof(Manager, units_load_start_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1950 BUS_PROPERTY_DUAL_TIMESTAMP("UnitsLoadFinishTimestamp", offsetof(Manager, units_load_finish_timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
718db961
LP
1951 SD_BUS_WRITABLE_PROPERTY("LogLevel", "s", property_get_log_level, property_set_log_level, 0, 0),
1952 SD_BUS_WRITABLE_PROPERTY("LogTarget", "s", property_get_log_target, property_set_log_target, 0, 0),
1953 SD_BUS_PROPERTY("NNames", "u", property_get_n_names, 0, 0),
03455c28 1954 SD_BUS_PROPERTY("NFailedUnits", "u", property_get_n_failed_units, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
718db961
LP
1955 SD_BUS_PROPERTY("NJobs", "u", property_get_n_jobs, 0, 0),
1956 SD_BUS_PROPERTY("NInstalledJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_installed_jobs), 0),
1957 SD_BUS_PROPERTY("NFailedJobs", "u", bus_property_get_unsigned, offsetof(Manager, n_failed_jobs), 0),
1958 SD_BUS_PROPERTY("Progress", "d", property_get_progress, 0, 0),
1959 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(Manager, environment), 0),
556089dc
LP
1960 SD_BUS_PROPERTY("ConfirmSpawn", "b", bus_property_get_bool, offsetof(Manager, confirm_spawn), SD_BUS_VTABLE_PROPERTY_CONST),
1961 SD_BUS_PROPERTY("ShowStatus", "b", bus_property_get_bool, offsetof(Manager, show_status), SD_BUS_VTABLE_PROPERTY_CONST),
1962 SD_BUS_PROPERTY("UnitPath", "as", NULL, offsetof(Manager, lookup_paths.unit_path), SD_BUS_VTABLE_PROPERTY_CONST),
1963 SD_BUS_PROPERTY("DefaultStandardOutput", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST),
1964 SD_BUS_PROPERTY("DefaultStandardError", "s", bus_property_get_exec_output, offsetof(Manager, default_std_output), SD_BUS_VTABLE_PROPERTY_CONST),
4c3f1641
LP
1965 SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", bus_property_get_usec, property_set_runtime_watchdog, offsetof(Manager, runtime_watchdog), 0),
1966 SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, shutdown_watchdog), 0),
b272b74d 1967 SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Manager, cgroup_root), 0),
f755e3b7 1968 SD_BUS_PROPERTY("SystemState", "s", property_get_system_state, 0, 0),
287419c1 1969 SD_BUS_PROPERTY("ExitCode", "y", bus_property_get_unsigned, offsetof(Manager, return_value), 0),
670a3efe
EV
1970 SD_BUS_PROPERTY("DefaultTimerAccuracyUSec", "t", bus_property_get_usec, offsetof(Manager, default_timer_accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST),
1971 SD_BUS_PROPERTY("DefaultTimeoutStartUSec", "t", bus_property_get_usec, offsetof(Manager, default_timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST),
1972 SD_BUS_PROPERTY("DefaultTimeoutStopUSec", "t", bus_property_get_usec, offsetof(Manager, default_timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
1973 SD_BUS_PROPERTY("DefaultRestartUSec", "t", bus_property_get_usec, offsetof(Manager, default_restart_usec), SD_BUS_VTABLE_PROPERTY_CONST),
1974 SD_BUS_PROPERTY("DefaultStartLimitInterval", "t", bus_property_get_usec, offsetof(Manager, default_start_limit_interval), SD_BUS_VTABLE_PROPERTY_CONST),
1975 SD_BUS_PROPERTY("DefaultStartLimitBurst", "u", bus_property_get_unsigned, offsetof(Manager, default_start_limit_burst), SD_BUS_VTABLE_PROPERTY_CONST),
1976 SD_BUS_PROPERTY("DefaultCPUAccounting", "b", bus_property_get_bool, offsetof(Manager, default_cpu_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
1977 SD_BUS_PROPERTY("DefaultBlockIOAccounting", "b", bus_property_get_bool, offsetof(Manager, default_blockio_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
1978 SD_BUS_PROPERTY("DefaultMemoryAccounting", "b", bus_property_get_bool, offsetof(Manager, default_memory_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
1979 SD_BUS_PROPERTY("DefaultTasksAccounting", "b", bus_property_get_bool, offsetof(Manager, default_tasks_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
97eb4231
EV
1980 SD_BUS_PROPERTY("DefaultLimitCPU", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
1981 SD_BUS_PROPERTY("DefaultLimitFSIZE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
1982 SD_BUS_PROPERTY("DefaultLimitDATA", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
1983 SD_BUS_PROPERTY("DefaultLimitSTACK", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
1984 SD_BUS_PROPERTY("DefaultLimitCORE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
1985 SD_BUS_PROPERTY("DefaultLimitRSS", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
1986 SD_BUS_PROPERTY("DefaultLimitNOFILE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
1987 SD_BUS_PROPERTY("DefaultLimitAS", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
1988 SD_BUS_PROPERTY("DefaultLimitNPROC", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
1989 SD_BUS_PROPERTY("DefaultLimitMEMLOCK", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
1990 SD_BUS_PROPERTY("DefaultLimitLOCKS", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
1991 SD_BUS_PROPERTY("DefaultLimitSIGPENDING", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
1992 SD_BUS_PROPERTY("DefaultLimitMSGQUEUE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
1993 SD_BUS_PROPERTY("DefaultLimitNICE", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
1994 SD_BUS_PROPERTY("DefaultLimitRTPRIO", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
1995 SD_BUS_PROPERTY("DefaultLimitRTTIME", "t", bus_property_get_rlimit, offsetof(Manager, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
718db961 1996
adacb957
LP
1997 SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, SD_BUS_VTABLE_UNPRIVILEGED),
1998 SD_BUS_METHOD("GetUnitByPID", "u", "o", method_get_unit_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
1999 SD_BUS_METHOD("LoadUnit", "s", "o", method_load_unit, SD_BUS_VTABLE_UNPRIVILEGED),
283868e1
SW
2000 SD_BUS_METHOD("StartUnit", "ss", "o", method_start_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2001 SD_BUS_METHOD("StartUnitReplace", "sss", "o", method_start_unit_replace, SD_BUS_VTABLE_UNPRIVILEGED),
2002 SD_BUS_METHOD("StopUnit", "ss", "o", method_stop_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2003 SD_BUS_METHOD("ReloadUnit", "ss", "o", method_reload_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2004 SD_BUS_METHOD("RestartUnit", "ss", "o", method_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2005 SD_BUS_METHOD("TryRestartUnit", "ss", "o", method_try_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2006 SD_BUS_METHOD("ReloadOrRestartUnit", "ss", "o", method_reload_or_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2007 SD_BUS_METHOD("ReloadOrTryRestartUnit", "ss", "o", method_reload_or_try_restart_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2008 SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2009 SD_BUS_METHOD("ResetFailedUnit", "s", NULL, method_reset_failed_unit, SD_BUS_VTABLE_UNPRIVILEGED),
2010 SD_BUS_METHOD("SetUnitProperties", "sba(sv)", NULL, method_set_unit_properties, SD_BUS_VTABLE_UNPRIVILEGED),
2011 SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit, SD_BUS_VTABLE_UNPRIVILEGED),
adacb957 2012 SD_BUS_METHOD("GetJob", "u", "o", method_get_job, SD_BUS_VTABLE_UNPRIVILEGED),
283868e1 2013 SD_BUS_METHOD("CancelJob", "u", NULL, method_cancel_job, SD_BUS_VTABLE_UNPRIVILEGED),
1d22e906
LP
2014 SD_BUS_METHOD("ClearJobs", NULL, NULL, method_clear_jobs, SD_BUS_VTABLE_UNPRIVILEGED),
2015 SD_BUS_METHOD("ResetFailed", NULL, NULL, method_reset_failed, SD_BUS_VTABLE_UNPRIVILEGED),
adacb957 2016 SD_BUS_METHOD("ListUnits", NULL, "a(ssssssouso)", method_list_units, SD_BUS_VTABLE_UNPRIVILEGED),
cdc06ed7 2017 SD_BUS_METHOD("ListUnitsFiltered", "as", "a(ssssssouso)", method_list_units_filtered, SD_BUS_VTABLE_UNPRIVILEGED),
adacb957
LP
2018 SD_BUS_METHOD("ListJobs", NULL, "a(usssoo)", method_list_jobs, SD_BUS_VTABLE_UNPRIVILEGED),
2019 SD_BUS_METHOD("Subscribe", NULL, NULL, method_subscribe, SD_BUS_VTABLE_UNPRIVILEGED),
2020 SD_BUS_METHOD("Unsubscribe", NULL, NULL, method_unsubscribe, SD_BUS_VTABLE_UNPRIVILEGED),
2021 SD_BUS_METHOD("Dump", NULL, "s", method_dump, SD_BUS_VTABLE_UNPRIVILEGED),
1d22e906
LP
2022 SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_create_snapshot, SD_BUS_VTABLE_UNPRIVILEGED),
2023 SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_remove_snapshot, SD_BUS_VTABLE_UNPRIVILEGED),
283868e1
SW
2024 SD_BUS_METHOD("Reload", NULL, NULL, method_reload, SD_BUS_VTABLE_UNPRIVILEGED),
2025 SD_BUS_METHOD("Reexecute", NULL, NULL, method_reexecute, SD_BUS_VTABLE_UNPRIVILEGED),
718db961 2026 SD_BUS_METHOD("Exit", NULL, NULL, method_exit, 0),
adacb957
LP
2027 SD_BUS_METHOD("Reboot", NULL, NULL, method_reboot, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
2028 SD_BUS_METHOD("PowerOff", NULL, NULL, method_poweroff, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
2029 SD_BUS_METHOD("Halt", NULL, NULL, method_halt, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
2030 SD_BUS_METHOD("KExec", NULL, NULL, method_kexec, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
2031 SD_BUS_METHOD("SwitchRoot", "ss", NULL, method_switch_root, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
1d22e906
LP
2032 SD_BUS_METHOD("SetEnvironment", "as", NULL, method_set_environment, SD_BUS_VTABLE_UNPRIVILEGED),
2033 SD_BUS_METHOD("UnsetEnvironment", "as", NULL, method_unset_environment, SD_BUS_VTABLE_UNPRIVILEGED),
2034 SD_BUS_METHOD("UnsetAndSetEnvironment", "asas", NULL, method_unset_and_set_environment, SD_BUS_VTABLE_UNPRIVILEGED),
adacb957
LP
2035 SD_BUS_METHOD("ListUnitFiles", NULL, "a(ss)", method_list_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2036 SD_BUS_METHOD("GetUnitFileState", "s", "s", method_get_unit_file_state, SD_BUS_VTABLE_UNPRIVILEGED),
283868e1
SW
2037 SD_BUS_METHOD("EnableUnitFiles", "asbb", "ba(sss)", method_enable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2038 SD_BUS_METHOD("DisableUnitFiles", "asb", "a(sss)", method_disable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2039 SD_BUS_METHOD("ReenableUnitFiles", "asbb", "ba(sss)", method_reenable_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2040 SD_BUS_METHOD("LinkUnitFiles", "asbb", "a(sss)", method_link_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2041 SD_BUS_METHOD("PresetUnitFiles", "asbb", "ba(sss)", method_preset_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2042 SD_BUS_METHOD("PresetUnitFilesWithMode", "assbb", "ba(sss)", method_preset_unit_files_with_mode, SD_BUS_VTABLE_UNPRIVILEGED),
2043 SD_BUS_METHOD("MaskUnitFiles", "asbb", "a(sss)", method_mask_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2044 SD_BUS_METHOD("UnmaskUnitFiles", "asb", "a(sss)", method_unmask_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
2045 SD_BUS_METHOD("SetDefaultTarget", "sb", "a(sss)", method_set_default_target, SD_BUS_VTABLE_UNPRIVILEGED),
adacb957 2046 SD_BUS_METHOD("GetDefaultTarget", NULL, "s", method_get_default_target, SD_BUS_VTABLE_UNPRIVILEGED),
283868e1 2047 SD_BUS_METHOD("PresetAllUnitFiles", "sbb", "a(sss)", method_preset_all_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
e94937df 2048 SD_BUS_METHOD("AddDependencyUnitFiles", "asssbb", "a(sss)", method_add_dependency_unit_files, SD_BUS_VTABLE_UNPRIVILEGED),
287419c1 2049 SD_BUS_METHOD("SetExitCode", "y", NULL, method_set_exit_code, SD_BUS_VTABLE_UNPRIVILEGED),
718db961
LP
2050
2051 SD_BUS_SIGNAL("UnitNew", "so", 0),
2052 SD_BUS_SIGNAL("UnitRemoved", "so", 0),
2053 SD_BUS_SIGNAL("JobNew", "uos", 0),
2054 SD_BUS_SIGNAL("JobRemoved", "uoss", 0),
2055 SD_BUS_SIGNAL("StartupFinished", "tttttt", 0),
2056 SD_BUS_SIGNAL("UnitFilesChanged", NULL, 0),
2057 SD_BUS_SIGNAL("Reloading", "b", 0),
2058
2059 SD_BUS_VTABLE_END
ea430986 2060};
718db961 2061
8f8f05a9 2062static int send_finished(sd_bus *bus, void *userdata) {
718db961
LP
2063 _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
2064 usec_t *times = userdata;
2065 int r;
2066
2067 assert(bus);
2068 assert(times);
2069
151b9b96 2070 r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished");
718db961
LP
2071 if (r < 0)
2072 return r;
2073
2074 r = sd_bus_message_append(message, "tttttt", times[0], times[1], times[2], times[3], times[4], times[5]);
2075 if (r < 0)
2076 return r;
2077
8f8f05a9 2078 return sd_bus_send(bus, message, NULL);
718db961
LP
2079}
2080
39abcaee 2081void bus_manager_send_finished(
718db961
LP
2082 Manager *m,
2083 usec_t firmware_usec,
2084 usec_t loader_usec,
2085 usec_t kernel_usec,
2086 usec_t initrd_usec,
2087 usec_t userspace_usec,
2088 usec_t total_usec) {
2089
39abcaee
LP
2090 int r;
2091
718db961
LP
2092 assert(m);
2093
8f8f05a9
LP
2094 r = bus_foreach_bus(
2095 m,
2096 NULL,
2097 send_finished,
2098 (usec_t[6]) {
2099 firmware_usec,
2100 loader_usec,
2101 kernel_usec,
2102 initrd_usec,
2103 userspace_usec,
2104 total_usec
2105 });
39abcaee 2106 if (r < 0)
da927ba9 2107 log_debug_errno(r, "Failed to send finished signal: %m");
718db961
LP
2108}
2109
8f8f05a9 2110static int send_reloading(sd_bus *bus, void *userdata) {
718db961
LP
2111 _cleanup_bus_message_unref_ sd_bus_message *message = NULL;
2112 int r;
2113
2114 assert(bus);
2115
151b9b96 2116 r = sd_bus_message_new_signal(bus, &message, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reloading");
718db961
LP
2117 if (r < 0)
2118 return r;
2119
2120 r = sd_bus_message_append(message, "b", PTR_TO_INT(userdata));
2121 if (r < 0)
2122 return r;
2123
8f8f05a9 2124 return sd_bus_send(bus, message, NULL);
718db961
LP
2125}
2126
39abcaee
LP
2127void bus_manager_send_reloading(Manager *m, bool active) {
2128 int r;
2129
718db961
LP
2130 assert(m);
2131
8f8f05a9 2132 r = bus_foreach_bus(m, NULL, send_reloading, INT_TO_PTR(active));
39abcaee 2133 if (r < 0)
da927ba9 2134 log_debug_errno(r, "Failed to send reloading signal: %m");
03455c28
LDM
2135}
2136
2137static int send_changed_signal(sd_bus *bus, void *userdata) {
2138 assert(bus);
2139
2140 return sd_bus_emit_properties_changed_strv(bus,
2141 "/org/freedesktop/systemd1",
2142 "org.freedesktop.systemd1.Manager",
2143 NULL);
2144}
39abcaee 2145
03455c28
LDM
2146void bus_manager_send_change_signal(Manager *m) {
2147 int r;
2148
2149 assert(m);
2150
2151 r = bus_foreach_bus(m, NULL, send_changed_signal, NULL);
2152 if (r < 0)
2153 log_debug_errno(r, "Failed to send manager change signal: %m");
718db961 2154}