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