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