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