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_errno(r, "Failed to connect to container %s: %m", *i);
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_errno(r, "Failed to get unit file list: %m");
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"
1485 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1486 "RequiredByOverridable\0"
1490 [DEPENDENCY_AFTER] = "After\0",
1491 [DEPENDENCY_BEFORE] = "Before\0",
1494 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1495 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1496 _cleanup_strv_free_ char **ret = NULL;
1497 _cleanup_free_ char *path = NULL;
1503 assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
1505 path = unit_dbus_path_from_name(name);
1509 r = sd_bus_call_method(
1511 "org.freedesktop.systemd1",
1513 "org.freedesktop.DBus.Properties",
1517 "s", "org.freedesktop.systemd1.Unit");
1519 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1523 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1525 return bus_log_parse_error(r);
1527 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1530 r = sd_bus_message_read(reply, "s", &prop);
1532 return bus_log_parse_error(r);
1534 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1535 r = sd_bus_message_skip(reply, "v");
1537 return bus_log_parse_error(r);
1540 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1542 return bus_log_parse_error(r);
1544 r = bus_message_read_strv_extend(reply, &ret);
1546 return bus_log_parse_error(r);
1548 r = sd_bus_message_exit_container(reply);
1550 return bus_log_parse_error(r);
1553 r = sd_bus_message_exit_container(reply);
1555 return bus_log_parse_error(r);
1559 return bus_log_parse_error(r);
1561 r = sd_bus_message_exit_container(reply);
1563 return bus_log_parse_error(r);
1571 static int list_dependencies_compare(const void *_a, const void *_b) {
1572 const char **a = (const char**) _a, **b = (const char**) _b;
1574 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1576 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1579 return strcasecmp(*a, *b);
1582 static int list_dependencies_one(
1587 unsigned int branches) {
1589 _cleanup_strv_free_ char **deps = NULL;
1597 r = strv_extend(units, name);
1601 r = list_dependencies_get_dependencies(bus, name, &deps);
1605 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1607 STRV_FOREACH(c, deps) {
1610 if (strv_contains(*units, *c)) {
1612 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1619 state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true);
1621 printf("%s%s%s ", ansi_highlight_green(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1623 printf("%s%s%s ", ansi_highlight_red(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1625 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1629 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1630 r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1637 strv_remove(*units, name);
1642 static int list_dependencies(sd_bus *bus, char **args) {
1643 _cleanup_strv_free_ char **units = NULL;
1644 _cleanup_free_ char *unit = NULL;
1650 unit = unit_name_mangle(args[1], MANGLE_NOGLOB);
1655 u = SPECIAL_DEFAULT_TARGET;
1657 pager_open_if_enabled();
1661 return list_dependencies_one(bus, u, 0, &units, 0);
1664 struct machine_info {
1668 char *control_group;
1669 uint32_t n_failed_units;
1674 static const struct bus_properties_map machine_info_property_map[] = {
1675 { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
1676 { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
1677 { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
1678 { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
1679 { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
1683 static void free_machines_list(struct machine_info *machine_infos, int n) {
1689 for (i = 0; i < n; i++) {
1690 free(machine_infos[i].name);
1691 free(machine_infos[i].state);
1692 free(machine_infos[i].control_group);
1695 free(machine_infos);
1698 static int compare_machine_info(const void *a, const void *b) {
1699 const struct machine_info *u = a, *v = b;
1701 if (u->is_host != v->is_host)
1702 return u->is_host > v->is_host ? -1 : 1;
1704 return strcasecmp(u->name, v->name);
1707 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1708 _cleanup_bus_close_unref_ sd_bus *container = NULL;
1714 r = sd_bus_open_system_container(&container, mi->name);
1721 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi);
1728 static bool output_show_machine(const char *name, char **patterns) {
1733 if (strv_isempty(patterns))
1736 STRV_FOREACH(i, patterns)
1737 if (fnmatch(*i, name, FNM_NOESCAPE) == 0)
1743 static int get_machine_list(
1745 struct machine_info **_machine_infos,
1748 struct machine_info *machine_infos = NULL;
1749 _cleanup_strv_free_ char **m = NULL;
1750 _cleanup_free_ char *hn = NULL;
1755 hn = gethostname_malloc();
1759 if (output_show_machine(hn, patterns)) {
1760 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1763 machine_infos[c].is_host = true;
1764 machine_infos[c].name = hn;
1767 get_machine_properties(bus, &machine_infos[c]);
1771 sd_get_machine_names(&m);
1772 STRV_FOREACH(i, m) {
1773 _cleanup_free_ char *class = NULL;
1775 if (!output_show_machine(*i, patterns))
1778 sd_machine_get_class(*i, &class);
1779 if (!streq_ptr(class, "container"))
1782 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1783 free_machines_list(machine_infos, c);
1787 machine_infos[c].is_host = false;
1788 machine_infos[c].name = strdup(*i);
1789 if (!machine_infos[c].name) {
1790 free_machines_list(machine_infos, c);
1794 get_machine_properties(NULL, &machine_infos[c]);
1798 *_machine_infos = machine_infos;
1802 static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1803 struct machine_info *m;
1806 namelen = sizeof("NAME") - 1,
1807 statelen = sizeof("STATE") - 1,
1808 failedlen = sizeof("FAILED") - 1,
1809 jobslen = sizeof("JOBS") - 1;
1811 assert(machine_infos || n == 0);
1813 for (m = machine_infos; m < machine_infos + n; m++) {
1814 namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
1815 statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
1816 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
1817 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
1819 if (!arg_no_legend && !streq_ptr(m->state, "running"))
1823 if (!arg_no_legend) {
1827 printf("%-*s %-*s %-*s %-*s\n",
1830 failedlen, "FAILED",
1834 for (m = machine_infos; m < machine_infos + n; m++) {
1835 const char *on_state = "", *off_state = "";
1836 const char *on_failed = "", *off_failed = "";
1837 bool circle = false;
1839 if (streq_ptr(m->state, "degraded")) {
1840 on_state = ansi_highlight_red();
1841 off_state = ansi_highlight_off();
1843 } else if (!streq_ptr(m->state, "running")) {
1844 on_state = ansi_highlight_yellow();
1845 off_state = ansi_highlight_off();
1849 if (m->n_failed_units > 0) {
1850 on_failed = ansi_highlight_red();
1851 off_failed = ansi_highlight_off();
1853 on_failed = off_failed = "";
1856 printf("%s%s%s ", on_state, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_state);
1859 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1860 (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
1861 on_state, statelen, strna(m->state), off_state,
1862 on_failed, failedlen, m->n_failed_units, off_failed,
1863 jobslen, m->n_jobs);
1865 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1866 namelen, strna(m->name),
1867 on_state, statelen, strna(m->state), off_state,
1868 on_failed, failedlen, m->n_failed_units, off_failed,
1869 jobslen, m->n_jobs);
1873 printf("\n%u machines listed.\n", n);
1876 static int list_machines(sd_bus *bus, char **args) {
1877 struct machine_info *machine_infos = NULL;
1882 if (geteuid() != 0) {
1883 log_error("Must be root.");
1887 pager_open_if_enabled();
1889 r = get_machine_list(bus, &machine_infos, strv_skip_first(args));
1893 qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
1894 output_machines_list(machine_infos, r);
1895 free_machines_list(machine_infos, r);
1900 static int get_default(sd_bus *bus, char **args) {
1901 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1902 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1903 _cleanup_free_ char *_path = NULL;
1907 if (!bus || avoid_bus()) {
1908 r = unit_file_get_default(arg_scope, arg_root, &_path);
1910 return log_error_errno(r, "Failed to get default target: %m");
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 return log_error_errno(r, "Failed to set default target: %m");
1994 dump_unit_file_changes(changes, n_changes);
1998 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1999 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2001 r = sd_bus_message_new_method_call(
2004 "org.freedesktop.systemd1",
2005 "/org/freedesktop/systemd1",
2006 "org.freedesktop.systemd1.Manager",
2007 "SetDefaultTarget");
2009 return bus_log_create_error(r);
2011 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2013 return bus_log_create_error(r);
2015 r = sd_bus_message_append(m, "sb", unit, 1);
2017 return bus_log_create_error(r);
2019 r = sd_bus_call(bus, m, 0, &error, &reply);
2021 log_error("Failed to set default target: %s", bus_error_message(&error, -r));
2025 r = deserialize_and_dump_unit_file_changes(reply);
2029 /* Try to reload if enabled */
2031 r = daemon_reload(bus, args);
2036 unit_file_changes_free(changes, n_changes);
2043 const char *name, *type, *state;
2046 static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
2047 unsigned id_len, unit_len, type_len, state_len;
2048 const struct job_info *j;
2049 const char *on, *off;
2050 bool shorten = false;
2052 assert(n == 0 || jobs);
2055 on = ansi_highlight_green();
2056 off = ansi_highlight_off();
2058 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
2062 pager_open_if_enabled();
2064 id_len = strlen("JOB");
2065 unit_len = strlen("UNIT");
2066 type_len = strlen("TYPE");
2067 state_len = strlen("STATE");
2069 for (j = jobs; j < jobs + n; j++) {
2070 uint32_t id = j->id;
2071 assert(j->name && j->type && j->state);
2073 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
2074 unit_len = MAX(unit_len, strlen(j->name));
2075 type_len = MAX(type_len, strlen(j->type));
2076 state_len = MAX(state_len, strlen(j->state));
2079 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
2080 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
2085 printf("%*s %-*s %-*s %-*s\n",
2089 state_len, "STATE");
2091 for (j = jobs; j < jobs + n; j++) {
2092 _cleanup_free_ char *e = NULL;
2094 if (streq(j->state, "running")) {
2095 on = ansi_highlight();
2096 off = ansi_highlight_off();
2100 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
2101 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2103 on, unit_len, e ? e : j->name, off,
2105 on, state_len, j->state, off);
2108 if (!arg_no_legend) {
2109 on = ansi_highlight();
2110 off = ansi_highlight_off();
2112 printf("\n%s%u jobs listed%s.\n", on, n, off);
2116 static bool output_show_job(struct job_info *job, char **patterns) {
2121 if (strv_isempty(patterns))
2124 STRV_FOREACH(pattern, patterns)
2125 if (fnmatch(*pattern, job->name, FNM_NOESCAPE) == 0)
2130 static int list_jobs(sd_bus *bus, char **args) {
2131 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2132 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2133 const char *name, *type, *state, *job_path, *unit_path;
2134 _cleanup_free_ struct job_info *jobs = NULL;
2139 bool skipped = false;
2141 r = sd_bus_call_method(
2143 "org.freedesktop.systemd1",
2144 "/org/freedesktop/systemd1",
2145 "org.freedesktop.systemd1.Manager",
2151 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
2155 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2157 return bus_log_parse_error(r);
2159 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
2160 struct job_info job = { id, name, type, state };
2162 if (!output_show_job(&job, strv_skip_first(args))) {
2167 if (!GREEDY_REALLOC(jobs, size, c + 1))
2173 return bus_log_parse_error(r);
2175 r = sd_bus_message_exit_container(reply);
2177 return bus_log_parse_error(r);
2179 output_jobs_list(jobs, c, skipped);
2183 static int cancel_job(sd_bus *bus, char **args) {
2184 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2190 if (strv_length(args) <= 1)
2191 return daemon_reload(bus, args);
2193 STRV_FOREACH(name, args+1) {
2194 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2198 q = safe_atou32(*name, &id);
2200 return log_error_errno(q, "Failed to parse job id \"%s\": %m", *name);
2202 q = sd_bus_message_new_method_call(
2205 "org.freedesktop.systemd1",
2206 "/org/freedesktop/systemd1",
2207 "org.freedesktop.systemd1.Manager",
2210 return bus_log_create_error(q);
2212 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2214 return bus_log_create_error(1);
2216 q = sd_bus_message_append(m, "u", id);
2218 return bus_log_create_error(q);
2220 q = sd_bus_call(bus, m, 0, &error, NULL);
2222 log_error("Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, q));
2231 static int need_daemon_reload(sd_bus *bus, const char *unit) {
2232 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2236 /* We ignore all errors here, since this is used to show a
2239 /* We don't use unit_dbus_path_from_name() directly since we
2240 * don't want to load the unit if it isn't loaded. */
2242 r = sd_bus_call_method(
2244 "org.freedesktop.systemd1",
2245 "/org/freedesktop/systemd1",
2246 "org.freedesktop.systemd1.Manager",
2254 r = sd_bus_message_read(reply, "o", &path);
2258 r = sd_bus_get_property_trivial(
2260 "org.freedesktop.systemd1",
2262 "org.freedesktop.systemd1.Unit",
2272 typedef struct WaitData {
2279 static int wait_filter(sd_bus *bus, sd_bus_message *m, void *data, sd_bus_error *error) {
2286 log_debug("Got D-Bus request: %s.%s() on %s",
2287 sd_bus_message_get_interface(m),
2288 sd_bus_message_get_member(m),
2289 sd_bus_message_get_path(m));
2291 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
2292 log_error("Warning! D-Bus connection terminated.");
2294 } else if (sd_bus_message_is_signal(m, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
2296 const char *path, *result, *unit;
2300 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
2302 ret = set_remove(d->set, (char*) path);
2308 if (!isempty(result))
2309 d->result = strdup(result);
2312 d->name = strdup(unit);
2317 r = sd_bus_message_read(m, "uos", &id, &path, &result);
2319 ret = set_remove(d->set, (char*) path);
2326 d->result = strdup(result);
2332 bus_log_parse_error(r);
2338 static int enable_wait_for_jobs(sd_bus *bus) {
2343 r = sd_bus_add_match(
2347 "sender='org.freedesktop.systemd1',"
2348 "interface='org.freedesktop.systemd1.Manager',"
2349 "member='JobRemoved',"
2350 "path='/org/freedesktop/systemd1'",
2353 log_error("Failed to add match");
2357 /* This is slightly dirty, since we don't undo the match registrations. */
2361 static int bus_process_wait(sd_bus *bus) {
2365 r = sd_bus_process(bus, NULL);
2370 r = sd_bus_wait(bus, (uint64_t) -1);
2376 static int check_wait_response(WaitData *d) {
2382 if (streq(d->result, "timeout"))
2383 log_error("Job for %s timed out.", strna(d->name));
2384 else if (streq(d->result, "canceled"))
2385 log_error("Job for %s canceled.", strna(d->name));
2386 else if (streq(d->result, "dependency"))
2387 log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
2388 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
2392 quotes = chars_intersect(d->name, SHELL_NEED_QUOTES);
2394 log_error("Job for %s failed. See \"systemctl status %s%s%s\" and \"journalctl -xe\" for details.",
2396 quotes ? "'" : "", d->name, quotes ? "'" : "");
2398 log_error("Job failed. See \"journalctl -xe\" for details.");
2402 if (streq(d->result, "timeout"))
2404 else if (streq(d->result, "canceled"))
2406 else if (streq(d->result, "dependency"))
2408 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2414 static int wait_for_jobs(sd_bus *bus, Set *s) {
2415 _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
2416 WaitData d = { .set = s };
2422 q = sd_bus_add_filter(bus, &slot, wait_filter, &d);
2426 while (!set_isempty(s)) {
2427 q = bus_process_wait(bus);
2429 return log_error_errno(q, "Failed to wait for response: %m");
2432 q = check_wait_response(&d);
2433 /* Return the first error as it is most likely to be
2435 if (q < 0 && r == 0)
2437 log_debug("Got result %s/%s for job %s",
2438 strna(d.result), strerror(-q), strna(d.name));
2451 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2452 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2453 _cleanup_free_ char *n = NULL, *state = NULL;
2459 n = unit_name_mangle(name, MANGLE_NOGLOB);
2463 /* We don't use unit_dbus_path_from_name() directly since we
2464 * don't want to load the unit if it isn't loaded. */
2466 r = sd_bus_call_method(
2468 "org.freedesktop.systemd1",
2469 "/org/freedesktop/systemd1",
2470 "org.freedesktop.systemd1.Manager",
2481 r = sd_bus_message_read(reply, "o", &path);
2483 return bus_log_parse_error(r);
2485 r = sd_bus_get_property_string(
2487 "org.freedesktop.systemd1",
2489 "org.freedesktop.systemd1.Unit",
2502 return nulstr_contains(good_states, state);
2505 static int check_triggering_units(
2509 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2510 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2511 _cleanup_strv_free_ char **triggered_by = NULL;
2512 bool print_warning_label = true;
2516 n = unit_name_mangle(name, MANGLE_NOGLOB);
2520 path = unit_dbus_path_from_name(n);
2524 r = sd_bus_get_property_string(
2526 "org.freedesktop.systemd1",
2528 "org.freedesktop.systemd1.Unit",
2533 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2537 if (streq(state, "masked"))
2540 r = sd_bus_get_property_strv(
2542 "org.freedesktop.systemd1",
2544 "org.freedesktop.systemd1.Unit",
2549 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2553 STRV_FOREACH(i, triggered_by) {
2554 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2556 return log_error_errno(r, "Failed to check unit: %m");
2561 if (print_warning_label) {
2562 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2563 print_warning_label = false;
2566 log_warning(" %s", *i);
2572 static const struct {
2575 } unit_actions[] = {
2576 { "start", "StartUnit" },
2577 { "stop", "StopUnit" },
2578 { "condstop", "StopUnit" },
2579 { "reload", "ReloadUnit" },
2580 { "restart", "RestartUnit" },
2581 { "try-restart", "TryRestartUnit" },
2582 { "condrestart", "TryRestartUnit" },
2583 { "reload-or-restart", "ReloadOrRestartUnit" },
2584 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2585 { "condreload", "ReloadOrTryRestartUnit" },
2586 { "force-reload", "ReloadOrTryRestartUnit" }
2589 static const char *verb_to_method(const char *verb) {
2592 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2593 if (streq_ptr(unit_actions[i].verb, verb))
2594 return unit_actions[i].method;
2599 static const char *method_to_verb(const char *method) {
2602 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2603 if (streq_ptr(unit_actions[i].method, method))
2604 return unit_actions[i].verb;
2609 static int start_unit_one(
2614 sd_bus_error *error,
2617 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2626 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2628 r = sd_bus_message_new_method_call(
2631 "org.freedesktop.systemd1",
2632 "/org/freedesktop/systemd1",
2633 "org.freedesktop.systemd1.Manager",
2636 return bus_log_create_error(r);
2638 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2640 return bus_log_create_error(r);
2642 r = sd_bus_message_append(m, "ss", name, mode);
2644 return bus_log_create_error(r);
2646 r = sd_bus_call(bus, m, 0, error, &reply);
2650 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2651 /* There's always a fallback possible for
2652 * legacy actions. */
2653 return -EADDRNOTAVAIL;
2655 verb = method_to_verb(method);
2657 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2661 r = sd_bus_message_read(reply, "o", &path);
2663 return bus_log_parse_error(r);
2665 if (need_daemon_reload(bus, name) > 0)
2666 log_warning("Warning: Unit file of %s changed on disk, 'systemctl%s daemon-reload' recommended.",
2667 name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2676 log_debug("Adding %s to the set", p);
2677 r = set_consume(s, p);
2685 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2687 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2691 STRV_FOREACH(name, names) {
2695 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2697 t = unit_name_mangle(*name, MANGLE_GLOB);
2701 if (string_is_glob(t))
2702 r = strv_consume(&globs, t);
2704 r = strv_consume(&mangled, t);
2709 /* Query the manager only if any of the names are a glob, since
2710 * this is fairly expensive */
2711 if (!strv_isempty(globs)) {
2712 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2713 _cleanup_free_ UnitInfo *unit_infos = NULL;
2715 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2719 for (i = 0; i < r; i++)
2720 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2725 mangled = NULL; /* do not free */
2730 static const struct {
2734 } action_table[_ACTION_MAX] = {
2735 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2736 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2737 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2738 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2739 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
2740 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
2741 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
2742 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
2743 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2744 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2745 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2746 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2747 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2748 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2749 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2752 static enum action verb_to_action(const char *verb) {
2755 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2756 if (streq_ptr(action_table[i].verb, verb))
2759 return _ACTION_INVALID;
2762 static int start_unit(sd_bus *bus, char **args) {
2763 _cleanup_set_free_free_ Set *s = NULL;
2764 _cleanup_strv_free_ char **names = NULL;
2765 const char *method, *mode, *one_name, *suffix = NULL;
2771 ask_password_agent_open_if_enabled();
2773 if (arg_action == ACTION_SYSTEMCTL) {
2775 method = verb_to_method(args[0]);
2776 action = verb_to_action(args[0]);
2778 if (streq(args[0], "isolate")) {
2782 mode = action_table[action].mode ?: arg_job_mode;
2784 one_name = action_table[action].target;
2786 assert(arg_action < ELEMENTSOF(action_table));
2787 assert(action_table[arg_action].target);
2789 method = "StartUnit";
2791 mode = action_table[arg_action].mode;
2792 one_name = action_table[arg_action].target;
2796 names = strv_new(one_name, NULL);
2798 r = expand_names(bus, args + 1, suffix, &names);
2800 log_error_errno(r, "Failed to expand names: %m");
2803 if (!arg_no_block) {
2804 r = enable_wait_for_jobs(bus);
2806 return log_error_errno(r, "Could not watch jobs: %m");
2808 s = set_new(&string_hash_ops);
2813 STRV_FOREACH(name, names) {
2814 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2817 q = start_unit_one(bus, method, *name, mode, &error, s);
2818 if (r >= 0 && q < 0)
2819 r = translate_bus_error_to_exit_status(q, &error);
2822 if (!arg_no_block) {
2825 q = wait_for_jobs(bus, s);
2829 /* When stopping units, warn if they can still be triggered by
2830 * another active unit (socket, path, timer) */
2831 if (!arg_quiet && streq(method, "StopUnit"))
2832 STRV_FOREACH(name, names)
2833 check_triggering_units(bus, *name);
2839 /* Ask systemd-logind, which might grant access to unprivileged users
2840 * through PolicyKit */
2841 static int reboot_with_logind(sd_bus *bus, enum action a) {
2843 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2850 polkit_agent_open_if_enabled();
2858 case ACTION_POWEROFF:
2859 method = "PowerOff";
2862 case ACTION_SUSPEND:
2866 case ACTION_HIBERNATE:
2867 method = "Hibernate";
2870 case ACTION_HYBRID_SLEEP:
2871 method = "HybridSleep";
2878 r = sd_bus_call_method(
2880 "org.freedesktop.login1",
2881 "/org/freedesktop/login1",
2882 "org.freedesktop.login1.Manager",
2886 "b", arg_ask_password);
2888 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2896 static int check_inhibitors(sd_bus *bus, enum action a) {
2898 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2899 _cleanup_strv_free_ char **sessions = NULL;
2900 const char *what, *who, *why, *mode;
2909 if (arg_ignore_inhibitors || arg_force > 0)
2921 r = sd_bus_call_method(
2923 "org.freedesktop.login1",
2924 "/org/freedesktop/login1",
2925 "org.freedesktop.login1.Manager",
2931 /* If logind is not around, then there are no inhibitors... */
2934 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2936 return bus_log_parse_error(r);
2938 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2939 _cleanup_free_ char *comm = NULL, *user = NULL;
2940 _cleanup_strv_free_ char **sv = NULL;
2942 if (!streq(mode, "block"))
2945 sv = strv_split(what, ":");
2949 if (!strv_contains(sv,
2951 a == ACTION_POWEROFF ||
2952 a == ACTION_REBOOT ||
2953 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2956 get_process_comm(pid, &comm);
2957 user = uid_to_name(uid);
2959 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
2960 who, pid, strna(comm), strna(user), why);
2965 return bus_log_parse_error(r);
2967 r = sd_bus_message_exit_container(reply);
2969 return bus_log_parse_error(r);
2971 /* Check for current sessions */
2972 sd_get_sessions(&sessions);
2973 STRV_FOREACH(s, sessions) {
2974 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2976 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2979 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2982 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2985 sd_session_get_tty(*s, &tty);
2986 sd_session_get_seat(*s, &seat);
2987 sd_session_get_service(*s, &service);
2988 user = uid_to_name(uid);
2990 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2997 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2998 action_table[a].verb);
3006 static int start_special(sd_bus *bus, char **args) {
3012 a = verb_to_action(args[0]);
3014 r = check_inhibitors(bus, a);
3018 if (arg_force >= 2 && geteuid() != 0) {
3019 log_error("Must be root.");
3023 if (arg_force >= 2 &&
3024 (a == ACTION_HALT ||
3025 a == ACTION_POWEROFF ||
3026 a == ACTION_REBOOT))
3029 if (arg_force >= 1 &&
3030 (a == ACTION_HALT ||
3031 a == ACTION_POWEROFF ||
3032 a == ACTION_REBOOT ||
3033 a == ACTION_KEXEC ||
3035 return daemon_reload(bus, args);
3037 /* first try logind, to allow authentication with polkit */
3038 if (geteuid() != 0 &&
3039 (a == ACTION_POWEROFF ||
3040 a == ACTION_REBOOT ||
3041 a == ACTION_SUSPEND ||
3042 a == ACTION_HIBERNATE ||
3043 a == ACTION_HYBRID_SLEEP)) {
3044 r = reboot_with_logind(bus, a);
3049 r = start_unit(bus, args);
3050 if (r == EXIT_SUCCESS)
3056 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
3057 _cleanup_strv_free_ char **names = NULL;
3064 r = expand_names(bus, args, NULL, &names);
3066 return log_error_errno(r, "Failed to expand names: %m");
3068 STRV_FOREACH(name, names) {
3071 state = check_one_unit(bus, *name, good_states, arg_quiet);
3081 static int check_unit_active(sd_bus *bus, char **args) {
3082 /* According to LSB: 3, "program is not running" */
3083 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
3086 static int check_unit_failed(sd_bus *bus, char **args) {
3087 return check_unit_generic(bus, 1, "failed\0", args + 1);
3090 static int kill_unit(sd_bus *bus, char **args) {
3091 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3092 _cleanup_strv_free_ char **names = NULL;
3100 arg_kill_who = "all";
3102 r = expand_names(bus, args + 1, NULL, &names);
3104 log_error_errno(r, "Failed to expand names: %m");
3106 STRV_FOREACH(name, names) {
3107 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3109 q = sd_bus_message_new_method_call(
3112 "org.freedesktop.systemd1",
3113 "/org/freedesktop/systemd1",
3114 "org.freedesktop.systemd1.Manager",
3117 return bus_log_create_error(q);
3119 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
3121 return bus_log_create_error(q);
3123 q = sd_bus_message_append(m, "ssi", *names, arg_kill_who, arg_signal);
3125 return bus_log_create_error(q);
3127 q = sd_bus_call(bus, m, 0, &error, NULL);
3129 log_error("Failed to kill unit %s: %s", *names, bus_error_message(&error, q));
3138 typedef struct ExecStatusInfo {
3146 usec_t start_timestamp;
3147 usec_t exit_timestamp;
3152 LIST_FIELDS(struct ExecStatusInfo, exec);
3155 static void exec_status_info_free(ExecStatusInfo *i) {
3164 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3165 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3168 int32_t code, status;
3174 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3176 return bus_log_parse_error(r);
3180 r = sd_bus_message_read(m, "s", &path);
3182 return bus_log_parse_error(r);
3184 i->path = strdup(path);
3188 r = sd_bus_message_read_strv(m, &i->argv);
3190 return bus_log_parse_error(r);
3192 r = sd_bus_message_read(m,
3195 &start_timestamp, &start_timestamp_monotonic,
3196 &exit_timestamp, &exit_timestamp_monotonic,
3200 return bus_log_parse_error(r);
3203 i->start_timestamp = (usec_t) start_timestamp;
3204 i->exit_timestamp = (usec_t) exit_timestamp;
3205 i->pid = (pid_t) pid;
3209 r = sd_bus_message_exit_container(m);
3211 return bus_log_parse_error(r);
3216 typedef struct UnitStatusInfo {
3218 const char *load_state;
3219 const char *active_state;
3220 const char *sub_state;
3221 const char *unit_file_state;
3223 const char *description;
3224 const char *following;
3226 char **documentation;
3228 const char *fragment_path;
3229 const char *source_path;
3230 const char *control_group;
3232 char **dropin_paths;
3234 const char *load_error;
3237 usec_t inactive_exit_timestamp;
3238 usec_t inactive_exit_timestamp_monotonic;
3239 usec_t active_enter_timestamp;
3240 usec_t active_exit_timestamp;
3241 usec_t inactive_enter_timestamp;
3243 bool need_daemon_reload;
3248 const char *status_text;
3249 const char *pid_file;
3253 usec_t start_timestamp;
3254 usec_t exit_timestamp;
3256 int exit_code, exit_status;
3258 usec_t condition_timestamp;
3259 bool condition_result;
3260 bool failed_condition_trigger;
3261 bool failed_condition_negate;
3262 const char *failed_condition;
3263 const char *failed_condition_parameter;
3265 usec_t assert_timestamp;
3267 bool failed_assert_trigger;
3268 bool failed_assert_negate;
3269 const char *failed_assert;
3270 const char *failed_assert_parameter;
3273 unsigned n_accepted;
3274 unsigned n_connections;
3277 /* Pairs of type, path */
3281 const char *sysfs_path;
3283 /* Mount, Automount */
3289 LIST_HEAD(ExecStatusInfo, exec);
3292 static void print_status_info(
3297 const char *active_on, *active_off, *on, *off, *ss;
3299 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3300 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3303 arg_all * OUTPUT_SHOW_ALL |
3304 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
3305 on_tty() * OUTPUT_COLOR |
3306 !arg_quiet * OUTPUT_WARN_CUTOFF |
3307 arg_full * OUTPUT_FULL_WIDTH;
3312 /* This shows pretty information about a unit. See
3313 * print_property() for a low-level property printer */
3315 if (streq_ptr(i->active_state, "failed")) {
3316 active_on = ansi_highlight_red();
3317 active_off = ansi_highlight_off();
3318 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3319 active_on = ansi_highlight_green();
3320 active_off = ansi_highlight_off();
3322 active_on = active_off = "";
3324 printf("%s%s%s %s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3326 if (i->description && !streq_ptr(i->id, i->description))
3327 printf(" - %s", i->description);
3332 printf(" Follow: unit currently follows state of %s\n", i->following);
3334 if (streq_ptr(i->load_state, "error")) {
3335 on = ansi_highlight_red();
3336 off = ansi_highlight_off();
3340 path = i->source_path ? i->source_path : i->fragment_path;
3343 printf(" Loaded: %s%s%s (Reason: %s)\n",
3344 on, strna(i->load_state), off, i->load_error);
3345 else if (path && i->unit_file_state)
3346 printf(" Loaded: %s%s%s (%s; %s)\n",
3347 on, strna(i->load_state), off, path, i->unit_file_state);
3349 printf(" Loaded: %s%s%s (%s)\n",
3350 on, strna(i->load_state), off, path);
3352 printf(" Loaded: %s%s%s\n",
3353 on, strna(i->load_state), off);
3355 if (!strv_isempty(i->dropin_paths)) {
3356 _cleanup_free_ char *dir = NULL;
3360 STRV_FOREACH(dropin, i->dropin_paths) {
3361 if (! dir || last) {
3362 printf(dir ? " " : " Drop-In: ");
3367 if (path_get_parent(*dropin, &dir) < 0) {
3372 printf("%s\n %s", dir,
3373 draw_special_char(DRAW_TREE_RIGHT));
3376 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3378 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3382 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3384 printf(" Active: %s%s (%s)%s",
3385 active_on, strna(i->active_state), ss, active_off);
3387 printf(" Active: %s%s%s",
3388 active_on, strna(i->active_state), active_off);
3390 if (!isempty(i->result) && !streq(i->result, "success"))
3391 printf(" (Result: %s)", i->result);
3393 timestamp = (streq_ptr(i->active_state, "active") ||
3394 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
3395 (streq_ptr(i->active_state, "inactive") ||
3396 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
3397 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
3398 i->active_exit_timestamp;
3400 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3401 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3404 printf(" since %s; %s\n", s2, s1);
3406 printf(" since %s\n", s2);
3410 if (!i->condition_result && i->condition_timestamp > 0) {
3411 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3412 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3414 printf("Condition: start %scondition failed%s at %s%s%s\n",
3415 ansi_highlight_yellow(), ansi_highlight_off(),
3416 s2, s1 ? "; " : "", s1 ? s1 : "");
3417 if (i->failed_condition_trigger)
3418 printf(" none of the trigger conditions were met\n");
3419 else if (i->failed_condition)
3420 printf(" %s=%s%s was not met\n",
3421 i->failed_condition,
3422 i->failed_condition_negate ? "!" : "",
3423 i->failed_condition_parameter);
3426 if (!i->assert_result && i->assert_timestamp > 0) {
3427 s1 = format_timestamp_relative(since1, sizeof(since1), i->assert_timestamp);
3428 s2 = format_timestamp(since2, sizeof(since2), i->assert_timestamp);
3430 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3431 ansi_highlight_red(), ansi_highlight_off(),
3432 s2, s1 ? "; " : "", s1 ? s1 : "");
3433 if (i->failed_assert_trigger)
3434 printf(" none of the trigger assertions were met\n");
3435 else if (i->failed_assert)
3436 printf(" %s=%s%s was not met\n",
3438 i->failed_assert_negate ? "!" : "",
3439 i->failed_assert_parameter);
3443 printf(" Device: %s\n", i->sysfs_path);
3445 printf(" Where: %s\n", i->where);
3447 printf(" What: %s\n", i->what);
3449 STRV_FOREACH(t, i->documentation)
3450 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3452 STRV_FOREACH_PAIR(t, t2, i->listen)
3453 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3456 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3458 LIST_FOREACH(exec, p, i->exec) {
3459 _cleanup_free_ char *argv = NULL;
3462 /* Only show exited processes here */
3466 argv = strv_join(p->argv, " ");
3467 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
3469 good = is_clean_exit_lsb(p->code, p->status, NULL);
3471 on = ansi_highlight_red();
3472 off = ansi_highlight_off();
3476 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3478 if (p->code == CLD_EXITED) {
3481 printf("status=%i", p->status);
3483 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3488 printf("signal=%s", signal_to_string(p->status));
3490 printf(")%s\n", off);
3492 if (i->main_pid == p->pid &&
3493 i->start_timestamp == p->start_timestamp &&
3494 i->exit_timestamp == p->start_timestamp)
3495 /* Let's not show this twice */
3498 if (p->pid == i->control_pid)
3502 if (i->main_pid > 0 || i->control_pid > 0) {
3503 if (i->main_pid > 0) {
3504 printf(" Main PID: "PID_FMT, i->main_pid);
3507 _cleanup_free_ char *comm = NULL;
3508 get_process_comm(i->main_pid, &comm);
3510 printf(" (%s)", comm);
3511 } else if (i->exit_code > 0) {
3512 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3514 if (i->exit_code == CLD_EXITED) {
3517 printf("status=%i", i->exit_status);
3519 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3524 printf("signal=%s", signal_to_string(i->exit_status));
3528 if (i->control_pid > 0)
3532 if (i->control_pid > 0) {
3533 _cleanup_free_ char *c = NULL;
3535 printf(" %8s: "PID_FMT, i->main_pid ? "" : " Control", i->control_pid);
3537 get_process_comm(i->control_pid, &c);
3546 printf(" Status: \"%s\"\n", i->status_text);
3547 if (i->status_errno > 0)
3548 printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
3550 if (i->control_group &&
3551 (i->main_pid > 0 || i->control_pid > 0 ||
3552 ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_CONTAINER) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3555 printf(" CGroup: %s\n", i->control_group);
3557 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
3560 static const char prefix[] = " ";
3563 if (c > sizeof(prefix) - 1)
3564 c -= sizeof(prefix) - 1;
3568 if (i->main_pid > 0)
3569 extra[k++] = i->main_pid;
3571 if (i->control_pid > 0)
3572 extra[k++] = i->control_pid;
3574 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, flags);
3578 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3579 show_journal_by_unit(stdout,
3583 i->inactive_exit_timestamp_monotonic,
3586 flags | OUTPUT_BEGIN_NEWLINE,
3587 arg_scope == UNIT_FILE_SYSTEM,
3591 if (i->need_daemon_reload)
3592 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
3593 ansi_highlight_red(),
3594 ansi_highlight_off(),
3595 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
3598 static void show_unit_help(UnitStatusInfo *i) {
3603 if (!i->documentation) {
3604 log_info("Documentation for %s not known.", i->id);
3608 STRV_FOREACH(p, i->documentation)
3609 if (startswith(*p, "man:"))
3610 show_man_page(*p + 4, false);
3612 log_info("Can't show: %s", *p);
3615 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3622 switch (contents[0]) {
3624 case SD_BUS_TYPE_STRING: {
3627 r = sd_bus_message_read(m, "s", &s);
3629 return bus_log_parse_error(r);
3632 if (streq(name, "Id"))
3634 else if (streq(name, "LoadState"))
3636 else if (streq(name, "ActiveState"))
3637 i->active_state = s;
3638 else if (streq(name, "SubState"))
3640 else if (streq(name, "Description"))
3642 else if (streq(name, "FragmentPath"))
3643 i->fragment_path = s;
3644 else if (streq(name, "SourcePath"))
3647 else if (streq(name, "DefaultControlGroup")) {
3649 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3651 i->control_group = e;
3654 else if (streq(name, "ControlGroup"))
3655 i->control_group = s;
3656 else if (streq(name, "StatusText"))
3658 else if (streq(name, "PIDFile"))
3660 else if (streq(name, "SysFSPath"))
3662 else if (streq(name, "Where"))
3664 else if (streq(name, "What"))
3666 else if (streq(name, "Following"))
3668 else if (streq(name, "UnitFileState"))
3669 i->unit_file_state = s;
3670 else if (streq(name, "Result"))
3677 case SD_BUS_TYPE_BOOLEAN: {
3680 r = sd_bus_message_read(m, "b", &b);
3682 return bus_log_parse_error(r);
3684 if (streq(name, "Accept"))
3686 else if (streq(name, "NeedDaemonReload"))
3687 i->need_daemon_reload = b;
3688 else if (streq(name, "ConditionResult"))
3689 i->condition_result = b;
3690 else if (streq(name, "AssertResult"))
3691 i->assert_result = b;
3696 case SD_BUS_TYPE_UINT32: {
3699 r = sd_bus_message_read(m, "u", &u);
3701 return bus_log_parse_error(r);
3703 if (streq(name, "MainPID")) {
3705 i->main_pid = (pid_t) u;
3708 } else if (streq(name, "ControlPID"))
3709 i->control_pid = (pid_t) u;
3710 else if (streq(name, "ExecMainPID")) {
3712 i->main_pid = (pid_t) u;
3713 } else if (streq(name, "NAccepted"))
3715 else if (streq(name, "NConnections"))
3716 i->n_connections = u;
3721 case SD_BUS_TYPE_INT32: {
3724 r = sd_bus_message_read(m, "i", &j);
3726 return bus_log_parse_error(r);
3728 if (streq(name, "ExecMainCode"))
3729 i->exit_code = (int) j;
3730 else if (streq(name, "ExecMainStatus"))
3731 i->exit_status = (int) j;
3732 else if (streq(name, "StatusErrno"))
3733 i->status_errno = (int) j;
3738 case SD_BUS_TYPE_UINT64: {
3741 r = sd_bus_message_read(m, "t", &u);
3743 return bus_log_parse_error(r);
3745 if (streq(name, "ExecMainStartTimestamp"))
3746 i->start_timestamp = (usec_t) u;
3747 else if (streq(name, "ExecMainExitTimestamp"))
3748 i->exit_timestamp = (usec_t) u;
3749 else if (streq(name, "ActiveEnterTimestamp"))
3750 i->active_enter_timestamp = (usec_t) u;
3751 else if (streq(name, "InactiveEnterTimestamp"))
3752 i->inactive_enter_timestamp = (usec_t) u;
3753 else if (streq(name, "InactiveExitTimestamp"))
3754 i->inactive_exit_timestamp = (usec_t) u;
3755 else if (streq(name, "InactiveExitTimestampMonotonic"))
3756 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3757 else if (streq(name, "ActiveExitTimestamp"))
3758 i->active_exit_timestamp = (usec_t) u;
3759 else if (streq(name, "ConditionTimestamp"))
3760 i->condition_timestamp = (usec_t) u;
3761 else if (streq(name, "AssertTimestamp"))
3762 i->assert_timestamp = (usec_t) u;
3767 case SD_BUS_TYPE_ARRAY:
3769 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3770 _cleanup_free_ ExecStatusInfo *info = NULL;
3772 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3774 return bus_log_parse_error(r);
3776 info = new0(ExecStatusInfo, 1);
3780 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3782 info->name = strdup(name);
3786 LIST_PREPEND(exec, i->exec, info);
3788 info = new0(ExecStatusInfo, 1);
3794 return bus_log_parse_error(r);
3796 r = sd_bus_message_exit_container(m);
3798 return bus_log_parse_error(r);
3802 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3803 const char *type, *path;
3805 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3807 return bus_log_parse_error(r);
3809 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3811 r = strv_extend(&i->listen, type);
3815 r = strv_extend(&i->listen, path);
3820 return bus_log_parse_error(r);
3822 r = sd_bus_message_exit_container(m);
3824 return bus_log_parse_error(r);
3828 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3830 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3832 return bus_log_parse_error(r);
3834 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3836 r = sd_bus_message_read_strv(m, &i->documentation);
3838 return bus_log_parse_error(r);
3840 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3841 const char *cond, *param;
3842 int trigger, negate;
3845 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3847 return bus_log_parse_error(r);
3849 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3850 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3851 if (state < 0 && (!trigger || !i->failed_condition)) {
3852 i->failed_condition = cond;
3853 i->failed_condition_trigger = trigger;
3854 i->failed_condition_negate = negate;
3855 i->failed_condition_parameter = param;
3859 return bus_log_parse_error(r);
3861 r = sd_bus_message_exit_container(m);
3863 return bus_log_parse_error(r);
3865 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Asserts")) {
3866 const char *cond, *param;
3867 int trigger, negate;
3870 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3872 return bus_log_parse_error(r);
3874 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3875 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3876 if (state < 0 && (!trigger || !i->failed_assert)) {
3877 i->failed_assert = cond;
3878 i->failed_assert_trigger = trigger;
3879 i->failed_assert_negate = negate;
3880 i->failed_assert_parameter = param;
3884 return bus_log_parse_error(r);
3886 r = sd_bus_message_exit_container(m);
3888 return bus_log_parse_error(r);
3895 case SD_BUS_TYPE_STRUCT_BEGIN:
3897 if (streq(name, "LoadError")) {
3898 const char *n, *message;
3900 r = sd_bus_message_read(m, "(ss)", &n, &message);
3902 return bus_log_parse_error(r);
3904 if (!isempty(message))
3905 i->load_error = message;
3918 r = sd_bus_message_skip(m, contents);
3920 return bus_log_parse_error(r);
3925 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3931 /* This is a low-level property printer, see
3932 * print_status_info() for the nicer output */
3934 if (arg_properties && !strv_find(arg_properties, name)) {
3935 /* skip what we didn't read */
3936 r = sd_bus_message_skip(m, contents);
3940 switch (contents[0]) {
3942 case SD_BUS_TYPE_STRUCT_BEGIN:
3944 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3947 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3949 return bus_log_parse_error(r);
3952 printf("%s=%"PRIu32"\n", name, u);
3954 printf("%s=\n", name);
3958 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3961 r = sd_bus_message_read(m, "(so)", &s, NULL);
3963 return bus_log_parse_error(r);
3965 if (arg_all || !isempty(s))
3966 printf("%s=%s\n", name, s);
3970 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3971 const char *a = NULL, *b = NULL;
3973 r = sd_bus_message_read(m, "(ss)", &a, &b);
3975 return bus_log_parse_error(r);
3977 if (arg_all || !isempty(a) || !isempty(b))
3978 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3981 } else if (streq_ptr(name, "SystemCallFilter")) {
3982 _cleanup_strv_free_ char **l = NULL;
3985 r = sd_bus_message_enter_container(m, 'r', "bas");
3987 return bus_log_parse_error(r);
3989 r = sd_bus_message_read(m, "b", &whitelist);
3991 return bus_log_parse_error(r);
3993 r = sd_bus_message_read_strv(m, &l);
3995 return bus_log_parse_error(r);
3997 r = sd_bus_message_exit_container(m);
3999 return bus_log_parse_error(r);
4001 if (arg_all || whitelist || !strv_isempty(l)) {
4005 fputs(name, stdout);
4011 STRV_FOREACH(i, l) {
4019 fputc('\n', stdout);
4027 case SD_BUS_TYPE_ARRAY:
4029 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
4033 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
4035 return bus_log_parse_error(r);
4037 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
4038 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
4041 return bus_log_parse_error(r);
4043 r = sd_bus_message_exit_container(m);
4045 return bus_log_parse_error(r);
4049 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
4050 const char *type, *path;
4052 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4054 return bus_log_parse_error(r);
4056 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4057 printf("%s=%s\n", type, path);
4059 return bus_log_parse_error(r);
4061 r = sd_bus_message_exit_container(m);
4063 return bus_log_parse_error(r);
4067 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
4068 const char *type, *path;
4070 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4072 return bus_log_parse_error(r);
4074 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4075 printf("Listen%s=%s\n", type, path);
4077 return bus_log_parse_error(r);
4079 r = sd_bus_message_exit_container(m);
4081 return bus_log_parse_error(r);
4085 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
4087 uint64_t value, next_elapse;
4089 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
4091 return bus_log_parse_error(r);
4093 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
4094 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
4096 printf("%s={ value=%s ; next_elapse=%s }\n",
4098 format_timespan(timespan1, sizeof(timespan1), value, 0),
4099 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
4102 return bus_log_parse_error(r);
4104 r = sd_bus_message_exit_container(m);
4106 return bus_log_parse_error(r);
4110 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
4111 ExecStatusInfo info = {};
4113 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
4115 return bus_log_parse_error(r);
4117 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
4118 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
4119 _cleanup_free_ char *tt;
4121 tt = strv_join(info.argv, " ");
4123 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",
4127 yes_no(info.ignore),
4128 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
4129 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
4131 sigchld_code_to_string(info.code),
4133 info.code == CLD_EXITED ? "" : "/",
4134 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
4137 strv_free(info.argv);
4141 r = sd_bus_message_exit_container(m);
4143 return bus_log_parse_error(r);
4147 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
4148 const char *path, *rwm;
4150 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4152 return bus_log_parse_error(r);
4154 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
4155 printf("%s=%s %s\n", name, strna(path), strna(rwm));
4157 return bus_log_parse_error(r);
4159 r = sd_bus_message_exit_container(m);
4161 return bus_log_parse_error(r);
4165 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
4169 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4171 return bus_log_parse_error(r);
4173 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4174 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
4176 return bus_log_parse_error(r);
4178 r = sd_bus_message_exit_container(m);
4180 return bus_log_parse_error(r);
4184 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
4188 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4190 return bus_log_parse_error(r);
4192 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4193 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
4195 return bus_log_parse_error(r);
4197 r = sd_bus_message_exit_container(m);
4199 return bus_log_parse_error(r);
4207 r = bus_print_property(name, m, arg_all);
4209 return bus_log_parse_error(r);
4212 r = sd_bus_message_skip(m, contents);
4214 return bus_log_parse_error(r);
4217 printf("%s=[unprintable]\n", name);
4223 static int show_one(
4227 bool show_properties,
4231 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4232 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4233 UnitStatusInfo info = {};
4240 log_debug("Showing one %s", path);
4242 r = sd_bus_call_method(
4244 "org.freedesktop.systemd1",
4246 "org.freedesktop.DBus.Properties",
4252 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4256 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4258 return bus_log_parse_error(r);
4265 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4266 const char *name, *contents;
4268 r = sd_bus_message_read(reply, "s", &name);
4270 return bus_log_parse_error(r);
4272 r = sd_bus_message_peek_type(reply, NULL, &contents);
4274 return bus_log_parse_error(r);
4276 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4278 return bus_log_parse_error(r);
4280 if (show_properties)
4281 r = print_property(name, reply, contents);
4283 r = status_property(name, reply, &info, contents);
4287 r = sd_bus_message_exit_container(reply);
4289 return bus_log_parse_error(r);
4291 r = sd_bus_message_exit_container(reply);
4293 return bus_log_parse_error(r);
4296 return bus_log_parse_error(r);
4298 r = sd_bus_message_exit_container(reply);
4300 return bus_log_parse_error(r);
4304 if (!show_properties) {
4305 if (streq(verb, "help"))
4306 show_unit_help(&info);
4308 print_status_info(&info, ellipsized);
4311 strv_free(info.documentation);
4312 strv_free(info.dropin_paths);
4313 strv_free(info.listen);
4315 if (!streq_ptr(info.active_state, "active") &&
4316 !streq_ptr(info.active_state, "reloading") &&
4317 streq(verb, "status")) {
4318 /* According to LSB: "program not running" */
4319 /* 0: program is running or service is OK
4320 * 1: program is dead and /run PID file exists
4321 * 2: program is dead and /run/lock lock file exists
4322 * 3: program is not running
4323 * 4: program or service status is unknown
4325 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4331 while ((p = info.exec)) {
4332 LIST_REMOVE(exec, info.exec, p);
4333 exec_status_info_free(p);
4339 static int get_unit_dbus_path_by_pid(
4344 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4345 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4349 r = sd_bus_call_method(
4351 "org.freedesktop.systemd1",
4352 "/org/freedesktop/systemd1",
4353 "org.freedesktop.systemd1.Manager",
4359 log_error("Failed to get unit for PID "PID_FMT": %s", pid, bus_error_message(&error, r));
4363 r = sd_bus_message_read(reply, "o", &u);
4365 return bus_log_parse_error(r);
4375 static int show_all(
4378 bool show_properties,
4382 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4383 _cleanup_free_ UnitInfo *unit_infos = NULL;
4388 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4392 pager_open_if_enabled();
4396 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4398 for (u = unit_infos; u < unit_infos + c; u++) {
4399 _cleanup_free_ char *p = NULL;
4401 p = unit_dbus_path_from_name(u->id);
4405 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4408 else if (r > 0 && ret == 0)
4415 static int show_system_status(sd_bus *bus) {
4416 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4417 _cleanup_free_ char *hn = NULL;
4418 struct machine_info mi = {};
4419 const char *on, *off;
4422 hn = gethostname_malloc();
4426 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4428 return log_error_errno(r, "Failed to read server status: %m");
4430 if (streq_ptr(mi.state, "degraded")) {
4431 on = ansi_highlight_red();
4432 off = ansi_highlight_off();
4433 } else if (!streq_ptr(mi.state, "running")) {
4434 on = ansi_highlight_yellow();
4435 off = ansi_highlight_off();
4439 printf("%s%s%s %s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4441 printf(" State: %s%s%s\n",
4442 on, strna(mi.state), off);
4444 printf(" Jobs: %u queued\n", mi.n_jobs);
4445 printf(" Failed: %u units\n", mi.n_failed_units);
4447 printf(" Since: %s; %s\n",
4448 format_timestamp(since2, sizeof(since2), mi.timestamp),
4449 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4451 printf(" CGroup: %s\n", mi.control_group ?: "/");
4452 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
4454 arg_all * OUTPUT_SHOW_ALL |
4455 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
4456 on_tty() * OUTPUT_COLOR |
4457 !arg_quiet * OUTPUT_WARN_CUTOFF |
4458 arg_full * OUTPUT_FULL_WIDTH;
4460 static const char prefix[] = " ";
4464 if (c > sizeof(prefix) - 1)
4465 c -= sizeof(prefix) - 1;
4469 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
4473 free(mi.control_group);
4478 static int show(sd_bus *bus, char **args) {
4479 bool show_properties, show_status, new_line = false;
4480 bool ellipsized = false;
4486 show_properties = streq(args[0], "show");
4487 show_status = streq(args[0], "status");
4489 if (show_properties)
4490 pager_open_if_enabled();
4492 /* If no argument is specified inspect the manager itself */
4494 if (show_properties && strv_length(args) <= 1)
4495 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4497 if (show_status && strv_length(args) <= 1) {
4499 pager_open_if_enabled();
4500 show_system_status(bus);
4504 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4506 _cleanup_free_ char **patterns = NULL;
4509 STRV_FOREACH(name, args + 1) {
4510 _cleanup_free_ char *unit = NULL;
4513 if (safe_atou32(*name, &id) < 0) {
4514 if (strv_push(&patterns, *name) < 0)
4518 } else if (show_properties) {
4519 /* Interpret as job id */
4520 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4524 /* Interpret as PID */
4525 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4532 r = show_one(args[0], bus, unit, show_properties,
4533 &new_line, &ellipsized);
4536 else if (r > 0 && ret == 0)
4540 if (!strv_isempty(patterns)) {
4541 _cleanup_strv_free_ char **names = NULL;
4543 r = expand_names(bus, patterns, NULL, &names);
4545 log_error_errno(r, "Failed to expand names: %m");
4547 STRV_FOREACH(name, names) {
4548 _cleanup_free_ char *unit;
4550 unit = unit_dbus_path_from_name(*name);
4554 r = show_one(args[0], bus, unit, show_properties,
4555 &new_line, &ellipsized);
4558 else if (r > 0 && ret == 0)
4564 if (ellipsized && !arg_quiet)
4565 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4570 static int cat(sd_bus *bus, char **args) {
4571 _cleanup_strv_free_ char **names = NULL;
4579 r = expand_names(bus, args + 1, NULL, &names);
4581 log_error_errno(r, "Failed to expand names: %m");
4583 pager_open_if_enabled();
4585 STRV_FOREACH(name, names) {
4586 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4587 _cleanup_strv_free_ char **dropin_paths = NULL;
4588 _cleanup_free_ char *fragment_path = NULL, *unit = NULL;
4591 unit = unit_dbus_path_from_name(*name);
4595 if (need_daemon_reload(bus, *name) > 0)
4596 log_warning("Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'.",
4597 *name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
4599 r = sd_bus_get_property_string(
4601 "org.freedesktop.systemd1",
4603 "org.freedesktop.systemd1.Unit",
4608 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
4612 r = sd_bus_get_property_strv(
4614 "org.freedesktop.systemd1",
4616 "org.freedesktop.systemd1.Unit",
4621 log_warning("Failed to get DropInPaths: %s", bus_error_message(&error, r));
4630 if (!isempty(fragment_path)) {
4631 printf("%s# %s%s\n",
4632 ansi_highlight_blue(),
4634 ansi_highlight_off());
4637 r = copy_file_fd(fragment_path, STDOUT_FILENO);
4639 log_warning_errno(r, "Failed to cat %s: %m", fragment_path);
4644 STRV_FOREACH(path, dropin_paths) {
4645 printf("%s%s# %s%s\n",
4646 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4647 ansi_highlight_blue(),
4649 ansi_highlight_off());
4652 r = copy_file_fd(*path, STDOUT_FILENO);
4654 log_warning_errno(r, "Failed to cat %s: %m", *path);
4660 return r < 0 ? r : 0;
4663 static int set_property(sd_bus *bus, char **args) {
4664 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4665 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4666 _cleanup_free_ char *n = NULL;
4670 r = sd_bus_message_new_method_call(
4673 "org.freedesktop.systemd1",
4674 "/org/freedesktop/systemd1",
4675 "org.freedesktop.systemd1.Manager",
4676 "SetUnitProperties");
4678 return bus_log_create_error(r);
4680 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4682 return bus_log_create_error(r);
4684 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4688 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4690 return bus_log_create_error(r);
4692 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4694 return bus_log_create_error(r);
4696 STRV_FOREACH(i, args + 2) {
4697 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4699 return bus_log_create_error(r);
4701 r = bus_append_unit_property_assignment(m, *i);
4705 r = sd_bus_message_close_container(m);
4707 return bus_log_create_error(r);
4710 r = sd_bus_message_close_container(m);
4712 return bus_log_create_error(r);
4714 r = sd_bus_call(bus, m, 0, &error, NULL);
4716 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4723 static int snapshot(sd_bus *bus, char **args) {
4724 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4725 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
4726 _cleanup_free_ char *n = NULL, *id = NULL;
4730 if (strv_length(args) > 1)
4731 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4737 r = sd_bus_message_new_method_call(
4740 "org.freedesktop.systemd1",
4741 "/org/freedesktop/systemd1",
4742 "org.freedesktop.systemd1.Manager",
4745 return bus_log_create_error(r);
4747 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4749 return bus_log_create_error(r);
4751 r = sd_bus_message_append(m, "sb", n, false);
4753 return bus_log_create_error(r);
4755 r = sd_bus_call(bus, m, 0, &error, &reply);
4757 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4761 r = sd_bus_message_read(reply, "o", &path);
4763 return bus_log_parse_error(r);
4765 r = sd_bus_get_property_string(
4767 "org.freedesktop.systemd1",
4769 "org.freedesktop.systemd1.Unit",
4774 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4784 static int delete_snapshot(sd_bus *bus, char **args) {
4785 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4786 _cleanup_strv_free_ char **names = NULL;
4792 r = expand_names(bus, args + 1, ".snapshot", &names);
4794 log_error_errno(r, "Failed to expand names: %m");
4796 STRV_FOREACH(name, names) {
4797 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4800 q = sd_bus_message_new_method_call(
4803 "org.freedesktop.systemd1",
4804 "/org/freedesktop/systemd1",
4805 "org.freedesktop.systemd1.Manager",
4808 return bus_log_create_error(q);
4810 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4812 return bus_log_create_error(q);
4814 q = sd_bus_message_append(m, "s", *name);
4816 return bus_log_create_error(q);
4818 q = sd_bus_call(bus, m, 0, &error, NULL);
4820 log_error("Failed to remove snapshot %s: %s", *name, bus_error_message(&error, q));
4829 static int daemon_reload(sd_bus *bus, char **args) {
4830 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4831 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4835 if (arg_action == ACTION_RELOAD)
4837 else if (arg_action == ACTION_REEXEC)
4838 method = "Reexecute";
4840 assert(arg_action == ACTION_SYSTEMCTL);
4843 streq(args[0], "clear-jobs") ||
4844 streq(args[0], "cancel") ? "ClearJobs" :
4845 streq(args[0], "daemon-reexec") ? "Reexecute" :
4846 streq(args[0], "reset-failed") ? "ResetFailed" :
4847 streq(args[0], "halt") ? "Halt" :
4848 streq(args[0], "poweroff") ? "PowerOff" :
4849 streq(args[0], "reboot") ? "Reboot" :
4850 streq(args[0], "kexec") ? "KExec" :
4851 streq(args[0], "exit") ? "Exit" :
4852 /* "daemon-reload" */ "Reload";
4855 r = sd_bus_message_new_method_call(
4858 "org.freedesktop.systemd1",
4859 "/org/freedesktop/systemd1",
4860 "org.freedesktop.systemd1.Manager",
4863 return bus_log_create_error(r);
4865 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4867 return bus_log_create_error(r);
4869 r = sd_bus_call(bus, m, 0, &error, NULL);
4870 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4871 /* There's always a fallback possible for
4872 * legacy actions. */
4874 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4875 /* On reexecution, we expect a disconnect, not a
4879 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4881 return r < 0 ? r : 0;
4884 static int reset_failed(sd_bus *bus, char **args) {
4885 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4886 _cleanup_strv_free_ char **names = NULL;
4890 if (strv_length(args) <= 1)
4891 return daemon_reload(bus, args);
4893 r = expand_names(bus, args + 1, NULL, &names);
4895 log_error_errno(r, "Failed to expand names: %m");
4897 STRV_FOREACH(name, names) {
4898 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4900 q = sd_bus_message_new_method_call(
4903 "org.freedesktop.systemd1",
4904 "/org/freedesktop/systemd1",
4905 "org.freedesktop.systemd1.Manager",
4908 return bus_log_create_error(q);
4910 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4912 return bus_log_create_error(q);
4914 q = sd_bus_message_append(m, "s", *name);
4916 return bus_log_create_error(q);
4918 q = sd_bus_call(bus, m, 0, &error, NULL);
4920 log_error("Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q));
4929 static int show_environment(sd_bus *bus, char **args) {
4930 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4931 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4935 pager_open_if_enabled();
4937 r = sd_bus_get_property(
4939 "org.freedesktop.systemd1",
4940 "/org/freedesktop/systemd1",
4941 "org.freedesktop.systemd1.Manager",
4947 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4951 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4953 return bus_log_parse_error(r);
4955 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4958 return bus_log_parse_error(r);
4960 r = sd_bus_message_exit_container(reply);
4962 return bus_log_parse_error(r);
4967 static int switch_root(sd_bus *bus, char **args) {
4968 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4969 _cleanup_free_ char *cmdline_init = NULL;
4970 const char *root, *init;
4974 l = strv_length(args);
4975 if (l < 2 || l > 3) {
4976 log_error("Wrong number of arguments.");
4985 r = parse_env_file("/proc/cmdline", WHITESPACE,
4986 "init", &cmdline_init,
4989 log_debug_errno(r, "Failed to parse /proc/cmdline: %m");
4991 init = cmdline_init;
4998 const char *root_systemd_path = NULL, *root_init_path = NULL;
5000 root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
5001 root_init_path = strappenda(root, "/", init);
5003 /* If the passed init is actually the same as the
5004 * systemd binary, then let's suppress it. */
5005 if (files_same(root_init_path, root_systemd_path) > 0)
5009 log_debug("Switching root - root: %s; init: %s", root, strna(init));
5011 r = sd_bus_call_method(
5013 "org.freedesktop.systemd1",
5014 "/org/freedesktop/systemd1",
5015 "org.freedesktop.systemd1.Manager",
5021 log_error("Failed to switch root: %s", bus_error_message(&error, r));
5028 static int set_environment(sd_bus *bus, char **args) {
5029 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5030 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
5037 method = streq(args[0], "set-environment")
5039 : "UnsetEnvironment";
5041 r = sd_bus_message_new_method_call(
5044 "org.freedesktop.systemd1",
5045 "/org/freedesktop/systemd1",
5046 "org.freedesktop.systemd1.Manager",
5049 return bus_log_create_error(r);
5051 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5053 return bus_log_create_error(r);
5055 r = sd_bus_message_append_strv(m, args + 1);
5057 return bus_log_create_error(r);
5059 r = sd_bus_call(bus, m, 0, &error, NULL);
5061 log_error("Failed to set environment: %s", bus_error_message(&error, r));
5068 static int import_environment(sd_bus *bus, char **args) {
5069 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5070 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
5076 r = sd_bus_message_new_method_call(
5079 "org.freedesktop.systemd1",
5080 "/org/freedesktop/systemd1",
5081 "org.freedesktop.systemd1.Manager",
5084 return bus_log_create_error(r);
5086 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5088 return bus_log_create_error(r);
5090 if (strv_isempty(args + 1))
5091 r = sd_bus_message_append_strv(m, environ);
5095 r = sd_bus_message_open_container(m, 'a', "s");
5097 return bus_log_create_error(r);
5099 STRV_FOREACH(a, args + 1) {
5101 if (!env_name_is_valid(*a)) {
5102 log_error("Not a valid environment variable name: %s", *a);
5106 STRV_FOREACH(b, environ) {
5109 eq = startswith(*b, *a);
5110 if (eq && *eq == '=') {
5112 r = sd_bus_message_append(m, "s", *b);
5114 return bus_log_create_error(r);
5121 r = sd_bus_message_close_container(m);
5124 return bus_log_create_error(r);
5126 r = sd_bus_call(bus, m, 0, &error, NULL);
5128 log_error("Failed to import environment: %s", bus_error_message(&error, r));
5135 static int enable_sysv_units(const char *verb, char **args) {
5138 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
5139 unsigned f = 1, t = 1;
5140 _cleanup_lookup_paths_free_ LookupPaths paths = {};
5142 if (arg_scope != UNIT_FILE_SYSTEM)
5145 if (!streq(verb, "enable") &&
5146 !streq(verb, "disable") &&
5147 !streq(verb, "is-enabled"))
5150 /* Processes all SysV units, and reshuffles the array so that
5151 * afterwards only the native units remain */
5153 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, arg_root, NULL, NULL, NULL);
5158 for (f = 0; args[f]; f++) {
5160 _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL;
5161 bool found_native = false, found_sysv;
5163 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
5171 if (!endswith(name, ".service"))
5174 if (path_is_absolute(name))
5177 STRV_FOREACH(k, paths.unit_path) {
5178 _cleanup_free_ char *path = NULL;
5180 path = path_join(arg_root, *k, name);
5184 found_native = access(path, F_OK) >= 0;
5192 p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name);
5196 p[strlen(p) - strlen(".service")] = 0;
5197 found_sysv = access(p, F_OK) >= 0;
5201 /* Mark this entry, so that we don't try enabling it as native unit */
5202 args[f] = (char*) "";
5204 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
5206 if (!isempty(arg_root))
5207 argv[c++] = q = strappend("--root=", arg_root);
5209 argv[c++] = basename(p);
5211 streq(verb, "enable") ? "on" :
5212 streq(verb, "disable") ? "off" : "--level=5";
5215 l = strv_join((char**)argv, " ");
5219 log_info("Executing %s", l);
5223 log_error("Failed to fork: %m");
5225 } else if (pid == 0) {
5228 execv(argv[0], (char**) argv);
5229 _exit(EXIT_FAILURE);
5232 j = wait_for_terminate(pid, &status);
5234 log_error_errno(r, "Failed to wait for child: %m");
5238 if (status.si_code == CLD_EXITED) {
5239 if (streq(verb, "is-enabled")) {
5240 if (status.si_status == 0) {
5249 } else if (status.si_status != 0)
5255 /* Drop all SysV units */
5256 for (f = 0, t = 0; args[f]; f++) {
5258 if (isempty(args[f]))
5261 args[t++] = args[f];
5270 static int mangle_names(char **original_names, char ***mangled_names) {
5271 char **i, **l, **name;
5273 l = new(char*, strv_length(original_names) + 1);
5278 STRV_FOREACH(name, original_names) {
5280 /* When enabling units qualified path names are OK,
5281 * too, hence allow them explicitly. */
5286 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5302 static int enable_unit(sd_bus *bus, char **args) {
5303 _cleanup_strv_free_ char **names = NULL;
5304 const char *verb = args[0];
5305 UnitFileChange *changes = NULL;
5306 unsigned n_changes = 0;
5307 int carries_install_info = -1;
5313 r = mangle_names(args+1, &names);
5317 r = enable_sysv_units(verb, names);
5321 /* If the operation was fully executed by the SysV compat,
5322 * let's finish early */
5323 if (strv_isempty(names))
5326 if (!bus || avoid_bus()) {
5327 if (streq(verb, "enable")) {
5328 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5329 carries_install_info = r;
5330 } else if (streq(verb, "disable"))
5331 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5332 else if (streq(verb, "reenable")) {
5333 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5334 carries_install_info = r;
5335 } else if (streq(verb, "link"))
5336 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5337 else if (streq(verb, "preset")) {
5338 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_preset_mode, arg_force, &changes, &n_changes);
5339 carries_install_info = r;
5340 } else if (streq(verb, "mask"))
5341 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5342 else if (streq(verb, "unmask"))
5343 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5345 assert_not_reached("Unknown verb");
5348 log_error_errno(r, "Operation failed: %m");
5353 dump_unit_file_changes(changes, n_changes);
5357 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5358 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5359 int expect_carries_install_info = false;
5360 bool send_force = true, send_preset_mode = false;
5363 if (streq(verb, "enable")) {
5364 method = "EnableUnitFiles";
5365 expect_carries_install_info = true;
5366 } else if (streq(verb, "disable")) {
5367 method = "DisableUnitFiles";
5369 } else if (streq(verb, "reenable")) {
5370 method = "ReenableUnitFiles";
5371 expect_carries_install_info = true;
5372 } else if (streq(verb, "link"))
5373 method = "LinkUnitFiles";
5374 else if (streq(verb, "preset")) {
5376 if (arg_preset_mode != UNIT_FILE_PRESET_FULL) {
5377 method = "PresetUnitFilesWithMode";
5378 send_preset_mode = true;
5380 method = "PresetUnitFiles";
5382 expect_carries_install_info = true;
5383 } else if (streq(verb, "mask"))
5384 method = "MaskUnitFiles";
5385 else if (streq(verb, "unmask")) {
5386 method = "UnmaskUnitFiles";
5389 assert_not_reached("Unknown verb");
5391 r = sd_bus_message_new_method_call(
5394 "org.freedesktop.systemd1",
5395 "/org/freedesktop/systemd1",
5396 "org.freedesktop.systemd1.Manager",
5399 return bus_log_create_error(r);
5401 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5403 return bus_log_create_error(r);
5405 r = sd_bus_message_append_strv(m, names);
5407 return bus_log_create_error(r);
5409 if (send_preset_mode) {
5410 r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode));
5412 return bus_log_create_error(r);
5415 r = sd_bus_message_append(m, "b", arg_runtime);
5417 return bus_log_create_error(r);
5420 r = sd_bus_message_append(m, "b", arg_force);
5422 return bus_log_create_error(r);
5425 r = sd_bus_call(bus, m, 0, &error, &reply);
5427 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5431 if (expect_carries_install_info) {
5432 r = sd_bus_message_read(reply, "b", &carries_install_info);
5434 return bus_log_parse_error(r);
5437 r = deserialize_and_dump_unit_file_changes(reply);
5441 /* Try to reload if enabled */
5443 r = daemon_reload(bus, args);
5448 if (carries_install_info == 0)
5449 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5450 "using systemctl.\n"
5451 "Possible reasons for having this kind of units are:\n"
5452 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5453 " .wants/ or .requires/ directory.\n"
5454 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5455 " a requirement dependency on it.\n"
5456 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5457 " D-Bus, udev, scripted systemctl call, ...).\n");
5460 unit_file_changes_free(changes, n_changes);
5465 static int add_dependency(sd_bus *bus, char **args) {
5466 _cleanup_strv_free_ char **names = NULL;
5467 _cleanup_free_ char *target = NULL;
5468 const char *verb = args[0];
5475 target = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
5479 r = mangle_names(args+2, &names);
5483 if (streq(verb, "add-wants"))
5485 else if (streq(verb, "add-requires"))
5486 dep = UNIT_REQUIRES;
5488 assert_not_reached("Unknown verb");
5490 if (!bus || avoid_bus()) {
5491 UnitFileChange *changes = NULL;
5492 unsigned n_changes = 0;
5494 r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes);
5497 return log_error_errno(r, "Can't add dependency: %m");
5500 dump_unit_file_changes(changes, n_changes);
5502 unit_file_changes_free(changes, n_changes);
5505 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5506 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5508 r = sd_bus_message_new_method_call(
5511 "org.freedesktop.systemd1",
5512 "/org/freedesktop/systemd1",
5513 "org.freedesktop.systemd1.Manager",
5514 "AddDependencyUnitFiles");
5516 return bus_log_create_error(r);
5518 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5520 return bus_log_create_error(r);
5522 r = sd_bus_message_append_strv(m, names);
5524 return bus_log_create_error(r);
5526 r = sd_bus_message_append(m, "ssbb", target, unit_dependency_to_string(dep), arg_runtime, arg_force);
5528 return bus_log_create_error(r);
5530 r = sd_bus_call(bus, m, 0, &error, &reply);
5532 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5536 r = deserialize_and_dump_unit_file_changes(reply);
5541 r = daemon_reload(bus, args);
5549 static int preset_all(sd_bus *bus, char **args) {
5550 UnitFileChange *changes = NULL;
5551 unsigned n_changes = 0;
5554 if (!bus || avoid_bus()) {
5556 r = unit_file_preset_all(arg_scope, arg_runtime, arg_root, arg_preset_mode, arg_force, &changes, &n_changes);
5558 log_error_errno(r, "Operation failed: %m");
5563 dump_unit_file_changes(changes, n_changes);
5568 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
5569 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5571 r = sd_bus_message_new_method_call(
5574 "org.freedesktop.systemd1",
5575 "/org/freedesktop/systemd1",
5576 "org.freedesktop.systemd1.Manager",
5577 "PresetAllUnitFiles");
5579 return bus_log_create_error(r);
5581 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5583 return bus_log_create_error(r);
5585 r = sd_bus_message_append(
5588 unit_file_preset_mode_to_string(arg_preset_mode),
5592 return bus_log_create_error(r);
5594 r = sd_bus_call(bus, m, 0, &error, &reply);
5596 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5600 r = deserialize_and_dump_unit_file_changes(reply);
5605 r = daemon_reload(bus, args);
5611 unit_file_changes_free(changes, n_changes);
5616 static int unit_is_enabled(sd_bus *bus, char **args) {
5618 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5619 _cleanup_strv_free_ char **names = NULL;
5624 r = mangle_names(args+1, &names);
5628 r = enable_sysv_units(args[0], names);
5634 if (!bus || avoid_bus()) {
5636 STRV_FOREACH(name, names) {
5637 UnitFileState state;
5639 state = unit_file_get_state(arg_scope, arg_root, *name);
5641 return log_error_errno(state, "Failed to get unit file state for %s: %m", *name);
5643 if (state == UNIT_FILE_ENABLED ||
5644 state == UNIT_FILE_ENABLED_RUNTIME ||
5645 state == UNIT_FILE_STATIC ||
5646 state == UNIT_FILE_INDIRECT)
5650 puts(unit_file_state_to_string(state));
5654 STRV_FOREACH(name, names) {
5655 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5658 r = sd_bus_call_method(
5660 "org.freedesktop.systemd1",
5661 "/org/freedesktop/systemd1",
5662 "org.freedesktop.systemd1.Manager",
5668 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5672 r = sd_bus_message_read(reply, "s", &s);
5674 return bus_log_parse_error(r);
5676 if (STR_IN_SET(s, "enabled", "enabled-runtime", "static", "indirect"))
5687 static int is_system_running(sd_bus *bus, char **args) {
5688 _cleanup_free_ char *state = NULL;
5691 r = sd_bus_get_property_string(
5693 "org.freedesktop.systemd1",
5694 "/org/freedesktop/systemd1",
5695 "org.freedesktop.systemd1.Manager",
5708 return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE;
5711 static void systemctl_help(void) {
5713 pager_open_if_enabled();
5715 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
5716 "Query or send control commands to the systemd manager.\n\n"
5717 " -h --help Show this help\n"
5718 " --version Show package version\n"
5719 " --system Connect to system manager\n"
5720 " --user Connect to user service manager\n"
5721 " -H --host=[USER@]HOST\n"
5722 " Operate on remote host\n"
5723 " -M --machine=CONTAINER\n"
5724 " Operate on local container\n"
5725 " -t --type=TYPE List only units of a particular type\n"
5726 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
5727 " -p --property=NAME Show only properties by this name\n"
5728 " -a --all Show all loaded units/properties, including dead/empty\n"
5729 " ones. To list all units installed on the system, use\n"
5730 " the 'list-unit-files' command instead.\n"
5731 " -l --full Don't ellipsize unit names on output\n"
5732 " -r --recursive Show unit list of host and local containers\n"
5733 " --reverse Show reverse dependencies with 'list-dependencies'\n"
5734 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
5735 " queueing a new job\n"
5736 " --show-types When showing sockets, explicitly show their type\n"
5737 " -i --ignore-inhibitors\n"
5738 " When shutting down or sleeping, ignore inhibitors\n"
5739 " --kill-who=WHO Who to send signal to\n"
5740 " -s --signal=SIGNAL Which signal to send\n"
5741 " -q --quiet Suppress output\n"
5742 " --no-block Do not wait until operation finished\n"
5743 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5744 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
5746 " --no-legend Do not print a legend (column headers and hints)\n"
5747 " --no-pager Do not pipe output into a pager\n"
5748 " --no-ask-password\n"
5749 " Do not ask for system passwords\n"
5750 " --global Enable/disable unit files globally\n"
5751 " --runtime Enable unit files only temporarily until next reboot\n"
5752 " -f --force When enabling unit files, override existing symlinks\n"
5753 " When shutting down, execute action immediately\n"
5754 " --preset-mode= Specifies whether fully apply presets, or only enable,\n"
5755 " or only disable\n"
5756 " --root=PATH Enable unit files in the specified root directory\n"
5757 " -n --lines=INTEGER Number of journal entries to show\n"
5758 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
5759 " verbose, export, json, json-pretty, json-sse, cat)\n"
5760 " --plain Print unit dependencies as a list instead of a tree\n\n"
5762 " list-units [PATTERN...] List loaded units\n"
5763 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
5764 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
5765 " start NAME... Start (activate) one or more units\n"
5766 " stop NAME... Stop (deactivate) one or more units\n"
5767 " reload NAME... Reload one or more units\n"
5768 " restart NAME... Start or restart one or more units\n"
5769 " try-restart NAME... Restart one or more units if active\n"
5770 " reload-or-restart NAME... Reload one or more units if possible,\n"
5771 " otherwise start or restart\n"
5772 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
5773 " otherwise restart if active\n"
5774 " isolate NAME Start one unit and stop all others\n"
5775 " kill NAME... Send signal to processes of a unit\n"
5776 " is-active PATTERN... Check whether units are active\n"
5777 " is-failed PATTERN... Check whether units are failed\n"
5778 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
5779 " show [PATTERN...|JOB...] Show properties of one or more\n"
5780 " units/jobs or the manager\n"
5781 " cat PATTERN... Show files and drop-ins of one or more units\n"
5782 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
5783 " help PATTERN...|PID... Show manual for one or more units\n"
5784 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
5786 " list-dependencies [NAME] Recursively show units which are required\n"
5787 " or wanted by this unit or by which this\n"
5788 " unit is required or wanted\n\n"
5789 "Unit File Commands:\n"
5790 " list-unit-files [PATTERN...] List installed unit files\n"
5791 " enable NAME... Enable one or more unit files\n"
5792 " disable NAME... Disable one or more unit files\n"
5793 " reenable NAME... Reenable one or more unit files\n"
5794 " preset NAME... Enable/disable one or more unit files\n"
5795 " based on preset configuration\n"
5796 " preset-all Enable/disable all unit files based on\n"
5797 " preset configuration\n"
5798 " is-enabled NAME... Check whether unit files are enabled\n\n"
5799 " mask NAME... Mask one or more units\n"
5800 " unmask NAME... Unmask one or more units\n"
5801 " link PATH... Link one or more units files into\n"
5802 " the search path\n"
5803 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
5804 " on specified one or more units\n"
5805 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
5806 " on specified one or more units\n"
5807 " get-default Get the name of the default target\n"
5808 " set-default NAME Set the default target\n\n"
5809 "Machine Commands:\n"
5810 " list-machines [PATTERN...] List local containers and host\n\n"
5812 " list-jobs [PATTERN...] List jobs\n"
5813 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
5814 "Snapshot Commands:\n"
5815 " snapshot [NAME] Create a snapshot\n"
5816 " delete NAME... Remove one or more snapshots\n\n"
5817 "Environment Commands:\n"
5818 " show-environment Dump environment\n"
5819 " set-environment NAME=VALUE... Set one or more environment variables\n"
5820 " unset-environment NAME... Unset one or more environment variables\n"
5821 " import-environment NAME... Import all, one or more environment variables\n\n"
5822 "Manager Lifecycle Commands:\n"
5823 " daemon-reload Reload systemd manager configuration\n"
5824 " daemon-reexec Reexecute systemd manager\n\n"
5825 "System Commands:\n"
5826 " is-system-running Check whether system is fully running\n"
5827 " default Enter system default mode\n"
5828 " rescue Enter system rescue mode\n"
5829 " emergency Enter system emergency mode\n"
5830 " halt Shut down and halt the system\n"
5831 " poweroff Shut down and power-off the system\n"
5832 " reboot [ARG] Shut down and reboot the system\n"
5833 " kexec Shut down and reboot the system with kexec\n"
5834 " exit Request user instance exit\n"
5835 " switch-root ROOT [INIT] Change to a different root file system\n"
5836 " suspend Suspend the system\n"
5837 " hibernate Hibernate the system\n"
5838 " hybrid-sleep Hibernate and suspend the system\n",
5839 program_invocation_short_name);
5842 static void halt_help(void) {
5843 printf("%s [OPTIONS...]%s\n\n"
5844 "%s the system.\n\n"
5845 " --help Show this help\n"
5846 " --halt Halt the machine\n"
5847 " -p --poweroff Switch off the machine\n"
5848 " --reboot Reboot the machine\n"
5849 " -f --force Force immediate halt/power-off/reboot\n"
5850 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
5851 " -d --no-wtmp Don't write wtmp record\n"
5852 " --no-wall Don't send wall message before halt/power-off/reboot\n",
5853 program_invocation_short_name,
5854 arg_action == ACTION_REBOOT ? " [ARG]" : "",
5855 arg_action == ACTION_REBOOT ? "Reboot" :
5856 arg_action == ACTION_POWEROFF ? "Power off" :
5860 static void shutdown_help(void) {
5861 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
5862 "Shut down the system.\n\n"
5863 " --help Show this help\n"
5864 " -H --halt Halt the machine\n"
5865 " -P --poweroff Power-off the machine\n"
5866 " -r --reboot Reboot the machine\n"
5867 " -h Equivalent to --poweroff, overridden by --halt\n"
5868 " -k Don't halt/power-off/reboot, just send warnings\n"
5869 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5870 " -c Cancel a pending shutdown\n",
5871 program_invocation_short_name);
5874 static void telinit_help(void) {
5875 printf("%s [OPTIONS...] {COMMAND}\n\n"
5876 "Send control commands to the init daemon.\n\n"
5877 " --help Show this help\n"
5878 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
5880 " 0 Power-off the machine\n"
5881 " 6 Reboot the machine\n"
5882 " 2, 3, 4, 5 Start runlevelX.target unit\n"
5883 " 1, s, S Enter rescue mode\n"
5884 " q, Q Reload init daemon configuration\n"
5885 " u, U Reexecute init daemon\n",
5886 program_invocation_short_name);
5889 static void runlevel_help(void) {
5890 printf("%s [OPTIONS...]\n\n"
5891 "Prints the previous and current runlevel of the init system.\n\n"
5892 " --help Show this help\n",
5893 program_invocation_short_name);
5896 static void help_types(void) {
5901 puts("Available unit types:");
5902 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
5903 t = unit_type_to_string(i);
5909 static int systemctl_parse_argv(int argc, char *argv[]) {
5918 ARG_IGNORE_DEPENDENCIES,
5930 ARG_NO_ASK_PASSWORD,
5940 static const struct option options[] = {
5941 { "help", no_argument, NULL, 'h' },
5942 { "version", no_argument, NULL, ARG_VERSION },
5943 { "type", required_argument, NULL, 't' },
5944 { "property", required_argument, NULL, 'p' },
5945 { "all", no_argument, NULL, 'a' },
5946 { "reverse", no_argument, NULL, ARG_REVERSE },
5947 { "after", no_argument, NULL, ARG_AFTER },
5948 { "before", no_argument, NULL, ARG_BEFORE },
5949 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
5950 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
5951 { "full", no_argument, NULL, 'l' },
5952 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
5953 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
5954 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
5955 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
5956 { "ignore-inhibitors", no_argument, NULL, 'i' },
5957 { "user", no_argument, NULL, ARG_USER },
5958 { "system", no_argument, NULL, ARG_SYSTEM },
5959 { "global", no_argument, NULL, ARG_GLOBAL },
5960 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
5961 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
5962 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
5963 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5964 { "quiet", no_argument, NULL, 'q' },
5965 { "root", required_argument, NULL, ARG_ROOT },
5966 { "force", no_argument, NULL, ARG_FORCE },
5967 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
5968 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
5969 { "signal", required_argument, NULL, 's' },
5970 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
5971 { "host", required_argument, NULL, 'H' },
5972 { "machine", required_argument, NULL, 'M' },
5973 { "runtime", no_argument, NULL, ARG_RUNTIME },
5974 { "lines", required_argument, NULL, 'n' },
5975 { "output", required_argument, NULL, 'o' },
5976 { "plain", no_argument, NULL, ARG_PLAIN },
5977 { "state", required_argument, NULL, ARG_STATE },
5978 { "recursive", no_argument, NULL, 'r' },
5979 { "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
5988 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
5997 puts(PACKAGE_STRING);
5998 puts(SYSTEMD_FEATURES);
6002 const char *word, *state;
6005 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6006 _cleanup_free_ char *type;
6008 type = strndup(word, size);
6012 if (streq(type, "help")) {
6017 if (unit_type_from_string(type) >= 0) {
6018 if (strv_push(&arg_types, type))
6024 /* It's much nicer to use --state= for
6025 * load states, but let's support this
6026 * in --types= too for compatibility
6027 * with old versions */
6028 if (unit_load_state_from_string(optarg) >= 0) {
6029 if (strv_push(&arg_states, type) < 0)
6035 log_error("Unknown unit type or load state '%s'.", type);
6036 log_info("Use -t help to see a list of allowed values.");
6044 /* Make sure that if the empty property list
6045 was specified, we won't show any properties. */
6046 if (isempty(optarg) && !arg_properties) {
6047 arg_properties = new0(char*, 1);
6048 if (!arg_properties)
6051 const char *word, *state;
6054 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6057 prop = strndup(word, size);
6061 if (strv_consume(&arg_properties, prop) < 0)
6066 /* If the user asked for a particular
6067 * property, show it to him, even if it is
6079 arg_dependency = DEPENDENCY_REVERSE;
6083 arg_dependency = DEPENDENCY_AFTER;
6087 arg_dependency = DEPENDENCY_BEFORE;
6090 case ARG_SHOW_TYPES:
6091 arg_show_types = true;
6095 arg_job_mode = optarg;
6099 arg_job_mode = "fail";
6102 case ARG_IRREVERSIBLE:
6103 arg_job_mode = "replace-irreversibly";
6106 case ARG_IGNORE_DEPENDENCIES:
6107 arg_job_mode = "ignore-dependencies";
6111 arg_scope = UNIT_FILE_USER;
6115 arg_scope = UNIT_FILE_SYSTEM;
6119 arg_scope = UNIT_FILE_GLOBAL;
6123 arg_no_block = true;
6127 arg_no_legend = true;
6131 arg_no_pager = true;
6147 if (strv_extend(&arg_states, "failed") < 0)
6165 arg_no_reload = true;
6169 arg_kill_who = optarg;
6173 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
6174 log_error("Failed to parse signal string %s.", optarg);
6179 case ARG_NO_ASK_PASSWORD:
6180 arg_ask_password = false;
6184 arg_transport = BUS_TRANSPORT_REMOTE;
6189 arg_transport = BUS_TRANSPORT_CONTAINER;
6198 if (safe_atou(optarg, &arg_lines) < 0) {
6199 log_error("Failed to parse lines '%s'", optarg);
6205 arg_output = output_mode_from_string(optarg);
6206 if (arg_output < 0) {
6207 log_error("Unknown output '%s'.", optarg);
6213 arg_ignore_inhibitors = true;
6221 const char *word, *state;
6224 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6227 s = strndup(word, size);
6231 if (strv_consume(&arg_states, s) < 0)
6238 if (geteuid() != 0) {
6239 log_error("--recursive requires root privileges.");
6243 arg_recursive = true;
6246 case ARG_PRESET_MODE:
6248 arg_preset_mode = unit_file_preset_mode_from_string(optarg);
6249 if (arg_preset_mode < 0) {
6250 log_error("Failed to parse preset mode: %s.", optarg);
6260 assert_not_reached("Unhandled option");
6263 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
6264 log_error("Cannot access user instance remotely.");
6271 static int halt_parse_argv(int argc, char *argv[]) {
6280 static const struct option options[] = {
6281 { "help", no_argument, NULL, ARG_HELP },
6282 { "halt", no_argument, NULL, ARG_HALT },
6283 { "poweroff", no_argument, NULL, 'p' },
6284 { "reboot", no_argument, NULL, ARG_REBOOT },
6285 { "force", no_argument, NULL, 'f' },
6286 { "wtmp-only", no_argument, NULL, 'w' },
6287 { "no-wtmp", no_argument, NULL, 'd' },
6288 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6297 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
6298 if (runlevel == '0' || runlevel == '6')
6301 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
6309 arg_action = ACTION_HALT;
6313 if (arg_action != ACTION_REBOOT)
6314 arg_action = ACTION_POWEROFF;
6318 arg_action = ACTION_REBOOT;
6340 /* Compatibility nops */
6347 assert_not_reached("Unhandled option");
6350 if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
6351 r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL);
6354 } else if (optind < argc) {
6355 log_error("Too many arguments.");
6362 static int parse_time_spec(const char *t, usec_t *_u) {
6366 if (streq(t, "now"))
6368 else if (!strchr(t, ':')) {
6371 if (safe_atou64(t, &u) < 0)
6374 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
6383 hour = strtol(t, &e, 10);
6384 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
6387 minute = strtol(e+1, &e, 10);
6388 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
6391 n = now(CLOCK_REALTIME);
6392 s = (time_t) (n / USEC_PER_SEC);
6394 assert_se(localtime_r(&s, &tm));
6396 tm.tm_hour = (int) hour;
6397 tm.tm_min = (int) minute;
6400 assert_se(s = mktime(&tm));
6402 *_u = (usec_t) s * USEC_PER_SEC;
6405 *_u += USEC_PER_DAY;
6411 static int shutdown_parse_argv(int argc, char *argv[]) {
6418 static const struct option options[] = {
6419 { "help", no_argument, NULL, ARG_HELP },
6420 { "halt", no_argument, NULL, 'H' },
6421 { "poweroff", no_argument, NULL, 'P' },
6422 { "reboot", no_argument, NULL, 'r' },
6423 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
6424 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6433 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0)
6441 arg_action = ACTION_HALT;
6445 arg_action = ACTION_POWEROFF;
6450 arg_action = ACTION_KEXEC;
6452 arg_action = ACTION_REBOOT;
6456 arg_action = ACTION_KEXEC;
6460 if (arg_action != ACTION_HALT)
6461 arg_action = ACTION_POWEROFF;
6474 /* Compatibility nops */
6478 arg_action = ACTION_CANCEL_SHUTDOWN;
6485 assert_not_reached("Unhandled option");
6488 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
6489 r = parse_time_spec(argv[optind], &arg_when);
6491 log_error("Failed to parse time specification: %s", argv[optind]);
6495 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
6497 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
6498 /* No time argument for shutdown cancel */
6499 arg_wall = argv + optind;
6500 else if (argc > optind + 1)
6501 /* We skip the time argument */
6502 arg_wall = argv + optind + 1;
6509 static int telinit_parse_argv(int argc, char *argv[]) {
6516 static const struct option options[] = {
6517 { "help", no_argument, NULL, ARG_HELP },
6518 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6522 static const struct {
6526 { '0', ACTION_POWEROFF },
6527 { '6', ACTION_REBOOT },
6528 { '1', ACTION_RESCUE },
6529 { '2', ACTION_RUNLEVEL2 },
6530 { '3', ACTION_RUNLEVEL3 },
6531 { '4', ACTION_RUNLEVEL4 },
6532 { '5', ACTION_RUNLEVEL5 },
6533 { 's', ACTION_RESCUE },
6534 { 'S', ACTION_RESCUE },
6535 { 'q', ACTION_RELOAD },
6536 { 'Q', ACTION_RELOAD },
6537 { 'u', ACTION_REEXEC },
6538 { 'U', ACTION_REEXEC }
6547 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6562 assert_not_reached("Unhandled option");
6565 if (optind >= argc) {
6566 log_error("%s: required argument missing.",
6567 program_invocation_short_name);
6571 if (optind + 1 < argc) {
6572 log_error("Too many arguments.");
6576 if (strlen(argv[optind]) != 1) {
6577 log_error("Expected single character argument.");
6581 for (i = 0; i < ELEMENTSOF(table); i++)
6582 if (table[i].from == argv[optind][0])
6585 if (i >= ELEMENTSOF(table)) {
6586 log_error("Unknown command '%s'.", argv[optind]);
6590 arg_action = table[i].to;
6597 static int runlevel_parse_argv(int argc, char *argv[]) {
6603 static const struct option options[] = {
6604 { "help", no_argument, NULL, ARG_HELP },
6613 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6624 assert_not_reached("Unhandled option");
6627 if (optind < argc) {
6628 log_error("Too many arguments.");
6635 static int parse_argv(int argc, char *argv[]) {
6639 if (program_invocation_short_name) {
6641 if (strstr(program_invocation_short_name, "halt")) {
6642 arg_action = ACTION_HALT;
6643 return halt_parse_argv(argc, argv);
6644 } else if (strstr(program_invocation_short_name, "poweroff")) {
6645 arg_action = ACTION_POWEROFF;
6646 return halt_parse_argv(argc, argv);
6647 } else if (strstr(program_invocation_short_name, "reboot")) {
6649 arg_action = ACTION_KEXEC;
6651 arg_action = ACTION_REBOOT;
6652 return halt_parse_argv(argc, argv);
6653 } else if (strstr(program_invocation_short_name, "shutdown")) {
6654 arg_action = ACTION_POWEROFF;
6655 return shutdown_parse_argv(argc, argv);
6656 } else if (strstr(program_invocation_short_name, "init")) {
6658 if (sd_booted() > 0) {
6659 arg_action = _ACTION_INVALID;
6660 return telinit_parse_argv(argc, argv);
6662 /* Hmm, so some other init system is
6663 * running, we need to forward this
6664 * request to it. For now we simply
6665 * guess that it is Upstart. */
6667 execv(TELINIT, argv);
6669 log_error("Couldn't find an alternative telinit implementation to spawn.");
6673 } else if (strstr(program_invocation_short_name, "runlevel")) {
6674 arg_action = ACTION_RUNLEVEL;
6675 return runlevel_parse_argv(argc, argv);
6679 arg_action = ACTION_SYSTEMCTL;
6680 return systemctl_parse_argv(argc, argv);
6683 _pure_ static int action_to_runlevel(void) {
6685 static const char table[_ACTION_MAX] = {
6686 [ACTION_HALT] = '0',
6687 [ACTION_POWEROFF] = '0',
6688 [ACTION_REBOOT] = '6',
6689 [ACTION_RUNLEVEL2] = '2',
6690 [ACTION_RUNLEVEL3] = '3',
6691 [ACTION_RUNLEVEL4] = '4',
6692 [ACTION_RUNLEVEL5] = '5',
6693 [ACTION_RESCUE] = '1'
6696 assert(arg_action < _ACTION_MAX);
6698 return table[arg_action];
6701 static int talk_initctl(void) {
6703 struct init_request request = {
6704 .magic = INIT_MAGIC,
6706 .cmd = INIT_CMD_RUNLVL
6709 _cleanup_close_ int fd = -1;
6713 rl = action_to_runlevel();
6717 request.runlevel = rl;
6719 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
6721 if (errno == ENOENT)
6724 log_error("Failed to open "INIT_FIFO": %m");
6729 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
6731 log_error("Failed to write to "INIT_FIFO": %m");
6732 return errno > 0 ? -errno : -EIO;
6738 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
6740 static const struct {
6748 int (* const dispatch)(sd_bus *bus, char **args);
6754 { "list-units", MORE, 0, list_units },
6755 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
6756 { "list-sockets", MORE, 1, list_sockets },
6757 { "list-timers", MORE, 1, list_timers },
6758 { "list-jobs", MORE, 1, list_jobs },
6759 { "list-machines", MORE, 1, list_machines },
6760 { "clear-jobs", EQUAL, 1, daemon_reload },
6761 { "cancel", MORE, 2, cancel_job },
6762 { "start", MORE, 2, start_unit },
6763 { "stop", MORE, 2, start_unit },
6764 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6765 { "reload", MORE, 2, start_unit },
6766 { "restart", MORE, 2, start_unit },
6767 { "try-restart", MORE, 2, start_unit },
6768 { "reload-or-restart", MORE, 2, start_unit },
6769 { "reload-or-try-restart", MORE, 2, start_unit },
6770 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
6771 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6772 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
6773 { "isolate", EQUAL, 2, start_unit },
6774 { "kill", MORE, 2, kill_unit },
6775 { "is-active", MORE, 2, check_unit_active },
6776 { "check", MORE, 2, check_unit_active },
6777 { "is-failed", MORE, 2, check_unit_failed },
6778 { "show", MORE, 1, show },
6779 { "cat", MORE, 2, cat },
6780 { "status", MORE, 1, show },
6781 { "help", MORE, 2, show },
6782 { "snapshot", LESS, 2, snapshot },
6783 { "delete", MORE, 2, delete_snapshot },
6784 { "daemon-reload", EQUAL, 1, daemon_reload },
6785 { "daemon-reexec", EQUAL, 1, daemon_reload },
6786 { "show-environment", EQUAL, 1, show_environment },
6787 { "set-environment", MORE, 2, set_environment },
6788 { "unset-environment", MORE, 2, set_environment },
6789 { "import-environment", MORE, 1, import_environment},
6790 { "halt", EQUAL, 1, start_special, FORCE },
6791 { "poweroff", EQUAL, 1, start_special, FORCE },
6792 { "reboot", EQUAL, 1, start_special, FORCE },
6793 { "kexec", EQUAL, 1, start_special },
6794 { "suspend", EQUAL, 1, start_special },
6795 { "hibernate", EQUAL, 1, start_special },
6796 { "hybrid-sleep", EQUAL, 1, start_special },
6797 { "default", EQUAL, 1, start_special },
6798 { "rescue", EQUAL, 1, start_special },
6799 { "emergency", EQUAL, 1, start_special },
6800 { "exit", EQUAL, 1, start_special },
6801 { "reset-failed", MORE, 1, reset_failed },
6802 { "enable", MORE, 2, enable_unit, NOBUS },
6803 { "disable", MORE, 2, enable_unit, NOBUS },
6804 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
6805 { "reenable", MORE, 2, enable_unit, NOBUS },
6806 { "preset", MORE, 2, enable_unit, NOBUS },
6807 { "preset-all", EQUAL, 1, preset_all, NOBUS },
6808 { "mask", MORE, 2, enable_unit, NOBUS },
6809 { "unmask", MORE, 2, enable_unit, NOBUS },
6810 { "link", MORE, 2, enable_unit, NOBUS },
6811 { "switch-root", MORE, 2, switch_root },
6812 { "list-dependencies", LESS, 2, list_dependencies },
6813 { "set-default", EQUAL, 2, set_default, NOBUS },
6814 { "get-default", EQUAL, 1, get_default, NOBUS },
6815 { "set-property", MORE, 3, set_property },
6816 { "is-system-running", EQUAL, 1, is_system_running },
6817 { "add-wants", MORE, 3, add_dependency, NOBUS },
6818 { "add-requires", MORE, 3, add_dependency, NOBUS },
6827 left = argc - optind;
6829 /* Special rule: no arguments (left == 0) means "list-units" */
6831 if (streq(argv[optind], "help") && !argv[optind+1]) {
6832 log_error("This command expects one or more "
6833 "unit names. Did you mean --help?");
6837 for (; verb->verb; verb++)
6838 if (streq(argv[optind], verb->verb))
6841 log_error("Unknown operation '%s'.", argv[optind]);
6846 switch (verb->argc_cmp) {
6849 if (left != verb->argc) {
6850 log_error("Invalid number of arguments.");
6857 if (left < verb->argc) {
6858 log_error("Too few arguments.");
6865 if (left > verb->argc) {
6866 log_error("Too many arguments.");
6873 assert_not_reached("Unknown comparison operator.");
6876 /* Require a bus connection for all operations but
6878 if (verb->bus == NOBUS) {
6879 if (!bus && !avoid_bus()) {
6880 log_error_errno(bus_error, "Failed to get D-Bus connection: %m");
6885 if (running_in_chroot() > 0) {
6886 log_info("Running in chroot, ignoring request.");
6890 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
6891 log_error_errno(bus_error, "Failed to get D-Bus connection: %m");
6896 return verb->dispatch(bus, argv + optind);
6899 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
6901 struct sd_shutdown_command c = {
6908 union sockaddr_union sockaddr = {
6909 .un.sun_family = AF_UNIX,
6910 .un.sun_path = "/run/systemd/shutdownd",
6913 struct iovec iovec[2] = {{
6914 .iov_base = (char*) &c,
6915 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
6918 struct msghdr msghdr = {
6919 .msg_name = &sockaddr,
6920 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
6921 + strlen("/run/systemd/shutdownd"),
6926 _cleanup_close_ int fd;
6928 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
6932 if (!isempty(message)) {
6933 iovec[1].iov_base = (char*) message;
6934 iovec[1].iov_len = strlen(message);
6935 msghdr.msg_iovlen++;
6938 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
6944 static int reload_with_fallback(sd_bus *bus) {
6947 /* First, try systemd via D-Bus. */
6948 if (daemon_reload(bus, NULL) >= 0)
6952 /* Nothing else worked, so let's try signals */
6953 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
6955 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
6956 log_error("kill() failed: %m");
6963 static int start_with_fallback(sd_bus *bus) {
6966 /* First, try systemd via D-Bus. */
6967 if (start_unit(bus, NULL) >= 0)
6971 /* Nothing else worked, so let's try
6973 if (talk_initctl() > 0)
6976 log_error("Failed to talk to init daemon.");
6980 warn_wall(arg_action);
6984 static int halt_now(enum action a) {
6986 /* The kernel will automaticall flush ATA disks and suchlike
6987 * on reboot(), but the file systems need to be synce'd
6988 * explicitly in advance. */
6991 /* Make sure C-A-D is handled by the kernel from this point
6993 reboot(RB_ENABLE_CAD);
6998 log_info("Halting.");
6999 reboot(RB_HALT_SYSTEM);
7002 case ACTION_POWEROFF:
7003 log_info("Powering off.");
7004 reboot(RB_POWER_OFF);
7007 case ACTION_REBOOT: {
7008 _cleanup_free_ char *param = NULL;
7010 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
7011 log_info("Rebooting with argument '%s'.", param);
7012 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
7013 LINUX_REBOOT_CMD_RESTART2, param);
7016 log_info("Rebooting.");
7017 reboot(RB_AUTOBOOT);
7022 assert_not_reached("Unknown action.");
7026 static int halt_main(sd_bus *bus) {
7029 r = check_inhibitors(bus, arg_action);
7033 if (geteuid() != 0) {
7034 /* Try logind if we are a normal user and no special
7035 * mode applies. Maybe PolicyKit allows us to shutdown
7038 if (arg_when <= 0 &&
7041 (arg_action == ACTION_POWEROFF ||
7042 arg_action == ACTION_REBOOT)) {
7043 r = reboot_with_logind(bus, arg_action);
7048 log_error("Must be root.");
7053 _cleanup_free_ char *m;
7055 m = strv_join(arg_wall, " ");
7059 r = send_shutdownd(arg_when,
7060 arg_action == ACTION_HALT ? 'H' :
7061 arg_action == ACTION_POWEROFF ? 'P' :
7062 arg_action == ACTION_KEXEC ? 'K' :
7069 log_warning_errno(r, "Failed to talk to shutdownd, proceeding with immediate shutdown: %m");
7071 char date[FORMAT_TIMESTAMP_MAX];
7073 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
7074 format_timestamp(date, sizeof(date), arg_when));
7079 if (!arg_dry && !arg_force)
7080 return start_with_fallback(bus);
7083 if (sd_booted() > 0)
7084 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7086 r = utmp_put_shutdown();
7088 log_warning_errno(r, "Failed to write utmp record: %m");
7095 r = halt_now(arg_action);
7096 log_error_errno(r, "Failed to reboot: %m");
7101 static int runlevel_main(void) {
7102 int r, runlevel, previous;
7104 r = utmp_get_runlevel(&runlevel, &previous);
7111 previous <= 0 ? 'N' : previous,
7112 runlevel <= 0 ? 'N' : runlevel);
7117 int main(int argc, char*argv[]) {
7118 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
7121 setlocale(LC_ALL, "");
7122 log_parse_environment();
7125 /* Explicitly not on_tty() to avoid setting cached value.
7126 * This becomes relevant for piping output which might be
7128 original_stdout_is_tty = isatty(STDOUT_FILENO);
7130 r = parse_argv(argc, argv);
7134 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
7135 * let's shortcut this */
7136 if (arg_action == ACTION_RUNLEVEL) {
7137 r = runlevel_main();
7141 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
7142 log_info("Running in chroot, ignoring request.");
7148 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
7150 /* systemctl_main() will print an error message for the bus
7151 * connection, but only if it needs to */
7153 switch (arg_action) {
7155 case ACTION_SYSTEMCTL:
7156 r = systemctl_main(bus, argc, argv, r);
7160 case ACTION_POWEROFF:
7166 case ACTION_RUNLEVEL2:
7167 case ACTION_RUNLEVEL3:
7168 case ACTION_RUNLEVEL4:
7169 case ACTION_RUNLEVEL5:
7171 case ACTION_EMERGENCY:
7172 case ACTION_DEFAULT:
7173 r = start_with_fallback(bus);
7178 r = reload_with_fallback(bus);
7181 case ACTION_CANCEL_SHUTDOWN: {
7182 _cleanup_free_ char *m = NULL;
7185 m = strv_join(arg_wall, " ");
7192 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
7194 log_warning_errno(r, "Failed to talk to shutdownd, shutdown hasn't been cancelled: %m");
7198 case ACTION_RUNLEVEL:
7199 case _ACTION_INVALID:
7201 assert_not_reached("Unknown action");
7206 ask_password_agent_close();
7207 polkit_agent_close();
7209 strv_free(arg_types);
7210 strv_free(arg_states);
7211 strv_free(arg_properties);
7213 return r < 0 ? EXIT_FAILURE : r;