1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Marc-Antoine Perennou
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/reboot.h>
24 #include <linux/reboot.h>
25 #include <sys/syscall.h>
32 #include <sys/ioctl.h>
36 #include <sys/socket.h>
39 #include <sys/prctl.h>
42 #include "sd-daemon.h"
43 #include "sd-shutdown.h"
50 #include "utmp-wtmp.h"
53 #include "path-util.h"
55 #include "cgroup-show.h"
56 #include "cgroup-util.h"
58 #include "path-lookup.h"
59 #include "conf-parser.h"
60 #include "exit-status.h"
62 #include "unit-name.h"
64 #include "spawn-ask-password-agent.h"
65 #include "spawn-polkit-agent.h"
67 #include "logs-show.h"
68 #include "socket-util.h"
73 #include "bus-message.h"
74 #include "bus-error.h"
75 #include "bus-errors.h"
77 static char **arg_types = NULL;
78 static char **arg_states = NULL;
79 static char **arg_properties = NULL;
80 static bool arg_all = false;
81 static enum dependency {
87 } arg_dependency = DEPENDENCY_FORWARD;
88 static const char *arg_job_mode = "replace";
89 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
90 static bool arg_no_block = false;
91 static bool arg_no_legend = false;
92 static bool arg_no_pager = false;
93 static bool arg_no_wtmp = false;
94 static bool arg_no_wall = false;
95 static bool arg_no_reload = false;
96 static bool arg_show_types = false;
97 static bool arg_ignore_inhibitors = false;
98 static bool arg_dry = false;
99 static bool arg_quiet = false;
100 static bool arg_full = false;
101 static bool arg_recursive = false;
102 static int arg_force = 0;
103 static bool arg_ask_password = true;
104 static bool arg_runtime = false;
105 static UnitFilePresetMode arg_preset_mode = UNIT_FILE_PRESET_FULL;
106 static char **arg_wall = NULL;
107 static const char *arg_kill_who = NULL;
108 static int arg_signal = SIGTERM;
109 static const char *arg_root = NULL;
110 static usec_t arg_when = 0;
132 ACTION_CANCEL_SHUTDOWN,
134 } arg_action = ACTION_SYSTEMCTL;
135 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
136 static char *arg_host = NULL;
137 static unsigned arg_lines = 10;
138 static OutputMode arg_output = OUTPUT_SHORT;
139 static bool arg_plain = false;
141 static bool original_stdout_is_tty;
143 static int daemon_reload(sd_bus *bus, char **args);
144 static int halt_now(enum action a);
145 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet);
147 static char** strv_skip_first(char **strv) {
148 if (strv_length(strv) > 0)
153 static void pager_open_if_enabled(void) {
161 static void ask_password_agent_open_if_enabled(void) {
163 /* Open the password agent as a child process if necessary */
165 if (!arg_ask_password)
168 if (arg_scope != UNIT_FILE_SYSTEM)
171 if (arg_transport != BUS_TRANSPORT_LOCAL)
174 ask_password_agent_open();
178 static void polkit_agent_open_if_enabled(void) {
180 /* Open the polkit agent as a child process if necessary */
182 if (!arg_ask_password)
185 if (arg_scope != UNIT_FILE_SYSTEM)
188 if (arg_transport != BUS_TRANSPORT_LOCAL)
195 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
198 if (!sd_bus_error_is_set(error))
201 if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) ||
202 sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
203 sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
204 sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
205 return EXIT_NOPERMISSION;
207 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
208 return EXIT_NOTINSTALLED;
210 if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
211 sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED))
212 return EXIT_NOTIMPLEMENTED;
214 if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
215 return EXIT_NOTCONFIGURED;
223 static void warn_wall(enum action a) {
224 static const char *table[_ACTION_MAX] = {
225 [ACTION_HALT] = "The system is going down for system halt NOW!",
226 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
227 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
228 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
229 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
230 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
231 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
238 _cleanup_free_ char *p;
240 p = strv_join(arg_wall, " ");
247 utmp_wall(p, NULL, NULL);
255 utmp_wall(table[a], NULL, NULL);
258 static bool avoid_bus(void) {
260 if (running_in_chroot() > 0)
263 if (sd_booted() <= 0)
266 if (!isempty(arg_root))
269 if (arg_scope == UNIT_FILE_GLOBAL)
275 static int compare_unit_info(const void *a, const void *b) {
276 const UnitInfo *u = a, *v = b;
280 /* First, order by machine */
281 if (!u->machine && v->machine)
283 if (u->machine && !v->machine)
285 if (u->machine && v->machine) {
286 r = strcasecmp(u->machine, v->machine);
291 /* Second, order by unit type */
292 d1 = strrchr(u->id, '.');
293 d2 = strrchr(v->id, '.');
295 r = strcasecmp(d1, d2);
300 /* Third, order by name */
301 return strcasecmp(u->id, v->id);
304 static bool output_show_unit(const UnitInfo *u, char **patterns) {
305 if (!strv_isempty(patterns)) {
308 STRV_FOREACH(pattern, patterns)
309 if (fnmatch(*pattern, u->id, FNM_NOESCAPE) == 0)
318 dot = strrchr(u->id, '.');
322 if (!strv_find(arg_types, dot+1))
332 if (streq(u->active_state, "inactive") || u->following[0])
338 static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
339 unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
341 unsigned n_shown = 0;
344 max_id_len = strlen("UNIT");
345 load_len = strlen("LOAD");
346 active_len = strlen("ACTIVE");
347 sub_len = strlen("SUB");
348 job_len = strlen("JOB");
351 for (u = unit_infos; u < unit_infos + c; u++) {
352 max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0));
353 load_len = MAX(load_len, strlen(u->load_state));
354 active_len = MAX(active_len, strlen(u->active_state));
355 sub_len = MAX(sub_len, strlen(u->sub_state));
357 if (u->job_id != 0) {
358 job_len = MAX(job_len, strlen(u->job_type));
362 if (!arg_no_legend &&
363 (streq(u->active_state, "failed") ||
364 STR_IN_SET(u->load_state, "error", "not-found", "masked")))
368 if (!arg_full && original_stdout_is_tty) {
371 id_len = MIN(max_id_len, 25u);
372 basic_len = circle_len + 5 + id_len + 5 + active_len + sub_len;
375 basic_len += job_len + 1;
377 if (basic_len < (unsigned) columns()) {
378 unsigned extra_len, incr;
379 extra_len = columns() - basic_len;
381 /* Either UNIT already got 25, or is fully satisfied.
382 * Grant up to 25 to DESC now. */
383 incr = MIN(extra_len, 25u);
387 /* split the remaining space between UNIT and DESC,
388 * but do not give UNIT more than it needs. */
390 incr = MIN(extra_len / 2, max_id_len - id_len);
392 desc_len += extra_len - incr;
398 for (u = unit_infos; u < unit_infos + c; u++) {
399 _cleanup_free_ char *e = NULL, *j = NULL;
400 const char *on_loaded = "", *off_loaded = "";
401 const char *on_active = "", *off_active = "";
402 const char *on_circle = "", *off_circle = "";
406 if (!n_shown && !arg_no_legend) {
411 printf("%-*s %-*s %-*s %-*s ",
414 active_len, "ACTIVE",
418 printf("%-*s ", job_len, "JOB");
420 if (!arg_full && arg_no_pager)
421 printf("%.*s\n", desc_len, "DESCRIPTION");
423 printf("%s\n", "DESCRIPTION");
428 if (STR_IN_SET(u->load_state, "error", "not-found", "masked")) {
429 on_loaded = ansi_highlight_red();
430 on_circle = ansi_highlight_yellow();
431 off_loaded = off_circle = ansi_highlight_off();
435 if (streq(u->active_state, "failed")) {
436 on_circle = on_active = ansi_highlight_red();
437 off_circle = off_active = ansi_highlight_off();
442 j = strjoin(u->machine, ":", u->id, NULL);
451 e = ellipsize(id, id_len, 33);
459 printf("%s%s%s ", on_circle, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_circle);
461 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
462 on_active, id_len, id, off_active,
463 on_loaded, load_len, u->load_state, off_loaded,
464 on_active, active_len, u->active_state,
465 sub_len, u->sub_state, off_active,
466 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
469 printf("%.*s\n", desc_len, u->description);
471 printf("%s\n", u->description);
474 if (!arg_no_legend) {
475 const char *on, *off;
479 "LOAD = Reflects whether the unit definition was properly loaded.\n"
480 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
481 "SUB = The low-level unit activation state, values depend on unit type.");
482 puts(job_count ? "JOB = Pending job for the unit.\n" : "");
483 on = ansi_highlight();
484 off = ansi_highlight_off();
486 on = ansi_highlight_red();
487 off = ansi_highlight_off();
491 printf("%s%u loaded units listed.%s\n"
492 "To show all installed unit files use 'systemctl list-unit-files'.\n",
495 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
496 "To show all installed unit files use 'systemctl list-unit-files'.\n",
503 static int get_unit_list(
507 UnitInfo **unit_infos,
509 sd_bus_message **_reply) {
511 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
512 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
513 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
522 r = sd_bus_message_new_method_call(
525 "org.freedesktop.systemd1",
526 "/org/freedesktop/systemd1",
527 "org.freedesktop.systemd1.Manager",
528 "ListUnitsFiltered");
531 return bus_log_create_error(r);
533 r = sd_bus_message_append_strv(m, arg_states);
535 return bus_log_create_error(r);
537 r = sd_bus_call(bus, m, 0, &error, &reply);
539 log_error("Failed to list units: %s", bus_error_message(&error, r));
543 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
545 return bus_log_parse_error(r);
547 while ((r = bus_parse_unit_info(reply, &u)) > 0) {
550 if (!output_show_unit(&u, patterns))
553 if (!GREEDY_REALLOC(*unit_infos, size, c+1))
556 (*unit_infos)[c++] = u;
559 return bus_log_parse_error(r);
561 r = sd_bus_message_exit_container(reply);
563 return bus_log_parse_error(r);
571 static void message_set_freep(Set **set) {
574 while ((m = set_steal_first(*set)))
575 sd_bus_message_unref(m);
580 static int get_unit_list_recursive(
583 UnitInfo **_unit_infos,
587 _cleanup_free_ UnitInfo *unit_infos = NULL;
588 _cleanup_(message_set_freep) Set *replies;
589 sd_bus_message *reply;
597 replies = set_new(NULL);
601 c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
605 r = set_put(replies, reply);
607 sd_bus_message_unref(reply);
612 _cleanup_strv_free_ char **machines = NULL;
615 r = sd_get_machine_names(&machines);
619 STRV_FOREACH(i, machines) {
620 _cleanup_bus_close_unref_ sd_bus *container = NULL;
623 r = sd_bus_open_system_container(&container, *i);
625 log_error("Failed to connect to container %s: %s", *i, strerror(-r));
629 k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
635 r = set_put(replies, reply);
637 sd_bus_message_unref(reply);
642 *_machines = machines;
647 *_unit_infos = unit_infos;
656 static int list_units(sd_bus *bus, char **args) {
657 _cleanup_free_ UnitInfo *unit_infos = NULL;
658 _cleanup_(message_set_freep) Set *replies = NULL;
659 _cleanup_strv_free_ char **machines = NULL;
662 pager_open_if_enabled();
664 r = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
668 qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
669 return output_units_list(unit_infos, r);
672 static int get_triggered_units(
677 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
680 r = sd_bus_get_property_strv(
682 "org.freedesktop.systemd1",
684 "org.freedesktop.systemd1.Unit",
690 log_error("Failed to determine triggers: %s", bus_error_message(&error, r));
695 static int get_listening(
697 const char* unit_path,
700 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
701 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
702 const char *type, *path;
705 r = sd_bus_get_property(
707 "org.freedesktop.systemd1",
709 "org.freedesktop.systemd1.Socket",
715 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r));
719 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
721 return bus_log_parse_error(r);
723 while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
725 r = strv_extend(listening, type);
729 r = strv_extend(listening, path);
736 return bus_log_parse_error(r);
738 r = sd_bus_message_exit_container(reply);
740 return bus_log_parse_error(r);
752 /* Note: triggered is a list here, although it almost certainly
753 * will always be one unit. Nevertheless, dbus API allows for multiple
754 * values, so let's follow that.*/
757 /* The strv above is shared. free is set only in the first one. */
761 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
767 if (!a->machine && b->machine)
769 if (a->machine && !b->machine)
771 if (a->machine && b->machine) {
772 o = strcasecmp(a->machine, b->machine);
777 o = strcmp(a->path, b->path);
779 o = strcmp(a->type, b->type);
784 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
785 struct socket_info *s;
786 unsigned pathlen = strlen("LISTEN"),
787 typelen = strlen("TYPE") * arg_show_types,
788 socklen = strlen("UNIT"),
789 servlen = strlen("ACTIVATES");
790 const char *on, *off;
792 for (s = socket_infos; s < socket_infos + cs; s++) {
796 socklen = MAX(socklen, strlen(s->id));
798 typelen = MAX(typelen, strlen(s->type));
799 pathlen = MAX(pathlen, strlen(s->path) + (s->machine ? strlen(s->machine)+1 : 0));
801 STRV_FOREACH(a, s->triggered)
802 tmp += strlen(*a) + 2*(a != s->triggered);
803 servlen = MAX(servlen, tmp);
808 printf("%-*s %-*.*s%-*s %s\n",
810 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
814 for (s = socket_infos; s < socket_infos + cs; s++) {
815 _cleanup_free_ char *j = NULL;
820 j = strjoin(s->machine, ":", s->path, NULL);
828 printf("%-*s %-*s %-*s",
829 pathlen, path, typelen, s->type, socklen, s->id);
832 pathlen, path, socklen, s->id);
833 STRV_FOREACH(a, s->triggered)
835 a == s->triggered ? "" : ",", *a);
839 on = ansi_highlight();
840 off = ansi_highlight_off();
844 on = ansi_highlight_red();
845 off = ansi_highlight_off();
848 if (!arg_no_legend) {
849 printf("%s%u sockets listed.%s\n", on, cs, off);
851 printf("Pass --all to see loaded but inactive sockets, too.\n");
857 static int list_sockets(sd_bus *bus, char **args) {
858 _cleanup_(message_set_freep) Set *replies = NULL;
859 _cleanup_strv_free_ char **machines = NULL;
860 _cleanup_free_ UnitInfo *unit_infos = NULL;
861 _cleanup_free_ struct socket_info *socket_infos = NULL;
863 struct socket_info *s;
868 pager_open_if_enabled();
870 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
874 for (u = unit_infos; u < unit_infos + n; u++) {
875 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
878 if (!endswith(u->id, ".socket"))
881 r = get_triggered_units(bus, u->unit_path, &triggered);
885 c = get_listening(bus, u->unit_path, &listening);
891 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
896 for (i = 0; i < c; i++)
897 socket_infos[cs + i] = (struct socket_info) {
898 .machine = u->machine,
900 .type = listening[i*2],
901 .path = listening[i*2 + 1],
902 .triggered = triggered,
903 .own_triggered = i==0,
906 /* from this point on we will cleanup those socket_infos */
909 listening = triggered = NULL; /* avoid cleanup */
912 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
913 (__compar_fn_t) socket_info_compare);
915 output_sockets_list(socket_infos, cs);
918 assert(cs == 0 || socket_infos);
919 for (s = socket_infos; s < socket_infos + cs; s++) {
922 if (s->own_triggered)
923 strv_free(s->triggered);
929 static int get_next_elapse(
932 dual_timestamp *next) {
934 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
942 r = sd_bus_get_property_trivial(
944 "org.freedesktop.systemd1",
946 "org.freedesktop.systemd1.Timer",
947 "NextElapseUSecMonotonic",
952 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
956 r = sd_bus_get_property_trivial(
958 "org.freedesktop.systemd1",
960 "org.freedesktop.systemd1.Timer",
961 "NextElapseUSecRealtime",
966 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
974 static int get_last_trigger(
979 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
986 r = sd_bus_get_property_trivial(
988 "org.freedesktop.systemd1",
990 "org.freedesktop.systemd1.Timer",
996 log_error("Failed to get last trigger time: %s", bus_error_message(&error, r));
1004 const char* machine;
1007 usec_t last_trigger;
1011 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
1017 if (!a->machine && b->machine)
1019 if (a->machine && !b->machine)
1021 if (a->machine && b->machine) {
1022 o = strcasecmp(a->machine, b->machine);
1027 if (a->next_elapse < b->next_elapse)
1029 if (a->next_elapse > b->next_elapse)
1032 return strcmp(a->id, b->id);
1035 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
1036 struct timer_info *t;
1038 nextlen = strlen("NEXT"),
1039 leftlen = strlen("LEFT"),
1040 lastlen = strlen("LAST"),
1041 passedlen = strlen("PASSED"),
1042 unitlen = strlen("UNIT"),
1043 activatelen = strlen("ACTIVATES");
1045 const char *on, *off;
1047 assert(timer_infos || n == 0);
1049 for (t = timer_infos; t < timer_infos + n; t++) {
1053 if (t->next_elapse > 0) {
1054 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1056 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
1057 nextlen = MAX(nextlen, strlen(tstamp) + 1);
1059 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
1060 leftlen = MAX(leftlen, strlen(trel));
1063 if (t->last_trigger > 0) {
1064 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1066 format_timestamp(tstamp, sizeof(tstamp), t->last_trigger);
1067 lastlen = MAX(lastlen, strlen(tstamp) + 1);
1069 format_timestamp_relative(trel, sizeof(trel), t->last_trigger);
1070 passedlen = MAX(passedlen, strlen(trel));
1073 unitlen = MAX(unitlen, strlen(t->id) + (t->machine ? strlen(t->machine)+1 : 0));
1075 STRV_FOREACH(a, t->triggered)
1076 ul += strlen(*a) + 2*(a != t->triggered);
1078 activatelen = MAX(activatelen, ul);
1083 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1087 passedlen, "PASSED",
1091 for (t = timer_infos; t < timer_infos + n; t++) {
1092 _cleanup_free_ char *j = NULL;
1094 char tstamp1[FORMAT_TIMESTAMP_MAX] = "n/a", trel1[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1095 char tstamp2[FORMAT_TIMESTAMP_MAX] = "n/a", trel2[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1098 format_timestamp(tstamp1, sizeof(tstamp1), t->next_elapse);
1099 format_timestamp_relative(trel1, sizeof(trel1), t->next_elapse);
1101 format_timestamp(tstamp2, sizeof(tstamp2), t->last_trigger);
1102 format_timestamp_relative(trel2, sizeof(trel2), t->last_trigger);
1105 j = strjoin(t->machine, ":", t->id, NULL);
1112 printf("%-*s %-*s %-*s %-*s %-*s",
1113 nextlen, tstamp1, leftlen, trel1, lastlen, tstamp2, passedlen, trel2, unitlen, unit);
1115 STRV_FOREACH(a, t->triggered)
1117 a == t->triggered ? "" : ",", *a);
1121 on = ansi_highlight();
1122 off = ansi_highlight_off();
1126 on = ansi_highlight_red();
1127 off = ansi_highlight_off();
1130 if (!arg_no_legend) {
1131 printf("%s%u timers listed.%s\n", on, n, off);
1133 printf("Pass --all to see loaded but inactive timers, too.\n");
1139 static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
1145 if (next->monotonic != USEC_INFINITY && next->monotonic > 0) {
1148 if (next->monotonic > nw->monotonic)
1149 converted = nw->realtime + (next->monotonic - nw->monotonic);
1151 converted = nw->realtime - (nw->monotonic - next->monotonic);
1153 if (next->realtime != USEC_INFINITY && next->realtime > 0)
1154 next_elapse = MIN(converted, next->realtime);
1156 next_elapse = converted;
1159 next_elapse = next->realtime;
1164 static int list_timers(sd_bus *bus, char **args) {
1165 _cleanup_(message_set_freep) Set *replies = NULL;
1166 _cleanup_strv_free_ char **machines = NULL;
1167 _cleanup_free_ struct timer_info *timer_infos = NULL;
1168 _cleanup_free_ UnitInfo *unit_infos = NULL;
1169 struct timer_info *t;
1176 pager_open_if_enabled();
1178 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
1182 dual_timestamp_get(&nw);
1184 for (u = unit_infos; u < unit_infos + n; u++) {
1185 _cleanup_strv_free_ char **triggered = NULL;
1186 dual_timestamp next = {};
1189 if (!endswith(u->id, ".timer"))
1192 r = get_triggered_units(bus, u->unit_path, &triggered);
1196 r = get_next_elapse(bus, u->unit_path, &next);
1200 get_last_trigger(bus, u->unit_path, &last);
1202 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
1207 m = calc_next_elapse(&nw, &next);
1209 timer_infos[c++] = (struct timer_info) {
1210 .machine = u->machine,
1213 .last_trigger = last,
1214 .triggered = triggered,
1217 triggered = NULL; /* avoid cleanup */
1220 qsort_safe(timer_infos, c, sizeof(struct timer_info),
1221 (__compar_fn_t) timer_info_compare);
1223 output_timers_list(timer_infos, c);
1226 for (t = timer_infos; t < timer_infos + c; t++)
1227 strv_free(t->triggered);
1232 static int compare_unit_file_list(const void *a, const void *b) {
1233 const char *d1, *d2;
1234 const UnitFileList *u = a, *v = b;
1236 d1 = strrchr(u->path, '.');
1237 d2 = strrchr(v->path, '.');
1242 r = strcasecmp(d1, d2);
1247 return strcasecmp(basename(u->path), basename(v->path));
1250 static bool output_show_unit_file(const UnitFileList *u, char **patterns) {
1251 if (!strv_isempty(patterns)) {
1254 STRV_FOREACH(pattern, patterns)
1255 if (fnmatch(*pattern, basename(u->path), FNM_NOESCAPE) == 0)
1261 if (!strv_isempty(arg_types)) {
1264 dot = strrchr(u->path, '.');
1268 if (!strv_find(arg_types, dot+1))
1272 if (!strv_isempty(arg_states)) {
1273 if (!strv_find(arg_states, unit_file_state_to_string(u->state)))
1280 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
1281 unsigned max_id_len, id_cols, state_cols;
1282 const UnitFileList *u;
1284 max_id_len = strlen("UNIT FILE");
1285 state_cols = strlen("STATE");
1287 for (u = units; u < units + c; u++) {
1288 max_id_len = MAX(max_id_len, strlen(basename(u->path)));
1289 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1293 unsigned basic_cols;
1295 id_cols = MIN(max_id_len, 25u);
1296 basic_cols = 1 + id_cols + state_cols;
1297 if (basic_cols < (unsigned) columns())
1298 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1300 id_cols = max_id_len;
1303 printf("%-*s %-*s\n",
1304 id_cols, "UNIT FILE",
1305 state_cols, "STATE");
1307 for (u = units; u < units + c; u++) {
1308 _cleanup_free_ char *e = NULL;
1309 const char *on, *off;
1312 if (u->state == UNIT_FILE_MASKED ||
1313 u->state == UNIT_FILE_MASKED_RUNTIME ||
1314 u->state == UNIT_FILE_DISABLED ||
1315 u->state == UNIT_FILE_INVALID) {
1316 on = ansi_highlight_red();
1317 off = ansi_highlight_off();
1318 } else if (u->state == UNIT_FILE_ENABLED) {
1319 on = ansi_highlight_green();
1320 off = ansi_highlight_off();
1324 id = basename(u->path);
1326 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1328 printf("%-*s %s%-*s%s\n",
1329 id_cols, e ? e : id,
1330 on, state_cols, unit_file_state_to_string(u->state), off);
1334 printf("\n%u unit files listed.\n", c);
1337 static int list_unit_files(sd_bus *bus, char **args) {
1338 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1339 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1340 _cleanup_free_ UnitFileList *units = NULL;
1348 pager_open_if_enabled();
1356 h = hashmap_new(&string_hash_ops);
1360 r = unit_file_get_list(arg_scope, arg_root, h);
1362 unit_file_list_free(h);
1363 log_error("Failed to get unit file list: %s", strerror(-r));
1367 n_units = hashmap_size(h);
1369 units = new(UnitFileList, n_units);
1370 if (!units && n_units > 0) {
1371 unit_file_list_free(h);
1375 HASHMAP_FOREACH(u, h, i) {
1376 if (!output_show_unit_file(u, strv_skip_first(args)))
1383 assert(c <= n_units);
1386 r = sd_bus_call_method(
1388 "org.freedesktop.systemd1",
1389 "/org/freedesktop/systemd1",
1390 "org.freedesktop.systemd1.Manager",
1396 log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1400 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1402 return bus_log_parse_error(r);
1404 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1406 if (!GREEDY_REALLOC(units, size, c + 1))
1409 units[c] = (struct UnitFileList) {
1411 unit_file_state_from_string(state)
1414 if (output_show_unit_file(&units[c], strv_skip_first(args)))
1419 return bus_log_parse_error(r);
1421 r = sd_bus_message_exit_container(reply);
1423 return bus_log_parse_error(r);
1426 qsort_safe(units, c, sizeof(UnitFileList), compare_unit_file_list);
1427 output_unit_file_list(units, c);
1430 for (unit = units; unit < units + c; unit++)
1437 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1438 _cleanup_free_ char *n = NULL;
1439 size_t max_len = MAX(columns(),20u);
1445 for (i = level - 1; i >= 0; i--) {
1447 if (len > max_len - 3 && !arg_full) {
1448 printf("%s...\n",max_len % 2 ? "" : " ");
1451 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERTICAL : DRAW_TREE_SPACE));
1455 if (len > max_len - 3 && !arg_full) {
1456 printf("%s...\n",max_len % 2 ? "" : " ");
1460 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
1464 printf("%s\n", name);
1468 n = ellipsize(name, max_len-len, 100);
1476 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1478 static const char *dependencies[_DEPENDENCY_MAX] = {
1479 [DEPENDENCY_FORWARD] = "Requires\0"
1480 "RequiresOverridable\0"
1482 "RequisiteOverridable\0"
1484 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1485 "RequiredByOverridable\0"
1488 [DEPENDENCY_AFTER] = "After\0",
1489 [DEPENDENCY_BEFORE] = "Before\0",
1492 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1493 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1494 _cleanup_strv_free_ char **ret = NULL;
1495 _cleanup_free_ char *path = NULL;
1501 assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
1503 path = unit_dbus_path_from_name(name);
1507 r = sd_bus_call_method(
1509 "org.freedesktop.systemd1",
1511 "org.freedesktop.DBus.Properties",
1515 "s", "org.freedesktop.systemd1.Unit");
1517 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1521 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1523 return bus_log_parse_error(r);
1525 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1528 r = sd_bus_message_read(reply, "s", &prop);
1530 return bus_log_parse_error(r);
1532 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1533 r = sd_bus_message_skip(reply, "v");
1535 return bus_log_parse_error(r);
1538 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1540 return bus_log_parse_error(r);
1542 r = bus_message_read_strv_extend(reply, &ret);
1544 return bus_log_parse_error(r);
1546 r = sd_bus_message_exit_container(reply);
1548 return bus_log_parse_error(r);
1551 r = sd_bus_message_exit_container(reply);
1553 return bus_log_parse_error(r);
1557 return bus_log_parse_error(r);
1559 r = sd_bus_message_exit_container(reply);
1561 return bus_log_parse_error(r);
1569 static int list_dependencies_compare(const void *_a, const void *_b) {
1570 const char **a = (const char**) _a, **b = (const char**) _b;
1572 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1574 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1577 return strcasecmp(*a, *b);
1580 static int list_dependencies_one(
1585 unsigned int branches) {
1587 _cleanup_strv_free_ char **deps = NULL;
1595 r = strv_extend(units, name);
1599 r = list_dependencies_get_dependencies(bus, name, &deps);
1603 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1605 STRV_FOREACH(c, deps) {
1608 if (strv_contains(*units, *c)) {
1610 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1617 state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true);
1619 printf("%s%s%s ", ansi_highlight_green(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1621 printf("%s%s%s ", ansi_highlight_red(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1623 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1627 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1628 r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1635 strv_remove(*units, name);
1640 static int list_dependencies(sd_bus *bus, char **args) {
1641 _cleanup_strv_free_ char **units = NULL;
1642 _cleanup_free_ char *unit = NULL;
1648 unit = unit_name_mangle(args[1], MANGLE_NOGLOB);
1653 u = SPECIAL_DEFAULT_TARGET;
1655 pager_open_if_enabled();
1659 return list_dependencies_one(bus, u, 0, &units, 0);
1662 struct machine_info {
1666 char *control_group;
1667 uint32_t n_failed_units;
1672 static const struct bus_properties_map machine_info_property_map[] = {
1673 { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
1674 { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
1675 { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
1676 { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
1677 { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
1681 static void free_machines_list(struct machine_info *machine_infos, int n) {
1687 for (i = 0; i < n; i++) {
1688 free(machine_infos[i].name);
1689 free(machine_infos[i].state);
1690 free(machine_infos[i].control_group);
1693 free(machine_infos);
1696 static int compare_machine_info(const void *a, const void *b) {
1697 const struct machine_info *u = a, *v = b;
1699 if (u->is_host != v->is_host)
1700 return u->is_host > v->is_host ? -1 : 1;
1702 return strcasecmp(u->name, v->name);
1705 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1706 _cleanup_bus_close_unref_ sd_bus *container = NULL;
1712 r = sd_bus_open_system_container(&container, mi->name);
1719 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi);
1726 static bool output_show_machine(const char *name, char **patterns) {
1731 if (strv_isempty(patterns))
1734 STRV_FOREACH(i, patterns)
1735 if (fnmatch(*i, name, FNM_NOESCAPE) == 0)
1741 static int get_machine_list(
1743 struct machine_info **_machine_infos,
1746 struct machine_info *machine_infos = NULL;
1747 _cleanup_strv_free_ char **m = NULL;
1748 _cleanup_free_ char *hn = NULL;
1753 hn = gethostname_malloc();
1757 if (output_show_machine(hn, patterns)) {
1758 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1761 machine_infos[c].is_host = true;
1762 machine_infos[c].name = hn;
1765 get_machine_properties(bus, &machine_infos[c]);
1769 sd_get_machine_names(&m);
1770 STRV_FOREACH(i, m) {
1771 _cleanup_free_ char *class = NULL;
1773 if (!output_show_machine(*i, patterns))
1776 sd_machine_get_class(*i, &class);
1777 if (!streq_ptr(class, "container"))
1780 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1781 free_machines_list(machine_infos, c);
1785 machine_infos[c].is_host = false;
1786 machine_infos[c].name = strdup(*i);
1787 if (!machine_infos[c].name) {
1788 free_machines_list(machine_infos, c);
1792 get_machine_properties(NULL, &machine_infos[c]);
1796 *_machine_infos = machine_infos;
1800 static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1801 struct machine_info *m;
1804 namelen = sizeof("NAME") - 1,
1805 statelen = sizeof("STATE") - 1,
1806 failedlen = sizeof("FAILED") - 1,
1807 jobslen = sizeof("JOBS") - 1;
1809 assert(machine_infos || n == 0);
1811 for (m = machine_infos; m < machine_infos + n; m++) {
1812 namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
1813 statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
1814 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
1815 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
1817 if (!arg_no_legend && !streq_ptr(m->state, "running"))
1821 if (!arg_no_legend) {
1825 printf("%-*s %-*s %-*s %-*s\n",
1828 failedlen, "FAILED",
1832 for (m = machine_infos; m < machine_infos + n; m++) {
1833 const char *on_state = "", *off_state = "";
1834 const char *on_failed = "", *off_failed = "";
1835 bool circle = false;
1837 if (streq_ptr(m->state, "degraded")) {
1838 on_state = ansi_highlight_red();
1839 off_state = ansi_highlight_off();
1841 } else if (!streq_ptr(m->state, "running")) {
1842 on_state = ansi_highlight_yellow();
1843 off_state = ansi_highlight_off();
1847 if (m->n_failed_units > 0) {
1848 on_failed = ansi_highlight_red();
1849 off_failed = ansi_highlight_off();
1851 on_failed = off_failed = "";
1854 printf("%s%s%s ", on_state, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_state);
1857 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1858 (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
1859 on_state, statelen, strna(m->state), off_state,
1860 on_failed, failedlen, m->n_failed_units, off_failed,
1861 jobslen, m->n_jobs);
1863 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1864 namelen, strna(m->name),
1865 on_state, statelen, strna(m->state), off_state,
1866 on_failed, failedlen, m->n_failed_units, off_failed,
1867 jobslen, m->n_jobs);
1871 printf("\n%u machines listed.\n", n);
1874 static int list_machines(sd_bus *bus, char **args) {
1875 struct machine_info *machine_infos = NULL;
1880 if (geteuid() != 0) {
1881 log_error("Must be root.");
1885 pager_open_if_enabled();
1887 r = get_machine_list(bus, &machine_infos, strv_skip_first(args));
1891 qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
1892 output_machines_list(machine_infos, r);
1893 free_machines_list(machine_infos, r);
1898 static int get_default(sd_bus *bus, char **args) {
1899 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1900 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1901 _cleanup_free_ char *_path = NULL;
1905 if (!bus || avoid_bus()) {
1906 r = unit_file_get_default(arg_scope, arg_root, &_path);
1908 log_error("Failed to get default target: %s", strerror(-r));
1914 r = sd_bus_call_method(
1916 "org.freedesktop.systemd1",
1917 "/org/freedesktop/systemd1",
1918 "org.freedesktop.systemd1.Manager",
1924 log_error("Failed to get default target: %s", bus_error_message(&error, -r));
1928 r = sd_bus_message_read(reply, "s", &path);
1930 return bus_log_parse_error(r);
1934 printf("%s\n", path);
1939 static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) {
1942 assert(changes || n_changes == 0);
1944 for (i = 0; i < n_changes; i++) {
1945 if (changes[i].type == UNIT_FILE_SYMLINK)
1946 log_info("Created symlink from %s to %s.", changes[i].path, changes[i].source);
1948 log_info("Removed symlink %s.", changes[i].path);
1952 static int deserialize_and_dump_unit_file_changes(sd_bus_message *m) {
1953 const char *type, *path, *source;
1956 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1958 return bus_log_parse_error(r);
1960 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1962 if (streq(type, "symlink"))
1963 log_info("Created symlink from %s to %s.", path, source);
1965 log_info("Removed symlink %s.", path);
1969 return bus_log_parse_error(r);
1971 r = sd_bus_message_exit_container(m);
1973 return bus_log_parse_error(r);
1978 static int set_default(sd_bus *bus, char **args) {
1979 _cleanup_free_ char *unit = NULL;
1980 UnitFileChange *changes = NULL;
1981 unsigned n_changes = 0;
1984 unit = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
1988 if (!bus || avoid_bus()) {
1989 r = unit_file_set_default(arg_scope, arg_root, unit, true, &changes, &n_changes);
1991 log_error("Failed to set default target: %s", strerror(-r));
1996 dump_unit_file_changes(changes, n_changes);
2000 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
2001 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2003 r = sd_bus_message_new_method_call(
2006 "org.freedesktop.systemd1",
2007 "/org/freedesktop/systemd1",
2008 "org.freedesktop.systemd1.Manager",
2009 "SetDefaultTarget");
2011 return bus_log_create_error(r);
2013 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2015 return bus_log_create_error(r);
2017 r = sd_bus_message_append(m, "sb", unit, 1);
2019 return bus_log_create_error(r);
2021 r = sd_bus_call(bus, m, 0, &error, &reply);
2023 log_error("Failed to set default target: %s", bus_error_message(&error, -r));
2027 r = deserialize_and_dump_unit_file_changes(reply);
2031 /* Try to reload if enabled */
2033 r = daemon_reload(bus, args);
2038 unit_file_changes_free(changes, n_changes);
2045 const char *name, *type, *state;
2048 static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
2049 unsigned id_len, unit_len, type_len, state_len;
2050 const struct job_info *j;
2051 const char *on, *off;
2052 bool shorten = false;
2054 assert(n == 0 || jobs);
2057 on = ansi_highlight_green();
2058 off = ansi_highlight_off();
2060 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
2064 pager_open_if_enabled();
2066 id_len = strlen("JOB");
2067 unit_len = strlen("UNIT");
2068 type_len = strlen("TYPE");
2069 state_len = strlen("STATE");
2071 for (j = jobs; j < jobs + n; j++) {
2072 uint32_t id = j->id;
2073 assert(j->name && j->type && j->state);
2075 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
2076 unit_len = MAX(unit_len, strlen(j->name));
2077 type_len = MAX(type_len, strlen(j->type));
2078 state_len = MAX(state_len, strlen(j->state));
2081 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
2082 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
2087 printf("%*s %-*s %-*s %-*s\n",
2091 state_len, "STATE");
2093 for (j = jobs; j < jobs + n; j++) {
2094 _cleanup_free_ char *e = NULL;
2096 if (streq(j->state, "running")) {
2097 on = ansi_highlight();
2098 off = ansi_highlight_off();
2102 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
2103 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2105 on, unit_len, e ? e : j->name, off,
2107 on, state_len, j->state, off);
2110 if (!arg_no_legend) {
2111 on = ansi_highlight();
2112 off = ansi_highlight_off();
2114 printf("\n%s%u jobs listed%s.\n", on, n, off);
2118 static bool output_show_job(struct job_info *job, char **patterns) {
2123 if (strv_isempty(patterns))
2126 STRV_FOREACH(pattern, patterns)
2127 if (fnmatch(*pattern, job->name, FNM_NOESCAPE) == 0)
2132 static int list_jobs(sd_bus *bus, char **args) {
2133 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2134 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2135 const char *name, *type, *state, *job_path, *unit_path;
2136 _cleanup_free_ struct job_info *jobs = NULL;
2141 bool skipped = false;
2143 r = sd_bus_call_method(
2145 "org.freedesktop.systemd1",
2146 "/org/freedesktop/systemd1",
2147 "org.freedesktop.systemd1.Manager",
2153 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
2157 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2159 return bus_log_parse_error(r);
2161 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
2162 struct job_info job = { id, name, type, state };
2164 if (!output_show_job(&job, strv_skip_first(args))) {
2169 if (!GREEDY_REALLOC(jobs, size, c + 1))
2175 return bus_log_parse_error(r);
2177 r = sd_bus_message_exit_container(reply);
2179 return bus_log_parse_error(r);
2181 output_jobs_list(jobs, c, skipped);
2185 static int cancel_job(sd_bus *bus, char **args) {
2186 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2192 if (strv_length(args) <= 1)
2193 return daemon_reload(bus, args);
2195 STRV_FOREACH(name, args+1) {
2196 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2200 q = safe_atou32(*name, &id);
2202 log_error("Failed to parse job id \"%s\": %s", *name, strerror(-q));
2206 q = sd_bus_message_new_method_call(
2209 "org.freedesktop.systemd1",
2210 "/org/freedesktop/systemd1",
2211 "org.freedesktop.systemd1.Manager",
2214 return bus_log_create_error(q);
2216 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2218 return bus_log_create_error(1);
2220 q = sd_bus_message_append(m, "u", id);
2222 return bus_log_create_error(q);
2224 q = sd_bus_call(bus, m, 0, &error, NULL);
2226 log_error("Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, q));
2235 static int need_daemon_reload(sd_bus *bus, const char *unit) {
2236 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2240 /* We ignore all errors here, since this is used to show a
2243 /* We don't use unit_dbus_path_from_name() directly since we
2244 * don't want to load the unit if it isn't loaded. */
2246 r = sd_bus_call_method(
2248 "org.freedesktop.systemd1",
2249 "/org/freedesktop/systemd1",
2250 "org.freedesktop.systemd1.Manager",
2258 r = sd_bus_message_read(reply, "o", &path);
2262 r = sd_bus_get_property_trivial(
2264 "org.freedesktop.systemd1",
2266 "org.freedesktop.systemd1.Unit",
2276 typedef struct WaitData {
2283 static int wait_filter(sd_bus *bus, sd_bus_message *m, void *data, sd_bus_error *error) {
2290 log_debug("Got D-Bus request: %s.%s() on %s",
2291 sd_bus_message_get_interface(m),
2292 sd_bus_message_get_member(m),
2293 sd_bus_message_get_path(m));
2295 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
2296 log_error("Warning! D-Bus connection terminated.");
2298 } else if (sd_bus_message_is_signal(m, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
2300 const char *path, *result, *unit;
2304 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
2306 ret = set_remove(d->set, (char*) path);
2312 if (!isempty(result))
2313 d->result = strdup(result);
2316 d->name = strdup(unit);
2321 r = sd_bus_message_read(m, "uos", &id, &path, &result);
2323 ret = set_remove(d->set, (char*) path);
2330 d->result = strdup(result);
2336 bus_log_parse_error(r);
2342 static int enable_wait_for_jobs(sd_bus *bus) {
2347 r = sd_bus_add_match(
2351 "sender='org.freedesktop.systemd1',"
2352 "interface='org.freedesktop.systemd1.Manager',"
2353 "member='JobRemoved',"
2354 "path='/org/freedesktop/systemd1'",
2357 log_error("Failed to add match");
2361 /* This is slightly dirty, since we don't undo the match registrations. */
2365 static int bus_process_wait(sd_bus *bus) {
2369 r = sd_bus_process(bus, NULL);
2374 r = sd_bus_wait(bus, (uint64_t) -1);
2380 static int check_wait_response(WaitData *d) {
2386 if (streq(d->result, "timeout"))
2387 log_error("Job for %s timed out.", strna(d->name));
2388 else if (streq(d->result, "canceled"))
2389 log_error("Job for %s canceled.", strna(d->name));
2390 else if (streq(d->result, "dependency"))
2391 log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
2392 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
2396 quotes = chars_intersect(d->name, SHELL_NEED_QUOTES);
2398 log_error("Job for %s failed. See \"systemctl status %s%s%s\" and \"journalctl -xe\" for details.",
2400 quotes ? "'" : "", d->name, quotes ? "'" : "");
2402 log_error("Job failed. See \"journalctl -xe\" for details.");
2406 if (streq(d->result, "timeout"))
2408 else if (streq(d->result, "canceled"))
2410 else if (streq(d->result, "dependency"))
2412 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2418 static int wait_for_jobs(sd_bus *bus, Set *s) {
2419 _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
2420 WaitData d = { .set = s };
2426 q = sd_bus_add_filter(bus, &slot, wait_filter, &d);
2430 while (!set_isempty(s)) {
2431 q = bus_process_wait(bus);
2433 log_error("Failed to wait for response: %s", strerror(-q));
2438 q = check_wait_response(&d);
2439 /* Return the first error as it is most likely to be
2441 if (q < 0 && r == 0)
2443 log_debug("Got result %s/%s for job %s",
2444 strna(d.result), strerror(-q), strna(d.name));
2457 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2458 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2459 _cleanup_free_ char *n = NULL, *state = NULL;
2465 n = unit_name_mangle(name, MANGLE_NOGLOB);
2469 /* We don't use unit_dbus_path_from_name() directly since we
2470 * don't want to load the unit if it isn't loaded. */
2472 r = sd_bus_call_method(
2474 "org.freedesktop.systemd1",
2475 "/org/freedesktop/systemd1",
2476 "org.freedesktop.systemd1.Manager",
2487 r = sd_bus_message_read(reply, "o", &path);
2489 return bus_log_parse_error(r);
2491 r = sd_bus_get_property_string(
2493 "org.freedesktop.systemd1",
2495 "org.freedesktop.systemd1.Unit",
2508 return nulstr_contains(good_states, state);
2511 static int check_triggering_units(
2515 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2516 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2517 _cleanup_strv_free_ char **triggered_by = NULL;
2518 bool print_warning_label = true;
2522 n = unit_name_mangle(name, MANGLE_NOGLOB);
2526 path = unit_dbus_path_from_name(n);
2530 r = sd_bus_get_property_string(
2532 "org.freedesktop.systemd1",
2534 "org.freedesktop.systemd1.Unit",
2539 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2543 if (streq(state, "masked"))
2546 r = sd_bus_get_property_strv(
2548 "org.freedesktop.systemd1",
2550 "org.freedesktop.systemd1.Unit",
2555 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2559 STRV_FOREACH(i, triggered_by) {
2560 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2562 log_error("Failed to check unit: %s", strerror(-r));
2569 if (print_warning_label) {
2570 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2571 print_warning_label = false;
2574 log_warning(" %s", *i);
2580 static const struct {
2583 } unit_actions[] = {
2584 { "start", "StartUnit" },
2585 { "stop", "StopUnit" },
2586 { "condstop", "StopUnit" },
2587 { "reload", "ReloadUnit" },
2588 { "restart", "RestartUnit" },
2589 { "try-restart", "TryRestartUnit" },
2590 { "condrestart", "TryRestartUnit" },
2591 { "reload-or-restart", "ReloadOrRestartUnit" },
2592 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2593 { "condreload", "ReloadOrTryRestartUnit" },
2594 { "force-reload", "ReloadOrTryRestartUnit" }
2597 static const char *verb_to_method(const char *verb) {
2600 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2601 if (streq_ptr(unit_actions[i].verb, verb))
2602 return unit_actions[i].method;
2607 static const char *method_to_verb(const char *method) {
2610 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2611 if (streq_ptr(unit_actions[i].method, method))
2612 return unit_actions[i].verb;
2617 static int start_unit_one(
2622 sd_bus_error *error,
2625 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2634 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2636 r = sd_bus_message_new_method_call(
2639 "org.freedesktop.systemd1",
2640 "/org/freedesktop/systemd1",
2641 "org.freedesktop.systemd1.Manager",
2644 return bus_log_create_error(r);
2646 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2648 return bus_log_create_error(r);
2650 r = sd_bus_message_append(m, "ss", name, mode);
2652 return bus_log_create_error(r);
2654 r = sd_bus_call(bus, m, 0, error, &reply);
2658 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2659 /* There's always a fallback possible for
2660 * legacy actions. */
2661 return -EADDRNOTAVAIL;
2663 verb = method_to_verb(method);
2665 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2669 r = sd_bus_message_read(reply, "o", &path);
2671 return bus_log_parse_error(r);
2673 if (need_daemon_reload(bus, name) > 0)
2674 log_warning("Warning: Unit file of %s changed on disk, 'systemctl%s daemon-reload' recommended.",
2675 name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2684 log_debug("Adding %s to the set", p);
2685 r = set_consume(s, p);
2693 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2695 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2699 STRV_FOREACH(name, names) {
2703 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2705 t = unit_name_mangle(*name, MANGLE_GLOB);
2709 if (string_is_glob(t))
2710 r = strv_consume(&globs, t);
2712 r = strv_consume(&mangled, t);
2717 /* Query the manager only if any of the names are a glob, since
2718 * this is fairly expensive */
2719 if (!strv_isempty(globs)) {
2720 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2721 _cleanup_free_ UnitInfo *unit_infos = NULL;
2723 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2727 for (i = 0; i < r; i++)
2728 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2733 mangled = NULL; /* do not free */
2738 static const struct {
2742 } action_table[_ACTION_MAX] = {
2743 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2744 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2745 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2746 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2747 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
2748 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
2749 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
2750 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
2751 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2752 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2753 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2754 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2755 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2756 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2757 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2760 static enum action verb_to_action(const char *verb) {
2763 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2764 if (streq_ptr(action_table[i].verb, verb))
2767 return _ACTION_INVALID;
2770 static int start_unit(sd_bus *bus, char **args) {
2771 _cleanup_set_free_free_ Set *s = NULL;
2772 _cleanup_strv_free_ char **names = NULL;
2773 const char *method, *mode, *one_name, *suffix = NULL;
2779 ask_password_agent_open_if_enabled();
2781 if (arg_action == ACTION_SYSTEMCTL) {
2783 method = verb_to_method(args[0]);
2784 action = verb_to_action(args[0]);
2786 if (streq(args[0], "isolate")) {
2790 mode = action_table[action].mode ?: arg_job_mode;
2792 one_name = action_table[action].target;
2794 assert(arg_action < ELEMENTSOF(action_table));
2795 assert(action_table[arg_action].target);
2797 method = "StartUnit";
2799 mode = action_table[arg_action].mode;
2800 one_name = action_table[arg_action].target;
2804 names = strv_new(one_name, NULL);
2806 r = expand_names(bus, args + 1, suffix, &names);
2808 log_error("Failed to expand names: %s", strerror(-r));
2811 if (!arg_no_block) {
2812 r = enable_wait_for_jobs(bus);
2814 log_error("Could not watch jobs: %s", strerror(-r));
2818 s = set_new(&string_hash_ops);
2823 STRV_FOREACH(name, names) {
2824 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2827 q = start_unit_one(bus, method, *name, mode, &error, s);
2828 if (r >= 0 && q < 0)
2829 r = translate_bus_error_to_exit_status(q, &error);
2832 if (!arg_no_block) {
2835 q = wait_for_jobs(bus, s);
2839 /* When stopping units, warn if they can still be triggered by
2840 * another active unit (socket, path, timer) */
2841 if (!arg_quiet && streq(method, "StopUnit"))
2842 STRV_FOREACH(name, names)
2843 check_triggering_units(bus, *name);
2849 /* Ask systemd-logind, which might grant access to unprivileged users
2850 * through PolicyKit */
2851 static int reboot_with_logind(sd_bus *bus, enum action a) {
2853 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2860 polkit_agent_open_if_enabled();
2868 case ACTION_POWEROFF:
2869 method = "PowerOff";
2872 case ACTION_SUSPEND:
2876 case ACTION_HIBERNATE:
2877 method = "Hibernate";
2880 case ACTION_HYBRID_SLEEP:
2881 method = "HybridSleep";
2888 r = sd_bus_call_method(
2890 "org.freedesktop.login1",
2891 "/org/freedesktop/login1",
2892 "org.freedesktop.login1.Manager",
2896 "b", arg_ask_password);
2898 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2906 static int check_inhibitors(sd_bus *bus, enum action a) {
2908 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2909 _cleanup_strv_free_ char **sessions = NULL;
2910 const char *what, *who, *why, *mode;
2919 if (arg_ignore_inhibitors || arg_force > 0)
2931 r = sd_bus_call_method(
2933 "org.freedesktop.login1",
2934 "/org/freedesktop/login1",
2935 "org.freedesktop.login1.Manager",
2941 /* If logind is not around, then there are no inhibitors... */
2944 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2946 return bus_log_parse_error(r);
2948 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2949 _cleanup_free_ char *comm = NULL, *user = NULL;
2950 _cleanup_strv_free_ char **sv = NULL;
2952 if (!streq(mode, "block"))
2955 sv = strv_split(what, ":");
2959 if (!strv_contains(sv,
2961 a == ACTION_POWEROFF ||
2962 a == ACTION_REBOOT ||
2963 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2966 get_process_comm(pid, &comm);
2967 user = uid_to_name(uid);
2969 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
2970 who, pid, strna(comm), strna(user), why);
2975 return bus_log_parse_error(r);
2977 r = sd_bus_message_exit_container(reply);
2979 return bus_log_parse_error(r);
2981 /* Check for current sessions */
2982 sd_get_sessions(&sessions);
2983 STRV_FOREACH(s, sessions) {
2984 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2986 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2989 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2992 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2995 sd_session_get_tty(*s, &tty);
2996 sd_session_get_seat(*s, &seat);
2997 sd_session_get_service(*s, &service);
2998 user = uid_to_name(uid);
3000 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
3007 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3008 action_table[a].verb);
3016 static int start_special(sd_bus *bus, char **args) {
3022 a = verb_to_action(args[0]);
3024 r = check_inhibitors(bus, a);
3028 if (arg_force >= 2 && geteuid() != 0) {
3029 log_error("Must be root.");
3033 if (arg_force >= 2 &&
3034 (a == ACTION_HALT ||
3035 a == ACTION_POWEROFF ||
3036 a == ACTION_REBOOT))
3039 if (arg_force >= 1 &&
3040 (a == ACTION_HALT ||
3041 a == ACTION_POWEROFF ||
3042 a == ACTION_REBOOT ||
3043 a == ACTION_KEXEC ||
3045 return daemon_reload(bus, args);
3047 /* first try logind, to allow authentication with polkit */
3048 if (geteuid() != 0 &&
3049 (a == ACTION_POWEROFF ||
3050 a == ACTION_REBOOT ||
3051 a == ACTION_SUSPEND ||
3052 a == ACTION_HIBERNATE ||
3053 a == ACTION_HYBRID_SLEEP)) {
3054 r = reboot_with_logind(bus, a);
3059 r = start_unit(bus, args);
3060 if (r == EXIT_SUCCESS)
3066 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
3067 _cleanup_strv_free_ char **names = NULL;
3074 r = expand_names(bus, args, NULL, &names);
3076 log_error("Failed to expand names: %s", strerror(-r));
3080 STRV_FOREACH(name, names) {
3083 state = check_one_unit(bus, *name, good_states, arg_quiet);
3093 static int check_unit_active(sd_bus *bus, char **args) {
3094 /* According to LSB: 3, "program is not running" */
3095 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
3098 static int check_unit_failed(sd_bus *bus, char **args) {
3099 return check_unit_generic(bus, 1, "failed\0", args + 1);
3102 static int kill_unit(sd_bus *bus, char **args) {
3103 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3104 _cleanup_strv_free_ char **names = NULL;
3112 arg_kill_who = "all";
3114 r = expand_names(bus, args + 1, NULL, &names);
3116 log_error("Failed to expand names: %s", strerror(-r));
3118 STRV_FOREACH(name, names) {
3119 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3121 q = sd_bus_message_new_method_call(
3124 "org.freedesktop.systemd1",
3125 "/org/freedesktop/systemd1",
3126 "org.freedesktop.systemd1.Manager",
3129 return bus_log_create_error(q);
3131 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
3133 return bus_log_create_error(q);
3135 q = sd_bus_message_append(m, "ssi", *names, arg_kill_who, arg_signal);
3137 return bus_log_create_error(q);
3139 q = sd_bus_call(bus, m, 0, &error, NULL);
3141 log_error("Failed to kill unit %s: %s", *names, bus_error_message(&error, q));
3150 typedef struct ExecStatusInfo {
3158 usec_t start_timestamp;
3159 usec_t exit_timestamp;
3164 LIST_FIELDS(struct ExecStatusInfo, exec);
3167 static void exec_status_info_free(ExecStatusInfo *i) {
3176 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3177 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3180 int32_t code, status;
3186 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3188 return bus_log_parse_error(r);
3192 r = sd_bus_message_read(m, "s", &path);
3194 return bus_log_parse_error(r);
3196 i->path = strdup(path);
3200 r = sd_bus_message_read_strv(m, &i->argv);
3202 return bus_log_parse_error(r);
3204 r = sd_bus_message_read(m,
3207 &start_timestamp, &start_timestamp_monotonic,
3208 &exit_timestamp, &exit_timestamp_monotonic,
3212 return bus_log_parse_error(r);
3215 i->start_timestamp = (usec_t) start_timestamp;
3216 i->exit_timestamp = (usec_t) exit_timestamp;
3217 i->pid = (pid_t) pid;
3221 r = sd_bus_message_exit_container(m);
3223 return bus_log_parse_error(r);
3228 typedef struct UnitStatusInfo {
3230 const char *load_state;
3231 const char *active_state;
3232 const char *sub_state;
3233 const char *unit_file_state;
3235 const char *description;
3236 const char *following;
3238 char **documentation;
3240 const char *fragment_path;
3241 const char *source_path;
3242 const char *control_group;
3244 char **dropin_paths;
3246 const char *load_error;
3249 usec_t inactive_exit_timestamp;
3250 usec_t inactive_exit_timestamp_monotonic;
3251 usec_t active_enter_timestamp;
3252 usec_t active_exit_timestamp;
3253 usec_t inactive_enter_timestamp;
3255 bool need_daemon_reload;
3260 const char *status_text;
3261 const char *pid_file;
3265 usec_t start_timestamp;
3266 usec_t exit_timestamp;
3268 int exit_code, exit_status;
3270 usec_t condition_timestamp;
3271 bool condition_result;
3272 bool failed_condition_trigger;
3273 bool failed_condition_negate;
3274 const char *failed_condition;
3275 const char *failed_condition_parameter;
3277 usec_t assert_timestamp;
3279 bool failed_assert_trigger;
3280 bool failed_assert_negate;
3281 const char *failed_assert;
3282 const char *failed_assert_parameter;
3285 unsigned n_accepted;
3286 unsigned n_connections;
3289 /* Pairs of type, path */
3293 const char *sysfs_path;
3295 /* Mount, Automount */
3301 LIST_HEAD(ExecStatusInfo, exec);
3304 static void print_status_info(
3309 const char *active_on, *active_off, *on, *off, *ss;
3311 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3312 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3315 arg_all * OUTPUT_SHOW_ALL |
3316 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
3317 on_tty() * OUTPUT_COLOR |
3318 !arg_quiet * OUTPUT_WARN_CUTOFF |
3319 arg_full * OUTPUT_FULL_WIDTH;
3324 /* This shows pretty information about a unit. See
3325 * print_property() for a low-level property printer */
3327 if (streq_ptr(i->active_state, "failed")) {
3328 active_on = ansi_highlight_red();
3329 active_off = ansi_highlight_off();
3330 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3331 active_on = ansi_highlight_green();
3332 active_off = ansi_highlight_off();
3334 active_on = active_off = "";
3336 printf("%s%s%s %s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3338 if (i->description && !streq_ptr(i->id, i->description))
3339 printf(" - %s", i->description);
3344 printf(" Follow: unit currently follows state of %s\n", i->following);
3346 if (streq_ptr(i->load_state, "error")) {
3347 on = ansi_highlight_red();
3348 off = ansi_highlight_off();
3352 path = i->source_path ? i->source_path : i->fragment_path;
3355 printf(" Loaded: %s%s%s (Reason: %s)\n",
3356 on, strna(i->load_state), off, i->load_error);
3357 else if (path && i->unit_file_state)
3358 printf(" Loaded: %s%s%s (%s; %s)\n",
3359 on, strna(i->load_state), off, path, i->unit_file_state);
3361 printf(" Loaded: %s%s%s (%s)\n",
3362 on, strna(i->load_state), off, path);
3364 printf(" Loaded: %s%s%s\n",
3365 on, strna(i->load_state), off);
3367 if (!strv_isempty(i->dropin_paths)) {
3368 _cleanup_free_ char *dir = NULL;
3372 STRV_FOREACH(dropin, i->dropin_paths) {
3373 if (! dir || last) {
3374 printf(dir ? " " : " Drop-In: ");
3379 if (path_get_parent(*dropin, &dir) < 0) {
3384 printf("%s\n %s", dir,
3385 draw_special_char(DRAW_TREE_RIGHT));
3388 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3390 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3394 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3396 printf(" Active: %s%s (%s)%s",
3397 active_on, strna(i->active_state), ss, active_off);
3399 printf(" Active: %s%s%s",
3400 active_on, strna(i->active_state), active_off);
3402 if (!isempty(i->result) && !streq(i->result, "success"))
3403 printf(" (Result: %s)", i->result);
3405 timestamp = (streq_ptr(i->active_state, "active") ||
3406 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
3407 (streq_ptr(i->active_state, "inactive") ||
3408 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
3409 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
3410 i->active_exit_timestamp;
3412 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3413 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3416 printf(" since %s; %s\n", s2, s1);
3418 printf(" since %s\n", s2);
3422 if (!i->condition_result && i->condition_timestamp > 0) {
3423 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3424 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3426 printf("Condition: start %scondition failed%s at %s%s%s\n",
3427 ansi_highlight_yellow(), ansi_highlight_off(),
3428 s2, s1 ? "; " : "", s1 ? s1 : "");
3429 if (i->failed_condition_trigger)
3430 printf(" none of the trigger conditions were met\n");
3431 else if (i->failed_condition)
3432 printf(" %s=%s%s was not met\n",
3433 i->failed_condition,
3434 i->failed_condition_negate ? "!" : "",
3435 i->failed_condition_parameter);
3438 if (!i->assert_result && i->assert_timestamp > 0) {
3439 s1 = format_timestamp_relative(since1, sizeof(since1), i->assert_timestamp);
3440 s2 = format_timestamp(since2, sizeof(since2), i->assert_timestamp);
3442 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3443 ansi_highlight_red(), ansi_highlight_off(),
3444 s2, s1 ? "; " : "", s1 ? s1 : "");
3445 if (i->failed_assert_trigger)
3446 printf(" none of the trigger assertions were met\n");
3447 else if (i->failed_assert)
3448 printf(" %s=%s%s was not met\n",
3450 i->failed_assert_negate ? "!" : "",
3451 i->failed_assert_parameter);
3455 printf(" Device: %s\n", i->sysfs_path);
3457 printf(" Where: %s\n", i->where);
3459 printf(" What: %s\n", i->what);
3461 STRV_FOREACH(t, i->documentation)
3462 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3464 STRV_FOREACH_PAIR(t, t2, i->listen)
3465 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3468 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3470 LIST_FOREACH(exec, p, i->exec) {
3471 _cleanup_free_ char *argv = NULL;
3474 /* Only show exited processes here */
3478 argv = strv_join(p->argv, " ");
3479 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
3481 good = is_clean_exit_lsb(p->code, p->status, NULL);
3483 on = ansi_highlight_red();
3484 off = ansi_highlight_off();
3488 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3490 if (p->code == CLD_EXITED) {
3493 printf("status=%i", p->status);
3495 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3500 printf("signal=%s", signal_to_string(p->status));
3502 printf(")%s\n", off);
3504 if (i->main_pid == p->pid &&
3505 i->start_timestamp == p->start_timestamp &&
3506 i->exit_timestamp == p->start_timestamp)
3507 /* Let's not show this twice */
3510 if (p->pid == i->control_pid)
3514 if (i->main_pid > 0 || i->control_pid > 0) {
3515 if (i->main_pid > 0) {
3516 printf(" Main PID: "PID_FMT, i->main_pid);
3519 _cleanup_free_ char *comm = NULL;
3520 get_process_comm(i->main_pid, &comm);
3522 printf(" (%s)", comm);
3523 } else if (i->exit_code > 0) {
3524 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3526 if (i->exit_code == CLD_EXITED) {
3529 printf("status=%i", i->exit_status);
3531 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3536 printf("signal=%s", signal_to_string(i->exit_status));
3540 if (i->control_pid > 0)
3544 if (i->control_pid > 0) {
3545 _cleanup_free_ char *c = NULL;
3547 printf(" %8s: "PID_FMT, i->main_pid ? "" : " Control", i->control_pid);
3549 get_process_comm(i->control_pid, &c);
3558 printf(" Status: \"%s\"\n", i->status_text);
3559 if (i->status_errno > 0)
3560 printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
3562 if (i->control_group &&
3563 (i->main_pid > 0 || i->control_pid > 0 ||
3564 ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_CONTAINER) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3567 printf(" CGroup: %s\n", i->control_group);
3569 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
3572 static const char prefix[] = " ";
3575 if (c > sizeof(prefix) - 1)
3576 c -= sizeof(prefix) - 1;
3580 if (i->main_pid > 0)
3581 extra[k++] = i->main_pid;
3583 if (i->control_pid > 0)
3584 extra[k++] = i->control_pid;
3586 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, flags);
3590 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3591 show_journal_by_unit(stdout,
3595 i->inactive_exit_timestamp_monotonic,
3598 flags | OUTPUT_BEGIN_NEWLINE,
3599 arg_scope == UNIT_FILE_SYSTEM,
3603 if (i->need_daemon_reload)
3604 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
3605 ansi_highlight_red(),
3606 ansi_highlight_off(),
3607 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
3610 static void show_unit_help(UnitStatusInfo *i) {
3615 if (!i->documentation) {
3616 log_info("Documentation for %s not known.", i->id);
3620 STRV_FOREACH(p, i->documentation)
3621 if (startswith(*p, "man:"))
3622 show_man_page(*p + 4, false);
3624 log_info("Can't show: %s", *p);
3627 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3634 switch (contents[0]) {
3636 case SD_BUS_TYPE_STRING: {
3639 r = sd_bus_message_read(m, "s", &s);
3641 return bus_log_parse_error(r);
3644 if (streq(name, "Id"))
3646 else if (streq(name, "LoadState"))
3648 else if (streq(name, "ActiveState"))
3649 i->active_state = s;
3650 else if (streq(name, "SubState"))
3652 else if (streq(name, "Description"))
3654 else if (streq(name, "FragmentPath"))
3655 i->fragment_path = s;
3656 else if (streq(name, "SourcePath"))
3659 else if (streq(name, "DefaultControlGroup")) {
3661 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3663 i->control_group = e;
3666 else if (streq(name, "ControlGroup"))
3667 i->control_group = s;
3668 else if (streq(name, "StatusText"))
3670 else if (streq(name, "PIDFile"))
3672 else if (streq(name, "SysFSPath"))
3674 else if (streq(name, "Where"))
3676 else if (streq(name, "What"))
3678 else if (streq(name, "Following"))
3680 else if (streq(name, "UnitFileState"))
3681 i->unit_file_state = s;
3682 else if (streq(name, "Result"))
3689 case SD_BUS_TYPE_BOOLEAN: {
3692 r = sd_bus_message_read(m, "b", &b);
3694 return bus_log_parse_error(r);
3696 if (streq(name, "Accept"))
3698 else if (streq(name, "NeedDaemonReload"))
3699 i->need_daemon_reload = b;
3700 else if (streq(name, "ConditionResult"))
3701 i->condition_result = b;
3702 else if (streq(name, "AssertResult"))
3703 i->assert_result = b;
3708 case SD_BUS_TYPE_UINT32: {
3711 r = sd_bus_message_read(m, "u", &u);
3713 return bus_log_parse_error(r);
3715 if (streq(name, "MainPID")) {
3717 i->main_pid = (pid_t) u;
3720 } else if (streq(name, "ControlPID"))
3721 i->control_pid = (pid_t) u;
3722 else if (streq(name, "ExecMainPID")) {
3724 i->main_pid = (pid_t) u;
3725 } else if (streq(name, "NAccepted"))
3727 else if (streq(name, "NConnections"))
3728 i->n_connections = u;
3733 case SD_BUS_TYPE_INT32: {
3736 r = sd_bus_message_read(m, "i", &j);
3738 return bus_log_parse_error(r);
3740 if (streq(name, "ExecMainCode"))
3741 i->exit_code = (int) j;
3742 else if (streq(name, "ExecMainStatus"))
3743 i->exit_status = (int) j;
3744 else if (streq(name, "StatusErrno"))
3745 i->status_errno = (int) j;
3750 case SD_BUS_TYPE_UINT64: {
3753 r = sd_bus_message_read(m, "t", &u);
3755 return bus_log_parse_error(r);
3757 if (streq(name, "ExecMainStartTimestamp"))
3758 i->start_timestamp = (usec_t) u;
3759 else if (streq(name, "ExecMainExitTimestamp"))
3760 i->exit_timestamp = (usec_t) u;
3761 else if (streq(name, "ActiveEnterTimestamp"))
3762 i->active_enter_timestamp = (usec_t) u;
3763 else if (streq(name, "InactiveEnterTimestamp"))
3764 i->inactive_enter_timestamp = (usec_t) u;
3765 else if (streq(name, "InactiveExitTimestamp"))
3766 i->inactive_exit_timestamp = (usec_t) u;
3767 else if (streq(name, "InactiveExitTimestampMonotonic"))
3768 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3769 else if (streq(name, "ActiveExitTimestamp"))
3770 i->active_exit_timestamp = (usec_t) u;
3771 else if (streq(name, "ConditionTimestamp"))
3772 i->condition_timestamp = (usec_t) u;
3773 else if (streq(name, "AssertTimestamp"))
3774 i->assert_timestamp = (usec_t) u;
3779 case SD_BUS_TYPE_ARRAY:
3781 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3782 _cleanup_free_ ExecStatusInfo *info = NULL;
3784 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3786 return bus_log_parse_error(r);
3788 info = new0(ExecStatusInfo, 1);
3792 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3794 info->name = strdup(name);
3798 LIST_PREPEND(exec, i->exec, info);
3800 info = new0(ExecStatusInfo, 1);
3806 return bus_log_parse_error(r);
3808 r = sd_bus_message_exit_container(m);
3810 return bus_log_parse_error(r);
3814 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3815 const char *type, *path;
3817 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3819 return bus_log_parse_error(r);
3821 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3823 r = strv_extend(&i->listen, type);
3827 r = strv_extend(&i->listen, path);
3832 return bus_log_parse_error(r);
3834 r = sd_bus_message_exit_container(m);
3836 return bus_log_parse_error(r);
3840 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3842 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3844 return bus_log_parse_error(r);
3846 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3848 r = sd_bus_message_read_strv(m, &i->documentation);
3850 return bus_log_parse_error(r);
3852 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3853 const char *cond, *param;
3854 int trigger, negate;
3857 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3859 return bus_log_parse_error(r);
3861 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3862 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3863 if (state < 0 && (!trigger || !i->failed_condition)) {
3864 i->failed_condition = cond;
3865 i->failed_condition_trigger = trigger;
3866 i->failed_condition_negate = negate;
3867 i->failed_condition_parameter = param;
3871 return bus_log_parse_error(r);
3873 r = sd_bus_message_exit_container(m);
3875 return bus_log_parse_error(r);
3877 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Asserts")) {
3878 const char *cond, *param;
3879 int trigger, negate;
3882 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3884 return bus_log_parse_error(r);
3886 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3887 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3888 if (state < 0 && (!trigger || !i->failed_assert)) {
3889 i->failed_assert = cond;
3890 i->failed_assert_trigger = trigger;
3891 i->failed_assert_negate = negate;
3892 i->failed_assert_parameter = param;
3896 return bus_log_parse_error(r);
3898 r = sd_bus_message_exit_container(m);
3900 return bus_log_parse_error(r);
3907 case SD_BUS_TYPE_STRUCT_BEGIN:
3909 if (streq(name, "LoadError")) {
3910 const char *n, *message;
3912 r = sd_bus_message_read(m, "(ss)", &n, &message);
3914 return bus_log_parse_error(r);
3916 if (!isempty(message))
3917 i->load_error = message;
3930 r = sd_bus_message_skip(m, contents);
3932 return bus_log_parse_error(r);
3937 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3943 /* This is a low-level property printer, see
3944 * print_status_info() for the nicer output */
3946 if (arg_properties && !strv_find(arg_properties, name)) {
3947 /* skip what we didn't read */
3948 r = sd_bus_message_skip(m, contents);
3952 switch (contents[0]) {
3954 case SD_BUS_TYPE_STRUCT_BEGIN:
3956 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3959 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3961 return bus_log_parse_error(r);
3964 printf("%s=%"PRIu32"\n", name, u);
3966 printf("%s=\n", name);
3970 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3973 r = sd_bus_message_read(m, "(so)", &s, NULL);
3975 return bus_log_parse_error(r);
3977 if (arg_all || !isempty(s))
3978 printf("%s=%s\n", name, s);
3982 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3983 const char *a = NULL, *b = NULL;
3985 r = sd_bus_message_read(m, "(ss)", &a, &b);
3987 return bus_log_parse_error(r);
3989 if (arg_all || !isempty(a) || !isempty(b))
3990 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3993 } else if (streq_ptr(name, "SystemCallFilter")) {
3994 _cleanup_strv_free_ char **l = NULL;
3997 r = sd_bus_message_enter_container(m, 'r', "bas");
3999 return bus_log_parse_error(r);
4001 r = sd_bus_message_read(m, "b", &whitelist);
4003 return bus_log_parse_error(r);
4005 r = sd_bus_message_read_strv(m, &l);
4007 return bus_log_parse_error(r);
4009 r = sd_bus_message_exit_container(m);
4011 return bus_log_parse_error(r);
4013 if (arg_all || whitelist || !strv_isempty(l)) {
4017 fputs(name, stdout);
4023 STRV_FOREACH(i, l) {
4031 fputc('\n', stdout);
4039 case SD_BUS_TYPE_ARRAY:
4041 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
4045 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
4047 return bus_log_parse_error(r);
4049 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
4050 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
4053 return bus_log_parse_error(r);
4055 r = sd_bus_message_exit_container(m);
4057 return bus_log_parse_error(r);
4061 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
4062 const char *type, *path;
4064 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4066 return bus_log_parse_error(r);
4068 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4069 printf("%s=%s\n", type, path);
4071 return bus_log_parse_error(r);
4073 r = sd_bus_message_exit_container(m);
4075 return bus_log_parse_error(r);
4079 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
4080 const char *type, *path;
4082 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4084 return bus_log_parse_error(r);
4086 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4087 printf("Listen%s=%s\n", type, path);
4089 return bus_log_parse_error(r);
4091 r = sd_bus_message_exit_container(m);
4093 return bus_log_parse_error(r);
4097 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
4099 uint64_t value, next_elapse;
4101 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
4103 return bus_log_parse_error(r);
4105 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
4106 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
4108 printf("%s={ value=%s ; next_elapse=%s }\n",
4110 format_timespan(timespan1, sizeof(timespan1), value, 0),
4111 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
4114 return bus_log_parse_error(r);
4116 r = sd_bus_message_exit_container(m);
4118 return bus_log_parse_error(r);
4122 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
4123 ExecStatusInfo info = {};
4125 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
4127 return bus_log_parse_error(r);
4129 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
4130 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
4131 _cleanup_free_ char *tt;
4133 tt = strv_join(info.argv, " ");
4135 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }\n",
4139 yes_no(info.ignore),
4140 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
4141 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
4143 sigchld_code_to_string(info.code),
4145 info.code == CLD_EXITED ? "" : "/",
4146 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
4149 strv_free(info.argv);
4153 r = sd_bus_message_exit_container(m);
4155 return bus_log_parse_error(r);
4159 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
4160 const char *path, *rwm;
4162 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4164 return bus_log_parse_error(r);
4166 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
4167 printf("%s=%s %s\n", name, strna(path), strna(rwm));
4169 return bus_log_parse_error(r);
4171 r = sd_bus_message_exit_container(m);
4173 return bus_log_parse_error(r);
4177 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
4181 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4183 return bus_log_parse_error(r);
4185 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4186 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
4188 return bus_log_parse_error(r);
4190 r = sd_bus_message_exit_container(m);
4192 return bus_log_parse_error(r);
4196 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
4200 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4202 return bus_log_parse_error(r);
4204 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4205 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
4207 return bus_log_parse_error(r);
4209 r = sd_bus_message_exit_container(m);
4211 return bus_log_parse_error(r);
4219 r = bus_print_property(name, m, arg_all);
4221 return bus_log_parse_error(r);
4224 r = sd_bus_message_skip(m, contents);
4226 return bus_log_parse_error(r);
4229 printf("%s=[unprintable]\n", name);
4235 static int show_one(
4239 bool show_properties,
4243 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4244 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4245 UnitStatusInfo info = {};
4252 log_debug("Showing one %s", path);
4254 r = sd_bus_call_method(
4256 "org.freedesktop.systemd1",
4258 "org.freedesktop.DBus.Properties",
4264 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4268 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4270 return bus_log_parse_error(r);
4277 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4278 const char *name, *contents;
4280 r = sd_bus_message_read(reply, "s", &name);
4282 return bus_log_parse_error(r);
4284 r = sd_bus_message_peek_type(reply, NULL, &contents);
4286 return bus_log_parse_error(r);
4288 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4290 return bus_log_parse_error(r);
4292 if (show_properties)
4293 r = print_property(name, reply, contents);
4295 r = status_property(name, reply, &info, contents);
4299 r = sd_bus_message_exit_container(reply);
4301 return bus_log_parse_error(r);
4303 r = sd_bus_message_exit_container(reply);
4305 return bus_log_parse_error(r);
4308 return bus_log_parse_error(r);
4310 r = sd_bus_message_exit_container(reply);
4312 return bus_log_parse_error(r);
4316 if (!show_properties) {
4317 if (streq(verb, "help"))
4318 show_unit_help(&info);
4320 print_status_info(&info, ellipsized);
4323 strv_free(info.documentation);
4324 strv_free(info.dropin_paths);
4325 strv_free(info.listen);
4327 if (!streq_ptr(info.active_state, "active") &&
4328 !streq_ptr(info.active_state, "reloading") &&
4329 streq(verb, "status")) {
4330 /* According to LSB: "program not running" */
4331 /* 0: program is running or service is OK
4332 * 1: program is dead and /run PID file exists
4333 * 2: program is dead and /run/lock lock file exists
4334 * 3: program is not running
4335 * 4: program or service status is unknown
4337 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4343 while ((p = info.exec)) {
4344 LIST_REMOVE(exec, info.exec, p);
4345 exec_status_info_free(p);
4351 static int get_unit_dbus_path_by_pid(
4356 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4357 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4361 r = sd_bus_call_method(
4363 "org.freedesktop.systemd1",
4364 "/org/freedesktop/systemd1",
4365 "org.freedesktop.systemd1.Manager",
4371 log_error("Failed to get unit for PID "PID_FMT": %s", pid, bus_error_message(&error, r));
4375 r = sd_bus_message_read(reply, "o", &u);
4377 return bus_log_parse_error(r);
4387 static int show_all(
4390 bool show_properties,
4394 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4395 _cleanup_free_ UnitInfo *unit_infos = NULL;
4400 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4404 pager_open_if_enabled();
4408 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4410 for (u = unit_infos; u < unit_infos + c; u++) {
4411 _cleanup_free_ char *p = NULL;
4413 p = unit_dbus_path_from_name(u->id);
4417 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4420 else if (r > 0 && ret == 0)
4427 static int show_system_status(sd_bus *bus) {
4428 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4429 _cleanup_free_ char *hn = NULL;
4430 struct machine_info mi = {};
4431 const char *on, *off;
4434 hn = gethostname_malloc();
4438 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4440 log_error("Failed to read server status: %s", strerror(-r));
4444 if (streq_ptr(mi.state, "degraded")) {
4445 on = ansi_highlight_red();
4446 off = ansi_highlight_off();
4447 } else if (!streq_ptr(mi.state, "running")) {
4448 on = ansi_highlight_yellow();
4449 off = ansi_highlight_off();
4453 printf("%s%s%s %s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4455 printf(" State: %s%s%s\n",
4456 on, strna(mi.state), off);
4458 printf(" Jobs: %u queued\n", mi.n_jobs);
4459 printf(" Failed: %u units\n", mi.n_failed_units);
4461 printf(" Since: %s; %s\n",
4462 format_timestamp(since2, sizeof(since2), mi.timestamp),
4463 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4465 printf(" CGroup: %s\n", mi.control_group ?: "/");
4466 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
4468 arg_all * OUTPUT_SHOW_ALL |
4469 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
4470 on_tty() * OUTPUT_COLOR |
4471 !arg_quiet * OUTPUT_WARN_CUTOFF |
4472 arg_full * OUTPUT_FULL_WIDTH;
4474 static const char prefix[] = " ";
4478 if (c > sizeof(prefix) - 1)
4479 c -= sizeof(prefix) - 1;
4483 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
4487 free(mi.control_group);
4492 static int show(sd_bus *bus, char **args) {
4493 bool show_properties, show_status, new_line = false;
4494 bool ellipsized = false;
4500 show_properties = streq(args[0], "show");
4501 show_status = streq(args[0], "status");
4503 if (show_properties)
4504 pager_open_if_enabled();
4506 /* If no argument is specified inspect the manager itself */
4508 if (show_properties && strv_length(args) <= 1)
4509 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4511 if (show_status && strv_length(args) <= 1) {
4513 pager_open_if_enabled();
4514 show_system_status(bus);
4518 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4520 _cleanup_free_ char **patterns = NULL;
4523 STRV_FOREACH(name, args + 1) {
4524 _cleanup_free_ char *unit = NULL;
4527 if (safe_atou32(*name, &id) < 0) {
4528 if (strv_push(&patterns, *name) < 0)
4532 } else if (show_properties) {
4533 /* Interpret as job id */
4534 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4538 /* Interpret as PID */
4539 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4546 r = show_one(args[0], bus, unit, show_properties,
4547 &new_line, &ellipsized);
4550 else if (r > 0 && ret == 0)
4554 if (!strv_isempty(patterns)) {
4555 _cleanup_strv_free_ char **names = NULL;
4557 r = expand_names(bus, patterns, NULL, &names);
4559 log_error("Failed to expand names: %s", strerror(-r));
4561 STRV_FOREACH(name, names) {
4562 _cleanup_free_ char *unit;
4564 unit = unit_dbus_path_from_name(*name);
4568 r = show_one(args[0], bus, unit, show_properties,
4569 &new_line, &ellipsized);
4572 else if (r > 0 && ret == 0)
4578 if (ellipsized && !arg_quiet)
4579 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4584 static int cat(sd_bus *bus, char **args) {
4585 _cleanup_strv_free_ char **names = NULL;
4593 r = expand_names(bus, args + 1, NULL, &names);
4595 log_error("Failed to expand names: %s", strerror(-r));
4597 pager_open_if_enabled();
4599 STRV_FOREACH(name, names) {
4600 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4601 _cleanup_strv_free_ char **dropin_paths = NULL;
4602 _cleanup_free_ char *fragment_path = NULL, *unit = NULL;
4605 unit = unit_dbus_path_from_name(*name);
4609 if (need_daemon_reload(bus, *name) > 0)
4610 log_warning("Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'.",
4611 *name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
4613 r = sd_bus_get_property_string(
4615 "org.freedesktop.systemd1",
4617 "org.freedesktop.systemd1.Unit",
4622 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
4626 r = sd_bus_get_property_strv(
4628 "org.freedesktop.systemd1",
4630 "org.freedesktop.systemd1.Unit",
4635 log_warning("Failed to get DropInPaths: %s", bus_error_message(&error, r));
4644 if (!isempty(fragment_path)) {
4645 printf("%s# %s%s\n",
4646 ansi_highlight_blue(),
4648 ansi_highlight_off());
4651 r = copy_file_fd(fragment_path, STDOUT_FILENO);
4653 log_warning("Failed to cat %s: %s", fragment_path, strerror(-r));
4658 STRV_FOREACH(path, dropin_paths) {
4659 printf("%s%s# %s%s\n",
4660 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4661 ansi_highlight_blue(),
4663 ansi_highlight_off());
4666 r = copy_file_fd(*path, STDOUT_FILENO);
4668 log_warning("Failed to cat %s: %s", *path, strerror(-r));
4674 return r < 0 ? r : 0;
4677 static int set_property(sd_bus *bus, char **args) {
4678 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4679 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4680 _cleanup_free_ char *n = NULL;
4684 r = sd_bus_message_new_method_call(
4687 "org.freedesktop.systemd1",
4688 "/org/freedesktop/systemd1",
4689 "org.freedesktop.systemd1.Manager",
4690 "SetUnitProperties");
4692 return bus_log_create_error(r);
4694 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4696 return bus_log_create_error(r);
4698 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4702 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4704 return bus_log_create_error(r);
4706 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4708 return bus_log_create_error(r);
4710 STRV_FOREACH(i, args + 2) {
4711 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4713 return bus_log_create_error(r);
4715 r = bus_append_unit_property_assignment(m, *i);
4719 r = sd_bus_message_close_container(m);
4721 return bus_log_create_error(r);
4724 r = sd_bus_message_close_container(m);
4726 return bus_log_create_error(r);
4728 r = sd_bus_call(bus, m, 0, &error, NULL);
4730 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4737 static int snapshot(sd_bus *bus, char **args) {
4738 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4739 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
4740 _cleanup_free_ char *n = NULL, *id = NULL;
4744 if (strv_length(args) > 1)
4745 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4751 r = sd_bus_message_new_method_call(
4754 "org.freedesktop.systemd1",
4755 "/org/freedesktop/systemd1",
4756 "org.freedesktop.systemd1.Manager",
4759 return bus_log_create_error(r);
4761 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4763 return bus_log_create_error(r);
4765 r = sd_bus_message_append(m, "sb", n, false);
4767 return bus_log_create_error(r);
4769 r = sd_bus_call(bus, m, 0, &error, &reply);
4771 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4775 r = sd_bus_message_read(reply, "o", &path);
4777 return bus_log_parse_error(r);
4779 r = sd_bus_get_property_string(
4781 "org.freedesktop.systemd1",
4783 "org.freedesktop.systemd1.Unit",
4788 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4798 static int delete_snapshot(sd_bus *bus, char **args) {
4799 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4800 _cleanup_strv_free_ char **names = NULL;
4806 r = expand_names(bus, args + 1, ".snapshot", &names);
4808 log_error("Failed to expand names: %s", strerror(-r));
4810 STRV_FOREACH(name, names) {
4811 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4814 q = sd_bus_message_new_method_call(
4817 "org.freedesktop.systemd1",
4818 "/org/freedesktop/systemd1",
4819 "org.freedesktop.systemd1.Manager",
4822 return bus_log_create_error(q);
4824 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4826 return bus_log_create_error(q);
4828 q = sd_bus_message_append(m, "s", *name);
4830 return bus_log_create_error(q);
4832 q = sd_bus_call(bus, m, 0, &error, NULL);
4834 log_error("Failed to remove snapshot %s: %s", *name, bus_error_message(&error, q));
4843 static int daemon_reload(sd_bus *bus, char **args) {
4844 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4845 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4849 if (arg_action == ACTION_RELOAD)
4851 else if (arg_action == ACTION_REEXEC)
4852 method = "Reexecute";
4854 assert(arg_action == ACTION_SYSTEMCTL);
4857 streq(args[0], "clear-jobs") ||
4858 streq(args[0], "cancel") ? "ClearJobs" :
4859 streq(args[0], "daemon-reexec") ? "Reexecute" :
4860 streq(args[0], "reset-failed") ? "ResetFailed" :
4861 streq(args[0], "halt") ? "Halt" :
4862 streq(args[0], "poweroff") ? "PowerOff" :
4863 streq(args[0], "reboot") ? "Reboot" :
4864 streq(args[0], "kexec") ? "KExec" :
4865 streq(args[0], "exit") ? "Exit" :
4866 /* "daemon-reload" */ "Reload";
4869 r = sd_bus_message_new_method_call(
4872 "org.freedesktop.systemd1",
4873 "/org/freedesktop/systemd1",
4874 "org.freedesktop.systemd1.Manager",
4877 return bus_log_create_error(r);
4879 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4881 return bus_log_create_error(r);
4883 r = sd_bus_call(bus, m, 0, &error, NULL);
4884 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4885 /* There's always a fallback possible for
4886 * legacy actions. */
4888 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4889 /* On reexecution, we expect a disconnect, not a
4893 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4895 return r < 0 ? r : 0;
4898 static int reset_failed(sd_bus *bus, char **args) {
4899 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4900 _cleanup_strv_free_ char **names = NULL;
4904 if (strv_length(args) <= 1)
4905 return daemon_reload(bus, args);
4907 r = expand_names(bus, args + 1, NULL, &names);
4909 log_error("Failed to expand names: %s", strerror(-r));
4911 STRV_FOREACH(name, names) {
4912 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4914 q = sd_bus_message_new_method_call(
4917 "org.freedesktop.systemd1",
4918 "/org/freedesktop/systemd1",
4919 "org.freedesktop.systemd1.Manager",
4922 return bus_log_create_error(q);
4924 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4926 return bus_log_create_error(q);
4928 q = sd_bus_message_append(m, "s", *name);
4930 return bus_log_create_error(q);
4932 q = sd_bus_call(bus, m, 0, &error, NULL);
4934 log_error("Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q));
4943 static int show_environment(sd_bus *bus, char **args) {
4944 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4945 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4949 pager_open_if_enabled();
4951 r = sd_bus_get_property(
4953 "org.freedesktop.systemd1",
4954 "/org/freedesktop/systemd1",
4955 "org.freedesktop.systemd1.Manager",
4961 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4965 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4967 return bus_log_parse_error(r);
4969 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4972 return bus_log_parse_error(r);
4974 r = sd_bus_message_exit_container(reply);
4976 return bus_log_parse_error(r);
4981 static int switch_root(sd_bus *bus, char **args) {
4982 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4983 _cleanup_free_ char *cmdline_init = NULL;
4984 const char *root, *init;
4988 l = strv_length(args);
4989 if (l < 2 || l > 3) {
4990 log_error("Wrong number of arguments.");
4999 r = parse_env_file("/proc/cmdline", WHITESPACE,
5000 "init", &cmdline_init,
5003 log_debug("Failed to parse /proc/cmdline: %s", strerror(-r));
5005 init = cmdline_init;
5012 const char *root_systemd_path = NULL, *root_init_path = NULL;
5014 root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
5015 root_init_path = strappenda(root, "/", init);
5017 /* If the passed init is actually the same as the
5018 * systemd binary, then let's suppress it. */
5019 if (files_same(root_init_path, root_systemd_path) > 0)
5023 log_debug("Switching root - root: %s; init: %s", root, strna(init));
5025 r = sd_bus_call_method(
5027 "org.freedesktop.systemd1",
5028 "/org/freedesktop/systemd1",
5029 "org.freedesktop.systemd1.Manager",
5035 log_error("Failed to switch root: %s", bus_error_message(&error, r));
5042 static int set_environment(sd_bus *bus, char **args) {
5043 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5044 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
5051 method = streq(args[0], "set-environment")
5053 : "UnsetEnvironment";
5055 r = sd_bus_message_new_method_call(
5058 "org.freedesktop.systemd1",
5059 "/org/freedesktop/systemd1",
5060 "org.freedesktop.systemd1.Manager",
5063 return bus_log_create_error(r);
5065 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5067 return bus_log_create_error(r);
5069 r = sd_bus_message_append_strv(m, args + 1);
5071 return bus_log_create_error(r);
5073 r = sd_bus_call(bus, m, 0, &error, NULL);
5075 log_error("Failed to set environment: %s", bus_error_message(&error, r));
5082 static int import_environment(sd_bus *bus, char **args) {
5083 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5084 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
5090 r = sd_bus_message_new_method_call(
5093 "org.freedesktop.systemd1",
5094 "/org/freedesktop/systemd1",
5095 "org.freedesktop.systemd1.Manager",
5098 return bus_log_create_error(r);
5100 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5102 return bus_log_create_error(r);
5104 if (strv_isempty(args + 1))
5105 r = sd_bus_message_append_strv(m, environ);
5109 r = sd_bus_message_open_container(m, 'a', "s");
5111 return bus_log_create_error(r);
5113 STRV_FOREACH(a, args + 1) {
5115 if (!env_name_is_valid(*a)) {
5116 log_error("Not a valid environment variable name: %s", *a);
5120 STRV_FOREACH(b, environ) {
5123 eq = startswith(*b, *a);
5124 if (eq && *eq == '=') {
5126 r = sd_bus_message_append(m, "s", *b);
5128 return bus_log_create_error(r);
5135 r = sd_bus_message_close_container(m);
5138 return bus_log_create_error(r);
5140 r = sd_bus_call(bus, m, 0, &error, NULL);
5142 log_error("Failed to import environment: %s", bus_error_message(&error, r));
5149 static int enable_sysv_units(const char *verb, char **args) {
5152 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
5153 unsigned f = 1, t = 1;
5154 _cleanup_lookup_paths_free_ LookupPaths paths = {};
5156 if (arg_scope != UNIT_FILE_SYSTEM)
5159 if (!streq(verb, "enable") &&
5160 !streq(verb, "disable") &&
5161 !streq(verb, "is-enabled"))
5164 /* Processes all SysV units, and reshuffles the array so that
5165 * afterwards only the native units remain */
5167 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, arg_root, NULL, NULL, NULL);
5172 for (f = 0; args[f]; f++) {
5174 _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL;
5175 bool found_native = false, found_sysv;
5177 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
5185 if (!endswith(name, ".service"))
5188 if (path_is_absolute(name))
5191 STRV_FOREACH(k, paths.unit_path) {
5192 _cleanup_free_ char *path = NULL;
5194 path = path_join(arg_root, *k, name);
5198 found_native = access(path, F_OK) >= 0;
5206 p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name);
5210 p[strlen(p) - strlen(".service")] = 0;
5211 found_sysv = access(p, F_OK) >= 0;
5215 /* Mark this entry, so that we don't try enabling it as native unit */
5216 args[f] = (char*) "";
5218 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
5220 if (!isempty(arg_root))
5221 argv[c++] = q = strappend("--root=", arg_root);
5223 argv[c++] = basename(p);
5225 streq(verb, "enable") ? "on" :
5226 streq(verb, "disable") ? "off" : "--level=5";
5229 l = strv_join((char**)argv, " ");
5233 log_info("Executing %s", l);
5237 log_error("Failed to fork: %m");
5239 } else if (pid == 0) {
5242 execv(argv[0], (char**) argv);
5243 _exit(EXIT_FAILURE);
5246 j = wait_for_terminate(pid, &status);
5248 log_error("Failed to wait for child: %s", strerror(-r));
5252 if (status.si_code == CLD_EXITED) {
5253 if (streq(verb, "is-enabled")) {
5254 if (status.si_status == 0) {
5263 } else if (status.si_status != 0)
5269 /* Drop all SysV units */
5270 for (f = 0, t = 0; args[f]; f++) {
5272 if (isempty(args[f]))
5275 args[t++] = args[f];
5284 static int mangle_names(char **original_names, char ***mangled_names) {
5285 char **i, **l, **name;
5287 l = new(char*, strv_length(original_names) + 1);
5292 STRV_FOREACH(name, original_names) {
5294 /* When enabling units qualified path names are OK,
5295 * too, hence allow them explicitly. */
5300 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5316 static int enable_unit(sd_bus *bus, char **args) {
5317 _cleanup_strv_free_ char **names = NULL;
5318 const char *verb = args[0];
5319 UnitFileChange *changes = NULL;
5320 unsigned n_changes = 0;
5321 int carries_install_info = -1;
5327 r = mangle_names(args+1, &names);
5331 r = enable_sysv_units(verb, names);
5335 /* If the operation was fully executed by the SysV compat,
5336 * let's finish early */
5337 if (strv_isempty(names))
5340 if (!bus || avoid_bus()) {
5341 if (streq(verb, "enable")) {
5342 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5343 carries_install_info = r;
5344 } else if (streq(verb, "disable"))
5345 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5346 else if (streq(verb, "reenable")) {
5347 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5348 carries_install_info = r;
5349 } else if (streq(verb, "link"))
5350 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5351 else if (streq(verb, "preset")) {
5352 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_preset_mode, arg_force, &changes, &n_changes);
5353 carries_install_info = r;
5354 } else if (streq(verb, "mask"))
5355 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5356 else if (streq(verb, "unmask"))
5357 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5359 assert_not_reached("Unknown verb");
5362 log_error("Operation failed: %s", strerror(-r));
5367 dump_unit_file_changes(changes, n_changes);
5371 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5372 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5373 int expect_carries_install_info = false;
5374 bool send_force = true, send_preset_mode = false;
5377 if (streq(verb, "enable")) {
5378 method = "EnableUnitFiles";
5379 expect_carries_install_info = true;
5380 } else if (streq(verb, "disable")) {
5381 method = "DisableUnitFiles";
5383 } else if (streq(verb, "reenable")) {
5384 method = "ReenableUnitFiles";
5385 expect_carries_install_info = true;
5386 } else if (streq(verb, "link"))
5387 method = "LinkUnitFiles";
5388 else if (streq(verb, "preset")) {
5390 if (arg_preset_mode != UNIT_FILE_PRESET_FULL) {
5391 method = "PresetUnitFilesWithMode";
5392 send_preset_mode = true;
5394 method = "PresetUnitFiles";
5396 expect_carries_install_info = true;
5397 } else if (streq(verb, "mask"))
5398 method = "MaskUnitFiles";
5399 else if (streq(verb, "unmask")) {
5400 method = "UnmaskUnitFiles";
5403 assert_not_reached("Unknown verb");
5405 r = sd_bus_message_new_method_call(
5408 "org.freedesktop.systemd1",
5409 "/org/freedesktop/systemd1",
5410 "org.freedesktop.systemd1.Manager",
5413 return bus_log_create_error(r);
5415 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5417 return bus_log_create_error(r);
5419 r = sd_bus_message_append_strv(m, names);
5421 return bus_log_create_error(r);
5423 if (send_preset_mode) {
5424 r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode));
5426 return bus_log_create_error(r);
5429 r = sd_bus_message_append(m, "b", arg_runtime);
5431 return bus_log_create_error(r);
5434 r = sd_bus_message_append(m, "b", arg_force);
5436 return bus_log_create_error(r);
5439 r = sd_bus_call(bus, m, 0, &error, &reply);
5441 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5445 if (expect_carries_install_info) {
5446 r = sd_bus_message_read(reply, "b", &carries_install_info);
5448 return bus_log_parse_error(r);
5451 r = deserialize_and_dump_unit_file_changes(reply);
5455 /* Try to reload if enabled */
5457 r = daemon_reload(bus, args);
5462 if (carries_install_info == 0)
5463 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5464 "using systemctl.\n"
5465 "Possible reasons for having this kind of units are:\n"
5466 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5467 " .wants/ or .requires/ directory.\n"
5468 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5469 " a requirement dependency on it.\n"
5470 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5471 " D-Bus, udev, scripted systemctl call, ...).\n");
5474 unit_file_changes_free(changes, n_changes);
5479 static int add_dependency(sd_bus *bus, char **args) {
5480 _cleanup_strv_free_ char **names = NULL;
5481 _cleanup_free_ char *target = NULL;
5482 const char *verb = args[0];
5489 target = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
5493 r = mangle_names(args+2, &names);
5497 if (streq(verb, "add-wants"))
5499 else if (streq(verb, "add-requires"))
5500 dep = UNIT_REQUIRES;
5502 assert_not_reached("Unknown verb");
5504 if (!bus || avoid_bus()) {
5505 UnitFileChange *changes = NULL;
5506 unsigned n_changes = 0;
5508 r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes);
5511 log_error("Can't add dependency: %s", strerror(-r));
5516 dump_unit_file_changes(changes, n_changes);
5518 unit_file_changes_free(changes, n_changes);
5521 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5522 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5524 r = sd_bus_message_new_method_call(
5527 "org.freedesktop.systemd1",
5528 "/org/freedesktop/systemd1",
5529 "org.freedesktop.systemd1.Manager",
5530 "AddDependencyUnitFiles");
5532 return bus_log_create_error(r);
5534 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5536 return bus_log_create_error(r);
5538 r = sd_bus_message_append_strv(m, names);
5540 return bus_log_create_error(r);
5542 r = sd_bus_message_append(m, "ssbb", target, unit_dependency_to_string(dep), arg_runtime, arg_force);
5544 return bus_log_create_error(r);
5546 r = sd_bus_call(bus, m, 0, &error, &reply);
5548 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5552 r = deserialize_and_dump_unit_file_changes(reply);
5557 r = daemon_reload(bus, args);
5565 static int preset_all(sd_bus *bus, char **args) {
5566 UnitFileChange *changes = NULL;
5567 unsigned n_changes = 0;
5570 if (!bus || avoid_bus()) {
5572 r = unit_file_preset_all(arg_scope, arg_runtime, arg_root, arg_preset_mode, arg_force, &changes, &n_changes);
5574 log_error("Operation failed: %s", strerror(-r));
5579 dump_unit_file_changes(changes, n_changes);
5584 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
5585 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5587 r = sd_bus_message_new_method_call(
5590 "org.freedesktop.systemd1",
5591 "/org/freedesktop/systemd1",
5592 "org.freedesktop.systemd1.Manager",
5593 "PresetAllUnitFiles");
5595 return bus_log_create_error(r);
5597 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5599 return bus_log_create_error(r);
5601 r = sd_bus_message_append(
5604 unit_file_preset_mode_to_string(arg_preset_mode),
5608 return bus_log_create_error(r);
5610 r = sd_bus_call(bus, m, 0, &error, &reply);
5612 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5616 r = deserialize_and_dump_unit_file_changes(reply);
5621 r = daemon_reload(bus, args);
5627 unit_file_changes_free(changes, n_changes);
5632 static int unit_is_enabled(sd_bus *bus, char **args) {
5634 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5635 _cleanup_strv_free_ char **names = NULL;
5640 r = mangle_names(args+1, &names);
5644 r = enable_sysv_units(args[0], names);
5650 if (!bus || avoid_bus()) {
5652 STRV_FOREACH(name, names) {
5653 UnitFileState state;
5655 state = unit_file_get_state(arg_scope, arg_root, *name);
5657 log_error("Failed to get unit file state for %s: %s", *name, strerror(-state));
5661 if (state == UNIT_FILE_ENABLED ||
5662 state == UNIT_FILE_ENABLED_RUNTIME ||
5663 state == UNIT_FILE_STATIC)
5667 puts(unit_file_state_to_string(state));
5671 STRV_FOREACH(name, names) {
5672 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5675 r = sd_bus_call_method(
5677 "org.freedesktop.systemd1",
5678 "/org/freedesktop/systemd1",
5679 "org.freedesktop.systemd1.Manager",
5685 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5689 r = sd_bus_message_read(reply, "s", &s);
5691 return bus_log_parse_error(r);
5693 if (streq(s, "enabled") ||
5694 streq(s, "enabled-runtime") ||
5706 static int is_system_running(sd_bus *bus, char **args) {
5707 _cleanup_free_ char *state = NULL;
5710 r = sd_bus_get_property_string(
5712 "org.freedesktop.systemd1",
5713 "/org/freedesktop/systemd1",
5714 "org.freedesktop.systemd1.Manager",
5727 return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE;
5730 static void systemctl_help(void) {
5732 pager_open_if_enabled();
5734 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
5735 "Query or send control commands to the systemd manager.\n\n"
5736 " -h --help Show this help\n"
5737 " --version Show package version\n"
5738 " --system Connect to system manager\n"
5739 " --user Connect to user service manager\n"
5740 " -H --host=[USER@]HOST\n"
5741 " Operate on remote host\n"
5742 " -M --machine=CONTAINER\n"
5743 " Operate on local container\n"
5744 " -t --type=TYPE List only units of a particular type\n"
5745 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
5746 " -p --property=NAME Show only properties by this name\n"
5747 " -a --all Show all loaded units/properties, including dead/empty\n"
5748 " ones. To list all units installed on the system, use\n"
5749 " the 'list-unit-files' command instead.\n"
5750 " -l --full Don't ellipsize unit names on output\n"
5751 " -r --recursive Show unit list of host and local containers\n"
5752 " --reverse Show reverse dependencies with 'list-dependencies'\n"
5753 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
5754 " queueing a new job\n"
5755 " --show-types When showing sockets, explicitly show their type\n"
5756 " -i --ignore-inhibitors\n"
5757 " When shutting down or sleeping, ignore inhibitors\n"
5758 " --kill-who=WHO Who to send signal to\n"
5759 " -s --signal=SIGNAL Which signal to send\n"
5760 " -q --quiet Suppress output\n"
5761 " --no-block Do not wait until operation finished\n"
5762 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5763 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
5765 " --no-legend Do not print a legend (column headers and hints)\n"
5766 " --no-pager Do not pipe output into a pager\n"
5767 " --no-ask-password\n"
5768 " Do not ask for system passwords\n"
5769 " --global Enable/disable unit files globally\n"
5770 " --runtime Enable unit files only temporarily until next reboot\n"
5771 " -f --force When enabling unit files, override existing symlinks\n"
5772 " When shutting down, execute action immediately\n"
5773 " --preset-mode= Specifies whether fully apply presets, or only enable,\n"
5774 " or only disable\n"
5775 " --root=PATH Enable unit files in the specified root directory\n"
5776 " -n --lines=INTEGER Number of journal entries to show\n"
5777 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
5778 " verbose, export, json, json-pretty, json-sse, cat)\n"
5779 " --plain Print unit dependencies as a list instead of a tree\n\n"
5781 " list-units [PATTERN...] List loaded units\n"
5782 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
5783 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
5784 " start NAME... Start (activate) one or more units\n"
5785 " stop NAME... Stop (deactivate) one or more units\n"
5786 " reload NAME... Reload one or more units\n"
5787 " restart NAME... Start or restart one or more units\n"
5788 " try-restart NAME... Restart one or more units if active\n"
5789 " reload-or-restart NAME... Reload one or more units if possible,\n"
5790 " otherwise start or restart\n"
5791 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
5792 " otherwise restart if active\n"
5793 " isolate NAME Start one unit and stop all others\n"
5794 " kill NAME... Send signal to processes of a unit\n"
5795 " is-active PATTERN... Check whether units are active\n"
5796 " is-failed PATTERN... Check whether units are failed\n"
5797 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
5798 " show [PATTERN...|JOB...] Show properties of one or more\n"
5799 " units/jobs or the manager\n"
5800 " cat PATTERN... Show files and drop-ins of one or more units\n"
5801 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
5802 " help PATTERN...|PID... Show manual for one or more units\n"
5803 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
5805 " list-dependencies [NAME] Recursively show units which are required\n"
5806 " or wanted by this unit or by which this\n"
5807 " unit is required or wanted\n\n"
5808 "Unit File Commands:\n"
5809 " list-unit-files [PATTERN...] List installed unit files\n"
5810 " enable NAME... Enable one or more unit files\n"
5811 " disable NAME... Disable one or more unit files\n"
5812 " reenable NAME... Reenable one or more unit files\n"
5813 " preset NAME... Enable/disable one or more unit files\n"
5814 " based on preset configuration\n"
5815 " preset-all Enable/disable all unit files based on\n"
5816 " preset configuration\n"
5817 " is-enabled NAME... Check whether unit files are enabled\n\n"
5818 " mask NAME... Mask one or more units\n"
5819 " unmask NAME... Unmask one or more units\n"
5820 " link PATH... Link one or more units files into\n"
5821 " the search path\n"
5822 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
5823 " on specified one or more units\n"
5824 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
5825 " on specified one or more units\n"
5826 " get-default Get the name of the default target\n"
5827 " set-default NAME Set the default target\n\n"
5828 "Machine Commands:\n"
5829 " list-machines [PATTERN...] List local containers and host\n\n"
5831 " list-jobs [PATTERN...] List jobs\n"
5832 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
5833 "Snapshot Commands:\n"
5834 " snapshot [NAME] Create a snapshot\n"
5835 " delete NAME... Remove one or more snapshots\n\n"
5836 "Environment Commands:\n"
5837 " show-environment Dump environment\n"
5838 " set-environment NAME=VALUE... Set one or more environment variables\n"
5839 " unset-environment NAME... Unset one or more environment variables\n"
5840 " import-environment NAME... Import all, one or more environment variables\n\n"
5841 "Manager Lifecycle Commands:\n"
5842 " daemon-reload Reload systemd manager configuration\n"
5843 " daemon-reexec Reexecute systemd manager\n\n"
5844 "System Commands:\n"
5845 " is-system-running Check whether system is fully running\n"
5846 " default Enter system default mode\n"
5847 " rescue Enter system rescue mode\n"
5848 " emergency Enter system emergency mode\n"
5849 " halt Shut down and halt the system\n"
5850 " poweroff Shut down and power-off the system\n"
5851 " reboot [ARG] Shut down and reboot the system\n"
5852 " kexec Shut down and reboot the system with kexec\n"
5853 " exit Request user instance exit\n"
5854 " switch-root ROOT [INIT] Change to a different root file system\n"
5855 " suspend Suspend the system\n"
5856 " hibernate Hibernate the system\n"
5857 " hybrid-sleep Hibernate and suspend the system\n",
5858 program_invocation_short_name);
5861 static void halt_help(void) {
5862 printf("%s [OPTIONS...]%s\n\n"
5863 "%s the system.\n\n"
5864 " --help Show this help\n"
5865 " --halt Halt the machine\n"
5866 " -p --poweroff Switch off the machine\n"
5867 " --reboot Reboot the machine\n"
5868 " -f --force Force immediate halt/power-off/reboot\n"
5869 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
5870 " -d --no-wtmp Don't write wtmp record\n"
5871 " --no-wall Don't send wall message before halt/power-off/reboot\n",
5872 program_invocation_short_name,
5873 arg_action == ACTION_REBOOT ? " [ARG]" : "",
5874 arg_action == ACTION_REBOOT ? "Reboot" :
5875 arg_action == ACTION_POWEROFF ? "Power off" :
5879 static void shutdown_help(void) {
5880 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
5881 "Shut down the system.\n\n"
5882 " --help Show this help\n"
5883 " -H --halt Halt the machine\n"
5884 " -P --poweroff Power-off the machine\n"
5885 " -r --reboot Reboot the machine\n"
5886 " -h Equivalent to --poweroff, overridden by --halt\n"
5887 " -k Don't halt/power-off/reboot, just send warnings\n"
5888 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5889 " -c Cancel a pending shutdown\n",
5890 program_invocation_short_name);
5893 static void telinit_help(void) {
5894 printf("%s [OPTIONS...] {COMMAND}\n\n"
5895 "Send control commands to the init daemon.\n\n"
5896 " --help Show this help\n"
5897 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
5899 " 0 Power-off the machine\n"
5900 " 6 Reboot the machine\n"
5901 " 2, 3, 4, 5 Start runlevelX.target unit\n"
5902 " 1, s, S Enter rescue mode\n"
5903 " q, Q Reload init daemon configuration\n"
5904 " u, U Reexecute init daemon\n",
5905 program_invocation_short_name);
5908 static void runlevel_help(void) {
5909 printf("%s [OPTIONS...]\n\n"
5910 "Prints the previous and current runlevel of the init system.\n\n"
5911 " --help Show this help\n",
5912 program_invocation_short_name);
5915 static void help_types(void) {
5920 puts("Available unit types:");
5921 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
5922 t = unit_type_to_string(i);
5928 static int systemctl_parse_argv(int argc, char *argv[]) {
5937 ARG_IGNORE_DEPENDENCIES,
5949 ARG_NO_ASK_PASSWORD,
5959 static const struct option options[] = {
5960 { "help", no_argument, NULL, 'h' },
5961 { "version", no_argument, NULL, ARG_VERSION },
5962 { "type", required_argument, NULL, 't' },
5963 { "property", required_argument, NULL, 'p' },
5964 { "all", no_argument, NULL, 'a' },
5965 { "reverse", no_argument, NULL, ARG_REVERSE },
5966 { "after", no_argument, NULL, ARG_AFTER },
5967 { "before", no_argument, NULL, ARG_BEFORE },
5968 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
5969 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
5970 { "full", no_argument, NULL, 'l' },
5971 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
5972 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
5973 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
5974 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
5975 { "ignore-inhibitors", no_argument, NULL, 'i' },
5976 { "user", no_argument, NULL, ARG_USER },
5977 { "system", no_argument, NULL, ARG_SYSTEM },
5978 { "global", no_argument, NULL, ARG_GLOBAL },
5979 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
5980 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
5981 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
5982 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5983 { "quiet", no_argument, NULL, 'q' },
5984 { "root", required_argument, NULL, ARG_ROOT },
5985 { "force", no_argument, NULL, ARG_FORCE },
5986 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
5987 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
5988 { "signal", required_argument, NULL, 's' },
5989 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
5990 { "host", required_argument, NULL, 'H' },
5991 { "machine", required_argument, NULL, 'M' },
5992 { "runtime", no_argument, NULL, ARG_RUNTIME },
5993 { "lines", required_argument, NULL, 'n' },
5994 { "output", required_argument, NULL, 'o' },
5995 { "plain", no_argument, NULL, ARG_PLAIN },
5996 { "state", required_argument, NULL, ARG_STATE },
5997 { "recursive", no_argument, NULL, 'r' },
5998 { "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
6007 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
6016 puts(PACKAGE_STRING);
6017 puts(SYSTEMD_FEATURES);
6021 const char *word, *state;
6024 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6025 _cleanup_free_ char *type;
6027 type = strndup(word, size);
6031 if (streq(type, "help")) {
6036 if (unit_type_from_string(type) >= 0) {
6037 if (strv_push(&arg_types, type))
6043 /* It's much nicer to use --state= for
6044 * load states, but let's support this
6045 * in --types= too for compatibility
6046 * with old versions */
6047 if (unit_load_state_from_string(optarg) >= 0) {
6048 if (strv_push(&arg_states, type) < 0)
6054 log_error("Unknown unit type or load state '%s'.", type);
6055 log_info("Use -t help to see a list of allowed values.");
6063 /* Make sure that if the empty property list
6064 was specified, we won't show any properties. */
6065 if (isempty(optarg) && !arg_properties) {
6066 arg_properties = new0(char*, 1);
6067 if (!arg_properties)
6070 const char *word, *state;
6073 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6076 prop = strndup(word, size);
6080 if (strv_consume(&arg_properties, prop) < 0)
6085 /* If the user asked for a particular
6086 * property, show it to him, even if it is
6098 arg_dependency = DEPENDENCY_REVERSE;
6102 arg_dependency = DEPENDENCY_AFTER;
6106 arg_dependency = DEPENDENCY_BEFORE;
6109 case ARG_SHOW_TYPES:
6110 arg_show_types = true;
6114 arg_job_mode = optarg;
6118 arg_job_mode = "fail";
6121 case ARG_IRREVERSIBLE:
6122 arg_job_mode = "replace-irreversibly";
6125 case ARG_IGNORE_DEPENDENCIES:
6126 arg_job_mode = "ignore-dependencies";
6130 arg_scope = UNIT_FILE_USER;
6134 arg_scope = UNIT_FILE_SYSTEM;
6138 arg_scope = UNIT_FILE_GLOBAL;
6142 arg_no_block = true;
6146 arg_no_legend = true;
6150 arg_no_pager = true;
6166 if (strv_extend(&arg_states, "failed") < 0)
6184 arg_no_reload = true;
6188 arg_kill_who = optarg;
6192 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
6193 log_error("Failed to parse signal string %s.", optarg);
6198 case ARG_NO_ASK_PASSWORD:
6199 arg_ask_password = false;
6203 arg_transport = BUS_TRANSPORT_REMOTE;
6208 arg_transport = BUS_TRANSPORT_CONTAINER;
6217 if (safe_atou(optarg, &arg_lines) < 0) {
6218 log_error("Failed to parse lines '%s'", optarg);
6224 arg_output = output_mode_from_string(optarg);
6225 if (arg_output < 0) {
6226 log_error("Unknown output '%s'.", optarg);
6232 arg_ignore_inhibitors = true;
6240 const char *word, *state;
6243 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6246 s = strndup(word, size);
6250 if (strv_consume(&arg_states, s) < 0)
6257 if (geteuid() != 0) {
6258 log_error("--recursive requires root privileges.");
6262 arg_recursive = true;
6265 case ARG_PRESET_MODE:
6267 arg_preset_mode = unit_file_preset_mode_from_string(optarg);
6268 if (arg_preset_mode < 0) {
6269 log_error("Failed to parse preset mode: %s.", optarg);
6279 assert_not_reached("Unhandled option");
6282 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
6283 log_error("Cannot access user instance remotely.");
6290 static int halt_parse_argv(int argc, char *argv[]) {
6299 static const struct option options[] = {
6300 { "help", no_argument, NULL, ARG_HELP },
6301 { "halt", no_argument, NULL, ARG_HALT },
6302 { "poweroff", no_argument, NULL, 'p' },
6303 { "reboot", no_argument, NULL, ARG_REBOOT },
6304 { "force", no_argument, NULL, 'f' },
6305 { "wtmp-only", no_argument, NULL, 'w' },
6306 { "no-wtmp", no_argument, NULL, 'd' },
6307 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6316 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
6317 if (runlevel == '0' || runlevel == '6')
6320 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
6328 arg_action = ACTION_HALT;
6332 if (arg_action != ACTION_REBOOT)
6333 arg_action = ACTION_POWEROFF;
6337 arg_action = ACTION_REBOOT;
6359 /* Compatibility nops */
6366 assert_not_reached("Unhandled option");
6369 if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
6370 r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL);
6373 } else if (optind < argc) {
6374 log_error("Too many arguments.");
6381 static int parse_time_spec(const char *t, usec_t *_u) {
6385 if (streq(t, "now"))
6387 else if (!strchr(t, ':')) {
6390 if (safe_atou64(t, &u) < 0)
6393 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
6402 hour = strtol(t, &e, 10);
6403 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
6406 minute = strtol(e+1, &e, 10);
6407 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
6410 n = now(CLOCK_REALTIME);
6411 s = (time_t) (n / USEC_PER_SEC);
6413 assert_se(localtime_r(&s, &tm));
6415 tm.tm_hour = (int) hour;
6416 tm.tm_min = (int) minute;
6419 assert_se(s = mktime(&tm));
6421 *_u = (usec_t) s * USEC_PER_SEC;
6424 *_u += USEC_PER_DAY;
6430 static int shutdown_parse_argv(int argc, char *argv[]) {
6437 static const struct option options[] = {
6438 { "help", no_argument, NULL, ARG_HELP },
6439 { "halt", no_argument, NULL, 'H' },
6440 { "poweroff", no_argument, NULL, 'P' },
6441 { "reboot", no_argument, NULL, 'r' },
6442 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
6443 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6452 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0)
6460 arg_action = ACTION_HALT;
6464 arg_action = ACTION_POWEROFF;
6469 arg_action = ACTION_KEXEC;
6471 arg_action = ACTION_REBOOT;
6475 arg_action = ACTION_KEXEC;
6479 if (arg_action != ACTION_HALT)
6480 arg_action = ACTION_POWEROFF;
6493 /* Compatibility nops */
6497 arg_action = ACTION_CANCEL_SHUTDOWN;
6504 assert_not_reached("Unhandled option");
6507 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
6508 r = parse_time_spec(argv[optind], &arg_when);
6510 log_error("Failed to parse time specification: %s", argv[optind]);
6514 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
6516 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
6517 /* No time argument for shutdown cancel */
6518 arg_wall = argv + optind;
6519 else if (argc > optind + 1)
6520 /* We skip the time argument */
6521 arg_wall = argv + optind + 1;
6528 static int telinit_parse_argv(int argc, char *argv[]) {
6535 static const struct option options[] = {
6536 { "help", no_argument, NULL, ARG_HELP },
6537 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6541 static const struct {
6545 { '0', ACTION_POWEROFF },
6546 { '6', ACTION_REBOOT },
6547 { '1', ACTION_RESCUE },
6548 { '2', ACTION_RUNLEVEL2 },
6549 { '3', ACTION_RUNLEVEL3 },
6550 { '4', ACTION_RUNLEVEL4 },
6551 { '5', ACTION_RUNLEVEL5 },
6552 { 's', ACTION_RESCUE },
6553 { 'S', ACTION_RESCUE },
6554 { 'q', ACTION_RELOAD },
6555 { 'Q', ACTION_RELOAD },
6556 { 'u', ACTION_REEXEC },
6557 { 'U', ACTION_REEXEC }
6566 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6581 assert_not_reached("Unhandled option");
6584 if (optind >= argc) {
6585 log_error("%s: required argument missing.",
6586 program_invocation_short_name);
6590 if (optind + 1 < argc) {
6591 log_error("Too many arguments.");
6595 if (strlen(argv[optind]) != 1) {
6596 log_error("Expected single character argument.");
6600 for (i = 0; i < ELEMENTSOF(table); i++)
6601 if (table[i].from == argv[optind][0])
6604 if (i >= ELEMENTSOF(table)) {
6605 log_error("Unknown command '%s'.", argv[optind]);
6609 arg_action = table[i].to;
6616 static int runlevel_parse_argv(int argc, char *argv[]) {
6622 static const struct option options[] = {
6623 { "help", no_argument, NULL, ARG_HELP },
6632 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6643 assert_not_reached("Unhandled option");
6646 if (optind < argc) {
6647 log_error("Too many arguments.");
6654 static int parse_argv(int argc, char *argv[]) {
6658 if (program_invocation_short_name) {
6660 if (strstr(program_invocation_short_name, "halt")) {
6661 arg_action = ACTION_HALT;
6662 return halt_parse_argv(argc, argv);
6663 } else if (strstr(program_invocation_short_name, "poweroff")) {
6664 arg_action = ACTION_POWEROFF;
6665 return halt_parse_argv(argc, argv);
6666 } else if (strstr(program_invocation_short_name, "reboot")) {
6668 arg_action = ACTION_KEXEC;
6670 arg_action = ACTION_REBOOT;
6671 return halt_parse_argv(argc, argv);
6672 } else if (strstr(program_invocation_short_name, "shutdown")) {
6673 arg_action = ACTION_POWEROFF;
6674 return shutdown_parse_argv(argc, argv);
6675 } else if (strstr(program_invocation_short_name, "init")) {
6677 if (sd_booted() > 0) {
6678 arg_action = _ACTION_INVALID;
6679 return telinit_parse_argv(argc, argv);
6681 /* Hmm, so some other init system is
6682 * running, we need to forward this
6683 * request to it. For now we simply
6684 * guess that it is Upstart. */
6686 execv(TELINIT, argv);
6688 log_error("Couldn't find an alternative telinit implementation to spawn.");
6692 } else if (strstr(program_invocation_short_name, "runlevel")) {
6693 arg_action = ACTION_RUNLEVEL;
6694 return runlevel_parse_argv(argc, argv);
6698 arg_action = ACTION_SYSTEMCTL;
6699 return systemctl_parse_argv(argc, argv);
6702 _pure_ static int action_to_runlevel(void) {
6704 static const char table[_ACTION_MAX] = {
6705 [ACTION_HALT] = '0',
6706 [ACTION_POWEROFF] = '0',
6707 [ACTION_REBOOT] = '6',
6708 [ACTION_RUNLEVEL2] = '2',
6709 [ACTION_RUNLEVEL3] = '3',
6710 [ACTION_RUNLEVEL4] = '4',
6711 [ACTION_RUNLEVEL5] = '5',
6712 [ACTION_RESCUE] = '1'
6715 assert(arg_action < _ACTION_MAX);
6717 return table[arg_action];
6720 static int talk_initctl(void) {
6722 struct init_request request = {
6723 .magic = INIT_MAGIC,
6725 .cmd = INIT_CMD_RUNLVL
6728 _cleanup_close_ int fd = -1;
6732 rl = action_to_runlevel();
6736 request.runlevel = rl;
6738 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
6740 if (errno == ENOENT)
6743 log_error("Failed to open "INIT_FIFO": %m");
6748 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
6750 log_error("Failed to write to "INIT_FIFO": %m");
6751 return errno > 0 ? -errno : -EIO;
6757 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
6759 static const struct {
6767 int (* const dispatch)(sd_bus *bus, char **args);
6773 { "list-units", MORE, 0, list_units },
6774 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
6775 { "list-sockets", MORE, 1, list_sockets },
6776 { "list-timers", MORE, 1, list_timers },
6777 { "list-jobs", MORE, 1, list_jobs },
6778 { "list-machines", MORE, 1, list_machines },
6779 { "clear-jobs", EQUAL, 1, daemon_reload },
6780 { "cancel", MORE, 2, cancel_job },
6781 { "start", MORE, 2, start_unit },
6782 { "stop", MORE, 2, start_unit },
6783 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6784 { "reload", MORE, 2, start_unit },
6785 { "restart", MORE, 2, start_unit },
6786 { "try-restart", MORE, 2, start_unit },
6787 { "reload-or-restart", MORE, 2, start_unit },
6788 { "reload-or-try-restart", MORE, 2, start_unit },
6789 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
6790 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6791 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
6792 { "isolate", EQUAL, 2, start_unit },
6793 { "kill", MORE, 2, kill_unit },
6794 { "is-active", MORE, 2, check_unit_active },
6795 { "check", MORE, 2, check_unit_active },
6796 { "is-failed", MORE, 2, check_unit_failed },
6797 { "show", MORE, 1, show },
6798 { "cat", MORE, 2, cat },
6799 { "status", MORE, 1, show },
6800 { "help", MORE, 2, show },
6801 { "snapshot", LESS, 2, snapshot },
6802 { "delete", MORE, 2, delete_snapshot },
6803 { "daemon-reload", EQUAL, 1, daemon_reload },
6804 { "daemon-reexec", EQUAL, 1, daemon_reload },
6805 { "show-environment", EQUAL, 1, show_environment },
6806 { "set-environment", MORE, 2, set_environment },
6807 { "unset-environment", MORE, 2, set_environment },
6808 { "import-environment", MORE, 1, import_environment},
6809 { "halt", EQUAL, 1, start_special, FORCE },
6810 { "poweroff", EQUAL, 1, start_special, FORCE },
6811 { "reboot", EQUAL, 1, start_special, FORCE },
6812 { "kexec", EQUAL, 1, start_special },
6813 { "suspend", EQUAL, 1, start_special },
6814 { "hibernate", EQUAL, 1, start_special },
6815 { "hybrid-sleep", EQUAL, 1, start_special },
6816 { "default", EQUAL, 1, start_special },
6817 { "rescue", EQUAL, 1, start_special },
6818 { "emergency", EQUAL, 1, start_special },
6819 { "exit", EQUAL, 1, start_special },
6820 { "reset-failed", MORE, 1, reset_failed },
6821 { "enable", MORE, 2, enable_unit, NOBUS },
6822 { "disable", MORE, 2, enable_unit, NOBUS },
6823 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
6824 { "reenable", MORE, 2, enable_unit, NOBUS },
6825 { "preset", MORE, 2, enable_unit, NOBUS },
6826 { "preset-all", EQUAL, 1, preset_all, NOBUS },
6827 { "mask", MORE, 2, enable_unit, NOBUS },
6828 { "unmask", MORE, 2, enable_unit, NOBUS },
6829 { "link", MORE, 2, enable_unit, NOBUS },
6830 { "switch-root", MORE, 2, switch_root },
6831 { "list-dependencies", LESS, 2, list_dependencies },
6832 { "set-default", EQUAL, 2, set_default, NOBUS },
6833 { "get-default", EQUAL, 1, get_default, NOBUS },
6834 { "set-property", MORE, 3, set_property },
6835 { "is-system-running", EQUAL, 1, is_system_running },
6836 { "add-wants", MORE, 3, add_dependency, NOBUS },
6837 { "add-requires", MORE, 3, add_dependency, NOBUS },
6846 left = argc - optind;
6848 /* Special rule: no arguments (left == 0) means "list-units" */
6850 if (streq(argv[optind], "help") && !argv[optind+1]) {
6851 log_error("This command expects one or more "
6852 "unit names. Did you mean --help?");
6856 for (; verb->verb; verb++)
6857 if (streq(argv[optind], verb->verb))
6860 log_error("Unknown operation '%s'.", argv[optind]);
6865 switch (verb->argc_cmp) {
6868 if (left != verb->argc) {
6869 log_error("Invalid number of arguments.");
6876 if (left < verb->argc) {
6877 log_error("Too few arguments.");
6884 if (left > verb->argc) {
6885 log_error("Too many arguments.");
6892 assert_not_reached("Unknown comparison operator.");
6895 /* Require a bus connection for all operations but
6897 if (verb->bus == NOBUS) {
6898 if (!bus && !avoid_bus()) {
6899 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6904 if (running_in_chroot() > 0) {
6905 log_info("Running in chroot, ignoring request.");
6909 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
6910 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6915 return verb->dispatch(bus, argv + optind);
6918 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
6920 struct sd_shutdown_command c = {
6927 union sockaddr_union sockaddr = {
6928 .un.sun_family = AF_UNIX,
6929 .un.sun_path = "/run/systemd/shutdownd",
6932 struct iovec iovec[2] = {{
6933 .iov_base = (char*) &c,
6934 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
6937 struct msghdr msghdr = {
6938 .msg_name = &sockaddr,
6939 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
6940 + strlen("/run/systemd/shutdownd"),
6945 _cleanup_close_ int fd;
6947 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
6951 if (!isempty(message)) {
6952 iovec[1].iov_base = (char*) message;
6953 iovec[1].iov_len = strlen(message);
6954 msghdr.msg_iovlen++;
6957 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
6963 static int reload_with_fallback(sd_bus *bus) {
6966 /* First, try systemd via D-Bus. */
6967 if (daemon_reload(bus, NULL) >= 0)
6971 /* Nothing else worked, so let's try signals */
6972 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
6974 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
6975 log_error("kill() failed: %m");
6982 static int start_with_fallback(sd_bus *bus) {
6985 /* First, try systemd via D-Bus. */
6986 if (start_unit(bus, NULL) >= 0)
6990 /* Nothing else worked, so let's try
6992 if (talk_initctl() > 0)
6995 log_error("Failed to talk to init daemon.");
6999 warn_wall(arg_action);
7003 static int halt_now(enum action a) {
7005 /* The kernel will automaticall flush ATA disks and suchlike
7006 * on reboot(), but the file systems need to be synce'd
7007 * explicitly in advance. */
7010 /* Make sure C-A-D is handled by the kernel from this point
7012 reboot(RB_ENABLE_CAD);
7017 log_info("Halting.");
7018 reboot(RB_HALT_SYSTEM);
7021 case ACTION_POWEROFF:
7022 log_info("Powering off.");
7023 reboot(RB_POWER_OFF);
7026 case ACTION_REBOOT: {
7027 _cleanup_free_ char *param = NULL;
7029 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
7030 log_info("Rebooting with argument '%s'.", param);
7031 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
7032 LINUX_REBOOT_CMD_RESTART2, param);
7035 log_info("Rebooting.");
7036 reboot(RB_AUTOBOOT);
7041 assert_not_reached("Unknown action.");
7045 static int halt_main(sd_bus *bus) {
7048 r = check_inhibitors(bus, arg_action);
7052 if (geteuid() != 0) {
7053 /* Try logind if we are a normal user and no special
7054 * mode applies. Maybe PolicyKit allows us to shutdown
7057 if (arg_when <= 0 &&
7060 (arg_action == ACTION_POWEROFF ||
7061 arg_action == ACTION_REBOOT)) {
7062 r = reboot_with_logind(bus, arg_action);
7067 log_error("Must be root.");
7072 _cleanup_free_ char *m;
7074 m = strv_join(arg_wall, " ");
7078 r = send_shutdownd(arg_when,
7079 arg_action == ACTION_HALT ? 'H' :
7080 arg_action == ACTION_POWEROFF ? 'P' :
7081 arg_action == ACTION_KEXEC ? 'K' :
7088 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
7090 char date[FORMAT_TIMESTAMP_MAX];
7092 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
7093 format_timestamp(date, sizeof(date), arg_when));
7098 if (!arg_dry && !arg_force)
7099 return start_with_fallback(bus);
7102 if (sd_booted() > 0)
7103 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7105 r = utmp_put_shutdown();
7107 log_warning("Failed to write utmp record: %s", strerror(-r));
7114 r = halt_now(arg_action);
7115 log_error("Failed to reboot: %s", strerror(-r));
7120 static int runlevel_main(void) {
7121 int r, runlevel, previous;
7123 r = utmp_get_runlevel(&runlevel, &previous);
7130 previous <= 0 ? 'N' : previous,
7131 runlevel <= 0 ? 'N' : runlevel);
7136 int main(int argc, char*argv[]) {
7137 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
7140 setlocale(LC_ALL, "");
7141 log_parse_environment();
7144 /* Explicitly not on_tty() to avoid setting cached value.
7145 * This becomes relevant for piping output which might be
7147 original_stdout_is_tty = isatty(STDOUT_FILENO);
7149 r = parse_argv(argc, argv);
7153 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
7154 * let's shortcut this */
7155 if (arg_action == ACTION_RUNLEVEL) {
7156 r = runlevel_main();
7160 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
7161 log_info("Running in chroot, ignoring request.");
7167 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
7169 /* systemctl_main() will print an error message for the bus
7170 * connection, but only if it needs to */
7172 switch (arg_action) {
7174 case ACTION_SYSTEMCTL:
7175 r = systemctl_main(bus, argc, argv, r);
7179 case ACTION_POWEROFF:
7185 case ACTION_RUNLEVEL2:
7186 case ACTION_RUNLEVEL3:
7187 case ACTION_RUNLEVEL4:
7188 case ACTION_RUNLEVEL5:
7190 case ACTION_EMERGENCY:
7191 case ACTION_DEFAULT:
7192 r = start_with_fallback(bus);
7197 r = reload_with_fallback(bus);
7200 case ACTION_CANCEL_SHUTDOWN: {
7201 _cleanup_free_ char *m = NULL;
7204 m = strv_join(arg_wall, " ");
7211 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
7213 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
7217 case ACTION_RUNLEVEL:
7218 case _ACTION_INVALID:
7220 assert_not_reached("Unknown action");
7225 ask_password_agent_close();
7226 polkit_agent_close();
7228 strv_free(arg_types);
7229 strv_free(arg_states);
7230 strv_free(arg_properties);
7232 return r < 0 ? EXIT_FAILURE : r;