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