]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/systemctl/systemctl.c
systemctl: when told to edit an instance, do not edit the template
[thirdparty/systemd.git] / src / systemctl / systemctl.c
... / ...
CommitLineData
1/***
2 This file is part of systemd.
3
4 Copyright 2010 Lennart Poettering
5 Copyright 2013 Marc-Antoine Perennou
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
21#include <errno.h>
22#include <fcntl.h>
23#include <getopt.h>
24#include <linux/reboot.h>
25#include <locale.h>
26#include <stdbool.h>
27#include <stddef.h>
28#include <stdio.h>
29#include <string.h>
30#include <sys/reboot.h>
31#include <sys/socket.h>
32#include <unistd.h>
33
34#include "sd-bus.h"
35#include "sd-daemon.h"
36#include "sd-login.h"
37
38#include "alloc-util.h"
39#include "bus-common-errors.h"
40#include "bus-error.h"
41#include "bus-message.h"
42#include "bus-unit-util.h"
43#include "bus-util.h"
44#include "cgroup-show.h"
45#include "cgroup-util.h"
46#include "copy.h"
47#include "dropin.h"
48#include "efivars.h"
49#include "env-util.h"
50#include "exit-status.h"
51#include "fd-util.h"
52#include "fileio.h"
53#include "format-util.h"
54#include "fs-util.h"
55#include "glob-util.h"
56#include "hostname-util.h"
57#include "initreq.h"
58#include "install.h"
59#include "io-util.h"
60#include "list.h"
61#include "locale-util.h"
62#include "log.h"
63#include "logs-show.h"
64#include "macro.h"
65#include "mkdir.h"
66#include "pager.h"
67#include "parse-util.h"
68#include "path-lookup.h"
69#include "path-util.h"
70#include "process-util.h"
71#include "rlimit-util.h"
72#include "set.h"
73#include "sigbus.h"
74#include "signal-util.h"
75#include "socket-util.h"
76#include "spawn-ask-password-agent.h"
77#include "spawn-polkit-agent.h"
78#include "special.h"
79#include "stat-util.h"
80#include "strv.h"
81#include "terminal-util.h"
82#include "unit-name.h"
83#include "user-util.h"
84#include "util.h"
85#include "utmp-wtmp.h"
86#include "verbs.h"
87#include "virt.h"
88
89/* The init script exit status codes
90 0 program is running or service is OK
91 1 program is dead and /var/run pid file exists
92 2 program is dead and /var/lock lock file exists
93 3 program is not running
94 4 program or service status is unknown
95 5-99 reserved for future LSB use
96 100-149 reserved for distribution use
97 150-199 reserved for application use
98 200-254 reserved
99*/
100enum {
101 EXIT_PROGRAM_RUNNING_OR_SERVICE_OK = 0,
102 EXIT_PROGRAM_DEAD_AND_PID_EXISTS = 1,
103 EXIT_PROGRAM_DEAD_AND_LOCK_FILE_EXISTS = 2,
104 EXIT_PROGRAM_NOT_RUNNING = 3,
105 EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN = 4,
106};
107
108static char **arg_types = NULL;
109static char **arg_states = NULL;
110static char **arg_properties = NULL;
111static bool arg_all = false;
112static enum dependency {
113 DEPENDENCY_FORWARD,
114 DEPENDENCY_REVERSE,
115 DEPENDENCY_AFTER,
116 DEPENDENCY_BEFORE,
117 _DEPENDENCY_MAX
118} arg_dependency = DEPENDENCY_FORWARD;
119static const char *arg_job_mode = "replace";
120static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
121static bool arg_wait = false;
122static bool arg_no_block = false;
123static bool arg_no_legend = false;
124static bool arg_no_pager = false;
125static bool arg_no_wtmp = false;
126static bool arg_no_sync = false;
127static bool arg_no_wall = false;
128static bool arg_no_reload = false;
129static bool arg_value = false;
130static bool arg_show_types = false;
131static bool arg_ignore_inhibitors = false;
132static bool arg_dry = false;
133static bool arg_quiet = false;
134static bool arg_full = false;
135static bool arg_recursive = false;
136static int arg_force = 0;
137static bool arg_ask_password = false;
138static bool arg_runtime = false;
139static UnitFilePresetMode arg_preset_mode = UNIT_FILE_PRESET_FULL;
140static char **arg_wall = NULL;
141static const char *arg_kill_who = NULL;
142static int arg_signal = SIGTERM;
143static char *arg_root = NULL;
144static usec_t arg_when = 0;
145static char *argv_cmdline = NULL;
146static enum action {
147 _ACTION_INVALID,
148 ACTION_SYSTEMCTL,
149 ACTION_HALT,
150 ACTION_POWEROFF,
151 ACTION_REBOOT,
152 ACTION_KEXEC,
153 ACTION_EXIT,
154 ACTION_SUSPEND,
155 ACTION_HIBERNATE,
156 ACTION_HYBRID_SLEEP,
157 ACTION_RUNLEVEL2,
158 ACTION_RUNLEVEL3,
159 ACTION_RUNLEVEL4,
160 ACTION_RUNLEVEL5,
161 ACTION_RESCUE,
162 ACTION_EMERGENCY,
163 ACTION_DEFAULT,
164 ACTION_RELOAD,
165 ACTION_REEXEC,
166 ACTION_RUNLEVEL,
167 ACTION_CANCEL_SHUTDOWN,
168 _ACTION_MAX
169} arg_action = ACTION_SYSTEMCTL;
170static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
171static const char *arg_host = NULL;
172static unsigned arg_lines = 10;
173static OutputMode arg_output = OUTPUT_SHORT;
174static bool arg_plain = false;
175static bool arg_firmware_setup = false;
176static bool arg_now = false;
177static bool arg_jobs_before = false;
178static bool arg_jobs_after = false;
179
180static int daemon_reload(int argc, char *argv[], void* userdata);
181static int trivial_method(int argc, char *argv[], void *userdata);
182static int halt_now(enum action a);
183static int get_state_one_unit(sd_bus *bus, const char *name, UnitActiveState *active_state);
184
185static bool original_stdout_is_tty;
186
187typedef enum BusFocus {
188 BUS_FULL, /* The full bus indicated via --system or --user */
189 BUS_MANAGER, /* The manager itself, possibly directly, possibly via the bus */
190 _BUS_FOCUS_MAX
191} BusFocus;
192
193static sd_bus *busses[_BUS_FOCUS_MAX] = {};
194
195static UnitFileFlags args_to_flags(void) {
196 return (arg_runtime ? UNIT_FILE_RUNTIME : 0) |
197 (arg_force ? UNIT_FILE_FORCE : 0);
198}
199
200static int acquire_bus(BusFocus focus, sd_bus **ret) {
201 int r;
202
203 assert(focus < _BUS_FOCUS_MAX);
204 assert(ret);
205
206 /* We only go directly to the manager, if we are using a local transport */
207 if (arg_transport != BUS_TRANSPORT_LOCAL)
208 focus = BUS_FULL;
209
210 if (getenv_bool("SYSTEMCTL_FORCE_BUS") > 0)
211 focus = BUS_FULL;
212
213 if (!busses[focus]) {
214 bool user;
215
216 user = arg_scope != UNIT_FILE_SYSTEM;
217
218 if (focus == BUS_MANAGER)
219 r = bus_connect_transport_systemd(arg_transport, arg_host, user, &busses[focus]);
220 else
221 r = bus_connect_transport(arg_transport, arg_host, user, &busses[focus]);
222 if (r < 0)
223 return log_error_errno(r, "Failed to connect to bus: %m");
224
225 (void) sd_bus_set_allow_interactive_authorization(busses[focus], arg_ask_password);
226 }
227
228 *ret = busses[focus];
229 return 0;
230}
231
232static void release_busses(void) {
233 BusFocus w;
234
235 for (w = 0; w < _BUS_FOCUS_MAX; w++)
236 busses[w] = sd_bus_flush_close_unref(busses[w]);
237}
238
239static int map_string_no_copy(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
240 char *s;
241 const char **p = userdata;
242 int r;
243
244 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &s);
245 if (r < 0)
246 return r;
247
248 if (!isempty(s))
249 *p = s;
250
251 return 0;
252}
253
254static void ask_password_agent_open_if_enabled(void) {
255
256 /* Open the password agent as a child process if necessary */
257
258 if (!arg_ask_password)
259 return;
260
261 if (arg_scope != UNIT_FILE_SYSTEM)
262 return;
263
264 if (arg_transport != BUS_TRANSPORT_LOCAL)
265 return;
266
267 ask_password_agent_open();
268}
269
270static void polkit_agent_open_if_enabled(void) {
271
272 /* Open the polkit agent as a child process if necessary */
273
274 if (!arg_ask_password)
275 return;
276
277 if (arg_scope != UNIT_FILE_SYSTEM)
278 return;
279
280 if (arg_transport != BUS_TRANSPORT_LOCAL)
281 return;
282
283 polkit_agent_open();
284}
285
286static OutputFlags get_output_flags(void) {
287 return
288 arg_all * OUTPUT_SHOW_ALL |
289 arg_full * OUTPUT_FULL_WIDTH |
290 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
291 colors_enabled() * OUTPUT_COLOR |
292 !arg_quiet * OUTPUT_WARN_CUTOFF;
293}
294
295static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
296 assert(error);
297
298 if (!sd_bus_error_is_set(error))
299 return r;
300
301 if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) ||
302 sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
303 sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
304 sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
305 return EXIT_NOPERMISSION;
306
307 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
308 return EXIT_NOTINSTALLED;
309
310 if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
311 sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED))
312 return EXIT_NOTIMPLEMENTED;
313
314 if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
315 return EXIT_NOTCONFIGURED;
316
317 if (r != 0)
318 return r;
319
320 return EXIT_FAILURE;
321}
322
323static bool install_client_side(void) {
324
325 /* Decides when to execute enable/disable/... operations
326 * client-side rather than server-side. */
327
328 if (running_in_chroot() > 0)
329 return true;
330
331 if (sd_booted() <= 0)
332 return true;
333
334 if (!isempty(arg_root))
335 return true;
336
337 if (arg_scope == UNIT_FILE_GLOBAL)
338 return true;
339
340 /* Unsupported environment variable, mostly for debugging purposes */
341 if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0)
342 return true;
343
344 return false;
345}
346
347static int compare_unit_info(const void *a, const void *b) {
348 const UnitInfo *u = a, *v = b;
349 const char *d1, *d2;
350 int r;
351
352 /* First, order by machine */
353 if (!u->machine && v->machine)
354 return -1;
355 if (u->machine && !v->machine)
356 return 1;
357 if (u->machine && v->machine) {
358 r = strcasecmp(u->machine, v->machine);
359 if (r != 0)
360 return r;
361 }
362
363 /* Second, order by unit type */
364 d1 = strrchr(u->id, '.');
365 d2 = strrchr(v->id, '.');
366 if (d1 && d2) {
367 r = strcasecmp(d1, d2);
368 if (r != 0)
369 return r;
370 }
371
372 /* Third, order by name */
373 return strcasecmp(u->id, v->id);
374}
375
376static const char* unit_type_suffix(const char *name) {
377 const char *dot;
378
379 dot = strrchr(name, '.');
380 if (!dot)
381 return "";
382
383 return dot + 1;
384}
385
386static bool output_show_unit(const UnitInfo *u, char **patterns) {
387 assert(u);
388
389 if (!strv_fnmatch_or_empty(patterns, u->id, FNM_NOESCAPE))
390 return false;
391
392 if (arg_types && !strv_find(arg_types, unit_type_suffix(u->id)))
393 return false;
394
395 if (arg_all)
396 return true;
397
398 /* Note that '--all' is not purely a state filter, but also a
399 * filter that hides units that "follow" other units (which is
400 * used for device units that appear under different names). */
401 if (!isempty(u->following))
402 return false;
403
404 if (!strv_isempty(arg_states))
405 return true;
406
407 /* By default show all units except the ones in inactive
408 * state and with no pending job */
409 if (u->job_id > 0)
410 return true;
411
412 if (streq(u->active_state, "inactive"))
413 return false;
414
415 return true;
416}
417
418static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
419 unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len, max_desc_len;
420 const UnitInfo *u;
421 unsigned n_shown = 0;
422 int job_count = 0;
423
424 max_id_len = strlen("UNIT");
425 load_len = strlen("LOAD");
426 active_len = strlen("ACTIVE");
427 sub_len = strlen("SUB");
428 job_len = strlen("JOB");
429 max_desc_len = strlen("DESCRIPTION");
430
431 for (u = unit_infos; u < unit_infos + c; u++) {
432 max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0));
433 load_len = MAX(load_len, strlen(u->load_state));
434 active_len = MAX(active_len, strlen(u->active_state));
435 sub_len = MAX(sub_len, strlen(u->sub_state));
436 max_desc_len = MAX(max_desc_len, strlen(u->description));
437
438 if (u->job_id != 0) {
439 job_len = MAX(job_len, strlen(u->job_type));
440 job_count++;
441 }
442
443 if (!arg_no_legend &&
444 (streq(u->active_state, "failed") ||
445 STR_IN_SET(u->load_state, "error", "not-found", "masked")))
446 circle_len = 2;
447 }
448
449 if (!arg_full && original_stdout_is_tty) {
450 unsigned basic_len;
451
452 id_len = MIN(max_id_len, 25u); /* as much as it needs, but at most 25 for now */
453 basic_len = circle_len + 1 + id_len + 1 + load_len + 1 + active_len + 1 + sub_len + 1;
454
455 if (job_count)
456 basic_len += job_len + 1;
457
458 if (basic_len < (unsigned) columns()) {
459 unsigned extra_len, incr;
460 extra_len = columns() - basic_len;
461
462 /* Either UNIT already got 25, or is fully satisfied.
463 * Grant up to 25 to DESC now. */
464 incr = MIN(extra_len, 25u);
465 desc_len = incr;
466 extra_len -= incr;
467
468 /* Of the remainder give as much as the ID needs to the ID, and give the rest to the
469 * description but not more than it needs. */
470 if (extra_len > 0) {
471 incr = MIN(max_id_len - id_len, extra_len);
472 id_len += incr;
473 desc_len += MIN(extra_len - incr, max_desc_len - desc_len);
474 }
475 } else
476 desc_len = 0;
477 } else {
478 id_len = max_id_len;
479 desc_len = max_desc_len;
480 }
481
482 for (u = unit_infos; u < unit_infos + c; u++) {
483 _cleanup_free_ char *e = NULL, *j = NULL;
484 const char *on_underline = "", *off_underline = "";
485 const char *on_loaded = "", *off_loaded = "";
486 const char *on_active = "", *off_active = "";
487 const char *on_circle = "", *off_circle = "";
488 const char *id;
489 bool circle = false, underline = false;
490
491 if (!n_shown && !arg_no_legend) {
492
493 if (circle_len > 0)
494 fputs(" ", stdout);
495
496 printf("%s%-*s %-*s %-*s %-*s ",
497 ansi_underline(),
498 id_len, "UNIT",
499 load_len, "LOAD",
500 active_len, "ACTIVE",
501 sub_len, "SUB");
502
503 if (job_count)
504 printf("%-*s ", job_len, "JOB");
505
506 printf("%-*.*s%s\n",
507 desc_len,
508 !arg_full && arg_no_pager ? (int) desc_len : -1,
509 "DESCRIPTION",
510 ansi_normal());
511 }
512
513 n_shown++;
514
515 if (u + 1 < unit_infos + c &&
516 !streq(unit_type_suffix(u->id), unit_type_suffix((u + 1)->id))) {
517 on_underline = ansi_underline();
518 off_underline = ansi_normal();
519 underline = true;
520 }
521
522 if (STR_IN_SET(u->load_state, "error", "not-found", "masked") && !arg_plain) {
523 on_circle = ansi_highlight_yellow();
524 off_circle = ansi_normal();
525 circle = true;
526 on_loaded = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
527 off_loaded = underline ? on_underline : ansi_normal();
528 } else if (streq(u->active_state, "failed") && !arg_plain) {
529 on_circle = ansi_highlight_red();
530 off_circle = ansi_normal();
531 circle = true;
532 on_active = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
533 off_active = underline ? on_underline : ansi_normal();
534 }
535
536 if (u->machine) {
537 j = strjoin(u->machine, ":", u->id);
538 if (!j)
539 return log_oom();
540
541 id = j;
542 } else
543 id = u->id;
544
545 if (arg_full) {
546 e = ellipsize(id, id_len, 33);
547 if (!e)
548 return log_oom();
549
550 id = e;
551 }
552
553 if (circle_len > 0)
554 printf("%s%s%s ", on_circle, circle ? special_glyph(BLACK_CIRCLE) : " ", off_circle);
555
556 printf("%s%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
557 on_underline,
558 on_active, id_len, id, off_active,
559 on_loaded, load_len, u->load_state, off_loaded,
560 on_active, active_len, u->active_state,
561 sub_len, u->sub_state, off_active,
562 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
563
564 printf("%-*.*s%s\n",
565 desc_len,
566 !arg_full && arg_no_pager ? (int) desc_len : -1,
567 u->description,
568 off_underline);
569 }
570
571 if (!arg_no_legend) {
572 const char *on, *off;
573
574 if (n_shown) {
575 puts("\n"
576 "LOAD = Reflects whether the unit definition was properly loaded.\n"
577 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
578 "SUB = The low-level unit activation state, values depend on unit type.");
579 puts(job_count ? "JOB = Pending job for the unit.\n" : "");
580 on = ansi_highlight();
581 off = ansi_normal();
582 } else {
583 on = ansi_highlight_red();
584 off = ansi_normal();
585 }
586
587 if (arg_all)
588 printf("%s%u loaded units listed.%s\n"
589 "To show all installed unit files use 'systemctl list-unit-files'.\n",
590 on, n_shown, off);
591 else
592 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
593 "To show all installed unit files use 'systemctl list-unit-files'.\n",
594 on, n_shown, off);
595 }
596
597 return 0;
598}
599
600static int get_unit_list(
601 sd_bus *bus,
602 const char *machine,
603 char **patterns,
604 UnitInfo **unit_infos,
605 int c,
606 sd_bus_message **_reply) {
607
608 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
609 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
610 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
611 size_t size = c;
612 int r;
613 UnitInfo u;
614 bool fallback = false;
615
616 assert(bus);
617 assert(unit_infos);
618 assert(_reply);
619
620 r = sd_bus_message_new_method_call(
621 bus,
622 &m,
623 "org.freedesktop.systemd1",
624 "/org/freedesktop/systemd1",
625 "org.freedesktop.systemd1.Manager",
626 "ListUnitsByPatterns");
627 if (r < 0)
628 return bus_log_create_error(r);
629
630 r = sd_bus_message_append_strv(m, arg_states);
631 if (r < 0)
632 return bus_log_create_error(r);
633
634 r = sd_bus_message_append_strv(m, patterns);
635 if (r < 0)
636 return bus_log_create_error(r);
637
638 r = sd_bus_call(bus, m, 0, &error, &reply);
639 if (r < 0 && (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD) ||
640 sd_bus_error_has_name(&error, SD_BUS_ERROR_ACCESS_DENIED))) {
641 /* Fallback to legacy ListUnitsFiltered method */
642 fallback = true;
643 log_debug_errno(r, "Failed to list units: %s Falling back to ListUnitsFiltered method.", bus_error_message(&error, r));
644 m = sd_bus_message_unref(m);
645 sd_bus_error_free(&error);
646
647 r = sd_bus_message_new_method_call(
648 bus,
649 &m,
650 "org.freedesktop.systemd1",
651 "/org/freedesktop/systemd1",
652 "org.freedesktop.systemd1.Manager",
653 "ListUnitsFiltered");
654 if (r < 0)
655 return bus_log_create_error(r);
656
657 r = sd_bus_message_append_strv(m, arg_states);
658 if (r < 0)
659 return bus_log_create_error(r);
660
661 r = sd_bus_call(bus, m, 0, &error, &reply);
662 }
663 if (r < 0)
664 return log_error_errno(r, "Failed to list units: %s", bus_error_message(&error, r));
665
666 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
667 if (r < 0)
668 return bus_log_parse_error(r);
669
670 while ((r = bus_parse_unit_info(reply, &u)) > 0) {
671 u.machine = machine;
672
673 if (!output_show_unit(&u, fallback ? patterns : NULL))
674 continue;
675
676 if (!GREEDY_REALLOC(*unit_infos, size, c+1))
677 return log_oom();
678
679 (*unit_infos)[c++] = u;
680 }
681 if (r < 0)
682 return bus_log_parse_error(r);
683
684 r = sd_bus_message_exit_container(reply);
685 if (r < 0)
686 return bus_log_parse_error(r);
687
688 *_reply = reply;
689 reply = NULL;
690
691 return c;
692}
693
694static void message_set_freep(Set **set) {
695 sd_bus_message *m;
696
697 while ((m = set_steal_first(*set)))
698 sd_bus_message_unref(m);
699
700 set_free(*set);
701}
702
703static int get_unit_list_recursive(
704 sd_bus *bus,
705 char **patterns,
706 UnitInfo **_unit_infos,
707 Set **_replies,
708 char ***_machines) {
709
710 _cleanup_free_ UnitInfo *unit_infos = NULL;
711 _cleanup_(message_set_freep) Set *replies;
712 sd_bus_message *reply;
713 int c, r;
714
715 assert(bus);
716 assert(_replies);
717 assert(_unit_infos);
718 assert(_machines);
719
720 replies = set_new(NULL);
721 if (!replies)
722 return log_oom();
723
724 c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
725 if (c < 0)
726 return c;
727
728 r = set_put(replies, reply);
729 if (r < 0) {
730 sd_bus_message_unref(reply);
731 return log_oom();
732 }
733
734 if (arg_recursive) {
735 _cleanup_strv_free_ char **machines = NULL;
736 char **i;
737
738 r = sd_get_machine_names(&machines);
739 if (r < 0)
740 return log_error_errno(r, "Failed to get machine names: %m");
741
742 STRV_FOREACH(i, machines) {
743 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *container = NULL;
744 int k;
745
746 r = sd_bus_open_system_machine(&container, *i);
747 if (r < 0) {
748 log_warning_errno(r, "Failed to connect to container %s, ignoring: %m", *i);
749 continue;
750 }
751
752 k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
753 if (k < 0)
754 return k;
755
756 c = k;
757
758 r = set_put(replies, reply);
759 if (r < 0) {
760 sd_bus_message_unref(reply);
761 return log_oom();
762 }
763 }
764
765 *_machines = machines;
766 machines = NULL;
767 } else
768 *_machines = NULL;
769
770 *_unit_infos = unit_infos;
771 unit_infos = NULL;
772
773 *_replies = replies;
774 replies = NULL;
775
776 return c;
777}
778
779static int list_units(int argc, char *argv[], void *userdata) {
780 _cleanup_free_ UnitInfo *unit_infos = NULL;
781 _cleanup_(message_set_freep) Set *replies = NULL;
782 _cleanup_strv_free_ char **machines = NULL;
783 sd_bus *bus;
784 int r;
785
786 r = acquire_bus(BUS_MANAGER, &bus);
787 if (r < 0)
788 return r;
789
790 pager_open(arg_no_pager, false);
791
792 r = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines);
793 if (r < 0)
794 return r;
795
796 qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
797 return output_units_list(unit_infos, r);
798}
799
800static int get_triggered_units(
801 sd_bus *bus,
802 const char* path,
803 char*** ret) {
804
805 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
806 int r;
807
808 assert(bus);
809 assert(path);
810 assert(ret);
811
812 r = sd_bus_get_property_strv(
813 bus,
814 "org.freedesktop.systemd1",
815 path,
816 "org.freedesktop.systemd1.Unit",
817 "Triggers",
818 &error,
819 ret);
820 if (r < 0)
821 return log_error_errno(r, "Failed to determine triggers: %s", bus_error_message(&error, r));
822
823 return 0;
824}
825
826static int get_listening(
827 sd_bus *bus,
828 const char* unit_path,
829 char*** listening) {
830
831 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
832 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
833 const char *type, *path;
834 int r, n = 0;
835
836 r = sd_bus_get_property(
837 bus,
838 "org.freedesktop.systemd1",
839 unit_path,
840 "org.freedesktop.systemd1.Socket",
841 "Listen",
842 &error,
843 &reply,
844 "a(ss)");
845 if (r < 0)
846 return log_error_errno(r, "Failed to get list of listening sockets: %s", bus_error_message(&error, r));
847
848 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
849 if (r < 0)
850 return bus_log_parse_error(r);
851
852 while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
853
854 r = strv_extend(listening, type);
855 if (r < 0)
856 return log_oom();
857
858 r = strv_extend(listening, path);
859 if (r < 0)
860 return log_oom();
861
862 n++;
863 }
864 if (r < 0)
865 return bus_log_parse_error(r);
866
867 r = sd_bus_message_exit_container(reply);
868 if (r < 0)
869 return bus_log_parse_error(r);
870
871 return n;
872}
873
874struct socket_info {
875 const char *machine;
876 const char* id;
877
878 char* type;
879 char* path;
880
881 /* Note: triggered is a list here, although it almost certainly
882 * will always be one unit. Nevertheless, dbus API allows for multiple
883 * values, so let's follow that. */
884 char** triggered;
885
886 /* The strv above is shared. free is set only in the first one. */
887 bool own_triggered;
888};
889
890static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
891 int o;
892
893 assert(a);
894 assert(b);
895
896 if (!a->machine && b->machine)
897 return -1;
898 if (a->machine && !b->machine)
899 return 1;
900 if (a->machine && b->machine) {
901 o = strcasecmp(a->machine, b->machine);
902 if (o != 0)
903 return o;
904 }
905
906 o = strcmp(a->path, b->path);
907 if (o == 0)
908 o = strcmp(a->type, b->type);
909
910 return o;
911}
912
913static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
914 struct socket_info *s;
915 unsigned pathlen = strlen("LISTEN"),
916 typelen = strlen("TYPE") * arg_show_types,
917 socklen = strlen("UNIT"),
918 servlen = strlen("ACTIVATES");
919 const char *on, *off;
920
921 for (s = socket_infos; s < socket_infos + cs; s++) {
922 unsigned tmp = 0;
923 char **a;
924
925 socklen = MAX(socklen, strlen(s->id));
926 if (arg_show_types)
927 typelen = MAX(typelen, strlen(s->type));
928 pathlen = MAX(pathlen, strlen(s->path) + (s->machine ? strlen(s->machine)+1 : 0));
929
930 STRV_FOREACH(a, s->triggered)
931 tmp += strlen(*a) + 2*(a != s->triggered);
932 servlen = MAX(servlen, tmp);
933 }
934
935 if (cs) {
936 if (!arg_no_legend)
937 printf("%-*s %-*.*s%-*s %s\n",
938 pathlen, "LISTEN",
939 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
940 socklen, "UNIT",
941 "ACTIVATES");
942
943 for (s = socket_infos; s < socket_infos + cs; s++) {
944 _cleanup_free_ char *j = NULL;
945 const char *path;
946 char **a;
947
948 if (s->machine) {
949 j = strjoin(s->machine, ":", s->path);
950 if (!j)
951 return log_oom();
952 path = j;
953 } else
954 path = s->path;
955
956 if (arg_show_types)
957 printf("%-*s %-*s %-*s",
958 pathlen, path, typelen, s->type, socklen, s->id);
959 else
960 printf("%-*s %-*s",
961 pathlen, path, socklen, s->id);
962 STRV_FOREACH(a, s->triggered)
963 printf("%s %s",
964 a == s->triggered ? "" : ",", *a);
965 printf("\n");
966 }
967
968 on = ansi_highlight();
969 off = ansi_normal();
970 if (!arg_no_legend)
971 printf("\n");
972 } else {
973 on = ansi_highlight_red();
974 off = ansi_normal();
975 }
976
977 if (!arg_no_legend) {
978 printf("%s%u sockets listed.%s\n", on, cs, off);
979 if (!arg_all)
980 printf("Pass --all to see loaded but inactive sockets, too.\n");
981 }
982
983 return 0;
984}
985
986static int list_sockets(int argc, char *argv[], void *userdata) {
987 _cleanup_(message_set_freep) Set *replies = NULL;
988 _cleanup_strv_free_ char **machines = NULL;
989 _cleanup_free_ UnitInfo *unit_infos = NULL;
990 _cleanup_free_ struct socket_info *socket_infos = NULL;
991 const UnitInfo *u;
992 struct socket_info *s;
993 unsigned cs = 0;
994 size_t size = 0;
995 int r = 0, n;
996 sd_bus *bus;
997
998 r = acquire_bus(BUS_MANAGER, &bus);
999 if (r < 0)
1000 return r;
1001
1002 pager_open(arg_no_pager, false);
1003
1004 n = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines);
1005 if (n < 0)
1006 return n;
1007
1008 for (u = unit_infos; u < unit_infos + n; u++) {
1009 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
1010 int i, c;
1011
1012 if (!endswith(u->id, ".socket"))
1013 continue;
1014
1015 r = get_triggered_units(bus, u->unit_path, &triggered);
1016 if (r < 0)
1017 goto cleanup;
1018
1019 c = get_listening(bus, u->unit_path, &listening);
1020 if (c < 0) {
1021 r = c;
1022 goto cleanup;
1023 }
1024
1025 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
1026 r = log_oom();
1027 goto cleanup;
1028 }
1029
1030 for (i = 0; i < c; i++)
1031 socket_infos[cs + i] = (struct socket_info) {
1032 .machine = u->machine,
1033 .id = u->id,
1034 .type = listening[i*2],
1035 .path = listening[i*2 + 1],
1036 .triggered = triggered,
1037 .own_triggered = i==0,
1038 };
1039
1040 /* from this point on we will cleanup those socket_infos */
1041 cs += c;
1042 free(listening);
1043 listening = triggered = NULL; /* avoid cleanup */
1044 }
1045
1046 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
1047 (__compar_fn_t) socket_info_compare);
1048
1049 output_sockets_list(socket_infos, cs);
1050
1051 cleanup:
1052 assert(cs == 0 || socket_infos);
1053 for (s = socket_infos; s < socket_infos + cs; s++) {
1054 free(s->type);
1055 free(s->path);
1056 if (s->own_triggered)
1057 strv_free(s->triggered);
1058 }
1059
1060 return r;
1061}
1062
1063static int get_next_elapse(
1064 sd_bus *bus,
1065 const char *path,
1066 dual_timestamp *next) {
1067
1068 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1069 dual_timestamp t;
1070 int r;
1071
1072 assert(bus);
1073 assert(path);
1074 assert(next);
1075
1076 r = sd_bus_get_property_trivial(
1077 bus,
1078 "org.freedesktop.systemd1",
1079 path,
1080 "org.freedesktop.systemd1.Timer",
1081 "NextElapseUSecMonotonic",
1082 &error,
1083 't',
1084 &t.monotonic);
1085 if (r < 0)
1086 return log_error_errno(r, "Failed to get next elapsation time: %s", bus_error_message(&error, r));
1087
1088 r = sd_bus_get_property_trivial(
1089 bus,
1090 "org.freedesktop.systemd1",
1091 path,
1092 "org.freedesktop.systemd1.Timer",
1093 "NextElapseUSecRealtime",
1094 &error,
1095 't',
1096 &t.realtime);
1097 if (r < 0)
1098 return log_error_errno(r, "Failed to get next elapsation time: %s", bus_error_message(&error, r));
1099
1100 *next = t;
1101 return 0;
1102}
1103
1104static int get_last_trigger(
1105 sd_bus *bus,
1106 const char *path,
1107 usec_t *last) {
1108
1109 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1110 int r;
1111
1112 assert(bus);
1113 assert(path);
1114 assert(last);
1115
1116 r = sd_bus_get_property_trivial(
1117 bus,
1118 "org.freedesktop.systemd1",
1119 path,
1120 "org.freedesktop.systemd1.Timer",
1121 "LastTriggerUSec",
1122 &error,
1123 't',
1124 last);
1125 if (r < 0)
1126 return log_error_errno(r, "Failed to get last trigger time: %s", bus_error_message(&error, r));
1127
1128 return 0;
1129}
1130
1131struct timer_info {
1132 const char* machine;
1133 const char* id;
1134 usec_t next_elapse;
1135 usec_t last_trigger;
1136 char** triggered;
1137};
1138
1139static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
1140 int o;
1141
1142 assert(a);
1143 assert(b);
1144
1145 if (!a->machine && b->machine)
1146 return -1;
1147 if (a->machine && !b->machine)
1148 return 1;
1149 if (a->machine && b->machine) {
1150 o = strcasecmp(a->machine, b->machine);
1151 if (o != 0)
1152 return o;
1153 }
1154
1155 if (a->next_elapse < b->next_elapse)
1156 return -1;
1157 if (a->next_elapse > b->next_elapse)
1158 return 1;
1159
1160 return strcmp(a->id, b->id);
1161}
1162
1163static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
1164 struct timer_info *t;
1165 unsigned
1166 nextlen = strlen("NEXT"),
1167 leftlen = strlen("LEFT"),
1168 lastlen = strlen("LAST"),
1169 passedlen = strlen("PASSED"),
1170 unitlen = strlen("UNIT"),
1171 activatelen = strlen("ACTIVATES");
1172
1173 const char *on, *off;
1174
1175 assert(timer_infos || n == 0);
1176
1177 for (t = timer_infos; t < timer_infos + n; t++) {
1178 unsigned ul = 0;
1179 char **a;
1180
1181 if (t->next_elapse > 0) {
1182 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1183
1184 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
1185 nextlen = MAX(nextlen, strlen(tstamp) + 1);
1186
1187 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
1188 leftlen = MAX(leftlen, strlen(trel));
1189 }
1190
1191 if (t->last_trigger > 0) {
1192 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1193
1194 format_timestamp(tstamp, sizeof(tstamp), t->last_trigger);
1195 lastlen = MAX(lastlen, strlen(tstamp) + 1);
1196
1197 format_timestamp_relative(trel, sizeof(trel), t->last_trigger);
1198 passedlen = MAX(passedlen, strlen(trel));
1199 }
1200
1201 unitlen = MAX(unitlen, strlen(t->id) + (t->machine ? strlen(t->machine)+1 : 0));
1202
1203 STRV_FOREACH(a, t->triggered)
1204 ul += strlen(*a) + 2*(a != t->triggered);
1205
1206 activatelen = MAX(activatelen, ul);
1207 }
1208
1209 if (n > 0) {
1210 if (!arg_no_legend)
1211 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1212 nextlen, "NEXT",
1213 leftlen, "LEFT",
1214 lastlen, "LAST",
1215 passedlen, "PASSED",
1216 unitlen, "UNIT",
1217 "ACTIVATES");
1218
1219 for (t = timer_infos; t < timer_infos + n; t++) {
1220 _cleanup_free_ char *j = NULL;
1221 const char *unit;
1222 char tstamp1[FORMAT_TIMESTAMP_MAX] = "n/a", trel1[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1223 char tstamp2[FORMAT_TIMESTAMP_MAX] = "n/a", trel2[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1224 char **a;
1225
1226 format_timestamp(tstamp1, sizeof(tstamp1), t->next_elapse);
1227 format_timestamp_relative(trel1, sizeof(trel1), t->next_elapse);
1228
1229 format_timestamp(tstamp2, sizeof(tstamp2), t->last_trigger);
1230 format_timestamp_relative(trel2, sizeof(trel2), t->last_trigger);
1231
1232 if (t->machine) {
1233 j = strjoin(t->machine, ":", t->id);
1234 if (!j)
1235 return log_oom();
1236 unit = j;
1237 } else
1238 unit = t->id;
1239
1240 printf("%-*s %-*s %-*s %-*s %-*s",
1241 nextlen, tstamp1, leftlen, trel1, lastlen, tstamp2, passedlen, trel2, unitlen, unit);
1242
1243 STRV_FOREACH(a, t->triggered)
1244 printf("%s %s",
1245 a == t->triggered ? "" : ",", *a);
1246 printf("\n");
1247 }
1248
1249 on = ansi_highlight();
1250 off = ansi_normal();
1251 if (!arg_no_legend)
1252 printf("\n");
1253 } else {
1254 on = ansi_highlight_red();
1255 off = ansi_normal();
1256 }
1257
1258 if (!arg_no_legend) {
1259 printf("%s%u timers listed.%s\n", on, n, off);
1260 if (!arg_all)
1261 printf("Pass --all to see loaded but inactive timers, too.\n");
1262 }
1263
1264 return 0;
1265}
1266
1267static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
1268 usec_t next_elapse;
1269
1270 assert(nw);
1271 assert(next);
1272
1273 if (next->monotonic != USEC_INFINITY && next->monotonic > 0) {
1274 usec_t converted;
1275
1276 if (next->monotonic > nw->monotonic)
1277 converted = nw->realtime + (next->monotonic - nw->monotonic);
1278 else
1279 converted = nw->realtime - (nw->monotonic - next->monotonic);
1280
1281 if (next->realtime != USEC_INFINITY && next->realtime > 0)
1282 next_elapse = MIN(converted, next->realtime);
1283 else
1284 next_elapse = converted;
1285
1286 } else
1287 next_elapse = next->realtime;
1288
1289 return next_elapse;
1290}
1291
1292static int list_timers(int argc, char *argv[], void *userdata) {
1293 _cleanup_(message_set_freep) Set *replies = NULL;
1294 _cleanup_strv_free_ char **machines = NULL;
1295 _cleanup_free_ struct timer_info *timer_infos = NULL;
1296 _cleanup_free_ UnitInfo *unit_infos = NULL;
1297 struct timer_info *t;
1298 const UnitInfo *u;
1299 size_t size = 0;
1300 int n, c = 0;
1301 dual_timestamp nw;
1302 sd_bus *bus;
1303 int r = 0;
1304
1305 r = acquire_bus(BUS_MANAGER, &bus);
1306 if (r < 0)
1307 return r;
1308
1309 pager_open(arg_no_pager, false);
1310
1311 n = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines);
1312 if (n < 0)
1313 return n;
1314
1315 dual_timestamp_get(&nw);
1316
1317 for (u = unit_infos; u < unit_infos + n; u++) {
1318 _cleanup_strv_free_ char **triggered = NULL;
1319 dual_timestamp next = DUAL_TIMESTAMP_NULL;
1320 usec_t m, last = 0;
1321
1322 if (!endswith(u->id, ".timer"))
1323 continue;
1324
1325 r = get_triggered_units(bus, u->unit_path, &triggered);
1326 if (r < 0)
1327 goto cleanup;
1328
1329 r = get_next_elapse(bus, u->unit_path, &next);
1330 if (r < 0)
1331 goto cleanup;
1332
1333 get_last_trigger(bus, u->unit_path, &last);
1334
1335 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
1336 r = log_oom();
1337 goto cleanup;
1338 }
1339
1340 m = calc_next_elapse(&nw, &next);
1341
1342 timer_infos[c++] = (struct timer_info) {
1343 .machine = u->machine,
1344 .id = u->id,
1345 .next_elapse = m,
1346 .last_trigger = last,
1347 .triggered = triggered,
1348 };
1349
1350 triggered = NULL; /* avoid cleanup */
1351 }
1352
1353 qsort_safe(timer_infos, c, sizeof(struct timer_info),
1354 (__compar_fn_t) timer_info_compare);
1355
1356 output_timers_list(timer_infos, c);
1357
1358 cleanup:
1359 for (t = timer_infos; t < timer_infos + c; t++)
1360 strv_free(t->triggered);
1361
1362 return r;
1363}
1364
1365static int compare_unit_file_list(const void *a, const void *b) {
1366 const char *d1, *d2;
1367 const UnitFileList *u = a, *v = b;
1368
1369 d1 = strrchr(u->path, '.');
1370 d2 = strrchr(v->path, '.');
1371
1372 if (d1 && d2) {
1373 int r;
1374
1375 r = strcasecmp(d1, d2);
1376 if (r != 0)
1377 return r;
1378 }
1379
1380 return strcasecmp(basename(u->path), basename(v->path));
1381}
1382
1383static bool output_show_unit_file(const UnitFileList *u, char **states, char **patterns) {
1384 assert(u);
1385
1386 if (!strv_fnmatch_or_empty(patterns, basename(u->path), FNM_NOESCAPE))
1387 return false;
1388
1389 if (!strv_isempty(arg_types)) {
1390 const char *dot;
1391
1392 dot = strrchr(u->path, '.');
1393 if (!dot)
1394 return false;
1395
1396 if (!strv_find(arg_types, dot+1))
1397 return false;
1398 }
1399
1400 if (!strv_isempty(states) &&
1401 !strv_find(states, unit_file_state_to_string(u->state)))
1402 return false;
1403
1404 return true;
1405}
1406
1407static void output_unit_file_list(const UnitFileList *units, unsigned c) {
1408 unsigned max_id_len, id_cols, state_cols;
1409 const UnitFileList *u;
1410
1411 max_id_len = strlen("UNIT FILE");
1412 state_cols = strlen("STATE");
1413
1414 for (u = units; u < units + c; u++) {
1415 max_id_len = MAX(max_id_len, strlen(basename(u->path)));
1416 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1417 }
1418
1419 if (!arg_full) {
1420 unsigned basic_cols;
1421
1422 id_cols = MIN(max_id_len, 25u);
1423 basic_cols = 1 + id_cols + state_cols;
1424 if (basic_cols < (unsigned) columns())
1425 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1426 } else
1427 id_cols = max_id_len;
1428
1429 if (!arg_no_legend && c > 0)
1430 printf("%s%-*s %-*s%s\n",
1431 ansi_underline(),
1432 id_cols, "UNIT FILE",
1433 state_cols, "STATE",
1434 ansi_normal());
1435
1436 for (u = units; u < units + c; u++) {
1437 _cleanup_free_ char *e = NULL;
1438 const char *on, *off, *on_underline = "", *off_underline = "";
1439 const char *id;
1440 bool underline = false;
1441
1442 if (u + 1 < units + c &&
1443 !streq(unit_type_suffix(u->path), unit_type_suffix((u + 1)->path))) {
1444 on_underline = ansi_underline();
1445 off_underline = ansi_normal();
1446 underline = true;
1447 }
1448
1449 if (IN_SET(u->state,
1450 UNIT_FILE_MASKED,
1451 UNIT_FILE_MASKED_RUNTIME,
1452 UNIT_FILE_DISABLED,
1453 UNIT_FILE_BAD))
1454 on = underline ? ansi_highlight_red_underline() : ansi_highlight_red();
1455 else if (u->state == UNIT_FILE_ENABLED)
1456 on = underline ? ansi_highlight_green_underline() : ansi_highlight_green();
1457 else
1458 on = on_underline;
1459 off = off_underline;
1460
1461 id = basename(u->path);
1462
1463 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1464
1465 printf("%s%-*s %s%-*s%s%s\n",
1466 on_underline,
1467 id_cols, e ? e : id,
1468 on, state_cols, unit_file_state_to_string(u->state), off,
1469 off_underline);
1470 }
1471
1472 if (!arg_no_legend)
1473 printf("\n%u unit files listed.\n", c);
1474}
1475
1476static int list_unit_files(int argc, char *argv[], void *userdata) {
1477 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1478 _cleanup_free_ UnitFileList *units = NULL;
1479 UnitFileList *unit;
1480 size_t size = 0;
1481 unsigned c = 0;
1482 const char *state;
1483 char *path;
1484 int r;
1485 bool fallback = false;
1486
1487 if (install_client_side()) {
1488 Hashmap *h;
1489 UnitFileList *u;
1490 Iterator i;
1491 unsigned n_units;
1492
1493 h = hashmap_new(&string_hash_ops);
1494 if (!h)
1495 return log_oom();
1496
1497 r = unit_file_get_list(arg_scope, arg_root, h, arg_states, strv_skip(argv, 1));
1498 if (r < 0) {
1499 unit_file_list_free(h);
1500 return log_error_errno(r, "Failed to get unit file list: %m");
1501 }
1502
1503 n_units = hashmap_size(h);
1504
1505 units = new(UnitFileList, n_units ?: 1); /* avoid malloc(0) */
1506 if (!units) {
1507 unit_file_list_free(h);
1508 return log_oom();
1509 }
1510
1511 HASHMAP_FOREACH(u, h, i) {
1512 if (!output_show_unit_file(u, NULL, NULL))
1513 continue;
1514
1515 units[c++] = *u;
1516 free(u);
1517 }
1518
1519 assert(c <= n_units);
1520 hashmap_free(h);
1521
1522 r = 0;
1523 } else {
1524 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1525 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1526 sd_bus *bus;
1527
1528 r = acquire_bus(BUS_MANAGER, &bus);
1529 if (r < 0)
1530 return r;
1531
1532 r = sd_bus_message_new_method_call(
1533 bus,
1534 &m,
1535 "org.freedesktop.systemd1",
1536 "/org/freedesktop/systemd1",
1537 "org.freedesktop.systemd1.Manager",
1538 "ListUnitFilesByPatterns");
1539 if (r < 0)
1540 return bus_log_create_error(r);
1541
1542 r = sd_bus_message_append_strv(m, arg_states);
1543 if (r < 0)
1544 return bus_log_create_error(r);
1545
1546 r = sd_bus_message_append_strv(m, strv_skip(argv, 1));
1547 if (r < 0)
1548 return bus_log_create_error(r);
1549
1550 r = sd_bus_call(bus, m, 0, &error, &reply);
1551 if (r < 0 && sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD)) {
1552 /* Fallback to legacy ListUnitFiles method */
1553 fallback = true;
1554 log_debug_errno(r, "Failed to list unit files: %s Falling back to ListUnitsFiles method.", bus_error_message(&error, r));
1555 m = sd_bus_message_unref(m);
1556 sd_bus_error_free(&error);
1557
1558 r = sd_bus_message_new_method_call(
1559 bus,
1560 &m,
1561 "org.freedesktop.systemd1",
1562 "/org/freedesktop/systemd1",
1563 "org.freedesktop.systemd1.Manager",
1564 "ListUnitFiles");
1565 if (r < 0)
1566 return bus_log_create_error(r);
1567
1568 r = sd_bus_call(bus, m, 0, &error, &reply);
1569 }
1570 if (r < 0)
1571 return log_error_errno(r, "Failed to list unit files: %s", bus_error_message(&error, r));
1572
1573 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1574 if (r < 0)
1575 return bus_log_parse_error(r);
1576
1577 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1578
1579 if (!GREEDY_REALLOC(units, size, c + 1))
1580 return log_oom();
1581
1582 units[c] = (struct UnitFileList) {
1583 path,
1584 unit_file_state_from_string(state)
1585 };
1586
1587 if (output_show_unit_file(&units[c],
1588 fallback ? arg_states : NULL,
1589 fallback ? strv_skip(argv, 1) : NULL))
1590 c++;
1591
1592 }
1593 if (r < 0)
1594 return bus_log_parse_error(r);
1595
1596 r = sd_bus_message_exit_container(reply);
1597 if (r < 0)
1598 return bus_log_parse_error(r);
1599 }
1600
1601 pager_open(arg_no_pager, false);
1602
1603 qsort_safe(units, c, sizeof(UnitFileList), compare_unit_file_list);
1604 output_unit_file_list(units, c);
1605
1606 if (install_client_side())
1607 for (unit = units; unit < units + c; unit++)
1608 free(unit->path);
1609
1610 return 0;
1611}
1612
1613static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1614 _cleanup_free_ char *n = NULL;
1615 size_t max_len = MAX(columns(),20u);
1616 size_t len = 0;
1617 int i;
1618
1619 if (!arg_plain) {
1620
1621 for (i = level - 1; i >= 0; i--) {
1622 len += 2;
1623 if (len > max_len - 3 && !arg_full) {
1624 printf("%s...\n",max_len % 2 ? "" : " ");
1625 return 0;
1626 }
1627 printf("%s", special_glyph(branches & (1 << i) ? TREE_VERTICAL : TREE_SPACE));
1628 }
1629 len += 2;
1630
1631 if (len > max_len - 3 && !arg_full) {
1632 printf("%s...\n",max_len % 2 ? "" : " ");
1633 return 0;
1634 }
1635
1636 printf("%s", special_glyph(last ? TREE_RIGHT : TREE_BRANCH));
1637 }
1638
1639 if (arg_full) {
1640 printf("%s\n", name);
1641 return 0;
1642 }
1643
1644 n = ellipsize(name, max_len-len, 100);
1645 if (!n)
1646 return log_oom();
1647
1648 printf("%s\n", n);
1649 return 0;
1650}
1651
1652static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1653
1654 static const char *dependencies[_DEPENDENCY_MAX] = {
1655 [DEPENDENCY_FORWARD] = "Requires\0"
1656 "Requisite\0"
1657 "Wants\0"
1658 "ConsistsOf\0"
1659 "BindsTo\0",
1660 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1661 "RequisiteOf\0"
1662 "WantedBy\0"
1663 "PartOf\0"
1664 "BoundBy\0",
1665 [DEPENDENCY_AFTER] = "After\0",
1666 [DEPENDENCY_BEFORE] = "Before\0",
1667 };
1668
1669 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1670 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1671 _cleanup_strv_free_ char **ret = NULL;
1672 _cleanup_free_ char *path = NULL;
1673 int r;
1674
1675 assert(bus);
1676 assert(name);
1677 assert(deps);
1678 assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
1679
1680 path = unit_dbus_path_from_name(name);
1681 if (!path)
1682 return log_oom();
1683
1684 r = sd_bus_call_method(
1685 bus,
1686 "org.freedesktop.systemd1",
1687 path,
1688 "org.freedesktop.DBus.Properties",
1689 "GetAll",
1690 &error,
1691 &reply,
1692 "s", "org.freedesktop.systemd1.Unit");
1693 if (r < 0)
1694 return log_error_errno(r, "Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1695
1696 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1697 if (r < 0)
1698 return bus_log_parse_error(r);
1699
1700 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1701 const char *prop;
1702
1703 r = sd_bus_message_read(reply, "s", &prop);
1704 if (r < 0)
1705 return bus_log_parse_error(r);
1706
1707 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1708 r = sd_bus_message_skip(reply, "v");
1709 if (r < 0)
1710 return bus_log_parse_error(r);
1711 } else {
1712
1713 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1714 if (r < 0)
1715 return bus_log_parse_error(r);
1716
1717 r = bus_message_read_strv_extend(reply, &ret);
1718 if (r < 0)
1719 return bus_log_parse_error(r);
1720
1721 r = sd_bus_message_exit_container(reply);
1722 if (r < 0)
1723 return bus_log_parse_error(r);
1724 }
1725
1726 r = sd_bus_message_exit_container(reply);
1727 if (r < 0)
1728 return bus_log_parse_error(r);
1729
1730 }
1731 if (r < 0)
1732 return bus_log_parse_error(r);
1733
1734 r = sd_bus_message_exit_container(reply);
1735 if (r < 0)
1736 return bus_log_parse_error(r);
1737
1738 *deps = strv_uniq(ret);
1739 ret = NULL;
1740
1741 return 0;
1742}
1743
1744static int list_dependencies_compare(const void *_a, const void *_b) {
1745 const char **a = (const char**) _a, **b = (const char**) _b;
1746
1747 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1748 return 1;
1749 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1750 return -1;
1751
1752 return strcasecmp(*a, *b);
1753}
1754
1755static int list_dependencies_one(
1756 sd_bus *bus,
1757 const char *name,
1758 int level,
1759 char ***units,
1760 unsigned int branches) {
1761
1762 _cleanup_strv_free_ char **deps = NULL;
1763 char **c;
1764 int r = 0;
1765
1766 assert(bus);
1767 assert(name);
1768 assert(units);
1769
1770 r = strv_extend(units, name);
1771 if (r < 0)
1772 return log_oom();
1773
1774 r = list_dependencies_get_dependencies(bus, name, &deps);
1775 if (r < 0)
1776 return r;
1777
1778 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1779
1780 STRV_FOREACH(c, deps) {
1781 if (strv_contains(*units, *c)) {
1782 if (!arg_plain) {
1783 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1784 if (r < 0)
1785 return r;
1786 }
1787 continue;
1788 }
1789
1790 if (arg_plain)
1791 printf(" ");
1792 else {
1793 UnitActiveState active_state = _UNIT_ACTIVE_STATE_INVALID;
1794 const char *on;
1795
1796 (void) get_state_one_unit(bus, *c, &active_state);
1797
1798 switch (active_state) {
1799 case UNIT_ACTIVE:
1800 case UNIT_RELOADING:
1801 case UNIT_ACTIVATING:
1802 on = ansi_highlight_green();
1803 break;
1804
1805 case UNIT_INACTIVE:
1806 case UNIT_DEACTIVATING:
1807 on = ansi_normal();
1808 break;
1809
1810 default:
1811 on = ansi_highlight_red();
1812 break;
1813 }
1814
1815 printf("%s%s%s ", on, special_glyph(BLACK_CIRCLE), ansi_normal());
1816 }
1817
1818 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1819 if (r < 0)
1820 return r;
1821
1822 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1823 r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1824 if (r < 0)
1825 return r;
1826 }
1827 }
1828
1829 if (!arg_plain)
1830 strv_remove(*units, name);
1831
1832 return 0;
1833}
1834
1835static int list_dependencies(int argc, char *argv[], void *userdata) {
1836 _cleanup_strv_free_ char **units = NULL;
1837 _cleanup_free_ char *unit = NULL;
1838 const char *u;
1839 sd_bus *bus;
1840 int r;
1841
1842 if (argv[1]) {
1843 r = unit_name_mangle(argv[1], UNIT_NAME_NOGLOB, &unit);
1844 if (r < 0)
1845 return log_error_errno(r, "Failed to mangle unit name: %m");
1846
1847 u = unit;
1848 } else
1849 u = SPECIAL_DEFAULT_TARGET;
1850
1851 r = acquire_bus(BUS_MANAGER, &bus);
1852 if (r < 0)
1853 return r;
1854
1855 pager_open(arg_no_pager, false);
1856
1857 puts(u);
1858
1859 return list_dependencies_one(bus, u, 0, &units, 0);
1860}
1861
1862struct machine_info {
1863 bool is_host;
1864 char *name;
1865 char *state;
1866 char *control_group;
1867 uint32_t n_failed_units;
1868 uint32_t n_jobs;
1869 usec_t timestamp;
1870};
1871
1872static const struct bus_properties_map machine_info_property_map[] = {
1873 { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
1874 { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
1875 { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
1876 { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
1877 { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
1878 {}
1879};
1880
1881static void machine_info_clear(struct machine_info *info) {
1882 assert(info);
1883
1884 free(info->name);
1885 free(info->state);
1886 free(info->control_group);
1887 zero(*info);
1888}
1889
1890static void free_machines_list(struct machine_info *machine_infos, int n) {
1891 int i;
1892
1893 if (!machine_infos)
1894 return;
1895
1896 for (i = 0; i < n; i++)
1897 machine_info_clear(&machine_infos[i]);
1898
1899 free(machine_infos);
1900}
1901
1902static int compare_machine_info(const void *a, const void *b) {
1903 const struct machine_info *u = a, *v = b;
1904
1905 if (u->is_host != v->is_host)
1906 return u->is_host > v->is_host ? -1 : 1;
1907
1908 return strcasecmp(u->name, v->name);
1909}
1910
1911static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1912 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *container = NULL;
1913 int r;
1914
1915 assert(mi);
1916
1917 if (!bus) {
1918 r = sd_bus_open_system_machine(&container, mi->name);
1919 if (r < 0)
1920 return r;
1921
1922 bus = container;
1923 }
1924
1925 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, NULL, mi);
1926 if (r < 0)
1927 return r;
1928
1929 return 0;
1930}
1931
1932static bool output_show_machine(const char *name, char **patterns) {
1933 return strv_fnmatch_or_empty(patterns, name, FNM_NOESCAPE);
1934}
1935
1936static int get_machine_list(
1937 sd_bus *bus,
1938 struct machine_info **_machine_infos,
1939 char **patterns) {
1940
1941 struct machine_info *machine_infos = NULL;
1942 _cleanup_strv_free_ char **m = NULL;
1943 _cleanup_free_ char *hn = NULL;
1944 size_t sz = 0;
1945 char **i;
1946 int c = 0, r;
1947
1948 hn = gethostname_malloc();
1949 if (!hn)
1950 return log_oom();
1951
1952 if (output_show_machine(hn, patterns)) {
1953 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1954 return log_oom();
1955
1956 machine_infos[c].is_host = true;
1957 machine_infos[c].name = hn;
1958 hn = NULL;
1959
1960 (void) get_machine_properties(bus, &machine_infos[c]);
1961 c++;
1962 }
1963
1964 r = sd_get_machine_names(&m);
1965 if (r < 0)
1966 return log_error_errno(r, "Failed to get machine list: %m");
1967
1968 STRV_FOREACH(i, m) {
1969 _cleanup_free_ char *class = NULL;
1970
1971 if (!output_show_machine(*i, patterns))
1972 continue;
1973
1974 sd_machine_get_class(*i, &class);
1975 if (!streq_ptr(class, "container"))
1976 continue;
1977
1978 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1979 free_machines_list(machine_infos, c);
1980 return log_oom();
1981 }
1982
1983 machine_infos[c].is_host = false;
1984 machine_infos[c].name = strdup(*i);
1985 if (!machine_infos[c].name) {
1986 free_machines_list(machine_infos, c);
1987 return log_oom();
1988 }
1989
1990 (void) get_machine_properties(NULL, &machine_infos[c]);
1991 c++;
1992 }
1993
1994 *_machine_infos = machine_infos;
1995 return c;
1996}
1997
1998static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1999 struct machine_info *m;
2000 unsigned
2001 circle_len = 0,
2002 namelen = sizeof("NAME") - 1,
2003 statelen = sizeof("STATE") - 1,
2004 failedlen = sizeof("FAILED") - 1,
2005 jobslen = sizeof("JOBS") - 1;
2006
2007 assert(machine_infos || n == 0);
2008
2009 for (m = machine_infos; m < machine_infos + n; m++) {
2010 namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
2011 statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
2012 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
2013 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
2014
2015 if (!arg_plain && !streq_ptr(m->state, "running"))
2016 circle_len = 2;
2017 }
2018
2019 if (!arg_no_legend) {
2020 if (circle_len > 0)
2021 fputs(" ", stdout);
2022
2023 printf("%-*s %-*s %-*s %-*s\n",
2024 namelen, "NAME",
2025 statelen, "STATE",
2026 failedlen, "FAILED",
2027 jobslen, "JOBS");
2028 }
2029
2030 for (m = machine_infos; m < machine_infos + n; m++) {
2031 const char *on_state = "", *off_state = "";
2032 const char *on_failed = "", *off_failed = "";
2033 bool circle = false;
2034
2035 if (streq_ptr(m->state, "degraded")) {
2036 on_state = ansi_highlight_red();
2037 off_state = ansi_normal();
2038 circle = true;
2039 } else if (!streq_ptr(m->state, "running")) {
2040 on_state = ansi_highlight_yellow();
2041 off_state = ansi_normal();
2042 circle = true;
2043 }
2044
2045 if (m->n_failed_units > 0) {
2046 on_failed = ansi_highlight_red();
2047 off_failed = ansi_normal();
2048 } else
2049 on_failed = off_failed = "";
2050
2051 if (circle_len > 0)
2052 printf("%s%s%s ", on_state, circle ? special_glyph(BLACK_CIRCLE) : " ", off_state);
2053
2054 if (m->is_host)
2055 printf("%-*s (host) %s%-*s%s %s%*" PRIu32 "%s %*" PRIu32 "\n",
2056 (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
2057 on_state, statelen, strna(m->state), off_state,
2058 on_failed, failedlen, m->n_failed_units, off_failed,
2059 jobslen, m->n_jobs);
2060 else
2061 printf("%-*s %s%-*s%s %s%*" PRIu32 "%s %*" PRIu32 "\n",
2062 namelen, strna(m->name),
2063 on_state, statelen, strna(m->state), off_state,
2064 on_failed, failedlen, m->n_failed_units, off_failed,
2065 jobslen, m->n_jobs);
2066 }
2067
2068 if (!arg_no_legend)
2069 printf("\n%u machines listed.\n", n);
2070}
2071
2072static int list_machines(int argc, char *argv[], void *userdata) {
2073 struct machine_info *machine_infos = NULL;
2074 sd_bus *bus;
2075 int r;
2076
2077 if (geteuid() != 0) {
2078 log_error("Must be root.");
2079 return -EPERM;
2080 }
2081
2082 r = acquire_bus(BUS_MANAGER, &bus);
2083 if (r < 0)
2084 return r;
2085
2086 r = get_machine_list(bus, &machine_infos, strv_skip(argv, 1));
2087 if (r < 0)
2088 return r;
2089
2090 pager_open(arg_no_pager, false);
2091
2092 qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
2093 output_machines_list(machine_infos, r);
2094 free_machines_list(machine_infos, r);
2095
2096 return 0;
2097}
2098
2099static int get_default(int argc, char *argv[], void *userdata) {
2100 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2101 _cleanup_free_ char *_path = NULL;
2102 const char *path;
2103 int r;
2104
2105 if (install_client_side()) {
2106 r = unit_file_get_default(arg_scope, arg_root, &_path);
2107 if (r < 0)
2108 return log_error_errno(r, "Failed to get default target: %m");
2109 path = _path;
2110
2111 r = 0;
2112 } else {
2113 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2114 sd_bus *bus;
2115
2116 r = acquire_bus(BUS_MANAGER, &bus);
2117 if (r < 0)
2118 return r;
2119
2120 r = sd_bus_call_method(
2121 bus,
2122 "org.freedesktop.systemd1",
2123 "/org/freedesktop/systemd1",
2124 "org.freedesktop.systemd1.Manager",
2125 "GetDefaultTarget",
2126 &error,
2127 &reply,
2128 NULL);
2129 if (r < 0)
2130 return log_error_errno(r, "Failed to get default target: %s", bus_error_message(&error, r));
2131
2132 r = sd_bus_message_read(reply, "s", &path);
2133 if (r < 0)
2134 return bus_log_parse_error(r);
2135 }
2136
2137 if (path)
2138 printf("%s\n", path);
2139
2140 return 0;
2141}
2142
2143static int set_default(int argc, char *argv[], void *userdata) {
2144 _cleanup_free_ char *unit = NULL;
2145 UnitFileChange *changes = NULL;
2146 unsigned n_changes = 0;
2147 int r;
2148
2149 assert(argc >= 2);
2150 assert(argv);
2151
2152 r = unit_name_mangle_with_suffix(argv[1], UNIT_NAME_NOGLOB, ".target", &unit);
2153 if (r < 0)
2154 return log_error_errno(r, "Failed to mangle unit name: %m");
2155
2156 if (install_client_side()) {
2157 r = unit_file_set_default(arg_scope, UNIT_FILE_FORCE, arg_root, unit, &changes, &n_changes);
2158 unit_file_dump_changes(r, "set default", changes, n_changes, arg_quiet);
2159
2160 if (r > 0)
2161 r = 0;
2162 } else {
2163 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2164 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2165 sd_bus *bus;
2166
2167 polkit_agent_open_if_enabled();
2168
2169 r = acquire_bus(BUS_MANAGER, &bus);
2170 if (r < 0)
2171 return r;
2172
2173 r = sd_bus_call_method(
2174 bus,
2175 "org.freedesktop.systemd1",
2176 "/org/freedesktop/systemd1",
2177 "org.freedesktop.systemd1.Manager",
2178 "SetDefaultTarget",
2179 &error,
2180 &reply,
2181 "sb", unit, 1);
2182 if (r < 0)
2183 return log_error_errno(r, "Failed to set default target: %s", bus_error_message(&error, r));
2184
2185 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes);
2186 if (r < 0)
2187 goto finish;
2188
2189 /* Try to reload if enabled */
2190 if (!arg_no_reload)
2191 r = daemon_reload(argc, argv, userdata);
2192 else
2193 r = 0;
2194 }
2195
2196finish:
2197 unit_file_changes_free(changes, n_changes);
2198
2199 return r;
2200}
2201
2202static int output_waiting_jobs(sd_bus *bus, uint32_t id, const char *method, const char *prefix) {
2203 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2204 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2205 const char *name, *type, *state, *job_path, *unit_path;
2206 uint32_t other_id;
2207 int r;
2208
2209 assert(bus);
2210
2211 r = sd_bus_call_method(
2212 bus,
2213 "org.freedesktop.systemd1",
2214 "/org/freedesktop/systemd1",
2215 "org.freedesktop.systemd1.Manager",
2216 method,
2217 &error,
2218 &reply,
2219 "u", id);
2220 if (r < 0)
2221 return log_debug_errno(r, "Failed to get waiting jobs for job %" PRIu32, id);
2222
2223 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2224 if (r < 0)
2225 return bus_log_parse_error(r);
2226
2227 while ((r = sd_bus_message_read(reply, "(usssoo)", &other_id, &name, &type, &state, &job_path, &unit_path)) > 0)
2228 printf("%s %u (%s/%s)\n", prefix, other_id, name, type);
2229 if (r < 0)
2230 return bus_log_parse_error(r);
2231
2232 r = sd_bus_message_exit_container(reply);
2233 if (r < 0)
2234 return bus_log_parse_error(r);
2235
2236 return 0;
2237}
2238
2239struct job_info {
2240 uint32_t id;
2241 const char *name, *type, *state;
2242};
2243
2244static void output_jobs_list(sd_bus *bus, const struct job_info* jobs, unsigned n, bool skipped) {
2245 unsigned id_len, unit_len, type_len, state_len;
2246 const struct job_info *j;
2247 const char *on, *off;
2248 bool shorten = false;
2249
2250 assert(n == 0 || jobs);
2251
2252 if (n == 0) {
2253 if (!arg_no_legend) {
2254 on = ansi_highlight_green();
2255 off = ansi_normal();
2256
2257 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
2258 }
2259 return;
2260 }
2261
2262 pager_open(arg_no_pager, false);
2263
2264 id_len = strlen("JOB");
2265 unit_len = strlen("UNIT");
2266 type_len = strlen("TYPE");
2267 state_len = strlen("STATE");
2268
2269 for (j = jobs; j < jobs + n; j++) {
2270 uint32_t id = j->id;
2271 assert(j->name && j->type && j->state);
2272
2273 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
2274 unit_len = MAX(unit_len, strlen(j->name));
2275 type_len = MAX(type_len, strlen(j->type));
2276 state_len = MAX(state_len, strlen(j->state));
2277 }
2278
2279 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
2280 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
2281 shorten = true;
2282 }
2283
2284 if (!arg_no_legend)
2285 printf("%*s %-*s %-*s %-*s\n",
2286 id_len, "JOB",
2287 unit_len, "UNIT",
2288 type_len, "TYPE",
2289 state_len, "STATE");
2290
2291 for (j = jobs; j < jobs + n; j++) {
2292 _cleanup_free_ char *e = NULL;
2293
2294 if (streq(j->state, "running")) {
2295 on = ansi_highlight();
2296 off = ansi_normal();
2297 } else
2298 on = off = "";
2299
2300 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
2301 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2302 id_len, j->id,
2303 on, unit_len, e ? e : j->name, off,
2304 type_len, j->type,
2305 on, state_len, j->state, off);
2306
2307 if (arg_jobs_after)
2308 output_waiting_jobs(bus, j->id, "GetJobAfter", "\twaiting for job");
2309 if (arg_jobs_before)
2310 output_waiting_jobs(bus, j->id, "GetJobBefore", "\tblocking job");
2311 }
2312
2313 if (!arg_no_legend) {
2314 on = ansi_highlight();
2315 off = ansi_normal();
2316
2317 printf("\n%s%u jobs listed%s.\n", on, n, off);
2318 }
2319}
2320
2321static bool output_show_job(struct job_info *job, char **patterns) {
2322 return strv_fnmatch_or_empty(patterns, job->name, FNM_NOESCAPE);
2323}
2324
2325static int list_jobs(int argc, char *argv[], void *userdata) {
2326 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2327 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2328 const char *name, *type, *state, *job_path, *unit_path;
2329 _cleanup_free_ struct job_info *jobs = NULL;
2330 size_t size = 0;
2331 unsigned c = 0;
2332 sd_bus *bus;
2333 uint32_t id;
2334 int r;
2335 bool skipped = false;
2336
2337 r = acquire_bus(BUS_MANAGER, &bus);
2338 if (r < 0)
2339 return r;
2340
2341 r = sd_bus_call_method(
2342 bus,
2343 "org.freedesktop.systemd1",
2344 "/org/freedesktop/systemd1",
2345 "org.freedesktop.systemd1.Manager",
2346 "ListJobs",
2347 &error,
2348 &reply,
2349 NULL);
2350 if (r < 0)
2351 return log_error_errno(r, "Failed to list jobs: %s", bus_error_message(&error, r));
2352
2353 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2354 if (r < 0)
2355 return bus_log_parse_error(r);
2356
2357 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
2358 struct job_info job = { id, name, type, state };
2359
2360 if (!output_show_job(&job, strv_skip(argv, 1))) {
2361 skipped = true;
2362 continue;
2363 }
2364
2365 if (!GREEDY_REALLOC(jobs, size, c + 1))
2366 return log_oom();
2367
2368 jobs[c++] = job;
2369 }
2370 if (r < 0)
2371 return bus_log_parse_error(r);
2372
2373 r = sd_bus_message_exit_container(reply);
2374 if (r < 0)
2375 return bus_log_parse_error(r);
2376
2377 pager_open(arg_no_pager, false);
2378
2379 output_jobs_list(bus, jobs, c, skipped);
2380 return 0;
2381}
2382
2383static int cancel_job(int argc, char *argv[], void *userdata) {
2384 sd_bus *bus;
2385 char **name;
2386 int r = 0;
2387
2388 if (argc <= 1)
2389 return trivial_method(argc, argv, userdata);
2390
2391 r = acquire_bus(BUS_MANAGER, &bus);
2392 if (r < 0)
2393 return r;
2394
2395 polkit_agent_open_if_enabled();
2396
2397 STRV_FOREACH(name, strv_skip(argv, 1)) {
2398 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2399 uint32_t id;
2400 int q;
2401
2402 q = safe_atou32(*name, &id);
2403 if (q < 0)
2404 return log_error_errno(q, "Failed to parse job id \"%s\": %m", *name);
2405
2406 q = sd_bus_call_method(
2407 bus,
2408 "org.freedesktop.systemd1",
2409 "/org/freedesktop/systemd1",
2410 "org.freedesktop.systemd1.Manager",
2411 "CancelJob",
2412 &error,
2413 NULL,
2414 "u", id);
2415 if (q < 0) {
2416 log_error_errno(q, "Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, q));
2417 if (r == 0)
2418 r = q;
2419 }
2420 }
2421
2422 return r;
2423}
2424
2425static int need_daemon_reload(sd_bus *bus, const char *unit) {
2426 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2427 const char *path;
2428 int b, r;
2429
2430 /* We ignore all errors here, since this is used to show a
2431 * warning only */
2432
2433 /* We don't use unit_dbus_path_from_name() directly since we
2434 * don't want to load the unit if it isn't loaded. */
2435
2436 r = sd_bus_call_method(
2437 bus,
2438 "org.freedesktop.systemd1",
2439 "/org/freedesktop/systemd1",
2440 "org.freedesktop.systemd1.Manager",
2441 "GetUnit",
2442 NULL,
2443 &reply,
2444 "s", unit);
2445 if (r < 0)
2446 return r;
2447
2448 r = sd_bus_message_read(reply, "o", &path);
2449 if (r < 0)
2450 return r;
2451
2452 r = sd_bus_get_property_trivial(
2453 bus,
2454 "org.freedesktop.systemd1",
2455 path,
2456 "org.freedesktop.systemd1.Unit",
2457 "NeedDaemonReload",
2458 NULL,
2459 'b', &b);
2460 if (r < 0)
2461 return r;
2462
2463 return b;
2464}
2465
2466static void warn_unit_file_changed(const char *name) {
2467 assert(name);
2468
2469 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2470 ansi_highlight_red(),
2471 ansi_normal(),
2472 name,
2473 arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2474}
2475
2476static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **unit_path) {
2477 char **p;
2478
2479 assert(lp);
2480 assert(unit_name);
2481 assert(unit_path);
2482
2483 STRV_FOREACH(p, lp->search_path) {
2484 _cleanup_free_ char *path = NULL, *lpath = NULL;
2485 int r;
2486
2487 path = path_join(NULL, *p, unit_name);
2488 if (!path)
2489 return log_oom();
2490
2491 r = chase_symlinks(path, arg_root, 0, &lpath);
2492 if (r == -ENOENT)
2493 continue;
2494 if (r == -ENOMEM)
2495 return log_oom();
2496 if (r < 0)
2497 return log_error_errno(r, "Failed to access path '%s': %m", path);
2498
2499 *unit_path = lpath;
2500 lpath = NULL;
2501 return 1;
2502 }
2503
2504 return 0;
2505}
2506
2507static int unit_find_paths(
2508 sd_bus *bus,
2509 const char *unit_name,
2510 LookupPaths *lp,
2511 char **fragment_path,
2512 char ***dropin_paths) {
2513
2514 _cleanup_free_ char *path = NULL;
2515 _cleanup_strv_free_ char **dropins = NULL;
2516 int r;
2517
2518 /**
2519 * Finds where the unit is defined on disk. Returns 0 if the unit
2520 * is not found. Returns 1 if it is found, and sets
2521 * - the path to the unit in *path, if it exists on disk,
2522 * - and a strv of existing drop-ins in *dropins,
2523 * if the arg is not NULL and any dropins were found.
2524 */
2525
2526 assert(unit_name);
2527 assert(fragment_path);
2528 assert(lp);
2529
2530 if (!install_client_side() && !unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) {
2531 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2532 _cleanup_free_ char *unit = NULL;
2533
2534 unit = unit_dbus_path_from_name(unit_name);
2535 if (!unit)
2536 return log_oom();
2537
2538 r = sd_bus_get_property_string(
2539 bus,
2540 "org.freedesktop.systemd1",
2541 unit,
2542 "org.freedesktop.systemd1.Unit",
2543 "FragmentPath",
2544 &error,
2545 &path);
2546 if (r < 0)
2547 return log_error_errno(r, "Failed to get FragmentPath: %s", bus_error_message(&error, r));
2548
2549 if (dropin_paths) {
2550 r = sd_bus_get_property_strv(
2551 bus,
2552 "org.freedesktop.systemd1",
2553 unit,
2554 "org.freedesktop.systemd1.Unit",
2555 "DropInPaths",
2556 &error,
2557 &dropins);
2558 if (r < 0)
2559 return log_error_errno(r, "Failed to get DropInPaths: %s", bus_error_message(&error, r));
2560 }
2561 } else {
2562 _cleanup_set_free_ Set *names;
2563 _cleanup_free_ char *template = NULL;
2564
2565 names = set_new(NULL);
2566 if (!names)
2567 return log_oom();
2568
2569 r = unit_file_find_path(lp, unit_name, &path);
2570 if (r < 0)
2571 return r;
2572
2573 if (r == 0) {
2574 r = unit_name_template(unit_name, &template);
2575 if (r < 0 && r != -EINVAL)
2576 return log_error_errno(r, "Failed to determine template name: %m");
2577 if (r >= 0) {
2578 r = unit_file_find_path(lp, template, &path);
2579 if (r < 0)
2580 return r;
2581 }
2582 }
2583
2584 if (path)
2585 /* We found the unit file. If we followed symlinks, this name might be
2586 * different then the unit_name with started with. Look for dropins matching
2587 * that "final" name. */
2588 r = set_put(names, basename(path));
2589 else if (!template)
2590 /* No unit file, let's look for dropins matching the original name.
2591 * systemd has fairly complicated rules (based on unit type and provenience),
2592 * which units are allowed not to have the main unit file. We err on the
2593 * side of including too many files, and always try to load dropins. */
2594 r = set_put(names, unit_name);
2595 else
2596 /* The cases where we allow a unit to exist without the main file are
2597 * never valid for templates. Don't try to load dropins in this case. */
2598 goto not_found;
2599
2600 if (r < 0)
2601 return log_error_errno(r, "Failed to add unit name: %m");
2602
2603 if (dropin_paths) {
2604 r = unit_file_find_dropin_conf_paths(arg_root, lp->search_path,
2605 NULL, names, &dropins);
2606 if (r < 0)
2607 return r;
2608 }
2609 }
2610
2611 r = 0;
2612
2613 if (!isempty(path)) {
2614 *fragment_path = path;
2615 path = NULL;
2616 r = 1;
2617 }
2618
2619 if (dropin_paths && !strv_isempty(dropins)) {
2620 *dropin_paths = dropins;
2621 dropins = NULL;
2622 r = 1;
2623 }
2624 not_found:
2625 if (r == 0 && !arg_force)
2626 log_error("No files found for %s.", unit_name);
2627
2628 return r;
2629}
2630
2631static int get_state_one_unit(sd_bus *bus, const char *name, UnitActiveState *active_state) {
2632 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2633 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2634 _cleanup_free_ char *buf = NULL;
2635 UnitActiveState state;
2636 const char *path;
2637 int r;
2638
2639 assert(name);
2640 assert(active_state);
2641
2642 /* We don't use unit_dbus_path_from_name() directly since we don't want to load the unit unnecessarily, if it
2643 * isn't loaded. */
2644 r = sd_bus_call_method(
2645 bus,
2646 "org.freedesktop.systemd1",
2647 "/org/freedesktop/systemd1",
2648 "org.freedesktop.systemd1.Manager",
2649 "GetUnit",
2650 &error,
2651 &reply,
2652 "s", name);
2653 if (r < 0) {
2654 if (!sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT))
2655 return log_error_errno(r, "Failed to retrieve unit: %s", bus_error_message(&error, r));
2656
2657 /* The unit is currently not loaded, hence say it's "inactive", since all units that aren't loaded are
2658 * considered inactive. */
2659 state = UNIT_INACTIVE;
2660
2661 } else {
2662 r = sd_bus_message_read(reply, "o", &path);
2663 if (r < 0)
2664 return bus_log_parse_error(r);
2665
2666 r = sd_bus_get_property_string(
2667 bus,
2668 "org.freedesktop.systemd1",
2669 path,
2670 "org.freedesktop.systemd1.Unit",
2671 "ActiveState",
2672 &error,
2673 &buf);
2674 if (r < 0)
2675 return log_error_errno(r, "Failed to retrieve unit state: %s", bus_error_message(&error, r));
2676
2677 state = unit_active_state_from_string(buf);
2678 if (state == _UNIT_ACTIVE_STATE_INVALID) {
2679 log_error("Invalid unit state '%s' for: %s", buf, name);
2680 return -EINVAL;
2681 }
2682 }
2683
2684 *active_state = state;
2685 return 0;
2686}
2687
2688static int check_triggering_units(
2689 sd_bus *bus,
2690 const char *name) {
2691
2692 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
2693 _cleanup_free_ char *path = NULL, *n = NULL, *load_state = NULL;
2694 _cleanup_strv_free_ char **triggered_by = NULL;
2695 bool print_warning_label = true;
2696 UnitActiveState active_state;
2697 char **i;
2698 int r;
2699
2700 r = unit_name_mangle(name, UNIT_NAME_NOGLOB, &n);
2701 if (r < 0)
2702 return log_error_errno(r, "Failed to mangle unit name: %m");
2703
2704 path = unit_dbus_path_from_name(n);
2705 if (!path)
2706 return log_oom();
2707
2708 r = sd_bus_get_property_string(
2709 bus,
2710 "org.freedesktop.systemd1",
2711 path,
2712 "org.freedesktop.systemd1.Unit",
2713 "LoadState",
2714 &error,
2715 &load_state);
2716 if (r < 0)
2717 return log_error_errno(r, "Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2718
2719 if (streq(load_state, "masked"))
2720 return 0;
2721
2722 r = sd_bus_get_property_strv(
2723 bus,
2724 "org.freedesktop.systemd1",
2725 path,
2726 "org.freedesktop.systemd1.Unit",
2727 "TriggeredBy",
2728 &error,
2729 &triggered_by);
2730 if (r < 0)
2731 return log_error_errno(r, "Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2732
2733 STRV_FOREACH(i, triggered_by) {
2734 r = get_state_one_unit(bus, *i, &active_state);
2735 if (r < 0)
2736 return r;
2737
2738 if (!IN_SET(active_state, UNIT_ACTIVE, UNIT_RELOADING))
2739 continue;
2740
2741 if (print_warning_label) {
2742 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2743 print_warning_label = false;
2744 }
2745
2746 log_warning(" %s", *i);
2747 }
2748
2749 return 0;
2750}
2751
2752static const struct {
2753 const char *verb;
2754 const char *method;
2755} unit_actions[] = {
2756 { "start", "StartUnit" },
2757 { "stop", "StopUnit" },
2758 { "condstop", "StopUnit" },
2759 { "reload", "ReloadUnit" },
2760 { "restart", "RestartUnit" },
2761 { "try-restart", "TryRestartUnit" },
2762 { "condrestart", "TryRestartUnit" },
2763 { "reload-or-restart", "ReloadOrRestartUnit" },
2764 { "try-reload-or-restart", "ReloadOrTryRestartUnit" },
2765 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2766 { "condreload", "ReloadOrTryRestartUnit" },
2767 { "force-reload", "ReloadOrTryRestartUnit" }
2768};
2769
2770static const char *verb_to_method(const char *verb) {
2771 uint i;
2772
2773 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2774 if (streq_ptr(unit_actions[i].verb, verb))
2775 return unit_actions[i].method;
2776
2777 return "StartUnit";
2778}
2779
2780static const char *method_to_verb(const char *method) {
2781 uint i;
2782
2783 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2784 if (streq_ptr(unit_actions[i].method, method))
2785 return unit_actions[i].verb;
2786
2787 return "n/a";
2788}
2789
2790typedef struct {
2791 sd_bus_slot *match;
2792 sd_event *event;
2793 Set *unit_paths;
2794 bool any_failed;
2795} WaitContext;
2796
2797static void wait_context_free(WaitContext *c) {
2798 c->match = sd_bus_slot_unref(c->match);
2799 c->event = sd_event_unref(c->event);
2800 c->unit_paths = set_free_free(c->unit_paths);
2801}
2802
2803static int on_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
2804 WaitContext *c = userdata;
2805 const char *path;
2806 int r;
2807
2808 path = sd_bus_message_get_path(m);
2809 if (!set_contains(c->unit_paths, path))
2810 return 0;
2811
2812 /* Check if ActiveState changed to inactive/failed */
2813 /* (s interface, a{sv} changed_properties, as invalidated_properties) */
2814 r = sd_bus_message_skip(m, "s");
2815 if (r < 0)
2816 return bus_log_parse_error(r);
2817
2818 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
2819 if (r < 0)
2820 return bus_log_parse_error(r);
2821
2822 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
2823 const char *s;
2824
2825 r = sd_bus_message_read(m, "s", &s);
2826 if (r < 0)
2827 return bus_log_parse_error(r);
2828
2829 if (streq(s, "ActiveState")) {
2830 bool is_failed;
2831
2832 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, "s");
2833 if (r < 0)
2834 return bus_log_parse_error(r);
2835
2836 r = sd_bus_message_read(m, "s", &s);
2837 if (r < 0)
2838 return bus_log_parse_error(r);
2839
2840 is_failed = streq(s, "failed");
2841 if (streq(s, "inactive") || is_failed) {
2842 log_debug("%s became %s, dropping from --wait tracking", path, s);
2843 free(set_remove(c->unit_paths, path));
2844 c->any_failed = c->any_failed || is_failed;
2845 } else
2846 log_debug("ActiveState on %s changed to %s", path, s);
2847
2848 break; /* no need to dissect the rest of the message */
2849 } else {
2850 /* other property */
2851 r = sd_bus_message_skip(m, "v");
2852 if (r < 0)
2853 return bus_log_parse_error(r);
2854 }
2855 r = sd_bus_message_exit_container(m);
2856 if (r < 0)
2857 return bus_log_parse_error(r);
2858 }
2859 if (r < 0)
2860 return bus_log_parse_error(r);
2861
2862 if (set_isempty(c->unit_paths))
2863 sd_event_exit(c->event, EXIT_SUCCESS);
2864
2865 return 0;
2866}
2867
2868static int start_unit_one(
2869 sd_bus *bus,
2870 const char *method,
2871 const char *name,
2872 const char *mode,
2873 sd_bus_error *error,
2874 BusWaitForJobs *w,
2875 WaitContext *wait_context) {
2876
2877 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2878 const char *path;
2879 int r;
2880
2881 assert(method);
2882 assert(name);
2883 assert(mode);
2884 assert(error);
2885
2886 if (wait_context) {
2887 _cleanup_free_ char *unit_path = NULL;
2888 const char* mt;
2889
2890 log_debug("Watching for property changes of %s", name);
2891 r = sd_bus_call_method(
2892 bus,
2893 "org.freedesktop.systemd1",
2894 "/org/freedesktop/systemd1",
2895 "org.freedesktop.systemd1.Manager",
2896 "RefUnit",
2897 error,
2898 NULL,
2899 "s", name);
2900 if (r < 0)
2901 return log_error_errno(r, "Failed to RefUnit %s: %s", name, bus_error_message(error, r));
2902
2903 unit_path = unit_dbus_path_from_name(name);
2904 if (!unit_path)
2905 return log_oom();
2906
2907 r = set_put_strdup(wait_context->unit_paths, unit_path);
2908 if (r < 0)
2909 return log_error_errno(r, "Failed to add unit path %s to set: %m", unit_path);
2910
2911 mt = strjoina("type='signal',"
2912 "interface='org.freedesktop.DBus.Properties',"
2913 "path='", unit_path, "',"
2914 "member='PropertiesChanged'");
2915 r = sd_bus_add_match(bus, &wait_context->match, mt, on_properties_changed, wait_context);
2916 if (r < 0)
2917 return log_error_errno(r, "Failed to add match for PropertiesChanged signal: %m");
2918 }
2919
2920 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2921
2922 r = sd_bus_call_method(
2923 bus,
2924 "org.freedesktop.systemd1",
2925 "/org/freedesktop/systemd1",
2926 "org.freedesktop.systemd1.Manager",
2927 method,
2928 error,
2929 &reply,
2930 "ss", name, mode);
2931 if (r < 0) {
2932 const char *verb;
2933
2934 /* There's always a fallback possible for legacy actions. */
2935 if (arg_action != ACTION_SYSTEMCTL)
2936 return r;
2937
2938 verb = method_to_verb(method);
2939
2940 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2941
2942 if (!sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) &&
2943 !sd_bus_error_has_name(error, BUS_ERROR_UNIT_MASKED))
2944 log_error("See %s logs and 'systemctl%s status%s %s' for details.",
2945 arg_scope == UNIT_FILE_SYSTEM ? "system" : "user",
2946 arg_scope == UNIT_FILE_SYSTEM ? "" : " --user",
2947 name[0] == '-' ? " --" : "",
2948 name);
2949
2950 return r;
2951 }
2952
2953 r = sd_bus_message_read(reply, "o", &path);
2954 if (r < 0)
2955 return bus_log_parse_error(r);
2956
2957 if (need_daemon_reload(bus, name) > 0)
2958 warn_unit_file_changed(name);
2959
2960 if (w) {
2961 log_debug("Adding %s to the set", path);
2962 r = bus_wait_for_jobs_add(w, path);
2963 if (r < 0)
2964 return log_oom();
2965 }
2966
2967 return 0;
2968}
2969
2970static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2971 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2972 char **name;
2973 int r, i;
2974
2975 assert(bus);
2976 assert(ret);
2977
2978 STRV_FOREACH(name, names) {
2979 char *t;
2980
2981 if (suffix)
2982 r = unit_name_mangle_with_suffix(*name, UNIT_NAME_GLOB, suffix, &t);
2983 else
2984 r = unit_name_mangle(*name, UNIT_NAME_GLOB, &t);
2985 if (r < 0)
2986 return log_error_errno(r, "Failed to mangle name: %m");
2987
2988 if (string_is_glob(t))
2989 r = strv_consume(&globs, t);
2990 else
2991 r = strv_consume(&mangled, t);
2992 if (r < 0)
2993 return log_oom();
2994 }
2995
2996 /* Query the manager only if any of the names are a glob, since
2997 * this is fairly expensive */
2998 if (!strv_isempty(globs)) {
2999 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3000 _cleanup_free_ UnitInfo *unit_infos = NULL;
3001 size_t allocated, n;
3002
3003 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
3004 if (r < 0)
3005 return r;
3006
3007 n = strv_length(mangled);
3008 allocated = n + 1;
3009
3010 for (i = 0; i < r; i++) {
3011 if (!GREEDY_REALLOC(mangled, allocated, n+2))
3012 return log_oom();
3013
3014 mangled[n] = strdup(unit_infos[i].id);
3015 if (!mangled[n])
3016 return log_oom();
3017
3018 mangled[++n] = NULL;
3019 }
3020 }
3021
3022 *ret = mangled;
3023 mangled = NULL; /* do not free */
3024
3025 return 0;
3026}
3027
3028static const struct {
3029 const char *target;
3030 const char *verb;
3031 const char *mode;
3032} action_table[_ACTION_MAX] = {
3033 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
3034 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
3035 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
3036 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
3037 [ACTION_RUNLEVEL2] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
3038 [ACTION_RUNLEVEL3] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
3039 [ACTION_RUNLEVEL4] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
3040 [ACTION_RUNLEVEL5] = { SPECIAL_GRAPHICAL_TARGET, NULL, "isolate" },
3041 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
3042 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
3043 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
3044 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
3045 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
3046 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
3047 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
3048};
3049
3050static enum action verb_to_action(const char *verb) {
3051 enum action i;
3052
3053 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
3054 if (streq_ptr(action_table[i].verb, verb))
3055 return i;
3056
3057 return _ACTION_INVALID;
3058}
3059
3060static int start_unit(int argc, char *argv[], void *userdata) {
3061 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
3062 const char *method, *mode, *one_name, *suffix = NULL;
3063 _cleanup_strv_free_ char **names = NULL;
3064 sd_bus *bus;
3065 _cleanup_(wait_context_free) WaitContext wait_context = {};
3066 char **name;
3067 int r = 0;
3068
3069 if (arg_wait && !strstr(argv[0], "start")) {
3070 log_error("--wait may only be used with a command that starts units.");
3071 return -EINVAL;
3072 }
3073
3074 /* we cannot do sender tracking on the private bus, so we need the full
3075 * one for RefUnit to implement --wait */
3076 r = acquire_bus(arg_wait ? BUS_FULL : BUS_MANAGER, &bus);
3077 if (r < 0)
3078 return r;
3079
3080 ask_password_agent_open_if_enabled();
3081 polkit_agent_open_if_enabled();
3082
3083 if (arg_action == ACTION_SYSTEMCTL) {
3084 enum action action;
3085
3086 method = verb_to_method(argv[0]);
3087 action = verb_to_action(argv[0]);
3088
3089 if (streq(argv[0], "isolate")) {
3090 mode = "isolate";
3091 suffix = ".target";
3092 } else
3093 mode = action_table[action].mode ?: arg_job_mode;
3094
3095 one_name = action_table[action].target;
3096 } else {
3097 assert(arg_action < ELEMENTSOF(action_table));
3098 assert(action_table[arg_action].target);
3099
3100 method = "StartUnit";
3101
3102 mode = action_table[arg_action].mode;
3103 one_name = action_table[arg_action].target;
3104 }
3105
3106 if (one_name)
3107 names = strv_new(one_name, NULL);
3108 else {
3109 r = expand_names(bus, strv_skip(argv, 1), suffix, &names);
3110 if (r < 0)
3111 return log_error_errno(r, "Failed to expand names: %m");
3112 }
3113
3114 if (!arg_no_block) {
3115 r = bus_wait_for_jobs_new(bus, &w);
3116 if (r < 0)
3117 return log_error_errno(r, "Could not watch jobs: %m");
3118 }
3119
3120 if (arg_wait) {
3121 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3122
3123 wait_context.unit_paths = set_new(&string_hash_ops);
3124 if (!wait_context.unit_paths)
3125 return log_oom();
3126
3127 r = sd_bus_call_method(
3128 bus,
3129 "org.freedesktop.systemd1",
3130 "/org/freedesktop/systemd1",
3131 "org.freedesktop.systemd1.Manager",
3132 "Subscribe",
3133 &error,
3134 NULL, NULL);
3135 if (r < 0)
3136 return log_error_errno(r, "Failed to enable subscription: %s", bus_error_message(&error, r));
3137 r = sd_event_default(&wait_context.event);
3138 if (r < 0)
3139 return log_error_errno(r, "Failed to allocate event loop: %m");
3140 r = sd_bus_attach_event(bus, wait_context.event, 0);
3141 if (r < 0)
3142 return log_error_errno(r, "Failed to attach bus to event loop: %m");
3143 }
3144
3145 STRV_FOREACH(name, names) {
3146 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3147 int q;
3148
3149 q = start_unit_one(bus, method, *name, mode, &error, w, arg_wait ? &wait_context : NULL);
3150 if (r >= 0 && q < 0)
3151 r = translate_bus_error_to_exit_status(q, &error);
3152 }
3153
3154 if (!arg_no_block) {
3155 int q, arg_count = 0;
3156 const char* extra_args[4] = {};
3157
3158 if (arg_scope != UNIT_FILE_SYSTEM)
3159 extra_args[arg_count++] = "--user";
3160
3161 assert(IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_REMOTE, BUS_TRANSPORT_MACHINE));
3162 if (arg_transport == BUS_TRANSPORT_REMOTE) {
3163 extra_args[arg_count++] = "-H";
3164 extra_args[arg_count++] = arg_host;
3165 } else if (arg_transport == BUS_TRANSPORT_MACHINE) {
3166 extra_args[arg_count++] = "-M";
3167 extra_args[arg_count++] = arg_host;
3168 }
3169
3170 q = bus_wait_for_jobs(w, arg_quiet, extra_args);
3171 if (q < 0)
3172 return q;
3173
3174 /* When stopping units, warn if they can still be triggered by
3175 * another active unit (socket, path, timer) */
3176 if (!arg_quiet && streq(method, "StopUnit"))
3177 STRV_FOREACH(name, names)
3178 check_triggering_units(bus, *name);
3179 }
3180
3181 if (r >= 0 && arg_wait) {
3182 int q;
3183 q = sd_event_loop(wait_context.event);
3184 if (q < 0)
3185 return log_error_errno(q, "Failed to run event loop: %m");
3186 if (wait_context.any_failed)
3187 r = EXIT_FAILURE;
3188 }
3189
3190 return r;
3191}
3192
3193static int logind_set_wall_message(void) {
3194#ifdef HAVE_LOGIND
3195 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3196 sd_bus *bus;
3197 _cleanup_free_ char *m = NULL;
3198 int r;
3199
3200 r = acquire_bus(BUS_FULL, &bus);
3201 if (r < 0)
3202 return r;
3203
3204 m = strv_join(arg_wall, " ");
3205 if (!m)
3206 return log_oom();
3207
3208 r = sd_bus_call_method(
3209 bus,
3210 "org.freedesktop.login1",
3211 "/org/freedesktop/login1",
3212 "org.freedesktop.login1.Manager",
3213 "SetWallMessage",
3214 &error,
3215 NULL,
3216 "sb",
3217 m,
3218 !arg_no_wall);
3219
3220 if (r < 0)
3221 return log_warning_errno(r, "Failed to set wall message, ignoring: %s", bus_error_message(&error, r));
3222
3223#endif
3224 return 0;
3225}
3226
3227/* Ask systemd-logind, which might grant access to unprivileged users
3228 * through PolicyKit */
3229static int logind_reboot(enum action a) {
3230#ifdef HAVE_LOGIND
3231 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3232 const char *method, *description;
3233 sd_bus *bus;
3234 int r;
3235
3236 r = acquire_bus(BUS_FULL, &bus);
3237 if (r < 0)
3238 return r;
3239
3240 switch (a) {
3241
3242 case ACTION_REBOOT:
3243 method = "Reboot";
3244 description = "reboot system";
3245 break;
3246
3247 case ACTION_POWEROFF:
3248 method = "PowerOff";
3249 description = "power off system";
3250 break;
3251
3252 case ACTION_SUSPEND:
3253 method = "Suspend";
3254 description = "suspend system";
3255 break;
3256
3257 case ACTION_HIBERNATE:
3258 method = "Hibernate";
3259 description = "hibernate system";
3260 break;
3261
3262 case ACTION_HYBRID_SLEEP:
3263 method = "HybridSleep";
3264 description = "put system into hybrid sleep";
3265 break;
3266
3267 default:
3268 return -EINVAL;
3269 }
3270
3271 polkit_agent_open_if_enabled();
3272 (void) logind_set_wall_message();
3273
3274 r = sd_bus_call_method(
3275 bus,
3276 "org.freedesktop.login1",
3277 "/org/freedesktop/login1",
3278 "org.freedesktop.login1.Manager",
3279 method,
3280 &error,
3281 NULL,
3282 "b", arg_ask_password);
3283 if (r < 0)
3284 return log_error_errno(r, "Failed to %s via logind: %s", description, bus_error_message(&error, r));
3285
3286 return 0;
3287#else
3288 return -ENOSYS;
3289#endif
3290}
3291
3292static int logind_check_inhibitors(enum action a) {
3293#ifdef HAVE_LOGIND
3294 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3295 _cleanup_strv_free_ char **sessions = NULL;
3296 const char *what, *who, *why, *mode;
3297 uint32_t uid, pid;
3298 sd_bus *bus;
3299 unsigned c = 0;
3300 char **s;
3301 int r;
3302
3303 if (arg_ignore_inhibitors || arg_force > 0)
3304 return 0;
3305
3306 if (arg_when > 0)
3307 return 0;
3308
3309 if (geteuid() == 0)
3310 return 0;
3311
3312 if (!on_tty())
3313 return 0;
3314
3315 if (arg_transport != BUS_TRANSPORT_LOCAL)
3316 return 0;
3317
3318 r = acquire_bus(BUS_FULL, &bus);
3319 if (r < 0)
3320 return r;
3321
3322 r = sd_bus_call_method(
3323 bus,
3324 "org.freedesktop.login1",
3325 "/org/freedesktop/login1",
3326 "org.freedesktop.login1.Manager",
3327 "ListInhibitors",
3328 NULL,
3329 &reply,
3330 NULL);
3331 if (r < 0)
3332 /* If logind is not around, then there are no inhibitors... */
3333 return 0;
3334
3335 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
3336 if (r < 0)
3337 return bus_log_parse_error(r);
3338
3339 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
3340 _cleanup_free_ char *comm = NULL, *user = NULL;
3341 _cleanup_strv_free_ char **sv = NULL;
3342
3343 if (!streq(mode, "block"))
3344 continue;
3345
3346 sv = strv_split(what, ":");
3347 if (!sv)
3348 return log_oom();
3349
3350 if ((pid_t) pid < 0)
3351 return log_error_errno(ERANGE, "Bad PID %"PRIu32": %m", pid);
3352
3353 if (!strv_contains(sv,
3354 IN_SET(a,
3355 ACTION_HALT,
3356 ACTION_POWEROFF,
3357 ACTION_REBOOT,
3358 ACTION_KEXEC) ? "shutdown" : "sleep"))
3359 continue;
3360
3361 get_process_comm(pid, &comm);
3362 user = uid_to_name(uid);
3363
3364 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
3365 who, (pid_t) pid, strna(comm), strna(user), why);
3366
3367 c++;
3368 }
3369 if (r < 0)
3370 return bus_log_parse_error(r);
3371
3372 r = sd_bus_message_exit_container(reply);
3373 if (r < 0)
3374 return bus_log_parse_error(r);
3375
3376 /* Check for current sessions */
3377 sd_get_sessions(&sessions);
3378 STRV_FOREACH(s, sessions) {
3379 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
3380
3381 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
3382 continue;
3383
3384 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
3385 continue;
3386
3387 if (sd_session_get_type(*s, &type) < 0 || !STR_IN_SET(type, "x11", "tty"))
3388 continue;
3389
3390 sd_session_get_tty(*s, &tty);
3391 sd_session_get_seat(*s, &seat);
3392 sd_session_get_service(*s, &service);
3393 user = uid_to_name(uid);
3394
3395 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
3396 c++;
3397 }
3398
3399 if (c <= 0)
3400 return 0;
3401
3402 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3403 action_table[a].verb);
3404
3405 return -EPERM;
3406#else
3407 return 0;
3408#endif
3409}
3410
3411static int logind_prepare_firmware_setup(void) {
3412#ifdef HAVE_LOGIND
3413 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3414 sd_bus *bus;
3415 int r;
3416
3417 r = acquire_bus(BUS_FULL, &bus);
3418 if (r < 0)
3419 return r;
3420
3421 r = sd_bus_call_method(
3422 bus,
3423 "org.freedesktop.login1",
3424 "/org/freedesktop/login1",
3425 "org.freedesktop.login1.Manager",
3426 "SetRebootToFirmwareSetup",
3427 &error,
3428 NULL,
3429 "b", true);
3430 if (r < 0)
3431 return log_error_errno(r, "Cannot indicate to EFI to boot into setup mode: %s", bus_error_message(&error, r));
3432
3433 return 0;
3434#else
3435 log_error("Cannot remotely indicate to EFI to boot into setup mode.");
3436 return -ENOSYS;
3437#endif
3438}
3439
3440static int prepare_firmware_setup(void) {
3441 int r;
3442
3443 if (!arg_firmware_setup)
3444 return 0;
3445
3446 if (arg_transport == BUS_TRANSPORT_LOCAL) {
3447
3448 r = efi_set_reboot_to_firmware(true);
3449 if (r < 0)
3450 log_debug_errno(r, "Cannot indicate to EFI to boot into setup mode, will retry via logind: %m");
3451 else
3452 return r;
3453 }
3454
3455 return logind_prepare_firmware_setup();
3456}
3457
3458static int set_exit_code(uint8_t code) {
3459 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3460 sd_bus *bus;
3461 int r;
3462
3463 r = acquire_bus(BUS_MANAGER, &bus);
3464 if (r < 0)
3465 return r;
3466
3467 r = sd_bus_call_method(
3468 bus,
3469 "org.freedesktop.systemd1",
3470 "/org/freedesktop/systemd1",
3471 "org.freedesktop.systemd1.Manager",
3472 "SetExitCode",
3473 &error,
3474 NULL,
3475 "y", code);
3476 if (r < 0)
3477 return log_error_errno(r, "Failed to set exit code: %s", bus_error_message(&error, r));
3478
3479 return 0;
3480}
3481
3482static int start_special(int argc, char *argv[], void *userdata) {
3483 enum action a;
3484 int r;
3485
3486 assert(argv);
3487
3488 a = verb_to_action(argv[0]);
3489
3490 r = logind_check_inhibitors(a);
3491 if (r < 0)
3492 return r;
3493
3494 if (arg_force >= 2 && geteuid() != 0) {
3495 log_error("Must be root.");
3496 return -EPERM;
3497 }
3498
3499 r = prepare_firmware_setup();
3500 if (r < 0)
3501 return r;
3502
3503 if (a == ACTION_REBOOT && argc > 1) {
3504 r = update_reboot_parameter_and_warn(argv[1]);
3505 if (r < 0)
3506 return r;
3507
3508 } else if (a == ACTION_EXIT && argc > 1) {
3509 uint8_t code;
3510
3511 /* If the exit code is not given on the command line,
3512 * don't reset it to zero: just keep it as it might
3513 * have been set previously. */
3514
3515 r = safe_atou8(argv[1], &code);
3516 if (r < 0)
3517 return log_error_errno(r, "Invalid exit code.");
3518
3519 r = set_exit_code(code);
3520 if (r < 0)
3521 return r;
3522 }
3523
3524 if (arg_force >= 2 &&
3525 IN_SET(a,
3526 ACTION_HALT,
3527 ACTION_POWEROFF,
3528 ACTION_REBOOT))
3529 return halt_now(a);
3530
3531 if (arg_force >= 1 &&
3532 IN_SET(a,
3533 ACTION_HALT,
3534 ACTION_POWEROFF,
3535 ACTION_REBOOT,
3536 ACTION_KEXEC,
3537 ACTION_EXIT))
3538 return trivial_method(argc, argv, userdata);
3539
3540 /* First try logind, to allow authentication with polkit */
3541 if (IN_SET(a,
3542 ACTION_POWEROFF,
3543 ACTION_REBOOT,
3544 ACTION_SUSPEND,
3545 ACTION_HIBERNATE,
3546 ACTION_HYBRID_SLEEP)) {
3547 r = logind_reboot(a);
3548 if (r >= 0)
3549 return r;
3550 if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS))
3551 /* requested operation is not supported or already in progress */
3552 return r;
3553
3554 /* On all other errors, try low-level operation */
3555 }
3556
3557 return start_unit(argc, argv, userdata);
3558}
3559
3560static int start_system_special(int argc, char *argv[], void *userdata) {
3561 /* Like start_special above, but raises an error when running in user mode */
3562
3563 if (arg_scope != UNIT_FILE_SYSTEM) {
3564 log_error("Bad action for %s mode.",
3565 arg_scope == UNIT_FILE_GLOBAL ? "--global" : "--user");
3566 return -EINVAL;
3567 }
3568
3569 return start_special(argc, argv, userdata);
3570}
3571
3572static int check_unit_generic(int code, const UnitActiveState good_states[], int nb_states, char **args) {
3573 _cleanup_strv_free_ char **names = NULL;
3574 UnitActiveState active_state;
3575 sd_bus *bus;
3576 char **name;
3577 int r, i;
3578 bool found = false;
3579
3580 r = acquire_bus(BUS_MANAGER, &bus);
3581 if (r < 0)
3582 return r;
3583
3584 r = expand_names(bus, args, NULL, &names);
3585 if (r < 0)
3586 return log_error_errno(r, "Failed to expand names: %m");
3587
3588 STRV_FOREACH(name, names) {
3589 r = get_state_one_unit(bus, *name, &active_state);
3590 if (r < 0)
3591 return r;
3592
3593 if (!arg_quiet)
3594 puts(unit_active_state_to_string(active_state));
3595
3596 for (i = 0; i < nb_states; ++i)
3597 if (good_states[i] == active_state)
3598 found = true;
3599 }
3600
3601 /* use the given return code for the case that we won't find
3602 * any unit which matches the list */
3603 return found ? 0 : code;
3604}
3605
3606static int check_unit_active(int argc, char *argv[], void *userdata) {
3607 const UnitActiveState states[] = { UNIT_ACTIVE, UNIT_RELOADING };
3608 /* According to LSB: 3, "program is not running" */
3609 return check_unit_generic(EXIT_PROGRAM_NOT_RUNNING, states, ELEMENTSOF(states), strv_skip(argv, 1));
3610}
3611
3612static int check_unit_failed(int argc, char *argv[], void *userdata) {
3613 const UnitActiveState states[] = { UNIT_FAILED };
3614 return check_unit_generic(EXIT_PROGRAM_DEAD_AND_PID_EXISTS, states, ELEMENTSOF(states), strv_skip(argv, 1));
3615}
3616
3617static int kill_unit(int argc, char *argv[], void *userdata) {
3618 _cleanup_strv_free_ char **names = NULL;
3619 char *kill_who = NULL, **name;
3620 sd_bus *bus;
3621 int r, q;
3622
3623 r = acquire_bus(BUS_MANAGER, &bus);
3624 if (r < 0)
3625 return r;
3626
3627 polkit_agent_open_if_enabled();
3628
3629 if (!arg_kill_who)
3630 arg_kill_who = "all";
3631
3632 /* --fail was specified */
3633 if (streq(arg_job_mode, "fail"))
3634 kill_who = strjoina(arg_kill_who, "-fail");
3635
3636 r = expand_names(bus, strv_skip(argv, 1), NULL, &names);
3637 if (r < 0)
3638 return log_error_errno(r, "Failed to expand names: %m");
3639
3640 STRV_FOREACH(name, names) {
3641 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3642
3643 q = sd_bus_call_method(
3644 bus,
3645 "org.freedesktop.systemd1",
3646 "/org/freedesktop/systemd1",
3647 "org.freedesktop.systemd1.Manager",
3648 "KillUnit",
3649 &error,
3650 NULL,
3651 "ssi", *name, kill_who ? kill_who : arg_kill_who, arg_signal);
3652 if (q < 0) {
3653 log_error_errno(q, "Failed to kill unit %s: %s", *name, bus_error_message(&error, q));
3654 if (r == 0)
3655 r = q;
3656 }
3657 }
3658
3659 return r;
3660}
3661
3662typedef struct ExecStatusInfo {
3663 char *name;
3664
3665 char *path;
3666 char **argv;
3667
3668 bool ignore;
3669
3670 usec_t start_timestamp;
3671 usec_t exit_timestamp;
3672 pid_t pid;
3673 int code;
3674 int status;
3675
3676 LIST_FIELDS(struct ExecStatusInfo, exec);
3677} ExecStatusInfo;
3678
3679static void exec_status_info_free(ExecStatusInfo *i) {
3680 assert(i);
3681
3682 free(i->name);
3683 free(i->path);
3684 strv_free(i->argv);
3685 free(i);
3686}
3687
3688static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3689 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3690 const char *path;
3691 uint32_t pid;
3692 int32_t code, status;
3693 int ignore, r;
3694
3695 assert(m);
3696 assert(i);
3697
3698 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3699 if (r < 0)
3700 return bus_log_parse_error(r);
3701 else if (r == 0)
3702 return 0;
3703
3704 r = sd_bus_message_read(m, "s", &path);
3705 if (r < 0)
3706 return bus_log_parse_error(r);
3707
3708 i->path = strdup(path);
3709 if (!i->path)
3710 return log_oom();
3711
3712 r = sd_bus_message_read_strv(m, &i->argv);
3713 if (r < 0)
3714 return bus_log_parse_error(r);
3715
3716 r = sd_bus_message_read(m,
3717 "bttttuii",
3718 &ignore,
3719 &start_timestamp, &start_timestamp_monotonic,
3720 &exit_timestamp, &exit_timestamp_monotonic,
3721 &pid,
3722 &code, &status);
3723 if (r < 0)
3724 return bus_log_parse_error(r);
3725
3726 i->ignore = ignore;
3727 i->start_timestamp = (usec_t) start_timestamp;
3728 i->exit_timestamp = (usec_t) exit_timestamp;
3729 i->pid = (pid_t) pid;
3730 i->code = code;
3731 i->status = status;
3732
3733 r = sd_bus_message_exit_container(m);
3734 if (r < 0)
3735 return bus_log_parse_error(r);
3736
3737 return 1;
3738}
3739
3740typedef struct UnitCondition {
3741 char *name;
3742 char *param;
3743 bool trigger;
3744 bool negate;
3745 int tristate;
3746
3747 LIST_FIELDS(struct UnitCondition, conditions);
3748} UnitCondition;
3749
3750static void unit_condition_free(UnitCondition *c) {
3751 if (!c)
3752 return;
3753
3754 free(c->name);
3755 free(c->param);
3756 free(c);
3757}
3758
3759DEFINE_TRIVIAL_CLEANUP_FUNC(UnitCondition*, unit_condition_free);
3760
3761typedef struct UnitStatusInfo {
3762 const char *id;
3763 const char *load_state;
3764 const char *active_state;
3765 const char *sub_state;
3766 const char *unit_file_state;
3767 const char *unit_file_preset;
3768
3769 const char *description;
3770 const char *following;
3771
3772 char **documentation;
3773
3774 const char *fragment_path;
3775 const char *source_path;
3776 const char *control_group;
3777
3778 char **dropin_paths;
3779
3780 const char *load_error;
3781 const char *result;
3782
3783 usec_t inactive_exit_timestamp;
3784 usec_t inactive_exit_timestamp_monotonic;
3785 usec_t active_enter_timestamp;
3786 usec_t active_exit_timestamp;
3787 usec_t inactive_enter_timestamp;
3788
3789 bool need_daemon_reload;
3790 bool transient;
3791
3792 /* Service */
3793 pid_t main_pid;
3794 pid_t control_pid;
3795 const char *status_text;
3796 const char *pid_file;
3797 bool running:1;
3798 int status_errno;
3799
3800 usec_t start_timestamp;
3801 usec_t exit_timestamp;
3802
3803 int exit_code, exit_status;
3804
3805 usec_t condition_timestamp;
3806 bool condition_result;
3807 LIST_HEAD(UnitCondition, conditions);
3808
3809 usec_t assert_timestamp;
3810 bool assert_result;
3811 bool failed_assert_trigger;
3812 bool failed_assert_negate;
3813 const char *failed_assert;
3814 const char *failed_assert_parameter;
3815
3816 /* Socket */
3817 unsigned n_accepted;
3818 unsigned n_connections;
3819 bool accept;
3820
3821 /* Pairs of type, path */
3822 char **listen;
3823
3824 /* Device */
3825 const char *sysfs_path;
3826
3827 /* Mount, Automount */
3828 const char *where;
3829
3830 /* Swap */
3831 const char *what;
3832
3833 /* CGroup */
3834 uint64_t memory_current;
3835 uint64_t memory_low;
3836 uint64_t memory_high;
3837 uint64_t memory_max;
3838 uint64_t memory_swap_max;
3839 uint64_t memory_limit;
3840 uint64_t cpu_usage_nsec;
3841 uint64_t tasks_current;
3842 uint64_t tasks_max;
3843
3844 LIST_HEAD(ExecStatusInfo, exec);
3845} UnitStatusInfo;
3846
3847static void unit_status_info_free(UnitStatusInfo *info) {
3848 ExecStatusInfo *p;
3849 UnitCondition *c;
3850
3851 strv_free(info->documentation);
3852 strv_free(info->dropin_paths);
3853 strv_free(info->listen);
3854
3855 while ((c = info->conditions)) {
3856 LIST_REMOVE(conditions, info->conditions, c);
3857 unit_condition_free(c);
3858 }
3859
3860 while ((p = info->exec)) {
3861 LIST_REMOVE(exec, info->exec, p);
3862 exec_status_info_free(p);
3863 }
3864}
3865
3866static void print_status_info(
3867 sd_bus *bus,
3868 UnitStatusInfo *i,
3869 bool *ellipsized) {
3870
3871 ExecStatusInfo *p;
3872 const char *active_on, *active_off, *on, *off, *ss;
3873 usec_t timestamp;
3874 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3875 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3876 const char *path;
3877 char **t, **t2;
3878 int r;
3879
3880 assert(i);
3881
3882 /* This shows pretty information about a unit. See
3883 * print_property() for a low-level property printer */
3884
3885 if (streq_ptr(i->active_state, "failed")) {
3886 active_on = ansi_highlight_red();
3887 active_off = ansi_normal();
3888 } else if (STRPTR_IN_SET(i->active_state, "active", "reloading")) {
3889 active_on = ansi_highlight_green();
3890 active_off = ansi_normal();
3891 } else
3892 active_on = active_off = "";
3893
3894 printf("%s%s%s %s", active_on, special_glyph(BLACK_CIRCLE), active_off, strna(i->id));
3895
3896 if (i->description && !streq_ptr(i->id, i->description))
3897 printf(" - %s", i->description);
3898
3899 printf("\n");
3900
3901 if (i->following)
3902 printf(" Follow: unit currently follows state of %s\n", i->following);
3903
3904 if (streq_ptr(i->load_state, "error")) {
3905 on = ansi_highlight_red();
3906 off = ansi_normal();
3907 } else
3908 on = off = "";
3909
3910 path = i->source_path ? i->source_path : i->fragment_path;
3911
3912 if (i->load_error != 0)
3913 printf(" Loaded: %s%s%s (Reason: %s)\n",
3914 on, strna(i->load_state), off, i->load_error);
3915 else if (path && !isempty(i->unit_file_state) && !isempty(i->unit_file_preset))
3916 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3917 on, strna(i->load_state), off, path, i->unit_file_state, i->unit_file_preset);
3918 else if (path && !isempty(i->unit_file_state))
3919 printf(" Loaded: %s%s%s (%s; %s)\n",
3920 on, strna(i->load_state), off, path, i->unit_file_state);
3921 else if (path)
3922 printf(" Loaded: %s%s%s (%s)\n",
3923 on, strna(i->load_state), off, path);
3924 else
3925 printf(" Loaded: %s%s%s\n",
3926 on, strna(i->load_state), off);
3927
3928 if (i->transient)
3929 printf("Transient: yes\n");
3930
3931 if (!strv_isempty(i->dropin_paths)) {
3932 _cleanup_free_ char *dir = NULL;
3933 bool last = false;
3934 char ** dropin;
3935
3936 STRV_FOREACH(dropin, i->dropin_paths) {
3937 if (! dir || last) {
3938 printf(dir ? " " : " Drop-In: ");
3939
3940 dir = mfree(dir);
3941
3942 dir = dirname_malloc(*dropin);
3943 if (!dir) {
3944 log_oom();
3945 return;
3946 }
3947
3948 printf("%s\n %s", dir,
3949 special_glyph(TREE_RIGHT));
3950 }
3951
3952 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3953
3954 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3955 }
3956 }
3957
3958 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3959 if (ss)
3960 printf(" Active: %s%s (%s)%s",
3961 active_on, strna(i->active_state), ss, active_off);
3962 else
3963 printf(" Active: %s%s%s",
3964 active_on, strna(i->active_state), active_off);
3965
3966 if (!isempty(i->result) && !streq(i->result, "success"))
3967 printf(" (Result: %s)", i->result);
3968
3969 timestamp = STRPTR_IN_SET(i->active_state, "active", "reloading") ? i->active_enter_timestamp :
3970 STRPTR_IN_SET(i->active_state, "inactive", "failed") ? i->inactive_enter_timestamp :
3971 STRPTR_IN_SET(i->active_state, "activating") ? i->inactive_exit_timestamp :
3972 i->active_exit_timestamp;
3973
3974 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3975 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3976
3977 if (s1)
3978 printf(" since %s; %s\n", s2, s1);
3979 else if (s2)
3980 printf(" since %s\n", s2);
3981 else
3982 printf("\n");
3983
3984 if (!i->condition_result && i->condition_timestamp > 0) {
3985 UnitCondition *c;
3986 int n = 0;
3987
3988 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3989 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3990
3991 printf("Condition: start %scondition failed%s at %s%s%s\n",
3992 ansi_highlight_yellow(), ansi_normal(),
3993 s2, s1 ? "; " : "", strempty(s1));
3994
3995 LIST_FOREACH(conditions, c, i->conditions)
3996 if (c->tristate < 0)
3997 n++;
3998
3999 LIST_FOREACH(conditions, c, i->conditions)
4000 if (c->tristate < 0)
4001 printf(" %s %s=%s%s%s was not met\n",
4002 --n ? special_glyph(TREE_BRANCH) : special_glyph(TREE_RIGHT),
4003 c->name,
4004 c->trigger ? "|" : "",
4005 c->negate ? "!" : "",
4006 c->param);
4007 }
4008
4009 if (!i->assert_result && i->assert_timestamp > 0) {
4010 s1 = format_timestamp_relative(since1, sizeof(since1), i->assert_timestamp);
4011 s2 = format_timestamp(since2, sizeof(since2), i->assert_timestamp);
4012
4013 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
4014 ansi_highlight_red(), ansi_normal(),
4015 s2, s1 ? "; " : "", strempty(s1));
4016 if (i->failed_assert_trigger)
4017 printf(" none of the trigger assertions were met\n");
4018 else if (i->failed_assert)
4019 printf(" %s=%s%s was not met\n",
4020 i->failed_assert,
4021 i->failed_assert_negate ? "!" : "",
4022 i->failed_assert_parameter);
4023 }
4024
4025 if (i->sysfs_path)
4026 printf(" Device: %s\n", i->sysfs_path);
4027 if (i->where)
4028 printf(" Where: %s\n", i->where);
4029 if (i->what)
4030 printf(" What: %s\n", i->what);
4031
4032 STRV_FOREACH(t, i->documentation)
4033 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
4034
4035 STRV_FOREACH_PAIR(t, t2, i->listen)
4036 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
4037
4038 if (i->accept)
4039 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
4040
4041 LIST_FOREACH(exec, p, i->exec) {
4042 _cleanup_free_ char *argv = NULL;
4043 bool good;
4044
4045 /* Only show exited processes here */
4046 if (p->code == 0)
4047 continue;
4048
4049 argv = strv_join(p->argv, " ");
4050 printf(" Process: "PID_FMT" %s=%s ", p->pid, p->name, strna(argv));
4051
4052 good = is_clean_exit(p->code, p->status, EXIT_CLEAN_DAEMON, NULL);
4053 if (!good) {
4054 on = ansi_highlight_red();
4055 off = ansi_normal();
4056 } else
4057 on = off = "";
4058
4059 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
4060
4061 if (p->code == CLD_EXITED) {
4062 const char *c;
4063
4064 printf("status=%i", p->status);
4065
4066 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
4067 if (c)
4068 printf("/%s", c);
4069
4070 } else
4071 printf("signal=%s", signal_to_string(p->status));
4072
4073 printf(")%s\n", off);
4074
4075 if (i->main_pid == p->pid &&
4076 i->start_timestamp == p->start_timestamp &&
4077 i->exit_timestamp == p->start_timestamp)
4078 /* Let's not show this twice */
4079 i->main_pid = 0;
4080
4081 if (p->pid == i->control_pid)
4082 i->control_pid = 0;
4083 }
4084
4085 if (i->main_pid > 0 || i->control_pid > 0) {
4086 if (i->main_pid > 0) {
4087 printf(" Main PID: "PID_FMT, i->main_pid);
4088
4089 if (i->running) {
4090 _cleanup_free_ char *comm = NULL;
4091 (void) get_process_comm(i->main_pid, &comm);
4092 if (comm)
4093 printf(" (%s)", comm);
4094 } else if (i->exit_code > 0) {
4095 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
4096
4097 if (i->exit_code == CLD_EXITED) {
4098 const char *c;
4099
4100 printf("status=%i", i->exit_status);
4101
4102 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
4103 if (c)
4104 printf("/%s", c);
4105
4106 } else
4107 printf("signal=%s", signal_to_string(i->exit_status));
4108 printf(")");
4109 }
4110 }
4111
4112 if (i->control_pid > 0) {
4113 _cleanup_free_ char *c = NULL;
4114
4115 if (i->main_pid > 0)
4116 fputs("; Control PID: ", stdout);
4117 else
4118 fputs("Cntrl PID: ", stdout); /* if first in column, abbreviated so it fits alignment */
4119
4120 printf(PID_FMT, i->control_pid);
4121
4122 (void) get_process_comm(i->control_pid, &c);
4123 if (c)
4124 printf(" (%s)", c);
4125 }
4126
4127 printf("\n");
4128 }
4129
4130 if (i->status_text)
4131 printf(" Status: \"%s\"\n", i->status_text);
4132 if (i->status_errno > 0)
4133 printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
4134
4135 if (i->tasks_current != (uint64_t) -1) {
4136 printf(" Tasks: %" PRIu64, i->tasks_current);
4137
4138 if (i->tasks_max != (uint64_t) -1)
4139 printf(" (limit: %" PRIu64 ")\n", i->tasks_max);
4140 else
4141 printf("\n");
4142 }
4143
4144 if (i->memory_current != (uint64_t) -1) {
4145 char buf[FORMAT_BYTES_MAX];
4146
4147 printf(" Memory: %s", format_bytes(buf, sizeof(buf), i->memory_current));
4148
4149 if (i->memory_low > 0 || i->memory_high != CGROUP_LIMIT_MAX ||
4150 i->memory_max != CGROUP_LIMIT_MAX || i->memory_swap_max != CGROUP_LIMIT_MAX ||
4151 i->memory_limit != CGROUP_LIMIT_MAX) {
4152 const char *prefix = "";
4153
4154 printf(" (");
4155 if (i->memory_low > 0) {
4156 printf("%slow: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_low));
4157 prefix = " ";
4158 }
4159 if (i->memory_high != CGROUP_LIMIT_MAX) {
4160 printf("%shigh: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_high));
4161 prefix = " ";
4162 }
4163 if (i->memory_max != CGROUP_LIMIT_MAX) {
4164 printf("%smax: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_max));
4165 prefix = " ";
4166 }
4167 if (i->memory_swap_max != CGROUP_LIMIT_MAX) {
4168 printf("%sswap max: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_swap_max));
4169 prefix = " ";
4170 }
4171 if (i->memory_limit != CGROUP_LIMIT_MAX) {
4172 printf("%slimit: %s", prefix, format_bytes(buf, sizeof(buf), i->memory_limit));
4173 prefix = " ";
4174 }
4175 printf(")");
4176 }
4177 printf("\n");
4178 }
4179
4180 if (i->cpu_usage_nsec != (uint64_t) -1) {
4181 char buf[FORMAT_TIMESPAN_MAX];
4182 printf(" CPU: %s\n", format_timespan(buf, sizeof(buf), i->cpu_usage_nsec / NSEC_PER_USEC, USEC_PER_MSEC));
4183 }
4184
4185 if (i->control_group) {
4186 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
4187 static const char prefix[] = " ";
4188 unsigned c;
4189
4190 printf(" CGroup: %s\n", i->control_group);
4191
4192 c = columns();
4193 if (c > sizeof(prefix) - 1)
4194 c -= sizeof(prefix) - 1;
4195 else
4196 c = 0;
4197
4198 r = unit_show_processes(bus, i->id, i->control_group, prefix, c, get_output_flags(), &error);
4199 if (r == -EBADR) {
4200 unsigned k = 0;
4201 pid_t extra[2];
4202
4203 /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */
4204
4205 if (i->main_pid > 0)
4206 extra[k++] = i->main_pid;
4207
4208 if (i->control_pid > 0)
4209 extra[k++] = i->control_pid;
4210
4211 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, extra, k, get_output_flags());
4212 } else if (r < 0)
4213 log_warning_errno(r, "Failed to dump process list, ignoring: %s", bus_error_message(&error, r));
4214 }
4215
4216 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL)
4217 show_journal_by_unit(
4218 stdout,
4219 i->id,
4220 arg_output,
4221 0,
4222 i->inactive_exit_timestamp_monotonic,
4223 arg_lines,
4224 getuid(),
4225 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
4226 SD_JOURNAL_LOCAL_ONLY,
4227 arg_scope == UNIT_FILE_SYSTEM,
4228 ellipsized);
4229
4230 if (i->need_daemon_reload)
4231 warn_unit_file_changed(i->id);
4232}
4233
4234static void show_unit_help(UnitStatusInfo *i) {
4235 char **p;
4236
4237 assert(i);
4238
4239 if (!i->documentation) {
4240 log_info("Documentation for %s not known.", i->id);
4241 return;
4242 }
4243
4244 STRV_FOREACH(p, i->documentation)
4245 if (startswith(*p, "man:"))
4246 show_man_page(*p + 4, false);
4247 else
4248 log_info("Can't show: %s", *p);
4249}
4250
4251static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
4252 int r;
4253
4254 assert(name);
4255 assert(m);
4256 assert(i);
4257
4258 switch (contents[0]) {
4259
4260 case SD_BUS_TYPE_STRING: {
4261 const char *s;
4262
4263 r = sd_bus_message_read(m, "s", &s);
4264 if (r < 0)
4265 return bus_log_parse_error(r);
4266
4267 if (!isempty(s)) {
4268 if (streq(name, "Id"))
4269 i->id = s;
4270 else if (streq(name, "LoadState"))
4271 i->load_state = s;
4272 else if (streq(name, "ActiveState"))
4273 i->active_state = s;
4274 else if (streq(name, "SubState"))
4275 i->sub_state = s;
4276 else if (streq(name, "Description"))
4277 i->description = s;
4278 else if (streq(name, "FragmentPath"))
4279 i->fragment_path = s;
4280 else if (streq(name, "SourcePath"))
4281 i->source_path = s;
4282#ifndef NOLEGACY
4283 else if (streq(name, "DefaultControlGroup")) {
4284 const char *e;
4285 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
4286 if (e)
4287 i->control_group = e;
4288 }
4289#endif
4290 else if (streq(name, "ControlGroup"))
4291 i->control_group = s;
4292 else if (streq(name, "StatusText"))
4293 i->status_text = s;
4294 else if (streq(name, "PIDFile"))
4295 i->pid_file = s;
4296 else if (streq(name, "SysFSPath"))
4297 i->sysfs_path = s;
4298 else if (streq(name, "Where"))
4299 i->where = s;
4300 else if (streq(name, "What"))
4301 i->what = s;
4302 else if (streq(name, "Following"))
4303 i->following = s;
4304 else if (streq(name, "UnitFileState"))
4305 i->unit_file_state = s;
4306 else if (streq(name, "UnitFilePreset"))
4307 i->unit_file_preset = s;
4308 else if (streq(name, "Result"))
4309 i->result = s;
4310 }
4311
4312 break;
4313 }
4314
4315 case SD_BUS_TYPE_BOOLEAN: {
4316 int b;
4317
4318 r = sd_bus_message_read(m, "b", &b);
4319 if (r < 0)
4320 return bus_log_parse_error(r);
4321
4322 if (streq(name, "Accept"))
4323 i->accept = b;
4324 else if (streq(name, "NeedDaemonReload"))
4325 i->need_daemon_reload = b;
4326 else if (streq(name, "ConditionResult"))
4327 i->condition_result = b;
4328 else if (streq(name, "AssertResult"))
4329 i->assert_result = b;
4330 else if (streq(name, "Transient"))
4331 i->transient = b;
4332
4333 break;
4334 }
4335
4336 case SD_BUS_TYPE_UINT32: {
4337 uint32_t u;
4338
4339 r = sd_bus_message_read(m, "u", &u);
4340 if (r < 0)
4341 return bus_log_parse_error(r);
4342
4343 if (streq(name, "MainPID")) {
4344 if (u > 0) {
4345 i->main_pid = (pid_t) u;
4346 i->running = true;
4347 }
4348 } else if (streq(name, "ControlPID"))
4349 i->control_pid = (pid_t) u;
4350 else if (streq(name, "ExecMainPID")) {
4351 if (u > 0)
4352 i->main_pid = (pid_t) u;
4353 } else if (streq(name, "NAccepted"))
4354 i->n_accepted = u;
4355 else if (streq(name, "NConnections"))
4356 i->n_connections = u;
4357
4358 break;
4359 }
4360
4361 case SD_BUS_TYPE_INT32: {
4362 int32_t j;
4363
4364 r = sd_bus_message_read(m, "i", &j);
4365 if (r < 0)
4366 return bus_log_parse_error(r);
4367
4368 if (streq(name, "ExecMainCode"))
4369 i->exit_code = (int) j;
4370 else if (streq(name, "ExecMainStatus"))
4371 i->exit_status = (int) j;
4372 else if (streq(name, "StatusErrno"))
4373 i->status_errno = (int) j;
4374
4375 break;
4376 }
4377
4378 case SD_BUS_TYPE_UINT64: {
4379 uint64_t u;
4380
4381 r = sd_bus_message_read(m, "t", &u);
4382 if (r < 0)
4383 return bus_log_parse_error(r);
4384
4385 if (streq(name, "ExecMainStartTimestamp"))
4386 i->start_timestamp = (usec_t) u;
4387 else if (streq(name, "ExecMainExitTimestamp"))
4388 i->exit_timestamp = (usec_t) u;
4389 else if (streq(name, "ActiveEnterTimestamp"))
4390 i->active_enter_timestamp = (usec_t) u;
4391 else if (streq(name, "InactiveEnterTimestamp"))
4392 i->inactive_enter_timestamp = (usec_t) u;
4393 else if (streq(name, "InactiveExitTimestamp"))
4394 i->inactive_exit_timestamp = (usec_t) u;
4395 else if (streq(name, "InactiveExitTimestampMonotonic"))
4396 i->inactive_exit_timestamp_monotonic = (usec_t) u;
4397 else if (streq(name, "ActiveExitTimestamp"))
4398 i->active_exit_timestamp = (usec_t) u;
4399 else if (streq(name, "ConditionTimestamp"))
4400 i->condition_timestamp = (usec_t) u;
4401 else if (streq(name, "AssertTimestamp"))
4402 i->assert_timestamp = (usec_t) u;
4403 else if (streq(name, "MemoryCurrent"))
4404 i->memory_current = u;
4405 else if (streq(name, "MemoryLow"))
4406 i->memory_low = u;
4407 else if (streq(name, "MemoryHigh"))
4408 i->memory_high = u;
4409 else if (streq(name, "MemoryMax"))
4410 i->memory_max = u;
4411 else if (streq(name, "MemorySwapMax"))
4412 i->memory_swap_max = u;
4413 else if (streq(name, "MemoryLimit"))
4414 i->memory_limit = u;
4415 else if (streq(name, "TasksCurrent"))
4416 i->tasks_current = u;
4417 else if (streq(name, "TasksMax"))
4418 i->tasks_max = u;
4419 else if (streq(name, "CPUUsageNSec"))
4420 i->cpu_usage_nsec = u;
4421
4422 break;
4423 }
4424
4425 case SD_BUS_TYPE_ARRAY:
4426
4427 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
4428 _cleanup_free_ ExecStatusInfo *info = NULL;
4429
4430 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
4431 if (r < 0)
4432 return bus_log_parse_error(r);
4433
4434 info = new0(ExecStatusInfo, 1);
4435 if (!info)
4436 return log_oom();
4437
4438 while ((r = exec_status_info_deserialize(m, info)) > 0) {
4439
4440 info->name = strdup(name);
4441 if (!info->name)
4442 return log_oom();
4443
4444 LIST_PREPEND(exec, i->exec, info);
4445
4446 info = new0(ExecStatusInfo, 1);
4447 if (!info)
4448 return log_oom();
4449 }
4450
4451 if (r < 0)
4452 return bus_log_parse_error(r);
4453
4454 r = sd_bus_message_exit_container(m);
4455 if (r < 0)
4456 return bus_log_parse_error(r);
4457
4458 return 0;
4459
4460 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
4461 const char *type, *path;
4462
4463 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4464 if (r < 0)
4465 return bus_log_parse_error(r);
4466
4467 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
4468
4469 r = strv_extend(&i->listen, type);
4470 if (r < 0)
4471 return r;
4472
4473 r = strv_extend(&i->listen, path);
4474 if (r < 0)
4475 return r;
4476 }
4477 if (r < 0)
4478 return bus_log_parse_error(r);
4479
4480 r = sd_bus_message_exit_container(m);
4481 if (r < 0)
4482 return bus_log_parse_error(r);
4483
4484 return 0;
4485
4486 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
4487
4488 r = sd_bus_message_read_strv(m, &i->dropin_paths);
4489 if (r < 0)
4490 return bus_log_parse_error(r);
4491
4492 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
4493
4494 r = sd_bus_message_read_strv(m, &i->documentation);
4495 if (r < 0)
4496 return bus_log_parse_error(r);
4497
4498 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
4499 const char *cond, *param;
4500 int trigger, negate;
4501 int32_t state;
4502
4503 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
4504 if (r < 0)
4505 return bus_log_parse_error(r);
4506
4507 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, &param, &state)) > 0) {
4508 _cleanup_(unit_condition_freep) UnitCondition *c = NULL;
4509
4510 log_debug("%s trigger=%d negate=%d %s →%d", cond, trigger, negate, param, state);
4511
4512 c = new0(UnitCondition, 1);
4513 if (!c)
4514 return log_oom();
4515
4516 c->name = strdup(cond);
4517 c->param = strdup(param);
4518 if (!c->name || !c->param)
4519 return log_oom();
4520
4521 c->trigger = trigger;
4522 c->negate = negate;
4523 c->tristate = state;
4524
4525 LIST_PREPEND(conditions, i->conditions, c);
4526 c = NULL;
4527 }
4528 if (r < 0)
4529 return bus_log_parse_error(r);
4530
4531 r = sd_bus_message_exit_container(m);
4532 if (r < 0)
4533 return bus_log_parse_error(r);
4534
4535 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Asserts")) {
4536 const char *cond, *param;
4537 int trigger, negate;
4538 int32_t state;
4539
4540 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
4541 if (r < 0)
4542 return bus_log_parse_error(r);
4543
4544 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, &param, &state)) > 0) {
4545 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
4546 if (state < 0 && (!trigger || !i->failed_assert)) {
4547 i->failed_assert = cond;
4548 i->failed_assert_trigger = trigger;
4549 i->failed_assert_negate = negate;
4550 i->failed_assert_parameter = param;
4551 }
4552 }
4553 if (r < 0)
4554 return bus_log_parse_error(r);
4555
4556 r = sd_bus_message_exit_container(m);
4557 if (r < 0)
4558 return bus_log_parse_error(r);
4559
4560 } else
4561 goto skip;
4562
4563 break;
4564
4565 case SD_BUS_TYPE_STRUCT_BEGIN:
4566
4567 if (streq(name, "LoadError")) {
4568 const char *n, *message;
4569
4570 r = sd_bus_message_read(m, "(ss)", &n, &message);
4571 if (r < 0)
4572 return bus_log_parse_error(r);
4573
4574 if (!isempty(message))
4575 i->load_error = message;
4576 } else
4577 goto skip;
4578
4579 break;
4580
4581 default:
4582 goto skip;
4583 }
4584
4585 return 0;
4586
4587skip:
4588 r = sd_bus_message_skip(m, contents);
4589 if (r < 0)
4590 return bus_log_parse_error(r);
4591
4592 return 0;
4593}
4594
4595#define print_prop(name, fmt, ...) \
4596 do { \
4597 if (arg_value) \
4598 printf(fmt "\n", __VA_ARGS__); \
4599 else \
4600 printf("%s=" fmt "\n", name, __VA_ARGS__); \
4601 } while(0)
4602
4603static int print_property(const char *name, sd_bus_message *m, const char *contents) {
4604 int r;
4605
4606 assert(name);
4607 assert(m);
4608
4609 /* This is a low-level property printer, see
4610 * print_status_info() for the nicer output */
4611
4612 if (arg_properties && !strv_find(arg_properties, name)) {
4613 /* skip what we didn't read */
4614 r = sd_bus_message_skip(m, contents);
4615 return r;
4616 }
4617
4618 switch (contents[0]) {
4619
4620 case SD_BUS_TYPE_STRUCT_BEGIN:
4621
4622 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
4623 uint32_t u;
4624
4625 r = sd_bus_message_read(m, "(uo)", &u, NULL);
4626 if (r < 0)
4627 return bus_log_parse_error(r);
4628
4629 if (u > 0)
4630 print_prop(name, "%"PRIu32, u);
4631 else if (arg_all)
4632 print_prop(name, "%s", "");
4633
4634 return 0;
4635
4636 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
4637 const char *s;
4638
4639 r = sd_bus_message_read(m, "(so)", &s, NULL);
4640 if (r < 0)
4641 return bus_log_parse_error(r);
4642
4643 if (arg_all || !isempty(s))
4644 print_prop(name, "%s", s);
4645
4646 return 0;
4647
4648 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
4649 const char *a = NULL, *b = NULL;
4650
4651 r = sd_bus_message_read(m, "(ss)", &a, &b);
4652 if (r < 0)
4653 return bus_log_parse_error(r);
4654
4655 if (arg_all || !isempty(a) || !isempty(b))
4656 print_prop(name, "%s \"%s\"", strempty(a), strempty(b));
4657
4658 return 0;
4659 } else if (streq_ptr(name, "SystemCallFilter")) {
4660 _cleanup_strv_free_ char **l = NULL;
4661 int whitelist;
4662
4663 r = sd_bus_message_enter_container(m, 'r', "bas");
4664 if (r < 0)
4665 return bus_log_parse_error(r);
4666
4667 r = sd_bus_message_read(m, "b", &whitelist);
4668 if (r < 0)
4669 return bus_log_parse_error(r);
4670
4671 r = sd_bus_message_read_strv(m, &l);
4672 if (r < 0)
4673 return bus_log_parse_error(r);
4674
4675 r = sd_bus_message_exit_container(m);
4676 if (r < 0)
4677 return bus_log_parse_error(r);
4678
4679 if (arg_all || whitelist || !strv_isempty(l)) {
4680 bool first = true;
4681 char **i;
4682
4683 if (!arg_value) {
4684 fputs(name, stdout);
4685 fputc('=', stdout);
4686 }
4687
4688 if (!whitelist)
4689 fputc('~', stdout);
4690
4691 STRV_FOREACH(i, l) {
4692 if (first)
4693 first = false;
4694 else
4695 fputc(' ', stdout);
4696
4697 fputs(*i, stdout);
4698 }
4699 fputc('\n', stdout);
4700 }
4701
4702 return 0;
4703 }
4704
4705 break;
4706
4707 case SD_BUS_TYPE_ARRAY:
4708
4709 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
4710 const char *path;
4711 int ignore;
4712
4713 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
4714 if (r < 0)
4715 return bus_log_parse_error(r);
4716
4717 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
4718 print_prop("EnvironmentFile", "%s (ignore_errors=%s)", path, yes_no(ignore));
4719
4720 if (r < 0)
4721 return bus_log_parse_error(r);
4722
4723 r = sd_bus_message_exit_container(m);
4724 if (r < 0)
4725 return bus_log_parse_error(r);
4726
4727 return 0;
4728
4729 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
4730 const char *type, *path;
4731
4732 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4733 if (r < 0)
4734 return bus_log_parse_error(r);
4735
4736 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4737 print_prop(type, "%s", path);
4738 if (r < 0)
4739 return bus_log_parse_error(r);
4740
4741 r = sd_bus_message_exit_container(m);
4742 if (r < 0)
4743 return bus_log_parse_error(r);
4744
4745 return 0;
4746
4747 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
4748 const char *type, *path;
4749
4750 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4751 if (r < 0)
4752 return bus_log_parse_error(r);
4753
4754 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4755 if (arg_value)
4756 puts(path);
4757 else
4758 printf("Listen%s=%s\n", type, path);
4759 if (r < 0)
4760 return bus_log_parse_error(r);
4761
4762 r = sd_bus_message_exit_container(m);
4763 if (r < 0)
4764 return bus_log_parse_error(r);
4765
4766 return 0;
4767
4768 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
4769 const char *base;
4770 uint64_t value, next_elapse;
4771
4772 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
4773 if (r < 0)
4774 return bus_log_parse_error(r);
4775
4776 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
4777 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
4778
4779 print_prop(base, "{ value=%s ; next_elapse=%s }",
4780 format_timespan(timespan1, sizeof(timespan1), value, 0),
4781 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
4782 }
4783 if (r < 0)
4784 return bus_log_parse_error(r);
4785
4786 r = sd_bus_message_exit_container(m);
4787 if (r < 0)
4788 return bus_log_parse_error(r);
4789
4790 return 0;
4791
4792 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
4793 ExecStatusInfo info = {};
4794
4795 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
4796 if (r < 0)
4797 return bus_log_parse_error(r);
4798
4799 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
4800 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
4801 _cleanup_free_ char *tt;
4802
4803 tt = strv_join(info.argv, " ");
4804
4805 print_prop(name,
4806 "{ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }",
4807 strna(info.path),
4808 strna(tt),
4809 yes_no(info.ignore),
4810 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
4811 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
4812 info.pid,
4813 sigchld_code_to_string(info.code),
4814 info.status,
4815 info.code == CLD_EXITED ? "" : "/",
4816 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
4817
4818 free(info.path);
4819 strv_free(info.argv);
4820 zero(info);
4821 }
4822
4823 r = sd_bus_message_exit_container(m);
4824 if (r < 0)
4825 return bus_log_parse_error(r);
4826
4827 return 0;
4828
4829 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
4830 const char *path, *rwm;
4831
4832 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4833 if (r < 0)
4834 return bus_log_parse_error(r);
4835
4836 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
4837 print_prop(name, "%s %s", strna(path), strna(rwm));
4838 if (r < 0)
4839 return bus_log_parse_error(r);
4840
4841 r = sd_bus_message_exit_container(m);
4842 if (r < 0)
4843 return bus_log_parse_error(r);
4844
4845 return 0;
4846
4847 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN &&
4848 STR_IN_SET(name, "IODeviceWeight", "BlockIODeviceWeight")) {
4849 const char *path;
4850 uint64_t weight;
4851
4852 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4853 if (r < 0)
4854 return bus_log_parse_error(r);
4855
4856 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4857 print_prop(name, "%s %"PRIu64, strna(path), weight);
4858 if (r < 0)
4859 return bus_log_parse_error(r);
4860
4861 r = sd_bus_message_exit_container(m);
4862 if (r < 0)
4863 return bus_log_parse_error(r);
4864
4865 return 0;
4866
4867 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN &&
4868 (cgroup_io_limit_type_from_string(name) >= 0 ||
4869 STR_IN_SET(name, "BlockIOReadBandwidth", "BlockIOWriteBandwidth"))) {
4870 const char *path;
4871 uint64_t bandwidth;
4872
4873 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4874 if (r < 0)
4875 return bus_log_parse_error(r);
4876
4877 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4878 print_prop(name, "%s %"PRIu64, strna(path), bandwidth);
4879 if (r < 0)
4880 return bus_log_parse_error(r);
4881
4882 r = sd_bus_message_exit_container(m);
4883 if (r < 0)
4884 return bus_log_parse_error(r);
4885
4886 return 0;
4887 }
4888
4889 break;
4890 }
4891
4892 r = bus_print_property(name, m, arg_value, arg_all);
4893 if (r < 0)
4894 return bus_log_parse_error(r);
4895
4896 if (r == 0) {
4897 r = sd_bus_message_skip(m, contents);
4898 if (r < 0)
4899 return bus_log_parse_error(r);
4900
4901 if (arg_all)
4902 printf("%s=[unprintable]\n", name);
4903 }
4904
4905 return 0;
4906}
4907
4908static int show_one(
4909 const char *verb,
4910 sd_bus *bus,
4911 const char *path,
4912 const char *unit,
4913 bool show_properties,
4914 bool *new_line,
4915 bool *ellipsized) {
4916
4917 static const struct bus_properties_map property_map[] = {
4918 { "LoadState", "s", map_string_no_copy, offsetof(UnitStatusInfo, load_state) },
4919 { "ActiveState", "s", map_string_no_copy, offsetof(UnitStatusInfo, active_state) },
4920 {}
4921 };
4922
4923 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
4924 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
4925 _cleanup_set_free_ Set *found_properties = NULL;
4926 _cleanup_(unit_status_info_free) UnitStatusInfo info = {
4927 .memory_current = (uint64_t) -1,
4928 .memory_high = CGROUP_LIMIT_MAX,
4929 .memory_max = CGROUP_LIMIT_MAX,
4930 .memory_swap_max = CGROUP_LIMIT_MAX,
4931 .memory_limit = (uint64_t) -1,
4932 .cpu_usage_nsec = (uint64_t) -1,
4933 .tasks_current = (uint64_t) -1,
4934 .tasks_max = (uint64_t) -1,
4935 };
4936 int r;
4937
4938 assert(path);
4939 assert(new_line);
4940
4941 log_debug("Showing one %s", path);
4942
4943 r = sd_bus_call_method(
4944 bus,
4945 "org.freedesktop.systemd1",
4946 path,
4947 "org.freedesktop.DBus.Properties",
4948 "GetAll",
4949 &error,
4950 &reply,
4951 "s", "");
4952 if (r < 0)
4953 return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
4954
4955 if (unit) {
4956 r = bus_message_map_all_properties(reply, property_map, &error, &info);
4957 if (r < 0)
4958 return log_error_errno(r, "Failed to map properties: %s", bus_error_message(&error, r));
4959
4960 if (streq_ptr(info.load_state, "not-found") && streq_ptr(info.active_state, "inactive")) {
4961 log_full(streq(verb, "status") ? LOG_ERR : LOG_DEBUG,
4962 "Unit %s could not be found.", unit);
4963
4964 if (streq(verb, "status"))
4965 return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN;
4966
4967 if (!streq(verb, "show"))
4968 return -ENOENT;
4969 }
4970
4971 r = sd_bus_message_rewind(reply, true);
4972 if (r < 0)
4973 return log_error_errno(r, "Failed to rewind: %s", bus_error_message(&error, r));
4974 }
4975
4976 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4977 if (r < 0)
4978 return bus_log_parse_error(r);
4979
4980 if (*new_line)
4981 printf("\n");
4982
4983 *new_line = true;
4984
4985 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4986 const char *name, *contents;
4987
4988 r = sd_bus_message_read(reply, "s", &name);
4989 if (r < 0)
4990 return bus_log_parse_error(r);
4991
4992 r = sd_bus_message_peek_type(reply, NULL, &contents);
4993 if (r < 0)
4994 return bus_log_parse_error(r);
4995
4996 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4997 if (r < 0)
4998 return bus_log_parse_error(r);
4999
5000 if (show_properties) {
5001 r = set_ensure_allocated(&found_properties, &string_hash_ops);
5002 if (r < 0)
5003 return log_oom();
5004
5005 r = set_put(found_properties, name);
5006 if (r < 0 && r != EEXIST)
5007 return log_oom();
5008
5009 r = print_property(name, reply, contents);
5010 } else
5011 r = status_property(name, reply, &info, contents);
5012 if (r < 0)
5013 return r;
5014
5015 r = sd_bus_message_exit_container(reply);
5016 if (r < 0)
5017 return bus_log_parse_error(r);
5018
5019 r = sd_bus_message_exit_container(reply);
5020 if (r < 0)
5021 return bus_log_parse_error(r);
5022 }
5023 if (r < 0)
5024 return bus_log_parse_error(r);
5025
5026 r = sd_bus_message_exit_container(reply);
5027 if (r < 0)
5028 return bus_log_parse_error(r);
5029
5030 r = 0;
5031 if (show_properties) {
5032 char **pp;
5033
5034 STRV_FOREACH(pp, arg_properties)
5035 if (!set_contains(found_properties, *pp))
5036 log_debug("Property %s does not exist.", *pp);
5037
5038 } else if (streq(verb, "help"))
5039 show_unit_help(&info);
5040 else if (streq(verb, "status")) {
5041 print_status_info(bus, &info, ellipsized);
5042
5043 if (info.active_state && !STR_IN_SET(info.active_state, "active", "reloading"))
5044 r = EXIT_PROGRAM_NOT_RUNNING;
5045 else
5046 r = EXIT_PROGRAM_RUNNING_OR_SERVICE_OK;
5047 }
5048
5049 return r;
5050}
5051
5052static int get_unit_dbus_path_by_pid(
5053 sd_bus *bus,
5054 uint32_t pid,
5055 char **unit) {
5056
5057 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5058 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
5059 char *u;
5060 int r;
5061
5062 r = sd_bus_call_method(
5063 bus,
5064 "org.freedesktop.systemd1",
5065 "/org/freedesktop/systemd1",
5066 "org.freedesktop.systemd1.Manager",
5067 "GetUnitByPID",
5068 &error,
5069 &reply,
5070 "u", pid);
5071 if (r < 0)
5072 return log_error_errno(r, "Failed to get unit for PID %"PRIu32": %s", pid, bus_error_message(&error, r));
5073
5074 r = sd_bus_message_read(reply, "o", &u);
5075 if (r < 0)
5076 return bus_log_parse_error(r);
5077
5078 u = strdup(u);
5079 if (!u)
5080 return log_oom();
5081
5082 *unit = u;
5083 return 0;
5084}
5085
5086static int show_all(
5087 const char* verb,
5088 sd_bus *bus,
5089 bool show_properties,
5090 bool *new_line,
5091 bool *ellipsized) {
5092
5093 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
5094 _cleanup_free_ UnitInfo *unit_infos = NULL;
5095 const UnitInfo *u;
5096 unsigned c;
5097 int r, ret = 0;
5098
5099 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
5100 if (r < 0)
5101 return r;
5102
5103 pager_open(arg_no_pager, false);
5104
5105 c = (unsigned) r;
5106
5107 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
5108
5109 for (u = unit_infos; u < unit_infos + c; u++) {
5110 _cleanup_free_ char *p = NULL;
5111
5112 p = unit_dbus_path_from_name(u->id);
5113 if (!p)
5114 return log_oom();
5115
5116 r = show_one(verb, bus, p, u->id, show_properties, new_line, ellipsized);
5117 if (r < 0)
5118 return r;
5119 else if (r > 0 && ret == 0)
5120 ret = r;
5121 }
5122
5123 return ret;
5124}
5125
5126static int show_system_status(sd_bus *bus) {
5127 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
5128 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5129 _cleanup_(machine_info_clear) struct machine_info mi = {};
5130 _cleanup_free_ char *hn = NULL;
5131 const char *on, *off;
5132 int r;
5133
5134 hn = gethostname_malloc();
5135 if (!hn)
5136 return log_oom();
5137
5138 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &error, &mi);
5139 if (r < 0)
5140 return log_error_errno(r, "Failed to read server status: %s", bus_error_message(&error, r));
5141
5142 if (streq_ptr(mi.state, "degraded")) {
5143 on = ansi_highlight_red();
5144 off = ansi_normal();
5145 } else if (!streq_ptr(mi.state, "running")) {
5146 on = ansi_highlight_yellow();
5147 off = ansi_normal();
5148 } else
5149 on = off = "";
5150
5151 printf("%s%s%s %s\n", on, special_glyph(BLACK_CIRCLE), off, arg_host ? arg_host : hn);
5152
5153 printf(" State: %s%s%s\n",
5154 on, strna(mi.state), off);
5155
5156 printf(" Jobs: %" PRIu32 " queued\n", mi.n_jobs);
5157 printf(" Failed: %" PRIu32 " units\n", mi.n_failed_units);
5158
5159 printf(" Since: %s; %s\n",
5160 format_timestamp(since2, sizeof(since2), mi.timestamp),
5161 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
5162
5163 printf(" CGroup: %s\n", mi.control_group ?: "/");
5164 if (IN_SET(arg_transport,
5165 BUS_TRANSPORT_LOCAL,
5166 BUS_TRANSPORT_MACHINE)) {
5167 static const char prefix[] = " ";
5168 unsigned c;
5169
5170 c = columns();
5171 if (c > sizeof(prefix) - 1)
5172 c -= sizeof(prefix) - 1;
5173 else
5174 c = 0;
5175
5176 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, get_output_flags());
5177 }
5178
5179 return 0;
5180}
5181
5182static int show(int argc, char *argv[], void *userdata) {
5183 bool show_properties, show_status, show_help, new_line = false;
5184 bool ellipsized = false;
5185 int r, ret = 0;
5186 sd_bus *bus;
5187
5188 assert(argv);
5189
5190 show_properties = streq(argv[0], "show");
5191 show_status = streq(argv[0], "status");
5192 show_help = streq(argv[0], "help");
5193
5194 if (show_help && argc <= 1) {
5195 log_error("This command expects one or more unit names. Did you mean --help?");
5196 return -EINVAL;
5197 }
5198
5199 r = acquire_bus(BUS_MANAGER, &bus);
5200 if (r < 0)
5201 return r;
5202
5203 pager_open(arg_no_pager, false);
5204
5205 if (show_status)
5206 /* Increase max number of open files to 16K if we can, we
5207 * might needs this when browsing journal files, which might
5208 * be split up into many files. */
5209 setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(16384));
5210
5211 /* If no argument is specified inspect the manager itself */
5212 if (show_properties && argc <= 1)
5213 return show_one(argv[0], bus, "/org/freedesktop/systemd1", NULL, show_properties, &new_line, &ellipsized);
5214
5215 if (show_status && argc <= 1) {
5216
5217 show_system_status(bus);
5218 new_line = true;
5219
5220 if (arg_all)
5221 ret = show_all(argv[0], bus, false, &new_line, &ellipsized);
5222 } else {
5223 _cleanup_free_ char **patterns = NULL;
5224 char **name;
5225
5226 STRV_FOREACH(name, strv_skip(argv, 1)) {
5227 _cleanup_free_ char *path = NULL, *unit = NULL;
5228 uint32_t id;
5229
5230 if (safe_atou32(*name, &id) < 0) {
5231 if (strv_push(&patterns, *name) < 0)
5232 return log_oom();
5233
5234 continue;
5235 } else if (show_properties) {
5236 /* Interpret as job id */
5237 if (asprintf(&path, "/org/freedesktop/systemd1/job/%u", id) < 0)
5238 return log_oom();
5239
5240 } else {
5241 /* Interpret as PID */
5242 r = get_unit_dbus_path_by_pid(bus, id, &path);
5243 if (r < 0) {
5244 ret = r;
5245 continue;
5246 }
5247
5248 r = unit_name_from_dbus_path(path, &unit);
5249 if (r < 0)
5250 return log_oom();
5251 }
5252
5253 r = show_one(argv[0], bus, path, unit, show_properties, &new_line, &ellipsized);
5254 if (r < 0)
5255 return r;
5256 else if (r > 0 && ret == 0)
5257 ret = r;
5258 }
5259
5260 if (!strv_isempty(patterns)) {
5261 _cleanup_strv_free_ char **names = NULL;
5262
5263 r = expand_names(bus, patterns, NULL, &names);
5264 if (r < 0)
5265 return log_error_errno(r, "Failed to expand names: %m");
5266
5267 STRV_FOREACH(name, names) {
5268 _cleanup_free_ char *path;
5269
5270 path = unit_dbus_path_from_name(*name);
5271 if (!path)
5272 return log_oom();
5273
5274 r = show_one(argv[0], bus, path, *name, show_properties, &new_line, &ellipsized);
5275 if (r < 0)
5276 return r;
5277 if (r > 0 && ret == 0)
5278 ret = r;
5279 }
5280 }
5281 }
5282
5283 if (ellipsized && !arg_quiet)
5284 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
5285
5286 return ret;
5287}
5288
5289static int cat_file(const char *filename, bool newline) {
5290 _cleanup_close_ int fd;
5291
5292 fd = open(filename, O_RDONLY|O_CLOEXEC|O_NOCTTY);
5293 if (fd < 0)
5294 return -errno;
5295
5296 printf("%s%s# %s%s\n",
5297 newline ? "\n" : "",
5298 ansi_highlight_blue(),
5299 filename,
5300 ansi_normal());
5301 fflush(stdout);
5302
5303 return copy_bytes(fd, STDOUT_FILENO, (uint64_t) -1, 0);
5304}
5305
5306static int cat(int argc, char *argv[], void *userdata) {
5307 _cleanup_lookup_paths_free_ LookupPaths lp = {};
5308 _cleanup_strv_free_ char **names = NULL;
5309 char **name;
5310 sd_bus *bus;
5311 bool first = true;
5312 int r;
5313
5314 if (arg_transport != BUS_TRANSPORT_LOCAL) {
5315 log_error("Cannot remotely cat units.");
5316 return -EINVAL;
5317 }
5318
5319 r = lookup_paths_init(&lp, arg_scope, 0, arg_root);
5320 if (r < 0)
5321 return log_error_errno(r, "Failed to determine unit paths: %m");
5322
5323 r = acquire_bus(BUS_MANAGER, &bus);
5324 if (r < 0)
5325 return r;
5326
5327 r = expand_names(bus, strv_skip(argv, 1), NULL, &names);
5328 if (r < 0)
5329 return log_error_errno(r, "Failed to expand names: %m");
5330
5331 pager_open(arg_no_pager, false);
5332
5333 STRV_FOREACH(name, names) {
5334 _cleanup_free_ char *fragment_path = NULL;
5335 _cleanup_strv_free_ char **dropin_paths = NULL;
5336 char **path;
5337
5338 r = unit_find_paths(bus, *name, &lp, &fragment_path, &dropin_paths);
5339 if (r < 0)
5340 return r;
5341 else if (r == 0)
5342 return -ENOENT;
5343
5344 if (first)
5345 first = false;
5346 else
5347 puts("");
5348
5349 if (need_daemon_reload(bus, *name) > 0) /* ignore errors (<0), this is informational output */
5350 fprintf(stderr,
5351 "%s# Warning: %s changed on disk, the version systemd has loaded is outdated.\n"
5352 "%s# This output shows the current version of the unit's original fragment and drop-in files.\n"
5353 "%s# If fragments or drop-ins were added or removed, they are not properly reflected in this output.\n"
5354 "%s# Run 'systemctl%s daemon-reload' to reload units.%s\n",
5355 ansi_highlight_red(),
5356 *name,
5357 ansi_highlight_red(),
5358 ansi_highlight_red(),
5359 ansi_highlight_red(),
5360 arg_scope == UNIT_FILE_SYSTEM ? "" : " --user",
5361 ansi_normal());
5362
5363 if (fragment_path) {
5364 r = cat_file(fragment_path, false);
5365 if (r < 0)
5366 return log_warning_errno(r, "Failed to cat %s: %m", fragment_path);
5367 }
5368
5369 STRV_FOREACH(path, dropin_paths) {
5370 r = cat_file(*path, path == dropin_paths);
5371 if (r < 0)
5372 return log_warning_errno(r, "Failed to cat %s: %m", *path);
5373 }
5374 }
5375
5376 return 0;
5377}
5378
5379static int set_property(int argc, char *argv[], void *userdata) {
5380 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
5381 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5382 _cleanup_free_ char *n = NULL;
5383 sd_bus *bus;
5384 int r;
5385
5386 r = acquire_bus(BUS_MANAGER, &bus);
5387 if (r < 0)
5388 return r;
5389
5390 polkit_agent_open_if_enabled();
5391
5392 r = sd_bus_message_new_method_call(
5393 bus,
5394 &m,
5395 "org.freedesktop.systemd1",
5396 "/org/freedesktop/systemd1",
5397 "org.freedesktop.systemd1.Manager",
5398 "SetUnitProperties");
5399 if (r < 0)
5400 return bus_log_create_error(r);
5401
5402 r = unit_name_mangle(argv[1], UNIT_NAME_NOGLOB, &n);
5403 if (r < 0)
5404 return log_error_errno(r, "Failed to mangle unit name: %m");
5405
5406 r = sd_bus_message_append(m, "sb", n, arg_runtime);
5407 if (r < 0)
5408 return bus_log_create_error(r);
5409
5410 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
5411 if (r < 0)
5412 return bus_log_create_error(r);
5413
5414 r = bus_append_unit_property_assignment_many(m, strv_skip(argv, 2));
5415 if (r < 0)
5416 return r;
5417
5418 r = sd_bus_message_close_container(m);
5419 if (r < 0)
5420 return bus_log_create_error(r);
5421
5422 r = sd_bus_call(bus, m, 0, &error, NULL);
5423 if (r < 0)
5424 return log_error_errno(r, "Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
5425
5426 return 0;
5427}
5428
5429static int daemon_reload(int argc, char *argv[], void *userdata) {
5430 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5431 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
5432 const char *method;
5433 sd_bus *bus;
5434 int r;
5435
5436 r = acquire_bus(BUS_MANAGER, &bus);
5437 if (r < 0)
5438 return r;
5439
5440 polkit_agent_open_if_enabled();
5441
5442 switch (arg_action) {
5443
5444 case ACTION_RELOAD:
5445 method = "Reload";
5446 break;
5447
5448 case ACTION_REEXEC:
5449 method = "Reexecute";
5450 break;
5451
5452 case ACTION_SYSTEMCTL:
5453 method = streq(argv[0], "daemon-reexec") ? "Reexecute" :
5454 /* "daemon-reload" */ "Reload";
5455 break;
5456
5457 default:
5458 assert_not_reached("Unexpected action");
5459 }
5460
5461 r = sd_bus_message_new_method_call(
5462 bus,
5463 &m,
5464 "org.freedesktop.systemd1",
5465 "/org/freedesktop/systemd1",
5466 "org.freedesktop.systemd1.Manager",
5467 method);
5468 if (r < 0)
5469 return bus_log_create_error(r);
5470
5471 /* Note we use an extra-long timeout here. This is because a reload or reexec means generators are rerun which
5472 * are timed out after DEFAULT_TIMEOUT_USEC. Let's use twice that time here, so that the generators can have
5473 * their timeout, and for everything else there's the same time budget in place. */
5474
5475 r = sd_bus_call(bus, m, DEFAULT_TIMEOUT_USEC * 2, &error, NULL);
5476
5477 /* On reexecution, we expect a disconnect, not a reply */
5478 if (IN_SET(r, -ETIMEDOUT, -ECONNRESET) && streq(method, "Reexecute"))
5479 r = 0;
5480
5481 if (r < 0 && arg_action == ACTION_SYSTEMCTL)
5482 return log_error_errno(r, "Failed to reload daemon: %s", bus_error_message(&error, r));
5483
5484 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5485 * old ways of doing things, hence don't log any error in that case here. */
5486
5487 return r < 0 ? r : 0;
5488}
5489
5490static int trivial_method(int argc, char *argv[], void *userdata) {
5491 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5492 const char *method;
5493 sd_bus *bus;
5494 int r;
5495
5496 r = acquire_bus(BUS_MANAGER, &bus);
5497 if (r < 0)
5498 return r;
5499
5500 polkit_agent_open_if_enabled();
5501
5502 method =
5503 streq(argv[0], "clear-jobs") ||
5504 streq(argv[0], "cancel") ? "ClearJobs" :
5505 streq(argv[0], "reset-failed") ? "ResetFailed" :
5506 streq(argv[0], "halt") ? "Halt" :
5507 streq(argv[0], "reboot") ? "Reboot" :
5508 streq(argv[0], "kexec") ? "KExec" :
5509 streq(argv[0], "exit") ? "Exit" :
5510 /* poweroff */ "PowerOff";
5511
5512 r = sd_bus_call_method(
5513 bus,
5514 "org.freedesktop.systemd1",
5515 "/org/freedesktop/systemd1",
5516 "org.freedesktop.systemd1.Manager",
5517 method,
5518 &error,
5519 NULL,
5520 NULL);
5521 if (r < 0 && arg_action == ACTION_SYSTEMCTL)
5522 return log_error_errno(r, "Failed to execute operation: %s", bus_error_message(&error, r));
5523
5524 /* Note that for the legacy commands (i.e. those with action != ACTION_SYSTEMCTL) we support fallbacks to the
5525 * old ways of doing things, hence don't log any error in that case here. */
5526
5527 return r < 0 ? r : 0;
5528}
5529
5530static int reset_failed(int argc, char *argv[], void *userdata) {
5531 _cleanup_strv_free_ char **names = NULL;
5532 sd_bus *bus;
5533 char **name;
5534 int r, q;
5535
5536 if (argc <= 1)
5537 return trivial_method(argc, argv, userdata);
5538
5539 r = acquire_bus(BUS_MANAGER, &bus);
5540 if (r < 0)
5541 return r;
5542
5543 polkit_agent_open_if_enabled();
5544
5545 r = expand_names(bus, strv_skip(argv, 1), NULL, &names);
5546 if (r < 0)
5547 return log_error_errno(r, "Failed to expand names: %m");
5548
5549 STRV_FOREACH(name, names) {
5550 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5551
5552 q = sd_bus_call_method(
5553 bus,
5554 "org.freedesktop.systemd1",
5555 "/org/freedesktop/systemd1",
5556 "org.freedesktop.systemd1.Manager",
5557 "ResetFailedUnit",
5558 &error,
5559 NULL,
5560 "s", *name);
5561 if (q < 0) {
5562 log_error_errno(q, "Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q));
5563 if (r == 0)
5564 r = q;
5565 }
5566 }
5567
5568 return r;
5569}
5570
5571static int show_environment(int argc, char *argv[], void *userdata) {
5572 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5573 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
5574 const char *text;
5575 sd_bus *bus;
5576 int r;
5577
5578 r = acquire_bus(BUS_MANAGER, &bus);
5579 if (r < 0)
5580 return r;
5581
5582 pager_open(arg_no_pager, false);
5583
5584 r = sd_bus_get_property(
5585 bus,
5586 "org.freedesktop.systemd1",
5587 "/org/freedesktop/systemd1",
5588 "org.freedesktop.systemd1.Manager",
5589 "Environment",
5590 &error,
5591 &reply,
5592 "as");
5593 if (r < 0)
5594 return log_error_errno(r, "Failed to get environment: %s", bus_error_message(&error, r));
5595
5596 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
5597 if (r < 0)
5598 return bus_log_parse_error(r);
5599
5600 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
5601 puts(text);
5602 if (r < 0)
5603 return bus_log_parse_error(r);
5604
5605 r = sd_bus_message_exit_container(reply);
5606 if (r < 0)
5607 return bus_log_parse_error(r);
5608
5609 return 0;
5610}
5611
5612static int switch_root(int argc, char *argv[], void *userdata) {
5613 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5614 _cleanup_free_ char *cmdline_init = NULL;
5615 const char *root, *init;
5616 sd_bus *bus;
5617 int r;
5618
5619 if (arg_transport != BUS_TRANSPORT_LOCAL) {
5620 log_error("Cannot switch root remotely.");
5621 return -EINVAL;
5622 }
5623
5624 if (argc < 2 || argc > 3) {
5625 log_error("Wrong number of arguments.");
5626 return -EINVAL;
5627 }
5628
5629 root = argv[1];
5630
5631 if (argc >= 3)
5632 init = argv[2];
5633 else {
5634 r = parse_env_file("/proc/cmdline", WHITESPACE,
5635 "init", &cmdline_init,
5636 NULL);
5637 if (r < 0)
5638 log_debug_errno(r, "Failed to parse /proc/cmdline: %m");
5639
5640 init = cmdline_init;
5641 }
5642
5643 init = empty_to_null(init);
5644 if (init) {
5645 const char *root_systemd_path = NULL, *root_init_path = NULL;
5646
5647 root_systemd_path = strjoina(root, "/" SYSTEMD_BINARY_PATH);
5648 root_init_path = strjoina(root, "/", init);
5649
5650 /* If the passed init is actually the same as the
5651 * systemd binary, then let's suppress it. */
5652 if (files_same(root_init_path, root_systemd_path) > 0)
5653 init = NULL;
5654 }
5655
5656 /* Instruct PID1 to exclude us from its killing spree applied during
5657 * the transition. Otherwise we would exit with a failure status even
5658 * though the switch to the new root has succeed. */
5659 argv_cmdline[0] = '@';
5660
5661 r = acquire_bus(BUS_MANAGER, &bus);
5662 if (r < 0)
5663 return r;
5664
5665 /* If we are slow to exit after the root switch, the new systemd instance
5666 * will send us a signal to terminate. Just ignore it and exit normally.
5667 * This way the unit does not end up as failed.
5668 */
5669 r = ignore_signals(SIGTERM, -1);
5670 if (r < 0)
5671 log_warning_errno(r, "Failed to change disposition of SIGTERM to ignore: %m");
5672
5673 log_debug("Switching root - root: %s; init: %s", root, strna(init));
5674
5675 r = sd_bus_call_method(
5676 bus,
5677 "org.freedesktop.systemd1",
5678 "/org/freedesktop/systemd1",
5679 "org.freedesktop.systemd1.Manager",
5680 "SwitchRoot",
5681 &error,
5682 NULL,
5683 "ss", root, init);
5684 if (r < 0) {
5685 (void) default_signals(SIGTERM, -1);
5686
5687 return log_error_errno(r, "Failed to switch root: %s", bus_error_message(&error, r));
5688 }
5689
5690 return 0;
5691}
5692
5693static int set_environment(int argc, char *argv[], void *userdata) {
5694 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5695 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
5696 const char *method;
5697 sd_bus *bus;
5698 int r;
5699
5700 assert(argc > 1);
5701 assert(argv);
5702
5703 r = acquire_bus(BUS_MANAGER, &bus);
5704 if (r < 0)
5705 return r;
5706
5707 polkit_agent_open_if_enabled();
5708
5709 method = streq(argv[0], "set-environment")
5710 ? "SetEnvironment"
5711 : "UnsetEnvironment";
5712
5713 r = sd_bus_message_new_method_call(
5714 bus,
5715 &m,
5716 "org.freedesktop.systemd1",
5717 "/org/freedesktop/systemd1",
5718 "org.freedesktop.systemd1.Manager",
5719 method);
5720 if (r < 0)
5721 return bus_log_create_error(r);
5722
5723 r = sd_bus_message_append_strv(m, strv_skip(argv, 1));
5724 if (r < 0)
5725 return bus_log_create_error(r);
5726
5727 r = sd_bus_call(bus, m, 0, &error, NULL);
5728 if (r < 0)
5729 return log_error_errno(r, "Failed to set environment: %s", bus_error_message(&error, r));
5730
5731 return 0;
5732}
5733
5734static int import_environment(int argc, char *argv[], void *userdata) {
5735 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5736 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
5737 sd_bus *bus;
5738 int r;
5739
5740 r = acquire_bus(BUS_MANAGER, &bus);
5741 if (r < 0)
5742 return r;
5743
5744 polkit_agent_open_if_enabled();
5745
5746 r = sd_bus_message_new_method_call(
5747 bus,
5748 &m,
5749 "org.freedesktop.systemd1",
5750 "/org/freedesktop/systemd1",
5751 "org.freedesktop.systemd1.Manager",
5752 "SetEnvironment");
5753 if (r < 0)
5754 return bus_log_create_error(r);
5755
5756 if (argc < 2)
5757 r = sd_bus_message_append_strv(m, environ);
5758 else {
5759 char **a, **b;
5760
5761 r = sd_bus_message_open_container(m, 'a', "s");
5762 if (r < 0)
5763 return bus_log_create_error(r);
5764
5765 STRV_FOREACH(a, strv_skip(argv, 1)) {
5766
5767 if (!env_name_is_valid(*a)) {
5768 log_error("Not a valid environment variable name: %s", *a);
5769 return -EINVAL;
5770 }
5771
5772 STRV_FOREACH(b, environ) {
5773 const char *eq;
5774
5775 eq = startswith(*b, *a);
5776 if (eq && *eq == '=') {
5777
5778 r = sd_bus_message_append(m, "s", *b);
5779 if (r < 0)
5780 return bus_log_create_error(r);
5781
5782 break;
5783 }
5784 }
5785 }
5786
5787 r = sd_bus_message_close_container(m);
5788 }
5789 if (r < 0)
5790 return bus_log_create_error(r);
5791
5792 r = sd_bus_call(bus, m, 0, &error, NULL);
5793 if (r < 0)
5794 return log_error_errno(r, "Failed to import environment: %s", bus_error_message(&error, r));
5795
5796 return 0;
5797}
5798
5799static int enable_sysv_units(const char *verb, char **args) {
5800 int r = 0;
5801
5802#if defined(HAVE_SYSV_COMPAT)
5803 _cleanup_lookup_paths_free_ LookupPaths paths = {};
5804 unsigned f = 0;
5805
5806 /* Processes all SysV units, and reshuffles the array so that afterwards only the native units remain */
5807
5808 if (arg_scope != UNIT_FILE_SYSTEM)
5809 return 0;
5810
5811 if (getenv_bool("SYSTEMCTL_SKIP_SYSV") > 0)
5812 return 0;
5813
5814 if (!STR_IN_SET(verb,
5815 "enable",
5816 "disable",
5817 "is-enabled"))
5818 return 0;
5819
5820 r = lookup_paths_init(&paths, arg_scope, LOOKUP_PATHS_EXCLUDE_GENERATED, arg_root);
5821 if (r < 0)
5822 return r;
5823
5824 r = 0;
5825 while (args[f]) {
5826
5827 const char *argv[] = {
5828 ROOTLIBEXECDIR "/systemd-sysv-install",
5829 NULL,
5830 NULL,
5831 NULL,
5832 NULL,
5833 };
5834
5835 _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL;
5836 bool found_native = false, found_sysv;
5837 siginfo_t status;
5838 const char *name;
5839 unsigned c = 1;
5840 pid_t pid;
5841 int j;
5842
5843 name = args[f++];
5844
5845 if (!endswith(name, ".service"))
5846 continue;
5847
5848 if (path_is_absolute(name))
5849 continue;
5850
5851 j = unit_file_exists(arg_scope, &paths, name);
5852 if (j < 0 && !IN_SET(j, -ELOOP, -ERFKILL, -EADDRNOTAVAIL))
5853 return log_error_errno(j, "Failed to lookup unit file state: %m");
5854 found_native = j != 0;
5855
5856 /* If we have both a native unit and a SysV script, enable/disable them both (below); for is-enabled,
5857 * prefer the native unit */
5858 if (found_native && streq(verb, "is-enabled"))
5859 continue;
5860
5861 p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name);
5862 if (!p)
5863 return log_oom();
5864
5865 p[strlen(p) - strlen(".service")] = 0;
5866 found_sysv = access(p, F_OK) >= 0;
5867 if (!found_sysv)
5868 continue;
5869
5870 if (!arg_quiet) {
5871 if (found_native)
5872 log_info("Synchronizing state of %s with SysV service script with %s.", name, argv[0]);
5873 else
5874 log_info("%s is not a native service, redirecting to systemd-sysv-install.", name);
5875 }
5876
5877 if (!isempty(arg_root))
5878 argv[c++] = q = strappend("--root=", arg_root);
5879
5880 argv[c++] = verb;
5881 argv[c++] = basename(p);
5882 argv[c] = NULL;
5883
5884 l = strv_join((char**)argv, " ");
5885 if (!l)
5886 return log_oom();
5887
5888 log_info("Executing: %s", l);
5889
5890 pid = fork();
5891 if (pid < 0)
5892 return log_error_errno(errno, "Failed to fork: %m");
5893 else if (pid == 0) {
5894 /* Child */
5895
5896 (void) reset_all_signal_handlers();
5897 (void) reset_signal_mask();
5898
5899 execv(argv[0], (char**) argv);
5900 log_error_errno(errno, "Failed to execute %s: %m", argv[0]);
5901 _exit(EXIT_FAILURE);
5902 }
5903
5904 j = wait_for_terminate(pid, &status);
5905 if (j < 0)
5906 return log_error_errno(j, "Failed to wait for child: %m");
5907
5908 if (status.si_code == CLD_EXITED) {
5909 if (streq(verb, "is-enabled")) {
5910 if (status.si_status == 0) {
5911 if (!arg_quiet)
5912 puts("enabled");
5913 r = 1;
5914 } else {
5915 if (!arg_quiet)
5916 puts("disabled");
5917 }
5918
5919 } else if (status.si_status != 0)
5920 return -EBADE; /* We don't warn here, under the assumption the script already showed an explanation */
5921 } else {
5922 log_error("Unexpected waitid() result.");
5923 return -EPROTO;
5924 }
5925
5926 if (found_native)
5927 continue;
5928
5929 /* Remove this entry, so that we don't try enabling it as native unit */
5930 assert(f > 0);
5931 f--;
5932 assert(args[f] == name);
5933 strv_remove(args, name);
5934 }
5935
5936#endif
5937 return r;
5938}
5939
5940static int mangle_names(char **original_names, char ***mangled_names) {
5941 char **i, **l, **name;
5942 int r;
5943
5944 l = i = new(char*, strv_length(original_names) + 1);
5945 if (!l)
5946 return log_oom();
5947
5948 STRV_FOREACH(name, original_names) {
5949
5950 /* When enabling units qualified path names are OK,
5951 * too, hence allow them explicitly. */
5952
5953 if (is_path(*name)) {
5954 *i = strdup(*name);
5955 if (!*i) {
5956 strv_free(l);
5957 return log_oom();
5958 }
5959 } else {
5960 r = unit_name_mangle(*name, UNIT_NAME_NOGLOB, i);
5961 if (r < 0) {
5962 strv_free(l);
5963 return log_error_errno(r, "Failed to mangle unit name: %m");
5964 }
5965 }
5966
5967 i++;
5968 }
5969
5970 *i = NULL;
5971 *mangled_names = l;
5972
5973 return 0;
5974}
5975
5976static int normalize_names(char **names, bool warn_if_path) {
5977 char **u;
5978 bool was_path = false;
5979
5980 STRV_FOREACH(u, names) {
5981 int r;
5982
5983 if (!is_path(*u))
5984 continue;
5985
5986 r = free_and_strdup(u, basename(*u));
5987 if (r < 0)
5988 return log_error_errno(r, "Failed to normalize unit file path: %m");
5989
5990 was_path = true;
5991 }
5992
5993 if (warn_if_path && was_path)
5994 log_warning("Warning: Can't execute disable on the unit file path. Proceeding with the unit name.");
5995
5996 return 0;
5997}
5998
5999static int unit_exists(const char *unit) {
6000 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
6001 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
6002 _cleanup_free_ char *path = NULL;
6003 static const struct bus_properties_map property_map[] = {
6004 { "LoadState", "s", map_string_no_copy, offsetof(UnitStatusInfo, load_state) },
6005 { "ActiveState", "s", map_string_no_copy, offsetof(UnitStatusInfo, active_state)},
6006 {},
6007 };
6008 UnitStatusInfo info = {};
6009 sd_bus *bus;
6010 int r;
6011
6012 path = unit_dbus_path_from_name(unit);
6013 if (!path)
6014 return log_oom();
6015
6016 r = acquire_bus(BUS_MANAGER, &bus);
6017 if (r < 0)
6018 return r;
6019
6020 r = sd_bus_call_method(
6021 bus,
6022 "org.freedesktop.systemd1",
6023 path,
6024 "org.freedesktop.DBus.Properties",
6025 "GetAll",
6026 &error,
6027 &reply,
6028 "s", "");
6029 if (r < 0)
6030 return log_error_errno(r, "Failed to get properties: %s", bus_error_message(&error, r));
6031
6032 r = bus_message_map_all_properties(reply, property_map, &error, &info);
6033 if (r < 0)
6034 return log_error_errno(r, "Failed to map properties: %s", bus_error_message(&error, r));
6035
6036 return !streq_ptr(info.load_state, "not-found") || !streq_ptr(info.active_state, "inactive");
6037}
6038
6039static int enable_unit(int argc, char *argv[], void *userdata) {
6040 _cleanup_strv_free_ char **names = NULL;
6041 const char *verb = argv[0];
6042 UnitFileChange *changes = NULL;
6043 unsigned n_changes = 0;
6044 int carries_install_info = -1;
6045 bool ignore_carries_install_info = arg_quiet;
6046 int r;
6047
6048 if (!argv[1])
6049 return 0;
6050
6051 r = mangle_names(strv_skip(argv, 1), &names);
6052 if (r < 0)
6053 return r;
6054
6055 r = enable_sysv_units(verb, names);
6056 if (r < 0)
6057 return r;
6058
6059 /* If the operation was fully executed by the SysV compat, let's finish early */
6060 if (strv_isempty(names)) {
6061 if (arg_no_reload || install_client_side())
6062 return 0;
6063 return daemon_reload(argc, argv, userdata);
6064 }
6065
6066 if (streq(verb, "disable")) {
6067 r = normalize_names(names, true);
6068 if (r < 0)
6069 return r;
6070 }
6071
6072 if (install_client_side()) {
6073 UnitFileFlags flags;
6074
6075 flags = args_to_flags();
6076 if (streq(verb, "enable")) {
6077 r = unit_file_enable(arg_scope, flags, arg_root, names, &changes, &n_changes);
6078 carries_install_info = r;
6079 } else if (streq(verb, "disable"))
6080 r = unit_file_disable(arg_scope, flags, arg_root, names, &changes, &n_changes);
6081 else if (streq(verb, "reenable")) {
6082 r = unit_file_reenable(arg_scope, flags, arg_root, names, &changes, &n_changes);
6083 carries_install_info = r;
6084 } else if (streq(verb, "link"))
6085 r = unit_file_link(arg_scope, flags, arg_root, names, &changes, &n_changes);
6086 else if (streq(verb, "preset")) {
6087 r = unit_file_preset(arg_scope, flags, arg_root, names, arg_preset_mode, &changes, &n_changes);
6088 } else if (streq(verb, "mask"))
6089 r = unit_file_mask(arg_scope, flags, arg_root, names, &changes, &n_changes);
6090 else if (streq(verb, "unmask"))
6091 r = unit_file_unmask(arg_scope, flags, arg_root, names, &changes, &n_changes);
6092 else if (streq(verb, "revert"))
6093 r = unit_file_revert(arg_scope, arg_root, names, &changes, &n_changes);
6094 else
6095 assert_not_reached("Unknown verb");
6096
6097 unit_file_dump_changes(r, verb, changes, n_changes, arg_quiet);
6098 if (r < 0)
6099 goto finish;
6100 r = 0;
6101 } else {
6102 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
6103 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
6104 bool expect_carries_install_info = false;
6105 bool send_runtime = true, send_force = true, send_preset_mode = false;
6106 const char *method;
6107 sd_bus *bus;
6108
6109 if (STR_IN_SET(verb, "mask", "unmask")) {
6110 r = unit_exists(*names);
6111 if (r < 0)
6112 return r;
6113 if (r == 0)
6114 log_notice("Unit %s does not exist, proceeding anyway.", *names);
6115 }
6116
6117 r = acquire_bus(BUS_MANAGER, &bus);
6118 if (r < 0)
6119 return r;
6120
6121 polkit_agent_open_if_enabled();
6122
6123 if (streq(verb, "enable")) {
6124 method = "EnableUnitFiles";
6125 expect_carries_install_info = true;
6126 } else if (streq(verb, "disable")) {
6127 method = "DisableUnitFiles";
6128 send_force = false;
6129 } else if (streq(verb, "reenable")) {
6130 method = "ReenableUnitFiles";
6131 expect_carries_install_info = true;
6132 } else if (streq(verb, "link"))
6133 method = "LinkUnitFiles";
6134 else if (streq(verb, "preset")) {
6135
6136 if (arg_preset_mode != UNIT_FILE_PRESET_FULL) {
6137 method = "PresetUnitFilesWithMode";
6138 send_preset_mode = true;
6139 } else
6140 method = "PresetUnitFiles";
6141
6142 expect_carries_install_info = true;
6143 ignore_carries_install_info = true;
6144 } else if (streq(verb, "mask"))
6145 method = "MaskUnitFiles";
6146 else if (streq(verb, "unmask")) {
6147 method = "UnmaskUnitFiles";
6148 send_force = false;
6149 } else if (streq(verb, "revert")) {
6150 method = "RevertUnitFiles";
6151 send_runtime = send_force = false;
6152 } else
6153 assert_not_reached("Unknown verb");
6154
6155 r = sd_bus_message_new_method_call(
6156 bus,
6157 &m,
6158 "org.freedesktop.systemd1",
6159 "/org/freedesktop/systemd1",
6160 "org.freedesktop.systemd1.Manager",
6161 method);
6162 if (r < 0)
6163 return bus_log_create_error(r);
6164
6165 r = sd_bus_message_append_strv(m, names);
6166 if (r < 0)
6167 return bus_log_create_error(r);
6168
6169 if (send_preset_mode) {
6170 r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode));
6171 if (r < 0)
6172 return bus_log_create_error(r);
6173 }
6174
6175 if (send_runtime) {
6176 r = sd_bus_message_append(m, "b", arg_runtime);
6177 if (r < 0)
6178 return bus_log_create_error(r);
6179 }
6180
6181 if (send_force) {
6182 r = sd_bus_message_append(m, "b", arg_force);
6183 if (r < 0)
6184 return bus_log_create_error(r);
6185 }
6186
6187 r = sd_bus_call(bus, m, 0, &error, &reply);
6188 if (r < 0)
6189 return log_error_errno(r, "Failed to %s unit: %s", verb, bus_error_message(&error, r));
6190
6191 if (expect_carries_install_info) {
6192 r = sd_bus_message_read(reply, "b", &carries_install_info);
6193 if (r < 0)
6194 return bus_log_parse_error(r);
6195 }
6196
6197 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes);
6198 if (r < 0)
6199 goto finish;
6200
6201 /* Try to reload if enabled */
6202 if (!arg_no_reload)
6203 r = daemon_reload(argc, argv, userdata);
6204 else
6205 r = 0;
6206 }
6207
6208 if (carries_install_info == 0 && !ignore_carries_install_info)
6209 log_warning("The unit files have no installation config (WantedBy, RequiredBy, Also, Alias\n"
6210 "settings in the [Install] section, and DefaultInstance for template units).\n"
6211 "This means they are not meant to be enabled using systemctl.\n"
6212 "Possible reasons for having this kind of units are:\n"
6213 "1) A unit may be statically enabled by being symlinked from another unit's\n"
6214 " .wants/ or .requires/ directory.\n"
6215 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
6216 " a requirement dependency on it.\n"
6217 "3) A unit may be started when needed via activation (socket, path, timer,\n"
6218 " D-Bus, udev, scripted systemctl call, ...).\n"
6219 "4) In case of template units, the unit is meant to be enabled with some\n"
6220 " instance name specified.");
6221
6222 if (arg_now && STR_IN_SET(argv[0], "enable", "disable", "mask")) {
6223 sd_bus *bus;
6224 unsigned len, i;
6225
6226 r = acquire_bus(BUS_MANAGER, &bus);
6227 if (r < 0)
6228 goto finish;
6229
6230 len = strv_length(names);
6231 {
6232 char *new_args[len + 2];
6233
6234 new_args[0] = (char*) (streq(argv[0], "enable") ? "start" : "stop");
6235 for (i = 0; i < len; i++)
6236 new_args[i + 1] = basename(names[i]);
6237 new_args[i + 1] = NULL;
6238
6239 r = start_unit(len + 1, new_args, userdata);
6240 }
6241 }
6242
6243finish:
6244 unit_file_changes_free(changes, n_changes);
6245
6246 return r;
6247}
6248
6249static int add_dependency(int argc, char *argv[], void *userdata) {
6250 _cleanup_strv_free_ char **names = NULL;
6251 _cleanup_free_ char *target = NULL;
6252 const char *verb = argv[0];
6253 UnitFileChange *changes = NULL;
6254 unsigned n_changes = 0;
6255 UnitDependency dep;
6256 int r = 0;
6257
6258 if (!argv[1])
6259 return 0;
6260
6261 r = unit_name_mangle_with_suffix(argv[1], UNIT_NAME_NOGLOB, ".target", &target);
6262 if (r < 0)
6263 return log_error_errno(r, "Failed to mangle unit name: %m");
6264
6265 r = mangle_names(strv_skip(argv, 2), &names);
6266 if (r < 0)
6267 return r;
6268
6269 if (streq(verb, "add-wants"))
6270 dep = UNIT_WANTS;
6271 else if (streq(verb, "add-requires"))
6272 dep = UNIT_REQUIRES;
6273 else
6274 assert_not_reached("Unknown verb");
6275
6276 if (install_client_side()) {
6277 r = unit_file_add_dependency(arg_scope, args_to_flags(), arg_root, names, target, dep, &changes, &n_changes);
6278 unit_file_dump_changes(r, "add dependency on", changes, n_changes, arg_quiet);
6279
6280 if (r > 0)
6281 r = 0;
6282 } else {
6283 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
6284 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
6285 sd_bus *bus;
6286
6287 r = acquire_bus(BUS_MANAGER, &bus);
6288 if (r < 0)
6289 return r;
6290
6291 polkit_agent_open_if_enabled();
6292
6293 r = sd_bus_message_new_method_call(
6294 bus,
6295 &m,
6296 "org.freedesktop.systemd1",
6297 "/org/freedesktop/systemd1",
6298 "org.freedesktop.systemd1.Manager",
6299 "AddDependencyUnitFiles");
6300 if (r < 0)
6301 return bus_log_create_error(r);
6302
6303 r = sd_bus_message_append_strv(m, names);
6304 if (r < 0)
6305 return bus_log_create_error(r);
6306
6307 r = sd_bus_message_append(m, "ssbb", target, unit_dependency_to_string(dep), arg_runtime, arg_force);
6308 if (r < 0)
6309 return bus_log_create_error(r);
6310
6311 r = sd_bus_call(bus, m, 0, &error, &reply);
6312 if (r < 0)
6313 return log_error_errno(r, "Failed to add dependency: %s", bus_error_message(&error, r));
6314
6315 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes);
6316 if (r < 0)
6317 goto finish;
6318
6319 if (arg_no_reload) {
6320 r = 0;
6321 goto finish;
6322 }
6323
6324 r = daemon_reload(argc, argv, userdata);
6325 }
6326
6327finish:
6328 unit_file_changes_free(changes, n_changes);
6329
6330 return r;
6331}
6332
6333static int preset_all(int argc, char *argv[], void *userdata) {
6334 UnitFileChange *changes = NULL;
6335 unsigned n_changes = 0;
6336 int r;
6337
6338 if (install_client_side()) {
6339 r = unit_file_preset_all(arg_scope, args_to_flags(), arg_root, arg_preset_mode, &changes, &n_changes);
6340 unit_file_dump_changes(r, "preset", changes, n_changes, arg_quiet);
6341
6342 if (r > 0)
6343 r = 0;
6344 } else {
6345 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
6346 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
6347 sd_bus *bus;
6348
6349 r = acquire_bus(BUS_MANAGER, &bus);
6350 if (r < 0)
6351 return r;
6352
6353 polkit_agent_open_if_enabled();
6354
6355 r = sd_bus_call_method(
6356 bus,
6357 "org.freedesktop.systemd1",
6358 "/org/freedesktop/systemd1",
6359 "org.freedesktop.systemd1.Manager",
6360 "PresetAllUnitFiles",
6361 &error,
6362 &reply,
6363 "sbb",
6364 unit_file_preset_mode_to_string(arg_preset_mode),
6365 arg_runtime,
6366 arg_force);
6367 if (r < 0)
6368 return log_error_errno(r, "Failed to preset all units: %s", bus_error_message(&error, r));
6369
6370 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes);
6371 if (r < 0)
6372 goto finish;
6373
6374 if (arg_no_reload) {
6375 r = 0;
6376 goto finish;
6377 }
6378
6379 r = daemon_reload(argc, argv, userdata);
6380 }
6381
6382finish:
6383 unit_file_changes_free(changes, n_changes);
6384
6385 return r;
6386}
6387
6388static int show_installation_targets_client_side(const char *name) {
6389 UnitFileChange *changes = NULL;
6390 unsigned n_changes = 0, i;
6391 UnitFileFlags flags;
6392 char **p;
6393 int r;
6394
6395 p = STRV_MAKE(name);
6396 flags = UNIT_FILE_DRY_RUN |
6397 (arg_runtime ? UNIT_FILE_RUNTIME : 0);
6398
6399 r = unit_file_disable(UNIT_FILE_SYSTEM, flags, NULL, p, &changes, &n_changes);
6400 if (r < 0)
6401 return log_error_errno(r, "Failed to get file links for %s: %m", name);
6402
6403 for (i = 0; i < n_changes; i++)
6404 if (changes[i].type == UNIT_FILE_UNLINK)
6405 printf(" %s\n", changes[i].path);
6406
6407 return 0;
6408}
6409
6410static int show_installation_targets(sd_bus *bus, const char *name) {
6411 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
6412 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
6413 const char *link;
6414 int r;
6415
6416 r = sd_bus_call_method(
6417 bus,
6418 "org.freedesktop.systemd1",
6419 "/org/freedesktop/systemd1",
6420 "org.freedesktop.systemd1.Manager",
6421 "GetUnitFileLinks",
6422 &error,
6423 &reply,
6424 "sb", name, arg_runtime);
6425 if (r < 0)
6426 return log_error_errno(r, "Failed to get unit file links for %s: %s", name, bus_error_message(&error, r));
6427
6428 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
6429 if (r < 0)
6430 return bus_log_parse_error(r);
6431
6432 while ((r = sd_bus_message_read(reply, "s", &link)) > 0)
6433 printf(" %s\n", link);
6434
6435 if (r < 0)
6436 return bus_log_parse_error(r);
6437
6438 r = sd_bus_message_exit_container(reply);
6439 if (r < 0)
6440 return bus_log_parse_error(r);
6441
6442 return 0;
6443}
6444
6445static int unit_is_enabled(int argc, char *argv[], void *userdata) {
6446
6447 _cleanup_strv_free_ char **names = NULL;
6448 bool enabled;
6449 char **name;
6450 int r;
6451
6452 r = mangle_names(strv_skip(argv, 1), &names);
6453 if (r < 0)
6454 return r;
6455
6456 r = enable_sysv_units(argv[0], names);
6457 if (r < 0)
6458 return r;
6459
6460 enabled = r > 0;
6461
6462 if (install_client_side()) {
6463 STRV_FOREACH(name, names) {
6464 UnitFileState state;
6465
6466 r = unit_file_get_state(arg_scope, arg_root, *name, &state);
6467 if (r < 0)
6468 return log_error_errno(r, "Failed to get unit file state for %s: %m", *name);
6469
6470 if (IN_SET(state,
6471 UNIT_FILE_ENABLED,
6472 UNIT_FILE_ENABLED_RUNTIME,
6473 UNIT_FILE_STATIC,
6474 UNIT_FILE_INDIRECT,
6475 UNIT_FILE_GENERATED))
6476 enabled = true;
6477
6478 if (!arg_quiet) {
6479 puts(unit_file_state_to_string(state));
6480 if (arg_full) {
6481 r = show_installation_targets_client_side(*name);
6482 if (r < 0)
6483 return r;
6484 }
6485 }
6486 }
6487
6488 r = 0;
6489 } else {
6490 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
6491 sd_bus *bus;
6492
6493 r = acquire_bus(BUS_MANAGER, &bus);
6494 if (r < 0)
6495 return r;
6496
6497 STRV_FOREACH(name, names) {
6498 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
6499 const char *s;
6500
6501 r = sd_bus_call_method(
6502 bus,
6503 "org.freedesktop.systemd1",
6504 "/org/freedesktop/systemd1",
6505 "org.freedesktop.systemd1.Manager",
6506 "GetUnitFileState",
6507 &error,
6508 &reply,
6509 "s", *name);
6510 if (r < 0)
6511 return log_error_errno(r, "Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
6512
6513 r = sd_bus_message_read(reply, "s", &s);
6514 if (r < 0)
6515 return bus_log_parse_error(r);
6516
6517 if (STR_IN_SET(s, "enabled", "enabled-runtime", "static", "indirect", "generated"))
6518 enabled = true;
6519
6520 if (!arg_quiet) {
6521 puts(s);
6522 if (arg_full) {
6523 r = show_installation_targets(bus, *name);
6524 if (r < 0)
6525 return r;
6526 }
6527 }
6528 }
6529 }
6530
6531 return enabled ? EXIT_SUCCESS : EXIT_FAILURE;
6532}
6533
6534static int is_system_running(int argc, char *argv[], void *userdata) {
6535 _cleanup_free_ char *state = NULL;
6536 sd_bus *bus;
6537 int r;
6538
6539 if (running_in_chroot() > 0 || (arg_transport == BUS_TRANSPORT_LOCAL && !sd_booted())) {
6540 if (!arg_quiet)
6541 puts("offline");
6542 return EXIT_FAILURE;
6543 }
6544
6545 r = acquire_bus(BUS_MANAGER, &bus);
6546 if (r < 0)
6547 return r;
6548
6549 r = sd_bus_get_property_string(
6550 bus,
6551 "org.freedesktop.systemd1",
6552 "/org/freedesktop/systemd1",
6553 "org.freedesktop.systemd1.Manager",
6554 "SystemState",
6555 NULL,
6556 &state);
6557 if (r < 0) {
6558 if (!arg_quiet)
6559 puts("unknown");
6560 return 0;
6561 }
6562
6563 if (!arg_quiet)
6564 puts(state);
6565
6566 return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE;
6567}
6568
6569static int create_edit_temp_file(const char *new_path, const char *original_path, char **ret_tmp_fn) {
6570 _cleanup_free_ char *t = NULL;
6571 int r;
6572
6573 assert(new_path);
6574 assert(original_path);
6575 assert(ret_tmp_fn);
6576
6577 r = tempfn_random(new_path, NULL, &t);
6578 if (r < 0)
6579 return log_error_errno(r, "Failed to determine temporary filename for \"%s\": %m", new_path);
6580
6581 r = mkdir_parents(new_path, 0755);
6582 if (r < 0)
6583 return log_error_errno(r, "Failed to create directories for \"%s\": %m", new_path);
6584
6585 r = copy_file(original_path, t, 0, 0644, 0, COPY_REFLINK);
6586 if (r == -ENOENT) {
6587
6588 r = touch(t);
6589 if (r < 0)
6590 return log_error_errno(r, "Failed to create temporary file \"%s\": %m", t);
6591
6592 } else if (r < 0)
6593 return log_error_errno(r, "Failed to create temporary file for \"%s\": %m", new_path);
6594
6595 *ret_tmp_fn = t;
6596 t = NULL;
6597
6598 return 0;
6599}
6600
6601static int get_file_to_edit(
6602 const LookupPaths *paths,
6603 const char *name,
6604 char **ret_path) {
6605
6606 _cleanup_free_ char *path = NULL, *run = NULL;
6607
6608 assert(name);
6609 assert(ret_path);
6610
6611 path = strjoin(paths->persistent_config, "/", name);
6612 if (!path)
6613 return log_oom();
6614
6615 if (arg_runtime) {
6616 run = strjoin(paths->runtime_config, "/", name);
6617 if (!run)
6618 return log_oom();
6619 }
6620
6621 if (arg_runtime) {
6622 if (access(path, F_OK) >= 0) {
6623 log_error("Refusing to create \"%s\" because it would be overridden by \"%s\" anyway.", run, path);
6624 return -EEXIST;
6625 }
6626
6627 *ret_path = run;
6628 run = NULL;
6629 } else {
6630 *ret_path = path;
6631 path = NULL;
6632 }
6633
6634 return 0;
6635}
6636
6637static int unit_file_create_new(
6638 const LookupPaths *paths,
6639 const char *unit_name,
6640 const char *suffix,
6641 char **ret_new_path,
6642 char **ret_tmp_path) {
6643
6644 char *tmp_new_path, *tmp_tmp_path, *ending;
6645 int r;
6646
6647 assert(unit_name);
6648 assert(ret_new_path);
6649 assert(ret_tmp_path);
6650
6651 ending = strjoina(unit_name, suffix);
6652 r = get_file_to_edit(paths, ending, &tmp_new_path);
6653 if (r < 0)
6654 return r;
6655
6656 r = create_edit_temp_file(tmp_new_path, tmp_new_path, &tmp_tmp_path);
6657 if (r < 0) {
6658 free(tmp_new_path);
6659 return r;
6660 }
6661
6662 *ret_new_path = tmp_new_path;
6663 *ret_tmp_path = tmp_tmp_path;
6664
6665 return 0;
6666}
6667
6668static int unit_file_create_copy(
6669 const LookupPaths *paths,
6670 const char *unit_name,
6671 const char *fragment_path,
6672 char **ret_new_path,
6673 char **ret_tmp_path) {
6674
6675 char *tmp_new_path, *tmp_tmp_path;
6676 int r;
6677
6678 assert(fragment_path);
6679 assert(unit_name);
6680 assert(ret_new_path);
6681 assert(ret_tmp_path);
6682
6683 r = get_file_to_edit(paths, unit_name, &tmp_new_path);
6684 if (r < 0)
6685 return r;
6686
6687 if (!path_equal(fragment_path, tmp_new_path) && access(tmp_new_path, F_OK) == 0) {
6688 char response;
6689
6690 r = ask_char(&response, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path, fragment_path);
6691 if (r < 0) {
6692 free(tmp_new_path);
6693 return r;
6694 }
6695 if (response != 'y') {
6696 log_warning("%s ignored", unit_name);
6697 free(tmp_new_path);
6698 return -EKEYREJECTED;
6699 }
6700 }
6701
6702 r = create_edit_temp_file(tmp_new_path, fragment_path, &tmp_tmp_path);
6703 if (r < 0) {
6704 free(tmp_new_path);
6705 return r;
6706 }
6707
6708 *ret_new_path = tmp_new_path;
6709 *ret_tmp_path = tmp_tmp_path;
6710
6711 return 0;
6712}
6713
6714static int run_editor(char **paths) {
6715 pid_t pid;
6716 int r;
6717
6718 assert(paths);
6719
6720 pid = fork();
6721 if (pid < 0)
6722 return log_error_errno(errno, "Failed to fork: %m");
6723
6724 if (pid == 0) {
6725 const char **args;
6726 char *editor, **editor_args = NULL;
6727 char **tmp_path, **original_path, *p;
6728 unsigned n_editor_args = 0, i = 1;
6729 size_t argc;
6730
6731 (void) reset_all_signal_handlers();
6732 (void) reset_signal_mask();
6733
6734 argc = strv_length(paths)/2 + 1;
6735
6736 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
6737 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
6738 * we try to execute well known editors
6739 */
6740 editor = getenv("SYSTEMD_EDITOR");
6741 if (!editor)
6742 editor = getenv("EDITOR");
6743 if (!editor)
6744 editor = getenv("VISUAL");
6745
6746 if (!isempty(editor)) {
6747 editor_args = strv_split(editor, WHITESPACE);
6748 if (!editor_args) {
6749 (void) log_oom();
6750 _exit(EXIT_FAILURE);
6751 }
6752 n_editor_args = strv_length(editor_args);
6753 argc += n_editor_args - 1;
6754 }
6755 args = newa(const char*, argc + 1);
6756
6757 if (n_editor_args > 0) {
6758 args[0] = editor_args[0];
6759 for (; i < n_editor_args; i++)
6760 args[i] = editor_args[i];
6761 }
6762
6763 STRV_FOREACH_PAIR(original_path, tmp_path, paths) {
6764 args[i] = *tmp_path;
6765 i++;
6766 }
6767 args[i] = NULL;
6768
6769 if (n_editor_args > 0)
6770 execvp(args[0], (char* const*) args);
6771
6772 FOREACH_STRING(p, "editor", "nano", "vim", "vi") {
6773 args[0] = p;
6774 execvp(p, (char* const*) args);
6775 /* We do not fail if the editor doesn't exist
6776 * because we want to try each one of them before
6777 * failing.
6778 */
6779 if (errno != ENOENT) {
6780 log_error_errno(errno, "Failed to execute %s: %m", editor);
6781 _exit(EXIT_FAILURE);
6782 }
6783 }
6784
6785 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
6786 _exit(EXIT_FAILURE);
6787 }
6788
6789 r = wait_for_terminate_and_warn("editor", pid, true);
6790 if (r < 0)
6791 return log_error_errno(r, "Failed to wait for child: %m");
6792
6793 return 0;
6794}
6795
6796static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
6797 _cleanup_lookup_paths_free_ LookupPaths lp = {};
6798 char **name;
6799 int r;
6800
6801 assert(names);
6802 assert(paths);
6803
6804 r = lookup_paths_init(&lp, arg_scope, 0, arg_root);
6805 if (r < 0)
6806 return r;
6807
6808 STRV_FOREACH(name, names) {
6809 _cleanup_free_ char *path = NULL, *new_path = NULL, *tmp_path = NULL, *tmp_name = NULL;
6810 const char *unit_name;
6811
6812 r = unit_find_paths(bus, *name, &lp, &path, NULL);
6813 if (r < 0)
6814 return r;
6815 else if (!arg_force) {
6816 if (r == 0) {
6817 log_error("Run 'systemctl edit --force %s' to create a new unit.", *name);
6818 return -ENOENT;
6819 } else if (!path) {
6820 // FIXME: support units with path==NULL (no FragmentPath)
6821 log_error("No fragment exists for %s.", *name);
6822 return -ENOENT;
6823 }
6824 }
6825
6826 unit_name = basename(path);
6827 /* We follow unit aliases, but we need to propagate the instance */
6828 if (unit_name_is_valid(*name, UNIT_NAME_INSTANCE) &&
6829 unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) {
6830 _cleanup_free_ char *instance = NULL;
6831
6832 r = unit_name_to_instance(*name, &instance);
6833 if (r < 0)
6834 return r;
6835
6836 r = unit_name_replace_instance(unit_name, instance, &tmp_name);
6837 if (r < 0)
6838 return r;
6839
6840 unit_name = tmp_name;
6841 }
6842
6843 if (path) {
6844 if (arg_full)
6845 r = unit_file_create_copy(&lp, unit_name, path, &new_path, &tmp_path);
6846 else
6847 r = unit_file_create_new(&lp, unit_name, ".d/override.conf", &new_path, &tmp_path);
6848 } else
6849 r = unit_file_create_new(&lp, *name, NULL, &new_path, &tmp_path);
6850 if (r < 0)
6851 return r;
6852
6853 r = strv_push_pair(paths, new_path, tmp_path);
6854 if (r < 0)
6855 return log_oom();
6856 new_path = tmp_path = NULL;
6857 }
6858
6859 return 0;
6860}
6861
6862static int edit(int argc, char *argv[], void *userdata) {
6863 _cleanup_strv_free_ char **names = NULL;
6864 _cleanup_strv_free_ char **paths = NULL;
6865 char **original, **tmp;
6866 sd_bus *bus;
6867 int r;
6868
6869 if (!on_tty()) {
6870 log_error("Cannot edit units if not on a tty.");
6871 return -EINVAL;
6872 }
6873
6874 if (arg_transport != BUS_TRANSPORT_LOCAL) {
6875 log_error("Cannot edit units remotely.");
6876 return -EINVAL;
6877 }
6878
6879 r = acquire_bus(BUS_MANAGER, &bus);
6880 if (r < 0)
6881 return r;
6882
6883 r = expand_names(bus, strv_skip(argv, 1), NULL, &names);
6884 if (r < 0)
6885 return log_error_errno(r, "Failed to expand names: %m");
6886
6887 r = find_paths_to_edit(bus, names, &paths);
6888 if (r < 0)
6889 return r;
6890
6891 if (strv_isempty(paths))
6892 return -ENOENT;
6893
6894 r = run_editor(paths);
6895 if (r < 0)
6896 goto end;
6897
6898 STRV_FOREACH_PAIR(original, tmp, paths) {
6899 /* If the temporary file is empty we ignore it. It's
6900 * useful if the user wants to cancel its modification
6901 */
6902 if (null_or_empty_path(*tmp)) {
6903 log_warning("Editing \"%s\" canceled: temporary file is empty.", *original);
6904 continue;
6905 }
6906
6907 r = rename(*tmp, *original);
6908 if (r < 0) {
6909 r = log_error_errno(errno, "Failed to rename \"%s\" to \"%s\": %m", *tmp, *original);
6910 goto end;
6911 }
6912 }
6913
6914 r = 0;
6915
6916 if (!arg_no_reload && !install_client_side())
6917 r = daemon_reload(argc, argv, userdata);
6918
6919end:
6920 STRV_FOREACH_PAIR(original, tmp, paths) {
6921 (void) unlink(*tmp);
6922
6923 /* Removing empty dropin dirs */
6924 if (!arg_full) {
6925 _cleanup_free_ char *dir;
6926
6927 dir = dirname_malloc(*original);
6928 if (!dir)
6929 return log_oom();
6930
6931 /* no need to check if the dir is empty, rmdir
6932 * does nothing if it is not the case.
6933 */
6934 (void) rmdir(dir);
6935 }
6936 }
6937
6938 return r;
6939}
6940
6941static void systemctl_help(void) {
6942
6943 pager_open(arg_no_pager, false);
6944
6945 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
6946 "Query or send control commands to the systemd manager.\n\n"
6947 " -h --help Show this help\n"
6948 " --version Show package version\n"
6949 " --system Connect to system manager\n"
6950 " --user Connect to user service manager\n"
6951 " -H --host=[USER@]HOST\n"
6952 " Operate on remote host\n"
6953 " -M --machine=CONTAINER\n"
6954 " Operate on local container\n"
6955 " -t --type=TYPE List units of a particular type\n"
6956 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
6957 " -p --property=NAME Show only properties by this name\n"
6958 " -a --all Show all properties/all units currently in memory,\n"
6959 " including dead/empty ones. To list all units installed on\n"
6960 " the system, use the 'list-unit-files' command instead.\n"
6961 " --failed Same as --state=failed\n"
6962 " -l --full Don't ellipsize unit names on output\n"
6963 " -r --recursive Show unit list of host and local containers\n"
6964 " --reverse Show reverse dependencies with 'list-dependencies'\n"
6965 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
6966 " queueing a new job\n"
6967 " --show-types When showing sockets, explicitly show their type\n"
6968 " --value When showing properties, only print the value\n"
6969 " -i --ignore-inhibitors\n"
6970 " When shutting down or sleeping, ignore inhibitors\n"
6971 " --kill-who=WHO Who to send signal to\n"
6972 " -s --signal=SIGNAL Which signal to send\n"
6973 " --now Start or stop unit in addition to enabling or disabling it\n"
6974 " -q --quiet Suppress output\n"
6975 " --wait For (re)start, wait until service stopped again\n"
6976 " --no-block Do not wait until operation finished\n"
6977 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6978 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
6979 " --no-legend Do not print a legend (column headers and hints)\n"
6980 " --no-pager Do not pipe output into a pager\n"
6981 " --no-ask-password\n"
6982 " Do not ask for system passwords\n"
6983 " --global Enable/disable unit files globally\n"
6984 " --runtime Enable unit files only temporarily until next reboot\n"
6985 " -f --force When enabling unit files, override existing symlinks\n"
6986 " When shutting down, execute action immediately\n"
6987 " --preset-mode= Apply only enable, only disable, or all presets\n"
6988 " --root=PATH Enable unit files in the specified root directory\n"
6989 " -n --lines=INTEGER Number of journal entries to show\n"
6990 " -o --output=STRING Change journal output mode (short, short-precise,\n"
6991 " short-iso, short-full, short-monotonic, short-unix,\n"
6992 " verbose, export, json, json-pretty, json-sse, cat)\n"
6993 " --firmware-setup Tell the firmware to show the setup menu on next boot\n"
6994 " --plain Print unit dependencies as a list instead of a tree\n\n"
6995 "Unit Commands:\n"
6996 " list-units [PATTERN...] List units currently in memory\n"
6997 " list-sockets [PATTERN...] List socket units currently in memory, ordered\n"
6998 " by address\n"
6999 " list-timers [PATTERN...] List timer units currently in memory, ordered\n"
7000 " by next elapse\n"
7001 " start NAME... Start (activate) one or more units\n"
7002 " stop NAME... Stop (deactivate) one or more units\n"
7003 " reload NAME... Reload one or more units\n"
7004 " restart NAME... Start or restart one or more units\n"
7005 " try-restart NAME... Restart one or more units if active\n"
7006 " reload-or-restart NAME... Reload one or more units if possible,\n"
7007 " otherwise start or restart\n"
7008 " try-reload-or-restart NAME... If active, reload one or more units,\n"
7009 " if supported, otherwise restart\n"
7010 " isolate NAME Start one unit and stop all others\n"
7011 " kill NAME... Send signal to processes of a unit\n"
7012 " is-active PATTERN... Check whether units are active\n"
7013 " is-failed PATTERN... Check whether units are failed\n"
7014 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
7015 " show [PATTERN...|JOB...] Show properties of one or more\n"
7016 " units/jobs or the manager\n"
7017 " cat PATTERN... Show files and drop-ins of one or more units\n"
7018 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
7019 " help PATTERN...|PID... Show manual for one or more units\n"
7020 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
7021 " units\n"
7022 " list-dependencies [NAME] Recursively show units which are required\n"
7023 " or wanted by this unit or by which this\n"
7024 " unit is required or wanted\n\n"
7025 "Unit File Commands:\n"
7026 " list-unit-files [PATTERN...] List installed unit files\n"
7027 " enable [NAME...|PATH...] Enable one or more unit files\n"
7028 " disable NAME... Disable one or more unit files\n"
7029 " reenable NAME... Reenable one or more unit files\n"
7030 " preset NAME... Enable/disable one or more unit files\n"
7031 " based on preset configuration\n"
7032 " preset-all Enable/disable all unit files based on\n"
7033 " preset configuration\n"
7034 " is-enabled NAME... Check whether unit files are enabled\n"
7035 " mask NAME... Mask one or more units\n"
7036 " unmask NAME... Unmask one or more units\n"
7037 " link PATH... Link one or more units files into\n"
7038 " the search path\n"
7039 " revert NAME... Revert one or more unit files to vendor\n"
7040 " version\n"
7041 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
7042 " on specified one or more units\n"
7043 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
7044 " on specified one or more units\n"
7045 " edit NAME... Edit one or more unit files\n"
7046 " get-default Get the name of the default target\n"
7047 " set-default NAME Set the default target\n\n"
7048 "Machine Commands:\n"
7049 " list-machines [PATTERN...] List local containers and host\n\n"
7050 "Job Commands:\n"
7051 " list-jobs [PATTERN...] List jobs\n"
7052 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
7053 "Environment Commands:\n"
7054 " show-environment Dump environment\n"
7055 " set-environment NAME=VALUE... Set one or more environment variables\n"
7056 " unset-environment NAME... Unset one or more environment variables\n"
7057 " import-environment [NAME...] Import all or some environment variables\n\n"
7058 "Manager Lifecycle Commands:\n"
7059 " daemon-reload Reload systemd manager configuration\n"
7060 " daemon-reexec Reexecute systemd manager\n\n"
7061 "System Commands:\n"
7062 " is-system-running Check whether system is fully running\n"
7063 " default Enter system default mode\n"
7064 " rescue Enter system rescue mode\n"
7065 " emergency Enter system emergency mode\n"
7066 " halt Shut down and halt the system\n"
7067 " poweroff Shut down and power-off the system\n"
7068 " reboot [ARG] Shut down and reboot the system\n"
7069 " kexec Shut down and reboot the system with kexec\n"
7070 " exit [EXIT_CODE] Request user instance or container exit\n"
7071 " switch-root ROOT [INIT] Change to a different root file system\n"
7072 " suspend Suspend the system\n"
7073 " hibernate Hibernate the system\n"
7074 " hybrid-sleep Hibernate and suspend the system\n",
7075 program_invocation_short_name);
7076}
7077
7078static void halt_help(void) {
7079 printf("%s [OPTIONS...]%s\n\n"
7080 "%s the system.\n\n"
7081 " --help Show this help\n"
7082 " --halt Halt the machine\n"
7083 " -p --poweroff Switch off the machine\n"
7084 " --reboot Reboot the machine\n"
7085 " -f --force Force immediate halt/power-off/reboot\n"
7086 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
7087 " -d --no-wtmp Don't write wtmp record\n"
7088 " --no-wall Don't send wall message before halt/power-off/reboot\n",
7089 program_invocation_short_name,
7090 arg_action == ACTION_REBOOT ? " [ARG]" : "",
7091 arg_action == ACTION_REBOOT ? "Reboot" :
7092 arg_action == ACTION_POWEROFF ? "Power off" :
7093 "Halt");
7094}
7095
7096static void shutdown_help(void) {
7097 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
7098 "Shut down the system.\n\n"
7099 " --help Show this help\n"
7100 " -H --halt Halt the machine\n"
7101 " -P --poweroff Power-off the machine\n"
7102 " -r --reboot Reboot the machine\n"
7103 " -h Equivalent to --poweroff, overridden by --halt\n"
7104 " -k Don't halt/power-off/reboot, just send warnings\n"
7105 " --no-wall Don't send wall message before halt/power-off/reboot\n"
7106 " -c Cancel a pending shutdown\n",
7107 program_invocation_short_name);
7108}
7109
7110static void telinit_help(void) {
7111 printf("%s [OPTIONS...] {COMMAND}\n\n"
7112 "Send control commands to the init daemon.\n\n"
7113 " --help Show this help\n"
7114 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
7115 "Commands:\n"
7116 " 0 Power-off the machine\n"
7117 " 6 Reboot the machine\n"
7118 " 2, 3, 4, 5 Start runlevelX.target unit\n"
7119 " 1, s, S Enter rescue mode\n"
7120 " q, Q Reload init daemon configuration\n"
7121 " u, U Reexecute init daemon\n",
7122 program_invocation_short_name);
7123}
7124
7125static void runlevel_help(void) {
7126 printf("%s [OPTIONS...]\n\n"
7127 "Prints the previous and current runlevel of the init system.\n\n"
7128 " --help Show this help\n",
7129 program_invocation_short_name);
7130}
7131
7132static void help_types(void) {
7133 int i;
7134
7135 if (!arg_no_legend)
7136 puts("Available unit types:");
7137 for (i = 0; i < _UNIT_TYPE_MAX; i++)
7138 puts(unit_type_to_string(i));
7139}
7140
7141static void help_states(void) {
7142 int i;
7143
7144 if (!arg_no_legend)
7145 puts("Available unit load states:");
7146 for (i = 0; i < _UNIT_LOAD_STATE_MAX; i++)
7147 puts(unit_load_state_to_string(i));
7148
7149 if (!arg_no_legend)
7150 puts("\nAvailable unit active states:");
7151 for (i = 0; i < _UNIT_ACTIVE_STATE_MAX; i++)
7152 puts(unit_active_state_to_string(i));
7153
7154 if (!arg_no_legend)
7155 puts("\nAvailable automount unit substates:");
7156 for (i = 0; i < _AUTOMOUNT_STATE_MAX; i++)
7157 puts(automount_state_to_string(i));
7158
7159 if (!arg_no_legend)
7160 puts("\nAvailable busname unit substates:");
7161 for (i = 0; i < _BUSNAME_STATE_MAX; i++)
7162 puts(busname_state_to_string(i));
7163
7164 if (!arg_no_legend)
7165 puts("\nAvailable device unit substates:");
7166 for (i = 0; i < _DEVICE_STATE_MAX; i++)
7167 puts(device_state_to_string(i));
7168
7169 if (!arg_no_legend)
7170 puts("\nAvailable mount unit substates:");
7171 for (i = 0; i < _MOUNT_STATE_MAX; i++)
7172 puts(mount_state_to_string(i));
7173
7174 if (!arg_no_legend)
7175 puts("\nAvailable path unit substates:");
7176 for (i = 0; i < _PATH_STATE_MAX; i++)
7177 puts(path_state_to_string(i));
7178
7179 if (!arg_no_legend)
7180 puts("\nAvailable scope unit substates:");
7181 for (i = 0; i < _SCOPE_STATE_MAX; i++)
7182 puts(scope_state_to_string(i));
7183
7184 if (!arg_no_legend)
7185 puts("\nAvailable service unit substates:");
7186 for (i = 0; i < _SERVICE_STATE_MAX; i++)
7187 puts(service_state_to_string(i));
7188
7189 if (!arg_no_legend)
7190 puts("\nAvailable slice unit substates:");
7191 for (i = 0; i < _SLICE_STATE_MAX; i++)
7192 puts(slice_state_to_string(i));
7193
7194 if (!arg_no_legend)
7195 puts("\nAvailable socket unit substates:");
7196 for (i = 0; i < _SOCKET_STATE_MAX; i++)
7197 puts(socket_state_to_string(i));
7198
7199 if (!arg_no_legend)
7200 puts("\nAvailable swap unit substates:");
7201 for (i = 0; i < _SWAP_STATE_MAX; i++)
7202 puts(swap_state_to_string(i));
7203
7204 if (!arg_no_legend)
7205 puts("\nAvailable target unit substates:");
7206 for (i = 0; i < _TARGET_STATE_MAX; i++)
7207 puts(target_state_to_string(i));
7208
7209 if (!arg_no_legend)
7210 puts("\nAvailable timer unit substates:");
7211 for (i = 0; i < _TIMER_STATE_MAX; i++)
7212 puts(timer_state_to_string(i));
7213}
7214
7215static int systemctl_parse_argv(int argc, char *argv[]) {
7216
7217 enum {
7218 ARG_FAIL = 0x100,
7219 ARG_REVERSE,
7220 ARG_AFTER,
7221 ARG_BEFORE,
7222 ARG_SHOW_TYPES,
7223 ARG_IRREVERSIBLE,
7224 ARG_IGNORE_DEPENDENCIES,
7225 ARG_VALUE,
7226 ARG_VERSION,
7227 ARG_USER,
7228 ARG_SYSTEM,
7229 ARG_GLOBAL,
7230 ARG_NO_BLOCK,
7231 ARG_NO_LEGEND,
7232 ARG_NO_PAGER,
7233 ARG_NO_WALL,
7234 ARG_ROOT,
7235 ARG_NO_RELOAD,
7236 ARG_KILL_WHO,
7237 ARG_NO_ASK_PASSWORD,
7238 ARG_FAILED,
7239 ARG_RUNTIME,
7240 ARG_FORCE,
7241 ARG_PLAIN,
7242 ARG_STATE,
7243 ARG_JOB_MODE,
7244 ARG_PRESET_MODE,
7245 ARG_FIRMWARE_SETUP,
7246 ARG_NOW,
7247 ARG_MESSAGE,
7248 ARG_WAIT,
7249 };
7250
7251 static const struct option options[] = {
7252 { "help", no_argument, NULL, 'h' },
7253 { "version", no_argument, NULL, ARG_VERSION },
7254 { "type", required_argument, NULL, 't' },
7255 { "property", required_argument, NULL, 'p' },
7256 { "all", no_argument, NULL, 'a' },
7257 { "reverse", no_argument, NULL, ARG_REVERSE },
7258 { "after", no_argument, NULL, ARG_AFTER },
7259 { "before", no_argument, NULL, ARG_BEFORE },
7260 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
7261 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
7262 { "full", no_argument, NULL, 'l' },
7263 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
7264 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
7265 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
7266 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
7267 { "ignore-inhibitors", no_argument, NULL, 'i' },
7268 { "value", no_argument, NULL, ARG_VALUE },
7269 { "user", no_argument, NULL, ARG_USER },
7270 { "system", no_argument, NULL, ARG_SYSTEM },
7271 { "global", no_argument, NULL, ARG_GLOBAL },
7272 { "wait", no_argument, NULL, ARG_WAIT },
7273 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
7274 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
7275 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
7276 { "no-wall", no_argument, NULL, ARG_NO_WALL },
7277 { "quiet", no_argument, NULL, 'q' },
7278 { "root", required_argument, NULL, ARG_ROOT },
7279 { "force", no_argument, NULL, ARG_FORCE },
7280 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
7281 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
7282 { "signal", required_argument, NULL, 's' },
7283 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
7284 { "host", required_argument, NULL, 'H' },
7285 { "machine", required_argument, NULL, 'M' },
7286 { "runtime", no_argument, NULL, ARG_RUNTIME },
7287 { "lines", required_argument, NULL, 'n' },
7288 { "output", required_argument, NULL, 'o' },
7289 { "plain", no_argument, NULL, ARG_PLAIN },
7290 { "state", required_argument, NULL, ARG_STATE },
7291 { "recursive", no_argument, NULL, 'r' },
7292 { "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
7293 { "firmware-setup", no_argument, NULL, ARG_FIRMWARE_SETUP },
7294 { "now", no_argument, NULL, ARG_NOW },
7295 { "message", required_argument, NULL, ARG_MESSAGE },
7296 {}
7297 };
7298
7299 const char *p;
7300 int c, r;
7301
7302 assert(argc >= 0);
7303 assert(argv);
7304
7305 /* we default to allowing interactive authorization only in systemctl (not in the legacy commands) */
7306 arg_ask_password = true;
7307
7308 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
7309
7310 switch (c) {
7311
7312 case 'h':
7313 systemctl_help();
7314 return 0;
7315
7316 case ARG_VERSION:
7317 return version();
7318
7319 case 't': {
7320 if (isempty(optarg)) {
7321 log_error("--type requires arguments.");
7322 return -EINVAL;
7323 }
7324
7325 for (p = optarg;;) {
7326 _cleanup_free_ char *type = NULL;
7327
7328 r = extract_first_word(&p, &type, ",", 0);
7329 if (r < 0)
7330 return log_error_errno(r, "Failed to parse type: %s", optarg);
7331 if (r == 0)
7332 break;
7333
7334 if (streq(type, "help")) {
7335 help_types();
7336 return 0;
7337 }
7338
7339 if (unit_type_from_string(type) >= 0) {
7340 if (strv_push(&arg_types, type) < 0)
7341 return log_oom();
7342 type = NULL;
7343 continue;
7344 }
7345
7346 /* It's much nicer to use --state= for
7347 * load states, but let's support this
7348 * in --types= too for compatibility
7349 * with old versions */
7350 if (unit_load_state_from_string(type) >= 0) {
7351 if (strv_push(&arg_states, type) < 0)
7352 return log_oom();
7353 type = NULL;
7354 continue;
7355 }
7356
7357 log_error("Unknown unit type or load state '%s'.", type);
7358 log_info("Use -t help to see a list of allowed values.");
7359 return -EINVAL;
7360 }
7361
7362 break;
7363 }
7364
7365 case 'p': {
7366 /* Make sure that if the empty property list
7367 was specified, we won't show any properties. */
7368 if (isempty(optarg) && !arg_properties) {
7369 arg_properties = new0(char*, 1);
7370 if (!arg_properties)
7371 return log_oom();
7372 } else
7373 for (p = optarg;;) {
7374 _cleanup_free_ char *prop = NULL;
7375
7376 r = extract_first_word(&p, &prop, ",", 0);
7377 if (r < 0)
7378 return log_error_errno(r, "Failed to parse property: %s", optarg);
7379 if (r == 0)
7380 break;
7381
7382 if (strv_push(&arg_properties, prop) < 0)
7383 return log_oom();
7384
7385 prop = NULL;
7386 }
7387
7388 /* If the user asked for a particular
7389 * property, show it to him, even if it is
7390 * empty. */
7391 arg_all = true;
7392
7393 break;
7394 }
7395
7396 case 'a':
7397 arg_all = true;
7398 break;
7399
7400 case ARG_REVERSE:
7401 arg_dependency = DEPENDENCY_REVERSE;
7402 break;
7403
7404 case ARG_AFTER:
7405 arg_dependency = DEPENDENCY_AFTER;
7406 arg_jobs_after = true;
7407 break;
7408
7409 case ARG_BEFORE:
7410 arg_dependency = DEPENDENCY_BEFORE;
7411 arg_jobs_before = true;
7412 break;
7413
7414 case ARG_SHOW_TYPES:
7415 arg_show_types = true;
7416 break;
7417
7418 case ARG_VALUE:
7419 arg_value = true;
7420 break;
7421
7422 case ARG_JOB_MODE:
7423 arg_job_mode = optarg;
7424 break;
7425
7426 case ARG_FAIL:
7427 arg_job_mode = "fail";
7428 break;
7429
7430 case ARG_IRREVERSIBLE:
7431 arg_job_mode = "replace-irreversibly";
7432 break;
7433
7434 case ARG_IGNORE_DEPENDENCIES:
7435 arg_job_mode = "ignore-dependencies";
7436 break;
7437
7438 case ARG_USER:
7439 arg_scope = UNIT_FILE_USER;
7440 break;
7441
7442 case ARG_SYSTEM:
7443 arg_scope = UNIT_FILE_SYSTEM;
7444 break;
7445
7446 case ARG_GLOBAL:
7447 arg_scope = UNIT_FILE_GLOBAL;
7448 break;
7449
7450 case ARG_WAIT:
7451 arg_wait = true;
7452 break;
7453
7454 case ARG_NO_BLOCK:
7455 arg_no_block = true;
7456 break;
7457
7458 case ARG_NO_LEGEND:
7459 arg_no_legend = true;
7460 break;
7461
7462 case ARG_NO_PAGER:
7463 arg_no_pager = true;
7464 break;
7465
7466 case ARG_NO_WALL:
7467 arg_no_wall = true;
7468 break;
7469
7470 case ARG_ROOT:
7471 r = parse_path_argument_and_warn(optarg, false, &arg_root);
7472 if (r < 0)
7473 return r;
7474 break;
7475
7476 case 'l':
7477 arg_full = true;
7478 break;
7479
7480 case ARG_FAILED:
7481 if (strv_extend(&arg_states, "failed") < 0)
7482 return log_oom();
7483
7484 break;
7485
7486 case 'q':
7487 arg_quiet = true;
7488 break;
7489
7490 case ARG_FORCE:
7491 arg_force++;
7492 break;
7493
7494 case 'f':
7495 arg_force++;
7496 break;
7497
7498 case ARG_NO_RELOAD:
7499 arg_no_reload = true;
7500 break;
7501
7502 case ARG_KILL_WHO:
7503 arg_kill_who = optarg;
7504 break;
7505
7506 case 's':
7507 arg_signal = signal_from_string_try_harder(optarg);
7508 if (arg_signal < 0) {
7509 log_error("Failed to parse signal string %s.", optarg);
7510 return -EINVAL;
7511 }
7512 break;
7513
7514 case ARG_NO_ASK_PASSWORD:
7515 arg_ask_password = false;
7516 break;
7517
7518 case 'H':
7519 arg_transport = BUS_TRANSPORT_REMOTE;
7520 arg_host = optarg;
7521 break;
7522
7523 case 'M':
7524 arg_transport = BUS_TRANSPORT_MACHINE;
7525 arg_host = optarg;
7526 break;
7527
7528 case ARG_RUNTIME:
7529 arg_runtime = true;
7530 break;
7531
7532 case 'n':
7533 if (safe_atou(optarg, &arg_lines) < 0) {
7534 log_error("Failed to parse lines '%s'", optarg);
7535 return -EINVAL;
7536 }
7537 break;
7538
7539 case 'o':
7540 arg_output = output_mode_from_string(optarg);
7541 if (arg_output < 0) {
7542 log_error("Unknown output '%s'.", optarg);
7543 return -EINVAL;
7544 }
7545 break;
7546
7547 case 'i':
7548 arg_ignore_inhibitors = true;
7549 break;
7550
7551 case ARG_PLAIN:
7552 arg_plain = true;
7553 break;
7554
7555 case ARG_FIRMWARE_SETUP:
7556 arg_firmware_setup = true;
7557 break;
7558
7559 case ARG_STATE: {
7560 if (isempty(optarg)) {
7561 log_error("--signal requires arguments.");
7562 return -EINVAL;
7563 }
7564
7565 for (p = optarg;;) {
7566 _cleanup_free_ char *s = NULL;
7567
7568 r = extract_first_word(&p, &s, ",", 0);
7569 if (r < 0)
7570 return log_error_errno(r, "Failed to parse signal: %s", optarg);
7571 if (r == 0)
7572 break;
7573
7574 if (streq(s, "help")) {
7575 help_states();
7576 return 0;
7577 }
7578
7579 if (strv_push(&arg_states, s) < 0)
7580 return log_oom();
7581
7582 s = NULL;
7583 }
7584 break;
7585 }
7586
7587 case 'r':
7588 if (geteuid() != 0) {
7589 log_error("--recursive requires root privileges.");
7590 return -EPERM;
7591 }
7592
7593 arg_recursive = true;
7594 break;
7595
7596 case ARG_PRESET_MODE:
7597
7598 arg_preset_mode = unit_file_preset_mode_from_string(optarg);
7599 if (arg_preset_mode < 0) {
7600 log_error("Failed to parse preset mode: %s.", optarg);
7601 return -EINVAL;
7602 }
7603
7604 break;
7605
7606 case ARG_NOW:
7607 arg_now = true;
7608 break;
7609
7610 case ARG_MESSAGE:
7611 if (strv_extend(&arg_wall, optarg) < 0)
7612 return log_oom();
7613 break;
7614
7615 case '?':
7616 return -EINVAL;
7617
7618 default:
7619 assert_not_reached("Unhandled option");
7620 }
7621
7622 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
7623 log_error("Cannot access user instance remotely.");
7624 return -EINVAL;
7625 }
7626
7627 if (arg_wait && arg_no_block) {
7628 log_error("--wait may not be combined with --no-block.");
7629 return -EINVAL;
7630 }
7631
7632 return 1;
7633}
7634
7635static int halt_parse_argv(int argc, char *argv[]) {
7636
7637 enum {
7638 ARG_HELP = 0x100,
7639 ARG_HALT,
7640 ARG_REBOOT,
7641 ARG_NO_WALL
7642 };
7643
7644 static const struct option options[] = {
7645 { "help", no_argument, NULL, ARG_HELP },
7646 { "halt", no_argument, NULL, ARG_HALT },
7647 { "poweroff", no_argument, NULL, 'p' },
7648 { "reboot", no_argument, NULL, ARG_REBOOT },
7649 { "force", no_argument, NULL, 'f' },
7650 { "wtmp-only", no_argument, NULL, 'w' },
7651 { "no-wtmp", no_argument, NULL, 'd' },
7652 { "no-sync", no_argument, NULL, 'n' },
7653 { "no-wall", no_argument, NULL, ARG_NO_WALL },
7654 {}
7655 };
7656
7657 int c, r, runlevel;
7658
7659 assert(argc >= 0);
7660 assert(argv);
7661
7662 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
7663 if (runlevel == '0' || runlevel == '6')
7664 arg_force = 2;
7665
7666 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
7667 switch (c) {
7668
7669 case ARG_HELP:
7670 halt_help();
7671 return 0;
7672
7673 case ARG_HALT:
7674 arg_action = ACTION_HALT;
7675 break;
7676
7677 case 'p':
7678 if (arg_action != ACTION_REBOOT)
7679 arg_action = ACTION_POWEROFF;
7680 break;
7681
7682 case ARG_REBOOT:
7683 arg_action = ACTION_REBOOT;
7684 break;
7685
7686 case 'f':
7687 arg_force = 2;
7688 break;
7689
7690 case 'w':
7691 arg_dry = true;
7692 break;
7693
7694 case 'd':
7695 arg_no_wtmp = true;
7696 break;
7697
7698 case 'n':
7699 arg_no_sync = true;
7700 break;
7701
7702 case ARG_NO_WALL:
7703 arg_no_wall = true;
7704 break;
7705
7706 case 'i':
7707 case 'h':
7708 /* Compatibility nops */
7709 break;
7710
7711 case '?':
7712 return -EINVAL;
7713
7714 default:
7715 assert_not_reached("Unhandled option");
7716 }
7717
7718 if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
7719 r = update_reboot_parameter_and_warn(argc == optind + 1 ? argv[optind] : NULL);
7720 if (r < 0)
7721 return r;
7722 } else if (optind < argc) {
7723 log_error("Too many arguments.");
7724 return -EINVAL;
7725 }
7726
7727 return 1;
7728}
7729
7730static int parse_shutdown_time_spec(const char *t, usec_t *_u) {
7731 assert(t);
7732 assert(_u);
7733
7734 if (streq(t, "now"))
7735 *_u = 0;
7736 else if (!strchr(t, ':')) {
7737 uint64_t u;
7738
7739 if (safe_atou64(t, &u) < 0)
7740 return -EINVAL;
7741
7742 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
7743 } else {
7744 char *e = NULL;
7745 long hour, minute;
7746 struct tm tm = {};
7747 time_t s;
7748 usec_t n;
7749
7750 errno = 0;
7751 hour = strtol(t, &e, 10);
7752 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
7753 return -EINVAL;
7754
7755 minute = strtol(e+1, &e, 10);
7756 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
7757 return -EINVAL;
7758
7759 n = now(CLOCK_REALTIME);
7760 s = (time_t) (n / USEC_PER_SEC);
7761
7762 assert_se(localtime_r(&s, &tm));
7763
7764 tm.tm_hour = (int) hour;
7765 tm.tm_min = (int) minute;
7766 tm.tm_sec = 0;
7767
7768 assert_se(s = mktime(&tm));
7769
7770 *_u = (usec_t) s * USEC_PER_SEC;
7771
7772 while (*_u <= n)
7773 *_u += USEC_PER_DAY;
7774 }
7775
7776 return 0;
7777}
7778
7779static int shutdown_parse_argv(int argc, char *argv[]) {
7780
7781 enum {
7782 ARG_HELP = 0x100,
7783 ARG_NO_WALL
7784 };
7785
7786 static const struct option options[] = {
7787 { "help", no_argument, NULL, ARG_HELP },
7788 { "halt", no_argument, NULL, 'H' },
7789 { "poweroff", no_argument, NULL, 'P' },
7790 { "reboot", no_argument, NULL, 'r' },
7791 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
7792 { "no-wall", no_argument, NULL, ARG_NO_WALL },
7793 {}
7794 };
7795
7796 char **wall = NULL;
7797 int c, r;
7798
7799 assert(argc >= 0);
7800 assert(argv);
7801
7802 while ((c = getopt_long(argc, argv, "HPrhkKtafFc", options, NULL)) >= 0)
7803 switch (c) {
7804
7805 case ARG_HELP:
7806 shutdown_help();
7807 return 0;
7808
7809 case 'H':
7810 arg_action = ACTION_HALT;
7811 break;
7812
7813 case 'P':
7814 arg_action = ACTION_POWEROFF;
7815 break;
7816
7817 case 'r':
7818 if (kexec_loaded())
7819 arg_action = ACTION_KEXEC;
7820 else
7821 arg_action = ACTION_REBOOT;
7822 break;
7823
7824 case 'K':
7825 arg_action = ACTION_KEXEC;
7826 break;
7827
7828 case 'h':
7829 if (arg_action != ACTION_HALT)
7830 arg_action = ACTION_POWEROFF;
7831 break;
7832
7833 case 'k':
7834 arg_dry = true;
7835 break;
7836
7837 case ARG_NO_WALL:
7838 arg_no_wall = true;
7839 break;
7840
7841 case 't':
7842 case 'a':
7843 case 'f':
7844 case 'F':
7845 /* Compatibility nops */
7846 break;
7847
7848 case 'c':
7849 arg_action = ACTION_CANCEL_SHUTDOWN;
7850 break;
7851
7852 case '?':
7853 return -EINVAL;
7854
7855 default:
7856 assert_not_reached("Unhandled option");
7857 }
7858
7859 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
7860 r = parse_shutdown_time_spec(argv[optind], &arg_when);
7861 if (r < 0) {
7862 log_error("Failed to parse time specification: %s", argv[optind]);
7863 return r;
7864 }
7865 } else
7866 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
7867
7868 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
7869 /* No time argument for shutdown cancel */
7870 wall = argv + optind;
7871 else if (argc > optind + 1)
7872 /* We skip the time argument */
7873 wall = argv + optind + 1;
7874
7875 if (wall) {
7876 arg_wall = strv_copy(wall);
7877 if (!arg_wall)
7878 return log_oom();
7879 }
7880
7881 optind = argc;
7882
7883 return 1;
7884}
7885
7886static int telinit_parse_argv(int argc, char *argv[]) {
7887
7888 enum {
7889 ARG_HELP = 0x100,
7890 ARG_NO_WALL
7891 };
7892
7893 static const struct option options[] = {
7894 { "help", no_argument, NULL, ARG_HELP },
7895 { "no-wall", no_argument, NULL, ARG_NO_WALL },
7896 {}
7897 };
7898
7899 static const struct {
7900 char from;
7901 enum action to;
7902 } table[] = {
7903 { '0', ACTION_POWEROFF },
7904 { '6', ACTION_REBOOT },
7905 { '1', ACTION_RESCUE },
7906 { '2', ACTION_RUNLEVEL2 },
7907 { '3', ACTION_RUNLEVEL3 },
7908 { '4', ACTION_RUNLEVEL4 },
7909 { '5', ACTION_RUNLEVEL5 },
7910 { 's', ACTION_RESCUE },
7911 { 'S', ACTION_RESCUE },
7912 { 'q', ACTION_RELOAD },
7913 { 'Q', ACTION_RELOAD },
7914 { 'u', ACTION_REEXEC },
7915 { 'U', ACTION_REEXEC }
7916 };
7917
7918 unsigned i;
7919 int c;
7920
7921 assert(argc >= 0);
7922 assert(argv);
7923
7924 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
7925 switch (c) {
7926
7927 case ARG_HELP:
7928 telinit_help();
7929 return 0;
7930
7931 case ARG_NO_WALL:
7932 arg_no_wall = true;
7933 break;
7934
7935 case '?':
7936 return -EINVAL;
7937
7938 default:
7939 assert_not_reached("Unhandled option");
7940 }
7941
7942 if (optind >= argc) {
7943 log_error("%s: required argument missing.", program_invocation_short_name);
7944 return -EINVAL;
7945 }
7946
7947 if (optind + 1 < argc) {
7948 log_error("Too many arguments.");
7949 return -EINVAL;
7950 }
7951
7952 if (strlen(argv[optind]) != 1) {
7953 log_error("Expected single character argument.");
7954 return -EINVAL;
7955 }
7956
7957 for (i = 0; i < ELEMENTSOF(table); i++)
7958 if (table[i].from == argv[optind][0])
7959 break;
7960
7961 if (i >= ELEMENTSOF(table)) {
7962 log_error("Unknown command '%s'.", argv[optind]);
7963 return -EINVAL;
7964 }
7965
7966 arg_action = table[i].to;
7967
7968 optind++;
7969
7970 return 1;
7971}
7972
7973static int runlevel_parse_argv(int argc, char *argv[]) {
7974
7975 enum {
7976 ARG_HELP = 0x100,
7977 };
7978
7979 static const struct option options[] = {
7980 { "help", no_argument, NULL, ARG_HELP },
7981 {}
7982 };
7983
7984 int c;
7985
7986 assert(argc >= 0);
7987 assert(argv);
7988
7989 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
7990 switch (c) {
7991
7992 case ARG_HELP:
7993 runlevel_help();
7994 return 0;
7995
7996 case '?':
7997 return -EINVAL;
7998
7999 default:
8000 assert_not_reached("Unhandled option");
8001 }
8002
8003 if (optind < argc) {
8004 log_error("Too many arguments.");
8005 return -EINVAL;
8006 }
8007
8008 return 1;
8009}
8010
8011static int parse_argv(int argc, char *argv[]) {
8012 assert(argc >= 0);
8013 assert(argv);
8014
8015 if (program_invocation_short_name) {
8016
8017 if (strstr(program_invocation_short_name, "halt")) {
8018 arg_action = ACTION_HALT;
8019 return halt_parse_argv(argc, argv);
8020 } else if (strstr(program_invocation_short_name, "poweroff")) {
8021 arg_action = ACTION_POWEROFF;
8022 return halt_parse_argv(argc, argv);
8023 } else if (strstr(program_invocation_short_name, "reboot")) {
8024 if (kexec_loaded())
8025 arg_action = ACTION_KEXEC;
8026 else
8027 arg_action = ACTION_REBOOT;
8028 return halt_parse_argv(argc, argv);
8029 } else if (strstr(program_invocation_short_name, "shutdown")) {
8030 arg_action = ACTION_POWEROFF;
8031 return shutdown_parse_argv(argc, argv);
8032 } else if (strstr(program_invocation_short_name, "init")) {
8033
8034 if (sd_booted() > 0) {
8035 arg_action = _ACTION_INVALID;
8036 return telinit_parse_argv(argc, argv);
8037 } else {
8038 /* Hmm, so some other init system is
8039 * running, we need to forward this
8040 * request to it. For now we simply
8041 * guess that it is Upstart. */
8042
8043 execv(TELINIT, argv);
8044
8045 log_error("Couldn't find an alternative telinit implementation to spawn.");
8046 return -EIO;
8047 }
8048
8049 } else if (strstr(program_invocation_short_name, "runlevel")) {
8050 arg_action = ACTION_RUNLEVEL;
8051 return runlevel_parse_argv(argc, argv);
8052 }
8053 }
8054
8055 arg_action = ACTION_SYSTEMCTL;
8056 return systemctl_parse_argv(argc, argv);
8057}
8058
8059#ifdef HAVE_SYSV_COMPAT
8060_pure_ static int action_to_runlevel(void) {
8061
8062 static const char table[_ACTION_MAX] = {
8063 [ACTION_HALT] = '0',
8064 [ACTION_POWEROFF] = '0',
8065 [ACTION_REBOOT] = '6',
8066 [ACTION_RUNLEVEL2] = '2',
8067 [ACTION_RUNLEVEL3] = '3',
8068 [ACTION_RUNLEVEL4] = '4',
8069 [ACTION_RUNLEVEL5] = '5',
8070 [ACTION_RESCUE] = '1'
8071 };
8072
8073 assert(arg_action < _ACTION_MAX);
8074
8075 return table[arg_action];
8076}
8077#endif
8078
8079static int talk_initctl(void) {
8080#ifdef HAVE_SYSV_COMPAT
8081 struct init_request request = {
8082 .magic = INIT_MAGIC,
8083 .sleeptime = 0,
8084 .cmd = INIT_CMD_RUNLVL
8085 };
8086
8087 _cleanup_close_ int fd = -1;
8088 char rl;
8089 int r;
8090
8091 rl = action_to_runlevel();
8092 if (!rl)
8093 return 0;
8094
8095 request.runlevel = rl;
8096
8097 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
8098 if (fd < 0) {
8099 if (errno == ENOENT)
8100 return 0;
8101
8102 return log_error_errno(errno, "Failed to open "INIT_FIFO": %m");
8103 }
8104
8105 r = loop_write(fd, &request, sizeof(request), false);
8106 if (r < 0)
8107 return log_error_errno(r, "Failed to write to "INIT_FIFO": %m");
8108
8109 return 1;
8110#else
8111 return 0;
8112#endif
8113}
8114
8115static int systemctl_main(int argc, char *argv[]) {
8116
8117 static const Verb verbs[] = {
8118 { "list-units", VERB_ANY, VERB_ANY, VERB_DEFAULT|VERB_NOCHROOT, list_units },
8119 { "list-unit-files", VERB_ANY, VERB_ANY, 0, list_unit_files },
8120 { "list-sockets", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_sockets },
8121 { "list-timers", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_timers },
8122 { "list-jobs", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_jobs },
8123 { "list-machines", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_machines },
8124 { "clear-jobs", VERB_ANY, 1, VERB_NOCHROOT, trivial_method },
8125 { "cancel", VERB_ANY, VERB_ANY, VERB_NOCHROOT, cancel_job },
8126 { "start", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
8127 { "stop", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
8128 { "condstop", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with ALTLinux */
8129 { "reload", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
8130 { "restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
8131 { "try-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
8132 { "reload-or-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
8133 { "reload-or-try-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatbility with old systemctl <= 228 */
8134 { "try-reload-or-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit },
8135 { "force-reload", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with SysV */
8136 { "condreload", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with ALTLinux */
8137 { "condrestart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with RH */
8138 { "isolate", 2, 2, VERB_NOCHROOT, start_unit },
8139 { "kill", 2, VERB_ANY, VERB_NOCHROOT, kill_unit },
8140 { "is-active", 2, VERB_ANY, VERB_NOCHROOT, check_unit_active },
8141 { "check", 2, VERB_ANY, VERB_NOCHROOT, check_unit_active },
8142 { "is-failed", 2, VERB_ANY, VERB_NOCHROOT, check_unit_failed },
8143 { "show", VERB_ANY, VERB_ANY, VERB_NOCHROOT, show },
8144 { "cat", 2, VERB_ANY, VERB_NOCHROOT, cat },
8145 { "status", VERB_ANY, VERB_ANY, VERB_NOCHROOT, show },
8146 { "help", VERB_ANY, VERB_ANY, VERB_NOCHROOT, show },
8147 { "daemon-reload", VERB_ANY, 1, VERB_NOCHROOT, daemon_reload },
8148 { "daemon-reexec", VERB_ANY, 1, VERB_NOCHROOT, daemon_reload },
8149 { "show-environment", VERB_ANY, 1, VERB_NOCHROOT, show_environment },
8150 { "set-environment", 2, VERB_ANY, VERB_NOCHROOT, set_environment },
8151 { "unset-environment", 2, VERB_ANY, VERB_NOCHROOT, set_environment },
8152 { "import-environment", VERB_ANY, VERB_ANY, VERB_NOCHROOT, import_environment },
8153 { "halt", VERB_ANY, 1, VERB_NOCHROOT, start_system_special },
8154 { "poweroff", VERB_ANY, 1, VERB_NOCHROOT, start_system_special },
8155 { "reboot", VERB_ANY, 2, VERB_NOCHROOT, start_system_special },
8156 { "kexec", VERB_ANY, 1, VERB_NOCHROOT, start_system_special },
8157 { "suspend", VERB_ANY, 1, VERB_NOCHROOT, start_system_special },
8158 { "hibernate", VERB_ANY, 1, VERB_NOCHROOT, start_system_special },
8159 { "hybrid-sleep", VERB_ANY, 1, VERB_NOCHROOT, start_system_special },
8160 { "default", VERB_ANY, 1, VERB_NOCHROOT, start_special },
8161 { "rescue", VERB_ANY, 1, VERB_NOCHROOT, start_system_special },
8162 { "emergency", VERB_ANY, 1, VERB_NOCHROOT, start_system_special },
8163 { "exit", VERB_ANY, 2, VERB_NOCHROOT, start_special },
8164 { "reset-failed", VERB_ANY, VERB_ANY, VERB_NOCHROOT, reset_failed },
8165 { "enable", 2, VERB_ANY, 0, enable_unit },
8166 { "disable", 2, VERB_ANY, 0, enable_unit },
8167 { "is-enabled", 2, VERB_ANY, 0, unit_is_enabled },
8168 { "reenable", 2, VERB_ANY, 0, enable_unit },
8169 { "preset", 2, VERB_ANY, 0, enable_unit },
8170 { "preset-all", VERB_ANY, 1, 0, preset_all },
8171 { "mask", 2, VERB_ANY, 0, enable_unit },
8172 { "unmask", 2, VERB_ANY, 0, enable_unit },
8173 { "link", 2, VERB_ANY, 0, enable_unit },
8174 { "revert", 2, VERB_ANY, 0, enable_unit },
8175 { "switch-root", 2, VERB_ANY, VERB_NOCHROOT, switch_root },
8176 { "list-dependencies", VERB_ANY, 2, VERB_NOCHROOT, list_dependencies },
8177 { "set-default", 2, 2, 0, set_default },
8178 { "get-default", VERB_ANY, 1, 0, get_default },
8179 { "set-property", 3, VERB_ANY, VERB_NOCHROOT, set_property },
8180 { "is-system-running", VERB_ANY, 1, 0, is_system_running },
8181 { "add-wants", 3, VERB_ANY, 0, add_dependency },
8182 { "add-requires", 3, VERB_ANY, 0, add_dependency },
8183 { "edit", 2, VERB_ANY, VERB_NOCHROOT, edit },
8184 {}
8185 };
8186
8187 return dispatch_verb(argc, argv, verbs, NULL);
8188}
8189
8190static int reload_with_fallback(void) {
8191
8192 /* First, try systemd via D-Bus. */
8193 if (daemon_reload(0, NULL, NULL) >= 0)
8194 return 0;
8195
8196 /* Nothing else worked, so let's try signals */
8197 assert(IN_SET(arg_action, ACTION_RELOAD, ACTION_REEXEC));
8198
8199 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0)
8200 return log_error_errno(errno, "kill() failed: %m");
8201
8202 return 0;
8203}
8204
8205static int start_with_fallback(void) {
8206
8207 /* First, try systemd via D-Bus. */
8208 if (start_unit(0, NULL, NULL) >= 0)
8209 return 0;
8210
8211 /* Nothing else worked, so let's try /dev/initctl */
8212 if (talk_initctl() > 0)
8213 return 0;
8214
8215 log_error("Failed to talk to init daemon.");
8216 return -EIO;
8217}
8218
8219static int halt_now(enum action a) {
8220 int r;
8221
8222 /* The kernel will automaticall flush ATA disks and suchlike
8223 * on reboot(), but the file systems need to be synce'd
8224 * explicitly in advance. */
8225 if (!arg_no_sync)
8226 (void) sync();
8227
8228 /* Make sure C-A-D is handled by the kernel from this point
8229 * on... */
8230 (void) reboot(RB_ENABLE_CAD);
8231
8232 switch (a) {
8233
8234 case ACTION_HALT:
8235 log_info("Halting.");
8236 (void) reboot(RB_HALT_SYSTEM);
8237 return -errno;
8238
8239 case ACTION_POWEROFF:
8240 log_info("Powering off.");
8241 (void) reboot(RB_POWER_OFF);
8242 return -errno;
8243
8244 case ACTION_KEXEC:
8245 case ACTION_REBOOT: {
8246 _cleanup_free_ char *param = NULL;
8247
8248 r = read_one_line_file("/run/systemd/reboot-param", &param);
8249 if (r < 0)
8250 log_warning_errno(r, "Failed to read reboot parameter file: %m");
8251
8252 if (!isempty(param)) {
8253 log_info("Rebooting with argument '%s'.", param);
8254 (void) syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, param);
8255 log_warning_errno(errno, "Failed to reboot with parameter, retrying without: %m");
8256 }
8257
8258 log_info("Rebooting.");
8259 (void) reboot(RB_AUTOBOOT);
8260 return -errno;
8261 }
8262
8263 default:
8264 assert_not_reached("Unknown action.");
8265 }
8266}
8267
8268static int logind_schedule_shutdown(void) {
8269
8270#ifdef HAVE_LOGIND
8271 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
8272 char date[FORMAT_TIMESTAMP_MAX];
8273 const char *action;
8274 sd_bus *bus;
8275 int r;
8276
8277 r = acquire_bus(BUS_FULL, &bus);
8278 if (r < 0)
8279 return r;
8280
8281 switch (arg_action) {
8282 case ACTION_HALT:
8283 action = "halt";
8284 break;
8285 case ACTION_POWEROFF:
8286 action = "poweroff";
8287 break;
8288 case ACTION_KEXEC:
8289 action = "kexec";
8290 break;
8291 case ACTION_EXIT:
8292 action = "exit";
8293 break;
8294 case ACTION_REBOOT:
8295 default:
8296 action = "reboot";
8297 break;
8298 }
8299
8300 if (arg_dry)
8301 action = strjoina("dry-", action);
8302
8303 (void) logind_set_wall_message();
8304
8305 r = sd_bus_call_method(
8306 bus,
8307 "org.freedesktop.login1",
8308 "/org/freedesktop/login1",
8309 "org.freedesktop.login1.Manager",
8310 "ScheduleShutdown",
8311 &error,
8312 NULL,
8313 "st",
8314 action,
8315 arg_when);
8316 if (r < 0)
8317 return log_warning_errno(r, "Failed to call ScheduleShutdown in logind, proceeding with immediate shutdown: %s", bus_error_message(&error, r));
8318
8319 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.", format_timestamp(date, sizeof(date), arg_when));
8320 return 0;
8321#else
8322 log_error("Cannot schedule shutdown without logind support, proceeding with immediate shutdown.");
8323 return -ENOSYS;
8324#endif
8325}
8326
8327static int halt_main(void) {
8328 int r;
8329
8330 r = logind_check_inhibitors(arg_action);
8331 if (r < 0)
8332 return r;
8333
8334 if (arg_when > 0)
8335 return logind_schedule_shutdown();
8336
8337 if (geteuid() != 0) {
8338 if (arg_dry || arg_force > 0) {
8339 log_error("Must be root.");
8340 return -EPERM;
8341 }
8342
8343 /* Try logind if we are a normal user and no special
8344 * mode applies. Maybe PolicyKit allows us to shutdown
8345 * the machine. */
8346 if (IN_SET(arg_action, ACTION_POWEROFF, ACTION_REBOOT)) {
8347 r = logind_reboot(arg_action);
8348 if (r >= 0)
8349 return r;
8350 if (IN_SET(r, -EOPNOTSUPP, -EINPROGRESS))
8351 /* requested operation is not
8352 * supported on the local system or
8353 * already in progress */
8354 return r;
8355 /* on all other errors, try low-level operation */
8356 }
8357 }
8358
8359 if (!arg_dry && !arg_force)
8360 return start_with_fallback();
8361
8362 assert(geteuid() == 0);
8363
8364 if (!arg_no_wtmp) {
8365 if (sd_booted() > 0)
8366 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
8367 else {
8368 r = utmp_put_shutdown();
8369 if (r < 0)
8370 log_warning_errno(r, "Failed to write utmp record: %m");
8371 }
8372 }
8373
8374 if (arg_dry)
8375 return 0;
8376
8377 r = halt_now(arg_action);
8378 return log_error_errno(r, "Failed to reboot: %m");
8379}
8380
8381static int runlevel_main(void) {
8382 int r, runlevel, previous;
8383
8384 r = utmp_get_runlevel(&runlevel, &previous);
8385 if (r < 0) {
8386 puts("unknown");
8387 return r;
8388 }
8389
8390 printf("%c %c\n",
8391 previous <= 0 ? 'N' : previous,
8392 runlevel <= 0 ? 'N' : runlevel);
8393
8394 return 0;
8395}
8396
8397static int logind_cancel_shutdown(void) {
8398#ifdef HAVE_LOGIND
8399 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
8400 sd_bus *bus;
8401 int r;
8402
8403 r = acquire_bus(BUS_FULL, &bus);
8404 if (r < 0)
8405 return r;
8406
8407 (void) logind_set_wall_message();
8408
8409 r = sd_bus_call_method(
8410 bus,
8411 "org.freedesktop.login1",
8412 "/org/freedesktop/login1",
8413 "org.freedesktop.login1.Manager",
8414 "CancelScheduledShutdown",
8415 &error,
8416 NULL, NULL);
8417 if (r < 0)
8418 return log_warning_errno(r, "Failed to talk to logind, shutdown hasn't been cancelled: %s", bus_error_message(&error, r));
8419
8420 return 0;
8421#else
8422 log_error("Not compiled with logind support, cannot cancel scheduled shutdowns.");
8423 return -ENOSYS;
8424#endif
8425}
8426
8427int main(int argc, char*argv[]) {
8428 int r;
8429
8430 argv_cmdline = argv[0];
8431
8432 setlocale(LC_ALL, "");
8433 log_parse_environment();
8434 log_open();
8435 sigbus_install();
8436
8437 /* Explicitly not on_tty() to avoid setting cached value.
8438 * This becomes relevant for piping output which might be
8439 * ellipsized. */
8440 original_stdout_is_tty = isatty(STDOUT_FILENO);
8441
8442 r = parse_argv(argc, argv);
8443 if (r <= 0)
8444 goto finish;
8445
8446 if (arg_action != ACTION_SYSTEMCTL && running_in_chroot() > 0) {
8447 log_info("Running in chroot, ignoring request.");
8448 r = 0;
8449 goto finish;
8450 }
8451
8452 /* systemctl_main() will print an error message for the bus
8453 * connection, but only if it needs to */
8454
8455 switch (arg_action) {
8456
8457 case ACTION_SYSTEMCTL:
8458 r = systemctl_main(argc, argv);
8459 break;
8460
8461 case ACTION_HALT:
8462 case ACTION_POWEROFF:
8463 case ACTION_REBOOT:
8464 case ACTION_KEXEC:
8465 r = halt_main();
8466 break;
8467
8468 case ACTION_RUNLEVEL2:
8469 case ACTION_RUNLEVEL3:
8470 case ACTION_RUNLEVEL4:
8471 case ACTION_RUNLEVEL5:
8472 case ACTION_RESCUE:
8473 case ACTION_EMERGENCY:
8474 case ACTION_DEFAULT:
8475 r = start_with_fallback();
8476 break;
8477
8478 case ACTION_RELOAD:
8479 case ACTION_REEXEC:
8480 r = reload_with_fallback();
8481 break;
8482
8483 case ACTION_CANCEL_SHUTDOWN:
8484 r = logind_cancel_shutdown();
8485 break;
8486
8487 case ACTION_RUNLEVEL:
8488 r = runlevel_main();
8489 break;
8490
8491 case _ACTION_INVALID:
8492 default:
8493 assert_not_reached("Unknown action");
8494 }
8495
8496finish:
8497 release_busses();
8498
8499 pager_close();
8500 ask_password_agent_close();
8501 polkit_agent_close();
8502
8503 strv_free(arg_types);
8504 strv_free(arg_states);
8505 strv_free(arg_properties);
8506
8507 strv_free(arg_wall);
8508 free(arg_root);
8509
8510 /* Note that we return r here, not EXIT_SUCCESS, so that we can implement the LSB-like return codes */
8511 return r < 0 ? EXIT_FAILURE : r;
8512}