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