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"
72 #include "bus-message.h"
73 #include "bus-error.h"
74 #include "bus-errors.h"
76 static char **arg_types = NULL;
77 static char **arg_states = NULL;
78 static char **arg_properties = NULL;
79 static bool arg_all = false;
80 static enum dependency {
86 } arg_dependency = DEPENDENCY_FORWARD;
87 static const char *arg_job_mode = "replace";
88 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
89 static bool arg_no_block = false;
90 static bool arg_no_legend = false;
91 static bool arg_no_pager = false;
92 static bool arg_no_wtmp = false;
93 static bool arg_no_wall = false;
94 static bool arg_no_reload = false;
95 static bool arg_show_types = false;
96 static bool arg_ignore_inhibitors = false;
97 static bool arg_dry = false;
98 static bool arg_quiet = false;
99 static bool arg_full = false;
100 static bool arg_recursive = false;
101 static int arg_force = 0;
102 static bool arg_ask_password = true;
103 static bool arg_runtime = false;
104 static char **arg_wall = NULL;
105 static const char *arg_kill_who = NULL;
106 static int arg_signal = SIGTERM;
107 static const char *arg_root = NULL;
108 static usec_t arg_when = 0;
130 ACTION_CANCEL_SHUTDOWN,
132 } arg_action = ACTION_SYSTEMCTL;
133 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
134 static char *arg_host = NULL;
135 static unsigned arg_lines = 10;
136 static OutputMode arg_output = OUTPUT_SHORT;
137 static bool arg_plain = false;
139 static const struct {
143 { "start", "StartUnit" },
144 { "stop", "StopUnit" },
145 { "condstop", "StopUnit" },
146 { "reload", "ReloadUnit" },
147 { "restart", "RestartUnit" },
148 { "try-restart", "TryRestartUnit" },
149 { "condrestart", "TryRestartUnit" },
150 { "reload-or-restart", "ReloadOrRestartUnit" },
151 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
152 { "condreload", "ReloadOrTryRestartUnit" },
153 { "force-reload", "ReloadOrTryRestartUnit" }
156 static bool original_stdout_is_tty;
158 static int daemon_reload(sd_bus *bus, char **args);
159 static int halt_now(enum action a);
160 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet);
162 static char** strv_skip_first(char **strv) {
163 if (strv_length(strv) > 0)
168 static void pager_open_if_enabled(void) {
176 static void ask_password_agent_open_if_enabled(void) {
178 /* Open the password agent as a child process if necessary */
180 if (!arg_ask_password)
183 if (arg_scope != UNIT_FILE_SYSTEM)
186 if (arg_transport != BUS_TRANSPORT_LOCAL)
189 ask_password_agent_open();
193 static void polkit_agent_open_if_enabled(void) {
195 /* Open the polkit agent as a child process if necessary */
197 if (!arg_ask_password)
200 if (arg_scope != UNIT_FILE_SYSTEM)
203 if (arg_transport != BUS_TRANSPORT_LOCAL)
210 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
213 if (!sd_bus_error_is_set(error))
216 if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) ||
217 sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
218 sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
219 sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
220 return EXIT_NOPERMISSION;
222 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
223 return EXIT_NOTINSTALLED;
225 if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
226 sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED))
227 return EXIT_NOTIMPLEMENTED;
229 if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
230 return EXIT_NOTCONFIGURED;
238 static void warn_wall(enum action a) {
239 static const char *table[_ACTION_MAX] = {
240 [ACTION_HALT] = "The system is going down for system halt NOW!",
241 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
242 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
243 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
244 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
245 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
246 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
253 _cleanup_free_ char *p;
255 p = strv_join(arg_wall, " ");
262 utmp_wall(p, NULL, NULL);
270 utmp_wall(table[a], NULL, NULL);
273 static bool avoid_bus(void) {
275 if (running_in_chroot() > 0)
278 if (sd_booted() <= 0)
281 if (!isempty(arg_root))
284 if (arg_scope == UNIT_FILE_GLOBAL)
290 static int compare_unit_info(const void *a, const void *b) {
291 const UnitInfo *u = a, *v = b;
295 /* First, order by machine */
296 if (!u->machine && v->machine)
298 if (u->machine && !v->machine)
300 if (u->machine && v->machine) {
301 r = strcasecmp(u->machine, v->machine);
306 /* Second, order by unit type */
307 d1 = strrchr(u->id, '.');
308 d2 = strrchr(v->id, '.');
310 r = strcasecmp(d1, d2);
315 /* Third, order by name */
316 return strcasecmp(u->id, v->id);
319 static bool output_show_unit(const UnitInfo *u, char **patterns) {
322 if (!strv_isempty(arg_states))
324 strv_contains(arg_states, u->load_state) ||
325 strv_contains(arg_states, u->sub_state) ||
326 strv_contains(arg_states, u->active_state);
328 if (!strv_isempty(patterns)) {
331 STRV_FOREACH(pattern, patterns)
332 if (fnmatch(*pattern, u->id, FNM_NOESCAPE) == 0)
337 return (!arg_types || ((dot = strrchr(u->id, '.')) &&
338 strv_find(arg_types, dot+1))) &&
339 (arg_all || !(streq(u->active_state, "inactive")
340 || u->following[0]) || u->job_id > 0);
343 static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
344 unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
346 unsigned n_shown = 0;
349 max_id_len = strlen("UNIT");
350 load_len = strlen("LOAD");
351 active_len = strlen("ACTIVE");
352 sub_len = strlen("SUB");
353 job_len = strlen("JOB");
356 for (u = unit_infos; u < unit_infos + c; u++) {
357 max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0));
358 load_len = MAX(load_len, strlen(u->load_state));
359 active_len = MAX(active_len, strlen(u->active_state));
360 sub_len = MAX(sub_len, strlen(u->sub_state));
362 if (u->job_id != 0) {
363 job_len = MAX(job_len, strlen(u->job_type));
367 if (!arg_no_legend &&
368 (streq(u->active_state, "failed") ||
369 STR_IN_SET(u->load_state, "error", "not-found", "masked")))
373 if (!arg_full && original_stdout_is_tty) {
376 id_len = MIN(max_id_len, 25u);
377 basic_len = circle_len + 5 + id_len + 5 + active_len + sub_len;
380 basic_len += job_len + 1;
382 if (basic_len < (unsigned) columns()) {
383 unsigned extra_len, incr;
384 extra_len = columns() - basic_len;
386 /* Either UNIT already got 25, or is fully satisfied.
387 * Grant up to 25 to DESC now. */
388 incr = MIN(extra_len, 25u);
392 /* split the remaining space between UNIT and DESC,
393 * but do not give UNIT more than it needs. */
395 incr = MIN(extra_len / 2, max_id_len - id_len);
397 desc_len += extra_len - incr;
403 for (u = unit_infos; u < unit_infos + c; u++) {
404 _cleanup_free_ char *e = NULL, *j = NULL;
405 const char *on_loaded = "", *off_loaded = "";
406 const char *on_active = "", *off_active = "";
407 const char *on_circle = "", *off_circle = "";
411 if (!n_shown && !arg_no_legend) {
416 printf("%-*s %-*s %-*s %-*s ",
419 active_len, "ACTIVE",
423 printf("%-*s ", job_len, "JOB");
425 if (!arg_full && arg_no_pager)
426 printf("%.*s\n", desc_len, "DESCRIPTION");
428 printf("%s\n", "DESCRIPTION");
433 if (STR_IN_SET(u->load_state, "error", "not-found", "masked")) {
434 on_loaded = ansi_highlight_red();
435 on_circle = ansi_highlight_yellow();
436 off_loaded = off_circle = ansi_highlight_off();
440 if (streq(u->active_state, "failed")) {
441 on_circle = on_active = ansi_highlight_red();
442 off_circle = off_active = ansi_highlight_off();
447 j = strjoin(u->machine, ":", u->id, NULL);
456 e = ellipsize(id, id_len, 33);
464 printf("%s%s%s", on_circle, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_circle);
466 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
467 on_active, id_len, id, off_active,
468 on_loaded, load_len, u->load_state, off_loaded,
469 on_active, active_len, u->active_state,
470 sub_len, u->sub_state, off_active,
471 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
474 printf("%.*s\n", desc_len, u->description);
476 printf("%s\n", u->description);
479 if (!arg_no_legend) {
480 const char *on, *off;
484 "LOAD = Reflects whether the unit definition was properly loaded.\n"
485 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
486 "SUB = The low-level unit activation state, values depend on unit type.");
487 puts(job_count ? "JOB = Pending job for the unit.\n" : "");
488 on = ansi_highlight();
489 off = ansi_highlight_off();
491 on = ansi_highlight_red();
492 off = ansi_highlight_off();
496 printf("%s%u loaded units listed.%s\n"
497 "To show all installed unit files use 'systemctl list-unit-files'.\n",
500 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
501 "To show all installed unit files use 'systemctl list-unit-files'.\n",
508 static int get_unit_list(
512 UnitInfo **unit_infos,
514 sd_bus_message **_reply) {
516 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
517 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
526 r = sd_bus_call_method(
528 "org.freedesktop.systemd1",
529 "/org/freedesktop/systemd1",
530 "org.freedesktop.systemd1.Manager",
536 log_error("Failed to list units: %s", bus_error_message(&error, r));
540 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
542 return bus_log_parse_error(r);
544 while ((r = bus_parse_unit_info(reply, &u)) > 0) {
547 if (!output_show_unit(&u, patterns))
550 if (!GREEDY_REALLOC(*unit_infos, size, c+1))
553 (*unit_infos)[c++] = u;
556 return bus_log_parse_error(r);
558 r = sd_bus_message_exit_container(reply);
560 return bus_log_parse_error(r);
568 static void message_set_freep(Set **set) {
571 while ((m = set_steal_first(*set)))
572 sd_bus_message_unref(m);
577 static int get_unit_list_recursive(
580 UnitInfo **_unit_infos,
584 _cleanup_free_ UnitInfo *unit_infos = NULL;
585 _cleanup_(message_set_freep) Set *replies;
586 sd_bus_message *reply;
594 replies = set_new(NULL, NULL);
598 c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
602 r = set_put(replies, reply);
604 sd_bus_message_unref(reply);
609 _cleanup_strv_free_ char **machines = NULL;
612 r = sd_get_machine_names(&machines);
616 STRV_FOREACH(i, machines) {
617 _cleanup_bus_unref_ sd_bus *container = NULL;
620 r = sd_bus_open_system_container(&container, *i);
622 log_error("Failed to connect to container %s: %s", *i, strerror(-r));
626 k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
632 r = set_put(replies, reply);
634 sd_bus_message_unref(reply);
639 *_machines = machines;
644 *_unit_infos = unit_infos;
653 static int list_units(sd_bus *bus, char **args) {
654 _cleanup_free_ UnitInfo *unit_infos = NULL;
655 _cleanup_(message_set_freep) Set *replies = NULL;
656 _cleanup_strv_free_ char **machines = NULL;
659 pager_open_if_enabled();
661 r = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
665 qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
666 return output_units_list(unit_infos, r);
669 static int get_triggered_units(
674 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
677 r = sd_bus_get_property_strv(
679 "org.freedesktop.systemd1",
681 "org.freedesktop.systemd1.Unit",
687 log_error("Failed to determine triggers: %s", bus_error_message(&error, r));
692 static int get_listening(
694 const char* unit_path,
697 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
698 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
699 const char *type, *path;
702 r = sd_bus_get_property(
704 "org.freedesktop.systemd1",
706 "org.freedesktop.systemd1.Socket",
712 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r));
716 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
718 return bus_log_parse_error(r);
720 while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
722 r = strv_extend(listening, type);
726 r = strv_extend(listening, path);
733 return bus_log_parse_error(r);
735 r = sd_bus_message_exit_container(reply);
737 return bus_log_parse_error(r);
749 /* Note: triggered is a list here, although it almost certainly
750 * will always be one unit. Nevertheless, dbus API allows for multiple
751 * values, so let's follow that.*/
754 /* The strv above is shared. free is set only in the first one. */
758 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
764 if (!a->machine && b->machine)
766 if (a->machine && !b->machine)
768 if (a->machine && b->machine) {
769 o = strcasecmp(a->machine, b->machine);
774 o = strcmp(a->path, b->path);
776 o = strcmp(a->type, b->type);
781 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
782 struct socket_info *s;
783 unsigned pathlen = strlen("LISTEN"),
784 typelen = strlen("TYPE") * arg_show_types,
785 socklen = strlen("UNIT"),
786 servlen = strlen("ACTIVATES");
787 const char *on, *off;
789 for (s = socket_infos; s < socket_infos + cs; s++) {
793 socklen = MAX(socklen, strlen(s->id));
795 typelen = MAX(typelen, strlen(s->type));
796 pathlen = MAX(pathlen, strlen(s->path) + (s->machine ? strlen(s->machine)+1 : 0));
798 STRV_FOREACH(a, s->triggered)
799 tmp += strlen(*a) + 2*(a != s->triggered);
800 servlen = MAX(servlen, tmp);
805 printf("%-*s %-*.*s%-*s %s\n",
807 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
811 for (s = socket_infos; s < socket_infos + cs; s++) {
812 _cleanup_free_ char *j = NULL;
817 j = strjoin(s->machine, ":", s->path, NULL);
825 printf("%-*s %-*s %-*s",
826 pathlen, path, typelen, s->type, socklen, s->id);
829 pathlen, path, socklen, s->id);
830 STRV_FOREACH(a, s->triggered)
832 a == s->triggered ? "" : ",", *a);
836 on = ansi_highlight();
837 off = ansi_highlight_off();
841 on = ansi_highlight_red();
842 off = ansi_highlight_off();
845 if (!arg_no_legend) {
846 printf("%s%u sockets listed.%s\n", on, cs, off);
848 printf("Pass --all to see loaded but inactive sockets, too.\n");
854 static int list_sockets(sd_bus *bus, char **args) {
855 _cleanup_(message_set_freep) Set *replies = NULL;
856 _cleanup_strv_free_ char **machines = NULL;
857 _cleanup_free_ UnitInfo *unit_infos = NULL;
858 _cleanup_free_ struct socket_info *socket_infos = NULL;
860 struct socket_info *s;
865 pager_open_if_enabled();
867 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
871 for (u = unit_infos; u < unit_infos + n; u++) {
872 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
875 if (!endswith(u->id, ".socket"))
878 r = get_triggered_units(bus, u->unit_path, &triggered);
882 c = get_listening(bus, u->unit_path, &listening);
888 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
893 for (i = 0; i < c; i++)
894 socket_infos[cs + i] = (struct socket_info) {
895 .machine = u->machine,
897 .type = listening[i*2],
898 .path = listening[i*2 + 1],
899 .triggered = triggered,
900 .own_triggered = i==0,
903 /* from this point on we will cleanup those socket_infos */
906 listening = triggered = NULL; /* avoid cleanup */
909 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
910 (__compar_fn_t) socket_info_compare);
912 output_sockets_list(socket_infos, cs);
915 assert(cs == 0 || socket_infos);
916 for (s = socket_infos; s < socket_infos + cs; s++) {
919 if (s->own_triggered)
920 strv_free(s->triggered);
926 static int get_next_elapse(
929 dual_timestamp *next) {
931 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
939 r = sd_bus_get_property_trivial(
941 "org.freedesktop.systemd1",
943 "org.freedesktop.systemd1.Timer",
944 "NextElapseUSecMonotonic",
949 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
953 r = sd_bus_get_property_trivial(
955 "org.freedesktop.systemd1",
957 "org.freedesktop.systemd1.Timer",
958 "NextElapseUSecRealtime",
963 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
971 static int get_last_trigger(
976 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
983 r = sd_bus_get_property_trivial(
985 "org.freedesktop.systemd1",
987 "org.freedesktop.systemd1.Timer",
993 log_error("Failed to get last trigger time: %s", bus_error_message(&error, r));
1001 const char* machine;
1004 usec_t last_trigger;
1008 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
1014 if (!a->machine && b->machine)
1016 if (a->machine && !b->machine)
1018 if (a->machine && b->machine) {
1019 o = strcasecmp(a->machine, b->machine);
1024 if (a->next_elapse < b->next_elapse)
1026 if (a->next_elapse > b->next_elapse)
1029 return strcmp(a->id, b->id);
1032 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
1033 struct timer_info *t;
1035 nextlen = strlen("NEXT"),
1036 leftlen = strlen("LEFT"),
1037 lastlen = strlen("LAST"),
1038 passedlen = strlen("PASSED"),
1039 unitlen = strlen("UNIT"),
1040 activatelen = strlen("ACTIVATES");
1042 const char *on, *off;
1044 assert(timer_infos || n == 0);
1046 for (t = timer_infos; t < timer_infos + n; t++) {
1050 if (t->next_elapse > 0) {
1051 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1053 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
1054 nextlen = MAX(nextlen, strlen(tstamp) + 1);
1056 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
1057 leftlen = MAX(leftlen, strlen(trel));
1060 if (t->last_trigger > 0) {
1061 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1063 format_timestamp(tstamp, sizeof(tstamp), t->last_trigger);
1064 lastlen = MAX(lastlen, strlen(tstamp) + 1);
1066 format_timestamp_relative(trel, sizeof(trel), t->last_trigger);
1067 passedlen = MAX(passedlen, strlen(trel));
1070 unitlen = MAX(unitlen, strlen(t->id) + (t->machine ? strlen(t->machine)+1 : 0));
1072 STRV_FOREACH(a, t->triggered)
1073 ul += strlen(*a) + 2*(a != t->triggered);
1075 activatelen = MAX(activatelen, ul);
1080 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1084 passedlen, "PASSED",
1088 for (t = timer_infos; t < timer_infos + n; t++) {
1089 _cleanup_free_ char *j = NULL;
1091 char tstamp1[FORMAT_TIMESTAMP_MAX] = "n/a", trel1[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1092 char tstamp2[FORMAT_TIMESTAMP_MAX] = "n/a", trel2[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1095 format_timestamp(tstamp1, sizeof(tstamp1), t->next_elapse);
1096 format_timestamp_relative(trel1, sizeof(trel1), t->next_elapse);
1098 format_timestamp(tstamp2, sizeof(tstamp2), t->last_trigger);
1099 format_timestamp_relative(trel2, sizeof(trel2), t->last_trigger);
1102 j = strjoin(t->machine, ":", t->id, NULL);
1109 printf("%-*s %-*s %-*s %-*s %-*s",
1110 nextlen, tstamp1, leftlen, trel1, lastlen, tstamp2, passedlen, trel2, unitlen, unit);
1112 STRV_FOREACH(a, t->triggered)
1114 a == t->triggered ? "" : ",", *a);
1118 on = ansi_highlight();
1119 off = ansi_highlight_off();
1123 on = ansi_highlight_red();
1124 off = ansi_highlight_off();
1127 if (!arg_no_legend) {
1128 printf("%s%u timers listed.%s\n", on, n, off);
1130 printf("Pass --all to see loaded but inactive timers, too.\n");
1136 static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
1142 if (next->monotonic != (usec_t) -1 && next->monotonic > 0) {
1145 if (next->monotonic > nw->monotonic)
1146 converted = nw->realtime + (next->monotonic - nw->monotonic);
1148 converted = nw->realtime - (nw->monotonic - next->monotonic);
1150 if (next->realtime != (usec_t) -1 && next->realtime > 0)
1151 next_elapse = MIN(converted, next->realtime);
1153 next_elapse = converted;
1156 next_elapse = next->realtime;
1161 static int list_timers(sd_bus *bus, char **args) {
1162 _cleanup_(message_set_freep) Set *replies = NULL;
1163 _cleanup_strv_free_ char **machines = NULL;
1164 _cleanup_free_ struct timer_info *timer_infos = NULL;
1165 _cleanup_free_ UnitInfo *unit_infos = NULL;
1166 struct timer_info *t;
1173 pager_open_if_enabled();
1175 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
1179 dual_timestamp_get(&nw);
1181 for (u = unit_infos; u < unit_infos + n; u++) {
1182 _cleanup_strv_free_ char **triggered = NULL;
1183 dual_timestamp next = {};
1186 if (!endswith(u->id, ".timer"))
1189 r = get_triggered_units(bus, u->unit_path, &triggered);
1193 r = get_next_elapse(bus, u->unit_path, &next);
1197 get_last_trigger(bus, u->unit_path, &last);
1199 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
1204 m = calc_next_elapse(&nw, &next);
1206 timer_infos[c++] = (struct timer_info) {
1207 .machine = u->machine,
1210 .last_trigger = last,
1211 .triggered = triggered,
1214 triggered = NULL; /* avoid cleanup */
1217 qsort_safe(timer_infos, c, sizeof(struct timer_info),
1218 (__compar_fn_t) timer_info_compare);
1220 output_timers_list(timer_infos, c);
1223 for (t = timer_infos; t < timer_infos + c; t++)
1224 strv_free(t->triggered);
1229 static int compare_unit_file_list(const void *a, const void *b) {
1230 const char *d1, *d2;
1231 const UnitFileList *u = a, *v = b;
1233 d1 = strrchr(u->path, '.');
1234 d2 = strrchr(v->path, '.');
1239 r = strcasecmp(d1, d2);
1244 return strcasecmp(basename(u->path), basename(v->path));
1247 static bool output_show_unit_file(const UnitFileList *u, char **patterns) {
1250 if (!strv_isempty(patterns)) {
1253 STRV_FOREACH(pattern, patterns)
1254 if (fnmatch(*pattern, basename(u->path), FNM_NOESCAPE) == 0)
1259 return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
1262 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
1263 unsigned max_id_len, id_cols, state_cols;
1264 const UnitFileList *u;
1266 max_id_len = strlen("UNIT FILE");
1267 state_cols = strlen("STATE");
1269 for (u = units; u < units + c; u++) {
1270 max_id_len = MAX(max_id_len, strlen(basename(u->path)));
1271 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1275 unsigned basic_cols;
1277 id_cols = MIN(max_id_len, 25u);
1278 basic_cols = 1 + id_cols + state_cols;
1279 if (basic_cols < (unsigned) columns())
1280 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1282 id_cols = max_id_len;
1285 printf("%-*s %-*s\n",
1286 id_cols, "UNIT FILE",
1287 state_cols, "STATE");
1289 for (u = units; u < units + c; u++) {
1290 _cleanup_free_ char *e = NULL;
1291 const char *on, *off;
1294 if (u->state == UNIT_FILE_MASKED ||
1295 u->state == UNIT_FILE_MASKED_RUNTIME ||
1296 u->state == UNIT_FILE_DISABLED ||
1297 u->state == UNIT_FILE_INVALID) {
1298 on = ansi_highlight_red();
1299 off = ansi_highlight_off();
1300 } else if (u->state == UNIT_FILE_ENABLED) {
1301 on = ansi_highlight_green();
1302 off = ansi_highlight_off();
1306 id = basename(u->path);
1308 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1310 printf("%-*s %s%-*s%s\n",
1311 id_cols, e ? e : id,
1312 on, state_cols, unit_file_state_to_string(u->state), off);
1316 printf("\n%u unit files listed.\n", c);
1319 static int list_unit_files(sd_bus *bus, char **args) {
1320 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1321 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1322 _cleanup_free_ UnitFileList *units = NULL;
1330 pager_open_if_enabled();
1338 h = hashmap_new(string_hash_func, string_compare_func);
1342 r = unit_file_get_list(arg_scope, arg_root, h);
1344 unit_file_list_free(h);
1345 log_error("Failed to get unit file list: %s", strerror(-r));
1349 n_units = hashmap_size(h);
1350 units = new(UnitFileList, n_units);
1352 unit_file_list_free(h);
1356 HASHMAP_FOREACH(u, h, i) {
1357 if (!output_show_unit_file(u, strv_skip_first(args)))
1364 assert(c <= n_units);
1367 r = sd_bus_call_method(
1369 "org.freedesktop.systemd1",
1370 "/org/freedesktop/systemd1",
1371 "org.freedesktop.systemd1.Manager",
1377 log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1381 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1383 return bus_log_parse_error(r);
1385 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1387 if (!GREEDY_REALLOC(units, size, c + 1))
1390 units[c] = (struct UnitFileList) {
1392 unit_file_state_from_string(state)
1395 if (output_show_unit_file(&units[c], strv_skip_first(args)))
1400 return bus_log_parse_error(r);
1402 r = sd_bus_message_exit_container(reply);
1404 return bus_log_parse_error(r);
1408 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
1409 output_unit_file_list(units, c);
1413 for (unit = units; unit < units + c; unit++)
1419 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1420 _cleanup_free_ char *n = NULL;
1421 size_t max_len = MAX(columns(),20u);
1427 for (i = level - 1; i >= 0; i--) {
1429 if (len > max_len - 3 && !arg_full) {
1430 printf("%s...\n",max_len % 2 ? "" : " ");
1433 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
1437 if (len > max_len - 3 && !arg_full) {
1438 printf("%s...\n",max_len % 2 ? "" : " ");
1442 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
1446 printf("%s\n", name);
1450 n = ellipsize(name, max_len-len, 100);
1458 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1460 static const char *dependencies[_DEPENDENCY_MAX] = {
1461 [DEPENDENCY_FORWARD] = "Requires\0"
1462 "RequiresOverridable\0"
1464 "RequisiteOverridable\0"
1466 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1467 "RequiredByOverridable\0"
1470 [DEPENDENCY_AFTER] = "After\0",
1471 [DEPENDENCY_BEFORE] = "Before\0",
1474 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1475 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1476 _cleanup_strv_free_ char **ret = NULL;
1477 _cleanup_free_ char *path = NULL;
1483 assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
1485 path = unit_dbus_path_from_name(name);
1489 r = sd_bus_call_method(
1491 "org.freedesktop.systemd1",
1493 "org.freedesktop.DBus.Properties",
1497 "s", "org.freedesktop.systemd1.Unit");
1499 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1503 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1505 return bus_log_parse_error(r);
1507 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1510 r = sd_bus_message_read(reply, "s", &prop);
1512 return bus_log_parse_error(r);
1514 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1515 r = sd_bus_message_skip(reply, "v");
1517 return bus_log_parse_error(r);
1520 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1522 return bus_log_parse_error(r);
1524 r = bus_message_read_strv_extend(reply, &ret);
1526 return bus_log_parse_error(r);
1528 r = sd_bus_message_exit_container(reply);
1530 return bus_log_parse_error(r);
1533 r = sd_bus_message_exit_container(reply);
1535 return bus_log_parse_error(r);
1539 return bus_log_parse_error(r);
1541 r = sd_bus_message_exit_container(reply);
1543 return bus_log_parse_error(r);
1551 static int list_dependencies_compare(const void *_a, const void *_b) {
1552 const char **a = (const char**) _a, **b = (const char**) _b;
1554 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1556 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1559 return strcasecmp(*a, *b);
1562 static int list_dependencies_one(
1567 unsigned int branches) {
1569 _cleanup_strv_free_ char **deps = NULL;
1577 r = strv_extend(units, name);
1581 r = list_dependencies_get_dependencies(bus, name, &deps);
1585 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1587 STRV_FOREACH(c, deps) {
1590 if (strv_contains(*units, *c)) {
1592 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1599 state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true);
1601 printf("%s%s%s", ansi_highlight_green(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1603 printf("%s%s%s", ansi_highlight_red(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1605 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1609 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1610 r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1617 strv_remove(*units, name);
1622 static int list_dependencies(sd_bus *bus, char **args) {
1623 _cleanup_strv_free_ char **units = NULL;
1624 _cleanup_free_ char *unit = NULL;
1630 unit = unit_name_mangle(args[1], MANGLE_NOGLOB);
1635 u = SPECIAL_DEFAULT_TARGET;
1637 pager_open_if_enabled();
1641 return list_dependencies_one(bus, u, 0, &units, 0);
1644 struct machine_info {
1648 char *control_group;
1649 uint32_t n_failed_units;
1654 static const struct bus_properties_map machine_info_property_map[] = {
1655 { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
1656 { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
1657 { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
1658 { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
1659 { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
1663 static void free_machines_list(struct machine_info *machine_infos, int n) {
1669 for (i = 0; i < n; i++) {
1670 free(machine_infos[i].name);
1671 free(machine_infos[i].state);
1672 free(machine_infos[i].control_group);
1675 free(machine_infos);
1678 static int compare_machine_info(const void *a, const void *b) {
1679 const struct machine_info *u = a, *v = b;
1681 if (u->is_host != v->is_host)
1682 return u->is_host > v->is_host ? -1 : 1;
1684 return strcasecmp(u->name, v->name);
1687 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1688 _cleanup_bus_unref_ sd_bus *container = NULL;
1694 r = sd_bus_open_system_container(&container, mi->name);
1701 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi);
1708 static bool output_show_machine(const char *name, char **patterns) {
1713 if (strv_isempty(patterns))
1716 STRV_FOREACH(i, patterns)
1717 if (fnmatch(*i, name, FNM_NOESCAPE) == 0)
1723 static int get_machine_list(
1725 struct machine_info **_machine_infos,
1728 struct machine_info *machine_infos = NULL;
1729 _cleanup_strv_free_ char **m = NULL;
1730 _cleanup_free_ char *hn = NULL;
1735 hn = gethostname_malloc();
1739 if (output_show_machine(hn, patterns)) {
1740 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1743 machine_infos[c].is_host = true;
1744 machine_infos[c].name = hn;
1747 get_machine_properties(bus, &machine_infos[c]);
1751 sd_get_machine_names(&m);
1752 STRV_FOREACH(i, m) {
1753 _cleanup_free_ char *class = NULL;
1755 if (!output_show_machine(*i, patterns))
1758 sd_machine_get_class(*i, &class);
1759 if (!streq_ptr(class, "container"))
1762 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1763 free_machines_list(machine_infos, c);
1767 machine_infos[c].is_host = false;
1768 machine_infos[c].name = strdup(*i);
1769 if (!machine_infos[c].name) {
1770 free_machines_list(machine_infos, c);
1774 get_machine_properties(NULL, &machine_infos[c]);
1778 *_machine_infos = machine_infos;
1782 static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1783 struct machine_info *m;
1786 namelen = sizeof("NAME") - 1,
1787 statelen = sizeof("STATE") - 1,
1788 failedlen = sizeof("FAILED") - 1,
1789 jobslen = sizeof("JOBS") - 1;
1791 assert(machine_infos || n == 0);
1793 for (m = machine_infos; m < machine_infos + n; m++) {
1794 namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
1795 statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
1796 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
1797 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
1799 if (!arg_no_legend && !streq_ptr(m->state, "running"))
1803 if (!arg_no_legend) {
1807 printf("%-*s %-*s %-*s %-*s\n",
1810 failedlen, "FAILED",
1814 for (m = machine_infos; m < machine_infos + n; m++) {
1815 const char *on_state = "", *off_state = "";
1816 const char *on_failed = "", *off_failed = "";
1817 bool circle = false;
1819 if (streq_ptr(m->state, "degraded")) {
1820 on_state = ansi_highlight_red();
1821 off_state = ansi_highlight_off();
1823 } else if (!streq_ptr(m->state, "running")) {
1824 on_state = ansi_highlight_yellow();
1825 off_state = ansi_highlight_off();
1829 if (m->n_failed_units > 0) {
1830 on_failed = ansi_highlight_red();
1831 off_failed = ansi_highlight_off();
1833 on_failed = off_failed = "";
1836 printf("%s%s%s", on_state, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_state);
1839 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1840 (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
1841 on_state, statelen, strna(m->state), off_state,
1842 on_failed, failedlen, m->n_failed_units, off_failed,
1843 jobslen, m->n_jobs);
1845 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1846 namelen, strna(m->name),
1847 on_state, statelen, strna(m->state), off_state,
1848 on_failed, failedlen, m->n_failed_units, off_failed,
1849 jobslen, m->n_jobs);
1853 printf("\n%u machines listed.\n", n);
1856 static int list_machines(sd_bus *bus, char **args) {
1857 struct machine_info *machine_infos = NULL;
1862 if (geteuid() != 0) {
1863 log_error("Must be root.");
1867 pager_open_if_enabled();
1869 r = get_machine_list(bus, &machine_infos, strv_skip_first(args));
1873 qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
1874 output_machines_list(machine_infos, r);
1875 free_machines_list(machine_infos, r);
1880 static int get_default(sd_bus *bus, char **args) {
1881 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1882 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1883 _cleanup_free_ char *_path = NULL;
1887 if (!bus || avoid_bus()) {
1888 r = unit_file_get_default(arg_scope, arg_root, &_path);
1890 log_error("Failed to get default target: %s", strerror(-r));
1896 r = sd_bus_call_method(
1898 "org.freedesktop.systemd1",
1899 "/org/freedesktop/systemd1",
1900 "org.freedesktop.systemd1.Manager",
1906 log_error("Failed to get default target: %s", bus_error_message(&error, -r));
1910 r = sd_bus_message_read(reply, "s", &path);
1912 return bus_log_parse_error(r);
1916 printf("%s\n", path);
1921 static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) {
1924 assert(changes || n_changes == 0);
1926 for (i = 0; i < n_changes; i++) {
1927 if (changes[i].type == UNIT_FILE_SYMLINK)
1928 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
1930 log_info("rm '%s'", changes[i].path);
1934 static int deserialize_and_dump_unit_file_changes(sd_bus_message *m) {
1935 const char *type, *path, *source;
1938 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1940 return bus_log_parse_error(r);
1942 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1944 if (streq(type, "symlink"))
1945 log_info("ln -s '%s' '%s'", source, path);
1947 log_info("rm '%s'", path);
1951 return bus_log_parse_error(r);
1953 r = sd_bus_message_exit_container(m);
1955 return bus_log_parse_error(r);
1960 static int set_default(sd_bus *bus, char **args) {
1961 _cleanup_free_ char *unit = NULL;
1962 UnitFileChange *changes = NULL;
1963 unsigned n_changes = 0;
1966 unit = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
1970 if (!bus || avoid_bus()) {
1971 r = unit_file_set_default(arg_scope, arg_root, unit, arg_force, &changes, &n_changes);
1973 log_error("Failed to set default target: %s", strerror(-r));
1978 dump_unit_file_changes(changes, n_changes);
1982 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1983 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1985 r = sd_bus_call_method(
1987 "org.freedesktop.systemd1",
1988 "/org/freedesktop/systemd1",
1989 "org.freedesktop.systemd1.Manager",
1993 "sb", unit, arg_force);
1995 log_error("Failed to set default target: %s", bus_error_message(&error, -r));
1999 r = deserialize_and_dump_unit_file_changes(reply);
2003 /* Try to reload if enabled */
2005 r = daemon_reload(bus, args);
2010 unit_file_changes_free(changes, n_changes);
2017 const char *name, *type, *state;
2020 static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
2021 unsigned id_len, unit_len, type_len, state_len;
2022 const struct job_info *j;
2023 const char *on, *off;
2024 bool shorten = false;
2026 assert(n == 0 || jobs);
2029 on = ansi_highlight_green();
2030 off = ansi_highlight_off();
2032 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
2036 pager_open_if_enabled();
2038 id_len = strlen("JOB");
2039 unit_len = strlen("UNIT");
2040 type_len = strlen("TYPE");
2041 state_len = strlen("STATE");
2043 for (j = jobs; j < jobs + n; j++) {
2044 uint32_t id = j->id;
2045 assert(j->name && j->type && j->state);
2047 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
2048 unit_len = MAX(unit_len, strlen(j->name));
2049 type_len = MAX(type_len, strlen(j->type));
2050 state_len = MAX(state_len, strlen(j->state));
2053 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
2054 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
2059 printf("%*s %-*s %-*s %-*s\n",
2063 state_len, "STATE");
2065 for (j = jobs; j < jobs + n; j++) {
2066 _cleanup_free_ char *e = NULL;
2068 if (streq(j->state, "running")) {
2069 on = ansi_highlight();
2070 off = ansi_highlight_off();
2074 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
2075 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2077 on, unit_len, e ? e : j->name, off,
2079 on, state_len, j->state, off);
2082 if (!arg_no_legend) {
2083 on = ansi_highlight();
2084 off = ansi_highlight_off();
2086 printf("\n%s%u jobs listed%s.\n", on, n, off);
2090 static bool output_show_job(struct job_info *job, char **patterns) {
2095 if (strv_isempty(patterns))
2098 STRV_FOREACH(pattern, patterns)
2099 if (fnmatch(*pattern, job->name, FNM_NOESCAPE) == 0)
2104 static int list_jobs(sd_bus *bus, char **args) {
2105 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2106 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2107 const char *name, *type, *state, *job_path, *unit_path;
2108 _cleanup_free_ struct job_info *jobs = NULL;
2113 bool skipped = false;
2115 r = sd_bus_call_method(
2117 "org.freedesktop.systemd1",
2118 "/org/freedesktop/systemd1",
2119 "org.freedesktop.systemd1.Manager",
2125 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
2129 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2131 return bus_log_parse_error(r);
2133 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
2134 struct job_info job = { id, name, type, state };
2136 if (!output_show_job(&job, strv_skip_first(args))) {
2141 if (!GREEDY_REALLOC(jobs, size, c + 1))
2147 return bus_log_parse_error(r);
2149 r = sd_bus_message_exit_container(reply);
2151 return bus_log_parse_error(r);
2153 output_jobs_list(jobs, c, skipped);
2157 static int cancel_job(sd_bus *bus, char **args) {
2158 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2163 if (strv_length(args) <= 1)
2164 return daemon_reload(bus, args);
2166 STRV_FOREACH(name, args+1) {
2170 r = safe_atou32(*name, &id);
2172 log_error("Failed to parse job id \"%s\": %s", *name, strerror(-r));
2176 r = sd_bus_call_method(
2178 "org.freedesktop.systemd1",
2179 "/org/freedesktop/systemd1",
2180 "org.freedesktop.systemd1.Manager",
2186 log_error("Failed to cancel job %u: %s", (unsigned) id, bus_error_message(&error, r));
2194 static int need_daemon_reload(sd_bus *bus, const char *unit) {
2195 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2199 /* We ignore all errors here, since this is used to show a
2202 /* We don't use unit_dbus_path_from_name() directly since we
2203 * don't want to load the unit if it isn't loaded. */
2205 r = sd_bus_call_method(
2207 "org.freedesktop.systemd1",
2208 "/org/freedesktop/systemd1",
2209 "org.freedesktop.systemd1.Manager",
2217 r = sd_bus_message_read(reply, "o", &path);
2221 r = sd_bus_get_property_trivial(
2223 "org.freedesktop.systemd1",
2225 "org.freedesktop.systemd1.Unit",
2235 typedef struct WaitData {
2242 static int wait_filter(sd_bus *bus, sd_bus_message *m, void *data, sd_bus_error *error) {
2249 log_debug("Got D-Bus request: %s.%s() on %s",
2250 sd_bus_message_get_interface(m),
2251 sd_bus_message_get_member(m),
2252 sd_bus_message_get_path(m));
2254 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
2255 log_error("Warning! D-Bus connection terminated.");
2257 } else if (sd_bus_message_is_signal(m, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
2259 const char *path, *result, *unit;
2263 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
2265 ret = set_remove(d->set, (char*) path);
2271 if (!isempty(result))
2272 d->result = strdup(result);
2275 d->name = strdup(unit);
2280 r = sd_bus_message_read(m, "uos", &id, &path, &result);
2282 ret = set_remove(d->set, (char*) path);
2289 d->result = strdup(result);
2295 bus_log_parse_error(r);
2301 static int enable_wait_for_jobs(sd_bus *bus) {
2306 r = sd_bus_add_match(
2309 "sender='org.freedesktop.systemd1',"
2310 "interface='org.freedesktop.systemd1.Manager',"
2311 "member='JobRemoved',"
2312 "path='/org/freedesktop/systemd1'",
2315 log_error("Failed to add match");
2319 /* This is slightly dirty, since we don't undo the match registrations. */
2323 static int bus_process_wait(sd_bus *bus) {
2327 r = sd_bus_process(bus, NULL);
2332 r = sd_bus_wait(bus, (uint64_t) -1);
2338 static int check_wait_response(WaitData *d) {
2344 if (streq(d->result, "timeout"))
2345 log_error("Job for %s timed out.", strna(d->name));
2346 else if (streq(d->result, "canceled"))
2347 log_error("Job for %s canceled.", strna(d->name));
2348 else if (streq(d->result, "dependency"))
2349 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d->name));
2350 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2351 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d->name), strna(d->name));
2354 if (streq(d->result, "timeout"))
2356 else if (streq(d->result, "canceled"))
2358 else if (streq(d->result, "dependency"))
2360 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2366 static int wait_for_jobs(sd_bus *bus, Set *s) {
2367 WaitData d = { .set = s };
2373 q = sd_bus_add_filter(bus, wait_filter, &d);
2377 while (!set_isempty(s)) {
2378 q = bus_process_wait(bus);
2380 log_error("Failed to wait for response: %s", strerror(-r));
2385 q = check_wait_response(&d);
2386 /* Return the first error as it is most likely to be
2388 if (q < 0 && r == 0)
2390 log_debug("Got result %s/%s for job %s",
2391 strna(d.result), strerror(-q), strna(d.name));
2401 q = sd_bus_remove_filter(bus, wait_filter, &d);
2402 if (q < 0 && r == 0)
2408 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2409 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2410 _cleanup_free_ char *n = NULL, *state = NULL;
2416 n = unit_name_mangle(name, MANGLE_NOGLOB);
2420 /* We don't use unit_dbus_path_from_name() directly since we
2421 * don't want to load the unit if it isn't loaded. */
2423 r = sd_bus_call_method(
2425 "org.freedesktop.systemd1",
2426 "/org/freedesktop/systemd1",
2427 "org.freedesktop.systemd1.Manager",
2438 r = sd_bus_message_read(reply, "o", &path);
2440 return bus_log_parse_error(r);
2442 r = sd_bus_get_property_string(
2444 "org.freedesktop.systemd1",
2446 "org.freedesktop.systemd1.Unit",
2459 return nulstr_contains(good_states, state);
2462 static int check_triggering_units(
2466 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2467 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2468 _cleanup_strv_free_ char **triggered_by = NULL;
2469 bool print_warning_label = true;
2473 n = unit_name_mangle(name, MANGLE_NOGLOB);
2477 path = unit_dbus_path_from_name(n);
2481 r = sd_bus_get_property_string(
2483 "org.freedesktop.systemd1",
2485 "org.freedesktop.systemd1.Unit",
2490 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2494 if (streq(state, "masked"))
2497 r = sd_bus_get_property_strv(
2499 "org.freedesktop.systemd1",
2501 "org.freedesktop.systemd1.Unit",
2506 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2510 STRV_FOREACH(i, triggered_by) {
2511 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2513 log_error("Failed to check unit: %s", strerror(-r));
2520 if (print_warning_label) {
2521 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2522 print_warning_label = false;
2525 log_warning(" %s", *i);
2531 static const char *verb_to_method(const char *verb) {
2534 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2535 if (streq_ptr(unit_actions[i].verb, verb))
2536 return unit_actions[i].method;
2541 static const char *method_to_verb(const char *method) {
2544 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2545 if (streq_ptr(unit_actions[i].method, method))
2546 return unit_actions[i].verb;
2551 static int start_unit_one(
2556 sd_bus_error *error,
2559 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2568 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2569 r = sd_bus_call_method(
2571 "org.freedesktop.systemd1",
2572 "/org/freedesktop/systemd1",
2573 "org.freedesktop.systemd1.Manager",
2581 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2582 /* There's always a fallback possible for
2583 * legacy actions. */
2584 return -EADDRNOTAVAIL;
2586 verb = method_to_verb(method);
2588 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2592 r = sd_bus_message_read(reply, "o", &path);
2594 return bus_log_parse_error(r);
2596 if (need_daemon_reload(bus, name) > 0)
2597 log_warning("Warning: Unit file of %s changed on disk, 'systemctl%s daemon-reload' recommended.",
2598 name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2607 log_debug("Adding %s to the set", p);
2608 r = set_consume(s, p);
2616 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2618 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2622 STRV_FOREACH(name, names) {
2626 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2628 t = unit_name_mangle(*name, MANGLE_GLOB);
2632 if (string_is_glob(t))
2633 r = strv_consume(&globs, t);
2635 r = strv_consume(&mangled, t);
2640 /* Query the manager only if any of the names are a glob, since
2641 * this is fairly expensive */
2642 if (!strv_isempty(globs)) {
2643 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2644 _cleanup_free_ UnitInfo *unit_infos = NULL;
2646 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2650 for (i = 0; i < r; i++)
2651 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2656 mangled = NULL; /* do not free */
2661 static const struct {
2665 } action_table[_ACTION_MAX] = {
2666 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2667 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2668 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2669 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2670 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
2671 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
2672 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
2673 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
2674 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2675 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2676 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2677 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2678 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2679 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2680 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2683 static enum action verb_to_action(const char *verb) {
2686 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2687 if (streq_ptr(action_table[i].verb, verb))
2690 return _ACTION_INVALID;
2693 static int start_unit(sd_bus *bus, char **args) {
2694 _cleanup_set_free_free_ Set *s = NULL;
2695 _cleanup_strv_free_ char **names = NULL;
2696 const char *method, *mode, *one_name;
2702 ask_password_agent_open_if_enabled();
2704 if (arg_action == ACTION_SYSTEMCTL) {
2706 method = verb_to_method(args[0]);
2707 action = verb_to_action(args[0]);
2709 mode = streq(args[0], "isolate") ? "isolate" :
2710 action_table[action].mode ?: arg_job_mode;
2712 one_name = action_table[action].target;
2714 assert(arg_action < ELEMENTSOF(action_table));
2715 assert(action_table[arg_action].target);
2717 method = "StartUnit";
2719 mode = action_table[arg_action].mode;
2720 one_name = action_table[arg_action].target;
2724 names = strv_new(one_name, NULL);
2726 r = expand_names(bus, args + 1, NULL, &names);
2728 log_error("Failed to expand names: %s", strerror(-r));
2731 if (!arg_no_block) {
2732 r = enable_wait_for_jobs(bus);
2734 log_error("Could not watch jobs: %s", strerror(-r));
2738 s = set_new(string_hash_func, string_compare_func);
2743 STRV_FOREACH(name, names) {
2744 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2747 q = start_unit_one(bus, method, *name, mode, &error, s);
2748 if (r >= 0 && q < 0)
2749 r = translate_bus_error_to_exit_status(q, &error);
2752 if (!arg_no_block) {
2755 q = wait_for_jobs(bus, s);
2759 /* When stopping units, warn if they can still be triggered by
2760 * another active unit (socket, path, timer) */
2761 if (!arg_quiet && streq(method, "StopUnit"))
2762 STRV_FOREACH(name, names)
2763 check_triggering_units(bus, *name);
2769 /* Ask systemd-logind, which might grant access to unprivileged users
2770 * through PolicyKit */
2771 static int reboot_with_logind(sd_bus *bus, enum action a) {
2773 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2780 polkit_agent_open_if_enabled();
2788 case ACTION_POWEROFF:
2789 method = "PowerOff";
2792 case ACTION_SUSPEND:
2796 case ACTION_HIBERNATE:
2797 method = "Hibernate";
2800 case ACTION_HYBRID_SLEEP:
2801 method = "HybridSleep";
2808 r = sd_bus_call_method(
2810 "org.freedesktop.login1",
2811 "/org/freedesktop/login1",
2812 "org.freedesktop.login1.Manager",
2818 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2826 static int check_inhibitors(sd_bus *bus, enum action a) {
2828 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2829 _cleanup_strv_free_ char **sessions = NULL;
2830 const char *what, *who, *why, *mode;
2839 if (arg_ignore_inhibitors || arg_force > 0)
2851 r = sd_bus_call_method(
2853 "org.freedesktop.login1",
2854 "/org/freedesktop/login1",
2855 "org.freedesktop.login1.Manager",
2861 /* If logind is not around, then there are no inhibitors... */
2864 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2866 return bus_log_parse_error(r);
2868 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2869 _cleanup_free_ char *comm = NULL, *user = NULL;
2870 _cleanup_strv_free_ char **sv = NULL;
2872 if (!streq(mode, "block"))
2875 sv = strv_split(what, ":");
2879 if (!strv_contains(sv,
2881 a == ACTION_POWEROFF ||
2882 a == ACTION_REBOOT ||
2883 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2886 get_process_comm(pid, &comm);
2887 user = uid_to_name(uid);
2889 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2890 who, (unsigned long) pid, strna(comm), strna(user), why);
2895 return bus_log_parse_error(r);
2897 r = sd_bus_message_exit_container(reply);
2899 return bus_log_parse_error(r);
2901 /* Check for current sessions */
2902 sd_get_sessions(&sessions);
2903 STRV_FOREACH(s, sessions) {
2904 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2906 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2909 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2912 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2915 sd_session_get_tty(*s, &tty);
2916 sd_session_get_seat(*s, &seat);
2917 sd_session_get_service(*s, &service);
2918 user = uid_to_name(uid);
2920 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2927 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2928 action_table[a].verb);
2936 static int start_special(sd_bus *bus, char **args) {
2942 a = verb_to_action(args[0]);
2944 r = check_inhibitors(bus, a);
2948 if (arg_force >= 2 && geteuid() != 0) {
2949 log_error("Must be root.");
2953 if (arg_force >= 2 &&
2954 (a == ACTION_HALT ||
2955 a == ACTION_POWEROFF ||
2956 a == ACTION_REBOOT))
2959 if (arg_force >= 1 &&
2960 (a == ACTION_HALT ||
2961 a == ACTION_POWEROFF ||
2962 a == ACTION_REBOOT ||
2963 a == ACTION_KEXEC ||
2965 return daemon_reload(bus, args);
2967 /* first try logind, to allow authentication with polkit */
2968 if (geteuid() != 0 &&
2969 (a == ACTION_POWEROFF ||
2970 a == ACTION_REBOOT ||
2971 a == ACTION_SUSPEND ||
2972 a == ACTION_HIBERNATE ||
2973 a == ACTION_HYBRID_SLEEP)) {
2974 r = reboot_with_logind(bus, a);
2979 r = start_unit(bus, args);
2980 if (r == EXIT_SUCCESS)
2986 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
2987 _cleanup_strv_free_ char **names = NULL;
2994 r = expand_names(bus, args, NULL, &names);
2996 log_error("Failed to expand names: %s", strerror(-r));
3000 STRV_FOREACH(name, names) {
3003 state = check_one_unit(bus, *name, good_states, arg_quiet);
3013 static int check_unit_active(sd_bus *bus, char **args) {
3014 /* According to LSB: 3, "program is not running" */
3015 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
3018 static int check_unit_failed(sd_bus *bus, char **args) {
3019 return check_unit_generic(bus, 1, "failed\0", args + 1);
3022 static int kill_unit(sd_bus *bus, char **args) {
3023 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3024 _cleanup_strv_free_ char **names = NULL;
3032 arg_kill_who = "all";
3034 r = expand_names(bus, args + 1, NULL, &names);
3036 log_error("Failed to expand names: %s", strerror(-r));
3038 STRV_FOREACH(name, names) {
3039 q = sd_bus_call_method(
3041 "org.freedesktop.systemd1",
3042 "/org/freedesktop/systemd1",
3043 "org.freedesktop.systemd1.Manager",
3047 "ssi", *names, arg_kill_who, arg_signal);
3049 log_error("Failed to kill unit %s: %s",
3050 *names, bus_error_message(&error, r));
3059 typedef struct ExecStatusInfo {
3067 usec_t start_timestamp;
3068 usec_t exit_timestamp;
3073 LIST_FIELDS(struct ExecStatusInfo, exec);
3076 static void exec_status_info_free(ExecStatusInfo *i) {
3085 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3086 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3089 int32_t code, status;
3095 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3097 return bus_log_parse_error(r);
3101 r = sd_bus_message_read(m, "s", &path);
3103 return bus_log_parse_error(r);
3105 i->path = strdup(path);
3109 r = sd_bus_message_read_strv(m, &i->argv);
3111 return bus_log_parse_error(r);
3113 r = sd_bus_message_read(m,
3116 &start_timestamp, &start_timestamp_monotonic,
3117 &exit_timestamp, &exit_timestamp_monotonic,
3121 return bus_log_parse_error(r);
3124 i->start_timestamp = (usec_t) start_timestamp;
3125 i->exit_timestamp = (usec_t) exit_timestamp;
3126 i->pid = (pid_t) pid;
3130 r = sd_bus_message_exit_container(m);
3132 return bus_log_parse_error(r);
3137 typedef struct UnitStatusInfo {
3139 const char *load_state;
3140 const char *active_state;
3141 const char *sub_state;
3142 const char *unit_file_state;
3144 const char *description;
3145 const char *following;
3147 char **documentation;
3149 const char *fragment_path;
3150 const char *source_path;
3151 const char *control_group;
3153 char **dropin_paths;
3155 const char *load_error;
3158 usec_t inactive_exit_timestamp;
3159 usec_t inactive_exit_timestamp_monotonic;
3160 usec_t active_enter_timestamp;
3161 usec_t active_exit_timestamp;
3162 usec_t inactive_enter_timestamp;
3164 bool need_daemon_reload;
3169 const char *status_text;
3170 const char *pid_file;
3173 usec_t start_timestamp;
3174 usec_t exit_timestamp;
3176 int exit_code, exit_status;
3178 usec_t condition_timestamp;
3179 bool condition_result;
3180 bool failed_condition_trigger;
3181 bool failed_condition_negate;
3182 const char *failed_condition;
3183 const char *failed_condition_param;
3186 unsigned n_accepted;
3187 unsigned n_connections;
3190 /* Pairs of type, path */
3194 const char *sysfs_path;
3196 /* Mount, Automount */
3202 LIST_HEAD(ExecStatusInfo, exec);
3205 static void print_status_info(
3210 const char *active_on, *active_off, *on, *off, *ss;
3212 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3213 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3216 arg_all * OUTPUT_SHOW_ALL |
3217 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
3218 on_tty() * OUTPUT_COLOR |
3219 !arg_quiet * OUTPUT_WARN_CUTOFF |
3220 arg_full * OUTPUT_FULL_WIDTH;
3225 /* This shows pretty information about a unit. See
3226 * print_property() for a low-level property printer */
3228 if (streq_ptr(i->active_state, "failed")) {
3229 active_on = ansi_highlight_red();
3230 active_off = ansi_highlight_off();
3231 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3232 active_on = ansi_highlight_green();
3233 active_off = ansi_highlight_off();
3235 active_on = active_off = "";
3237 printf("%s%s%s%s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3239 if (i->description && !streq_ptr(i->id, i->description))
3240 printf(" - %s", i->description);
3245 printf(" Follow: unit currently follows state of %s\n", i->following);
3247 if (streq_ptr(i->load_state, "error")) {
3248 on = ansi_highlight_red();
3249 off = ansi_highlight_off();
3253 path = i->source_path ? i->source_path : i->fragment_path;
3256 printf(" Loaded: %s%s%s (Reason: %s)\n",
3257 on, strna(i->load_state), off, i->load_error);
3258 else if (path && i->unit_file_state)
3259 printf(" Loaded: %s%s%s (%s; %s)\n",
3260 on, strna(i->load_state), off, path, i->unit_file_state);
3262 printf(" Loaded: %s%s%s (%s)\n",
3263 on, strna(i->load_state), off, path);
3265 printf(" Loaded: %s%s%s\n",
3266 on, strna(i->load_state), off);
3268 if (!strv_isempty(i->dropin_paths)) {
3269 _cleanup_free_ char *dir = NULL;
3273 STRV_FOREACH(dropin, i->dropin_paths) {
3274 if (! dir || last) {
3275 printf(dir ? " " : " Drop-In: ");
3280 if (path_get_parent(*dropin, &dir) < 0) {
3285 printf("%s\n %s", dir,
3286 draw_special_char(DRAW_TREE_RIGHT));
3289 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3291 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3295 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3297 printf(" Active: %s%s (%s)%s",
3298 active_on, strna(i->active_state), ss, active_off);
3300 printf(" Active: %s%s%s",
3301 active_on, strna(i->active_state), active_off);
3303 if (!isempty(i->result) && !streq(i->result, "success"))
3304 printf(" (Result: %s)", i->result);
3306 timestamp = (streq_ptr(i->active_state, "active") ||
3307 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
3308 (streq_ptr(i->active_state, "inactive") ||
3309 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
3310 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
3311 i->active_exit_timestamp;
3313 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3314 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3317 printf(" since %s; %s\n", s2, s1);
3319 printf(" since %s\n", s2);
3323 if (!i->condition_result && i->condition_timestamp > 0) {
3324 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3325 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3327 printf(" start condition failed at %s%s%s\n",
3328 s2, s1 ? "; " : "", s1 ? s1 : "");
3329 if (i->failed_condition_trigger)
3330 printf(" none of the trigger conditions were met\n");
3331 else if (i->failed_condition)
3332 printf(" %s=%s%s was not met\n",
3333 i->failed_condition,
3334 i->failed_condition_negate ? "!" : "",
3335 i->failed_condition_param);
3339 printf(" Device: %s\n", i->sysfs_path);
3341 printf(" Where: %s\n", i->where);
3343 printf(" What: %s\n", i->what);
3345 STRV_FOREACH(t, i->documentation)
3346 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3348 STRV_FOREACH_PAIR(t, t2, i->listen)
3349 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3352 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3354 LIST_FOREACH(exec, p, i->exec) {
3355 _cleanup_free_ char *argv = NULL;
3358 /* Only show exited processes here */
3362 argv = strv_join(p->argv, " ");
3363 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
3365 good = is_clean_exit_lsb(p->code, p->status, NULL);
3367 on = ansi_highlight_red();
3368 off = ansi_highlight_off();
3372 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3374 if (p->code == CLD_EXITED) {
3377 printf("status=%i", p->status);
3379 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3384 printf("signal=%s", signal_to_string(p->status));
3386 printf(")%s\n", off);
3388 if (i->main_pid == p->pid &&
3389 i->start_timestamp == p->start_timestamp &&
3390 i->exit_timestamp == p->start_timestamp)
3391 /* Let's not show this twice */
3394 if (p->pid == i->control_pid)
3398 if (i->main_pid > 0 || i->control_pid > 0) {
3399 if (i->main_pid > 0) {
3400 printf(" Main PID: %u", (unsigned) i->main_pid);
3403 _cleanup_free_ char *comm = NULL;
3404 get_process_comm(i->main_pid, &comm);
3406 printf(" (%s)", comm);
3407 } else if (i->exit_code > 0) {
3408 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3410 if (i->exit_code == CLD_EXITED) {
3413 printf("status=%i", i->exit_status);
3415 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3420 printf("signal=%s", signal_to_string(i->exit_status));
3424 if (i->control_pid > 0)
3428 if (i->control_pid > 0) {
3429 _cleanup_free_ char *c = NULL;
3431 printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
3433 get_process_comm(i->control_pid, &c);
3442 printf(" Status: \"%s\"\n", i->status_text);
3444 if (i->control_group &&
3445 (i->main_pid > 0 || i->control_pid > 0 ||
3446 ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_CONTAINER) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3449 printf(" CGroup: %s\n", i->control_group);
3451 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
3454 static const char prefix[] = " ";
3457 if (c > sizeof(prefix) - 1)
3458 c -= sizeof(prefix) - 1;
3462 if (i->main_pid > 0)
3463 extra[k++] = i->main_pid;
3465 if (i->control_pid > 0)
3466 extra[k++] = i->control_pid;
3468 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, flags);
3472 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3473 show_journal_by_unit(stdout,
3477 i->inactive_exit_timestamp_monotonic,
3480 flags | OUTPUT_BEGIN_NEWLINE,
3481 arg_scope == UNIT_FILE_SYSTEM,
3485 if (i->need_daemon_reload)
3486 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
3487 ansi_highlight_red(),
3488 ansi_highlight_off(),
3489 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
3492 static void show_unit_help(UnitStatusInfo *i) {
3497 if (!i->documentation) {
3498 log_info("Documentation for %s not known.", i->id);
3502 STRV_FOREACH(p, i->documentation) {
3504 if (startswith(*p, "man:")) {
3505 const char *args[4] = { "man", NULL, NULL, NULL };
3506 _cleanup_free_ char *page = NULL, *section = NULL;
3513 if ((*p)[k-1] == ')')
3514 e = strrchr(*p, '(');
3517 page = strndup((*p) + 4, e - *p - 4);
3518 section = strndup(e + 1, *p + k - e - 2);
3519 if (!page || !section) {
3531 log_error("Failed to fork: %m");
3537 execvp(args[0], (char**) args);
3538 log_error("Failed to execute man: %m");
3539 _exit(EXIT_FAILURE);
3542 wait_for_terminate(pid, NULL);
3544 log_info("Can't show: %s", *p);
3548 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3555 switch (contents[0]) {
3557 case SD_BUS_TYPE_STRING: {
3560 r = sd_bus_message_read(m, "s", &s);
3562 return bus_log_parse_error(r);
3565 if (streq(name, "Id"))
3567 else if (streq(name, "LoadState"))
3569 else if (streq(name, "ActiveState"))
3570 i->active_state = s;
3571 else if (streq(name, "SubState"))
3573 else if (streq(name, "Description"))
3575 else if (streq(name, "FragmentPath"))
3576 i->fragment_path = s;
3577 else if (streq(name, "SourcePath"))
3580 else if (streq(name, "DefaultControlGroup")) {
3582 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3584 i->control_group = e;
3587 else if (streq(name, "ControlGroup"))
3588 i->control_group = s;
3589 else if (streq(name, "StatusText"))
3591 else if (streq(name, "PIDFile"))
3593 else if (streq(name, "SysFSPath"))
3595 else if (streq(name, "Where"))
3597 else if (streq(name, "What"))
3599 else if (streq(name, "Following"))
3601 else if (streq(name, "UnitFileState"))
3602 i->unit_file_state = s;
3603 else if (streq(name, "Result"))
3610 case SD_BUS_TYPE_BOOLEAN: {
3613 r = sd_bus_message_read(m, "b", &b);
3615 return bus_log_parse_error(r);
3617 if (streq(name, "Accept"))
3619 else if (streq(name, "NeedDaemonReload"))
3620 i->need_daemon_reload = b;
3621 else if (streq(name, "ConditionResult"))
3622 i->condition_result = b;
3627 case SD_BUS_TYPE_UINT32: {
3630 r = sd_bus_message_read(m, "u", &u);
3632 return bus_log_parse_error(r);
3634 if (streq(name, "MainPID")) {
3636 i->main_pid = (pid_t) u;
3639 } else if (streq(name, "ControlPID"))
3640 i->control_pid = (pid_t) u;
3641 else if (streq(name, "ExecMainPID")) {
3643 i->main_pid = (pid_t) u;
3644 } else if (streq(name, "NAccepted"))
3646 else if (streq(name, "NConnections"))
3647 i->n_connections = u;
3652 case SD_BUS_TYPE_INT32: {
3655 r = sd_bus_message_read(m, "i", &j);
3657 return bus_log_parse_error(r);
3659 if (streq(name, "ExecMainCode"))
3660 i->exit_code = (int) j;
3661 else if (streq(name, "ExecMainStatus"))
3662 i->exit_status = (int) j;
3667 case SD_BUS_TYPE_UINT64: {
3670 r = sd_bus_message_read(m, "t", &u);
3672 return bus_log_parse_error(r);
3674 if (streq(name, "ExecMainStartTimestamp"))
3675 i->start_timestamp = (usec_t) u;
3676 else if (streq(name, "ExecMainExitTimestamp"))
3677 i->exit_timestamp = (usec_t) u;
3678 else if (streq(name, "ActiveEnterTimestamp"))
3679 i->active_enter_timestamp = (usec_t) u;
3680 else if (streq(name, "InactiveEnterTimestamp"))
3681 i->inactive_enter_timestamp = (usec_t) u;
3682 else if (streq(name, "InactiveExitTimestamp"))
3683 i->inactive_exit_timestamp = (usec_t) u;
3684 else if (streq(name, "InactiveExitTimestampMonotonic"))
3685 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3686 else if (streq(name, "ActiveExitTimestamp"))
3687 i->active_exit_timestamp = (usec_t) u;
3688 else if (streq(name, "ConditionTimestamp"))
3689 i->condition_timestamp = (usec_t) u;
3694 case SD_BUS_TYPE_ARRAY:
3696 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3697 _cleanup_free_ ExecStatusInfo *info = NULL;
3699 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3701 return bus_log_parse_error(r);
3703 info = new0(ExecStatusInfo, 1);
3707 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3709 info->name = strdup(name);
3713 LIST_PREPEND(exec, i->exec, info);
3715 info = new0(ExecStatusInfo, 1);
3721 return bus_log_parse_error(r);
3723 r = sd_bus_message_exit_container(m);
3725 return bus_log_parse_error(r);
3729 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3730 const char *type, *path;
3732 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3734 return bus_log_parse_error(r);
3736 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3738 r = strv_extend(&i->listen, type);
3742 r = strv_extend(&i->listen, path);
3747 return bus_log_parse_error(r);
3749 r = sd_bus_message_exit_container(m);
3751 return bus_log_parse_error(r);
3755 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3757 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3759 return bus_log_parse_error(r);
3761 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3763 r = sd_bus_message_read_strv(m, &i->documentation);
3765 return bus_log_parse_error(r);
3767 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3768 const char *cond, *param;
3769 int trigger, negate;
3772 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3774 return bus_log_parse_error(r);
3776 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3777 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3778 if (state < 0 && (!trigger || !i->failed_condition)) {
3779 i->failed_condition = cond;
3780 i->failed_condition_trigger = trigger;
3781 i->failed_condition_negate = negate;
3782 i->failed_condition_param = param;
3786 return bus_log_parse_error(r);
3788 r = sd_bus_message_exit_container(m);
3790 return bus_log_parse_error(r);
3797 case SD_BUS_TYPE_STRUCT_BEGIN:
3799 if (streq(name, "LoadError")) {
3800 const char *n, *message;
3802 r = sd_bus_message_read(m, "(ss)", &n, &message);
3804 return bus_log_parse_error(r);
3806 if (!isempty(message))
3807 i->load_error = message;
3820 r = sd_bus_message_skip(m, contents);
3822 return bus_log_parse_error(r);
3827 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3833 /* This is a low-level property printer, see
3834 * print_status_info() for the nicer output */
3836 if (arg_properties && !strv_find(arg_properties, name)) {
3837 /* skip what we didn't read */
3838 r = sd_bus_message_skip(m, contents);
3842 switch (contents[0]) {
3844 case SD_BUS_TYPE_STRUCT_BEGIN:
3846 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3849 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3851 return bus_log_parse_error(r);
3854 printf("%s=%u\n", name, (unsigned) u);
3856 printf("%s=\n", name);
3860 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3863 r = sd_bus_message_read(m, "(so)", &s, NULL);
3865 return bus_log_parse_error(r);
3867 if (arg_all || !isempty(s))
3868 printf("%s=%s\n", name, s);
3872 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3873 const char *a = NULL, *b = NULL;
3875 r = sd_bus_message_read(m, "(ss)", &a, &b);
3877 return bus_log_parse_error(r);
3879 if (arg_all || !isempty(a) || !isempty(b))
3880 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3883 } else if (streq_ptr(name, "SystemCallFilter")) {
3884 _cleanup_strv_free_ char **l = NULL;
3887 r = sd_bus_message_enter_container(m, 'r', "bas");
3889 return bus_log_parse_error(r);
3891 r = sd_bus_message_read(m, "b", &whitelist);
3893 return bus_log_parse_error(r);
3895 r = sd_bus_message_read_strv(m, &l);
3897 return bus_log_parse_error(r);
3899 r = sd_bus_message_exit_container(m);
3901 return bus_log_parse_error(r);
3903 if (arg_all || whitelist || !strv_isempty(l)) {
3907 fputs(name, stdout);
3913 STRV_FOREACH(i, l) {
3921 fputc('\n', stdout);
3929 case SD_BUS_TYPE_ARRAY:
3931 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
3935 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
3937 return bus_log_parse_error(r);
3939 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
3940 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3943 return bus_log_parse_error(r);
3945 r = sd_bus_message_exit_container(m);
3947 return bus_log_parse_error(r);
3951 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
3952 const char *type, *path;
3954 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3956 return bus_log_parse_error(r);
3958 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3959 printf("%s=%s\n", type, path);
3961 return bus_log_parse_error(r);
3963 r = sd_bus_message_exit_container(m);
3965 return bus_log_parse_error(r);
3969 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3970 const char *type, *path;
3972 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3974 return bus_log_parse_error(r);
3976 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3977 printf("Listen%s=%s\n", type, path);
3979 return bus_log_parse_error(r);
3981 r = sd_bus_message_exit_container(m);
3983 return bus_log_parse_error(r);
3987 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
3989 uint64_t value, next_elapse;
3991 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
3993 return bus_log_parse_error(r);
3995 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
3996 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3998 printf("%s={ value=%s ; next_elapse=%s }\n",
4000 format_timespan(timespan1, sizeof(timespan1), value, 0),
4001 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
4004 return bus_log_parse_error(r);
4006 r = sd_bus_message_exit_container(m);
4008 return bus_log_parse_error(r);
4012 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
4013 ExecStatusInfo info = {};
4015 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
4017 return bus_log_parse_error(r);
4019 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
4020 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
4021 _cleanup_free_ char *tt;
4023 tt = strv_join(info.argv, " ");
4025 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
4029 yes_no(info.ignore),
4030 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
4031 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
4032 (unsigned) info. pid,
4033 sigchld_code_to_string(info.code),
4035 info.code == CLD_EXITED ? "" : "/",
4036 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
4039 strv_free(info.argv);
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, "DeviceAllow")) {
4050 const char *path, *rwm;
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)", &path, &rwm)) > 0)
4057 printf("%s=%s %s\n", name, strna(path), strna(rwm));
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, "BlockIODeviceWeight")) {
4071 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4073 return bus_log_parse_error(r);
4075 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4076 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
4078 return bus_log_parse_error(r);
4080 r = sd_bus_message_exit_container(m);
4082 return bus_log_parse_error(r);
4086 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
4090 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4092 return bus_log_parse_error(r);
4094 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4095 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
4097 return bus_log_parse_error(r);
4099 r = sd_bus_message_exit_container(m);
4101 return bus_log_parse_error(r);
4109 r = bus_print_property(name, m, arg_all);
4111 return bus_log_parse_error(r);
4114 r = sd_bus_message_skip(m, contents);
4116 return bus_log_parse_error(r);
4119 printf("%s=[unprintable]\n", name);
4125 static int show_one(
4129 bool show_properties,
4133 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4134 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4135 UnitStatusInfo info = {};
4142 log_debug("Showing one %s", path);
4144 r = sd_bus_call_method(
4146 "org.freedesktop.systemd1",
4148 "org.freedesktop.DBus.Properties",
4154 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4158 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4160 return bus_log_parse_error(r);
4167 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4168 const char *name, *contents;
4170 r = sd_bus_message_read(reply, "s", &name);
4172 return bus_log_parse_error(r);
4174 r = sd_bus_message_peek_type(reply, NULL, &contents);
4176 return bus_log_parse_error(r);
4178 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4180 return bus_log_parse_error(r);
4182 if (show_properties)
4183 r = print_property(name, reply, contents);
4185 r = status_property(name, reply, &info, contents);
4189 r = sd_bus_message_exit_container(reply);
4191 return bus_log_parse_error(r);
4193 r = sd_bus_message_exit_container(reply);
4195 return bus_log_parse_error(r);
4198 return bus_log_parse_error(r);
4200 r = sd_bus_message_exit_container(reply);
4202 return bus_log_parse_error(r);
4206 if (!show_properties) {
4207 if (streq(verb, "help"))
4208 show_unit_help(&info);
4210 print_status_info(&info, ellipsized);
4213 strv_free(info.documentation);
4214 strv_free(info.dropin_paths);
4215 strv_free(info.listen);
4217 if (!streq_ptr(info.active_state, "active") &&
4218 !streq_ptr(info.active_state, "reloading") &&
4219 streq(verb, "status")) {
4220 /* According to LSB: "program not running" */
4221 /* 0: program is running or service is OK
4222 * 1: program is dead and /run PID file exists
4223 * 2: program is dead and /run/lock lock file exists
4224 * 3: program is not running
4225 * 4: program or service status is unknown
4227 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4233 while ((p = info.exec)) {
4234 LIST_REMOVE(exec, info.exec, p);
4235 exec_status_info_free(p);
4241 static int get_unit_dbus_path_by_pid(
4246 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4247 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4251 r = sd_bus_call_method(
4253 "org.freedesktop.systemd1",
4254 "/org/freedesktop/systemd1",
4255 "org.freedesktop.systemd1.Manager",
4261 log_error("Failed to get unit for PID %lu: %s", (unsigned long) pid, bus_error_message(&error, r));
4265 r = sd_bus_message_read(reply, "o", &u);
4267 return bus_log_parse_error(r);
4277 static int show_all(
4280 bool show_properties,
4284 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4285 _cleanup_free_ UnitInfo *unit_infos = NULL;
4290 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4294 pager_open_if_enabled();
4298 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4300 for (u = unit_infos; u < unit_infos + c; u++) {
4301 _cleanup_free_ char *p = NULL;
4303 p = unit_dbus_path_from_name(u->id);
4307 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4315 static int show_system_status(sd_bus *bus) {
4316 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4317 _cleanup_free_ char *hn = NULL;
4318 struct machine_info mi = {};
4319 const char *on, *off;
4322 hn = gethostname_malloc();
4326 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4328 log_error("Failed to read server status: %s", strerror(-r));
4332 if (streq_ptr(mi.state, "degraded")) {
4333 on = ansi_highlight_red();
4334 off = ansi_highlight_off();
4335 } else if (!streq_ptr(mi.state, "running")) {
4336 on = ansi_highlight_yellow();
4337 off = ansi_highlight_off();
4341 printf("%s%s%s%s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4343 printf(" State: %s%s%s\n",
4344 on, strna(mi.state), off);
4346 printf(" Jobs: %u queued\n", mi.n_jobs);
4347 printf(" Failed: %u units\n", mi.n_failed_units);
4349 printf(" Since: %s; %s\n",
4350 format_timestamp(since2, sizeof(since2), mi.timestamp),
4351 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4353 printf(" CGroup: %s\n", mi.control_group ?: "/");
4354 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
4356 arg_all * OUTPUT_SHOW_ALL |
4357 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
4358 on_tty() * OUTPUT_COLOR |
4359 !arg_quiet * OUTPUT_WARN_CUTOFF |
4360 arg_full * OUTPUT_FULL_WIDTH;
4362 static const char prefix[] = " ";
4366 if (c > sizeof(prefix) - 1)
4367 c -= sizeof(prefix) - 1;
4371 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
4375 free(mi.control_group);
4380 static int show(sd_bus *bus, char **args) {
4381 bool show_properties, show_status, new_line = false;
4382 bool ellipsized = false;
4388 show_properties = streq(args[0], "show");
4389 show_status = streq(args[0], "status");
4391 if (show_properties)
4392 pager_open_if_enabled();
4394 /* If no argument is specified inspect the manager itself */
4396 if (show_properties && strv_length(args) <= 1)
4397 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4399 if (show_status && strv_length(args) <= 1) {
4401 pager_open_if_enabled();
4402 show_system_status(bus);
4406 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4408 _cleanup_free_ char **patterns = NULL;
4411 STRV_FOREACH(name, args + 1) {
4412 _cleanup_free_ char *unit = NULL;
4415 if (safe_atou32(*name, &id) < 0) {
4416 if (strv_push(&patterns, *name) < 0)
4420 } else if (show_properties) {
4421 /* Interpret as job id */
4422 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4426 /* Interpret as PID */
4427 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4434 show_one(args[0], bus, unit, show_properties, &new_line, &ellipsized);
4437 if (!strv_isempty(patterns)) {
4438 _cleanup_strv_free_ char **names = NULL;
4440 r = expand_names(bus, patterns, NULL, &names);
4442 log_error("Failed to expand names: %s", strerror(-r));
4444 STRV_FOREACH(name, names) {
4445 _cleanup_free_ char *unit;
4447 unit = unit_dbus_path_from_name(*name);
4451 show_one(args[0], bus, unit, show_properties, &new_line, &ellipsized);
4456 if (ellipsized && !arg_quiet)
4457 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4462 static int cat(sd_bus *bus, char **args) {
4463 _cleanup_free_ char *unit = NULL;
4464 _cleanup_strv_free_ char **names = NULL;
4472 r = expand_names(bus, args + 1, NULL, &names);
4474 log_error("Failed to expand names: %s", strerror(-r));
4476 pager_open_if_enabled();
4478 STRV_FOREACH(name, names) {
4479 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4480 _cleanup_strv_free_ char **dropin_paths = NULL;
4481 _cleanup_free_ char *fragment_path = NULL;
4484 unit = unit_dbus_path_from_name(*name);
4488 if (need_daemon_reload(bus, *name) > 0)
4489 log_warning("Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'.",
4490 *name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
4492 r = sd_bus_get_property_string(
4494 "org.freedesktop.systemd1",
4496 "org.freedesktop.systemd1.Unit",
4501 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
4505 r = sd_bus_get_property_strv(
4507 "org.freedesktop.systemd1",
4509 "org.freedesktop.systemd1.Unit",
4514 log_warning("Failed to get DropInPaths: %s", bus_error_message(&error, r));
4523 if (!isempty(fragment_path)) {
4524 printf("%s# %s%s\n",
4525 ansi_highlight_blue(),
4527 ansi_highlight_off());
4530 r = sendfile_full(STDOUT_FILENO, fragment_path);
4532 log_warning("Failed to cat %s: %s", fragment_path, strerror(-r));
4537 STRV_FOREACH(path, dropin_paths) {
4538 printf("%s%s# %s%s\n",
4539 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4540 ansi_highlight_blue(),
4542 ansi_highlight_off());
4545 r = sendfile_full(STDOUT_FILENO, *path);
4547 log_warning("Failed to cat %s: %s", *path, strerror(-r));
4553 return r < 0 ? r : 0;
4556 static int set_property(sd_bus *bus, char **args) {
4557 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4558 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4559 _cleanup_free_ char *n = NULL;
4563 r = sd_bus_message_new_method_call(
4566 "org.freedesktop.systemd1",
4567 "/org/freedesktop/systemd1",
4568 "org.freedesktop.systemd1.Manager",
4569 "SetUnitProperties");
4571 return bus_log_create_error(r);
4573 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4577 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4579 return bus_log_create_error(r);
4581 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4583 return bus_log_create_error(r);
4585 STRV_FOREACH(i, args + 2) {
4586 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4588 return bus_log_create_error(r);
4590 r = bus_append_unit_property_assignment(m, *i);
4594 r = sd_bus_message_close_container(m);
4596 return bus_log_create_error(r);
4599 r = sd_bus_message_close_container(m);
4601 return bus_log_create_error(r);
4603 r = sd_bus_call(bus, m, 0, &error, NULL);
4605 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4612 static int snapshot(sd_bus *bus, char **args) {
4613 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4614 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4615 _cleanup_free_ char *n = NULL, *id = NULL;
4619 if (strv_length(args) > 1)
4620 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4626 r = sd_bus_call_method(
4628 "org.freedesktop.systemd1",
4629 "/org/freedesktop/systemd1",
4630 "org.freedesktop.systemd1.Manager",
4636 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4640 r = sd_bus_message_read(reply, "o", &path);
4642 return bus_log_parse_error(r);
4644 r = sd_bus_get_property_string(
4646 "org.freedesktop.systemd1",
4648 "org.freedesktop.systemd1.Unit",
4653 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4663 static int delete_snapshot(sd_bus *bus, char **args) {
4664 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4665 _cleanup_strv_free_ char **names = NULL;
4671 r = expand_names(bus, args + 1, ".snapshot", &names);
4673 log_error("Failed to expand names: %s", strerror(-r));
4675 STRV_FOREACH(name, names) {
4676 q = sd_bus_call_method(
4678 "org.freedesktop.systemd1",
4679 "/org/freedesktop/systemd1",
4680 "org.freedesktop.systemd1.Manager",
4686 log_error("Failed to remove snapshot %s: %s",
4687 *name, bus_error_message(&error, r));
4696 static int daemon_reload(sd_bus *bus, char **args) {
4697 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4701 if (arg_action == ACTION_RELOAD)
4703 else if (arg_action == ACTION_REEXEC)
4704 method = "Reexecute";
4706 assert(arg_action == ACTION_SYSTEMCTL);
4709 streq(args[0], "clear-jobs") ||
4710 streq(args[0], "cancel") ? "ClearJobs" :
4711 streq(args[0], "daemon-reexec") ? "Reexecute" :
4712 streq(args[0], "reset-failed") ? "ResetFailed" :
4713 streq(args[0], "halt") ? "Halt" :
4714 streq(args[0], "poweroff") ? "PowerOff" :
4715 streq(args[0], "reboot") ? "Reboot" :
4716 streq(args[0], "kexec") ? "KExec" :
4717 streq(args[0], "exit") ? "Exit" :
4718 /* "daemon-reload" */ "Reload";
4721 r = sd_bus_call_method(
4723 "org.freedesktop.systemd1",
4724 "/org/freedesktop/systemd1",
4725 "org.freedesktop.systemd1.Manager",
4731 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4732 /* There's always a fallback possible for
4733 * legacy actions. */
4735 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4736 /* On reexecution, we expect a disconnect, not a
4740 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4742 return r < 0 ? r : 0;
4745 static int reset_failed(sd_bus *bus, char **args) {
4746 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4747 _cleanup_strv_free_ char **names = NULL;
4751 if (strv_length(args) <= 1)
4752 return daemon_reload(bus, args);
4754 r = expand_names(bus, args + 1, NULL, &names);
4756 log_error("Failed to expand names: %s", strerror(-r));
4758 STRV_FOREACH(name, names) {
4759 q = sd_bus_call_method(
4761 "org.freedesktop.systemd1",
4762 "/org/freedesktop/systemd1",
4763 "org.freedesktop.systemd1.Manager",
4769 log_error("Failed to reset failed state of unit %s: %s",
4770 *name, bus_error_message(&error, r));
4779 static int show_environment(sd_bus *bus, char **args) {
4780 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4781 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4785 pager_open_if_enabled();
4787 r = sd_bus_get_property(
4789 "org.freedesktop.systemd1",
4790 "/org/freedesktop/systemd1",
4791 "org.freedesktop.systemd1.Manager",
4797 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4801 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4803 return bus_log_parse_error(r);
4805 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4808 return bus_log_parse_error(r);
4810 r = sd_bus_message_exit_container(reply);
4812 return bus_log_parse_error(r);
4817 static int switch_root(sd_bus *bus, char **args) {
4818 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4819 _cleanup_free_ char *cmdline_init = NULL;
4820 const char *root, *init;
4824 l = strv_length(args);
4825 if (l < 2 || l > 3) {
4826 log_error("Wrong number of arguments.");
4835 r = parse_env_file("/proc/cmdline", WHITESPACE,
4836 "init", &cmdline_init,
4839 log_debug("Failed to parse /proc/cmdline: %s", strerror(-r));
4841 init = cmdline_init;
4848 const char *root_systemd_path = NULL, *root_init_path = NULL;
4850 root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
4851 root_init_path = strappenda3(root, "/", init);
4853 /* If the passed init is actually the same as the
4854 * systemd binary, then let's suppress it. */
4855 if (files_same(root_init_path, root_systemd_path) > 0)
4859 log_debug("Switching root - root: %s; init: %s", root, strna(init));
4861 r = sd_bus_call_method(
4863 "org.freedesktop.systemd1",
4864 "/org/freedesktop/systemd1",
4865 "org.freedesktop.systemd1.Manager",
4871 log_error("Failed to switch root: %s", bus_error_message(&error, r));
4878 static int set_environment(sd_bus *bus, char **args) {
4879 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4880 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4887 method = streq(args[0], "set-environment")
4889 : "UnsetEnvironment";
4891 r = sd_bus_message_new_method_call(
4894 "org.freedesktop.systemd1",
4895 "/org/freedesktop/systemd1",
4896 "org.freedesktop.systemd1.Manager",
4899 return bus_log_create_error(r);
4901 r = sd_bus_message_append_strv(m, args + 1);
4903 return bus_log_create_error(r);
4905 r = sd_bus_call(bus, m, 0, &error, NULL);
4907 log_error("Failed to set environment: %s", bus_error_message(&error, r));
4914 static int import_environment(sd_bus *bus, char **args) {
4915 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4916 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4922 r = sd_bus_message_new_method_call(
4925 "org.freedesktop.systemd1",
4926 "/org/freedesktop/systemd1",
4927 "org.freedesktop.systemd1.Manager",
4930 return bus_log_create_error(r);
4932 if (strv_isempty(args + 1))
4933 r = sd_bus_message_append_strv(m, environ);
4937 r = sd_bus_message_open_container(m, 'a', "s");
4939 return bus_log_create_error(r);
4941 STRV_FOREACH(a, args + 1) {
4943 if (!env_name_is_valid(*a)) {
4944 log_error("Not a valid environment variable name: %s", *a);
4948 STRV_FOREACH(b, environ) {
4951 eq = startswith(*b, *a);
4952 if (eq && *eq == '=') {
4954 r = sd_bus_message_append(m, "s", *b);
4956 return bus_log_create_error(r);
4963 r = sd_bus_message_close_container(m);
4966 return bus_log_create_error(r);
4968 r = sd_bus_call(bus, m, 0, &error, NULL);
4970 log_error("Failed to import environment: %s", bus_error_message(&error, r));
4977 static int enable_sysv_units(const char *verb, char **args) {
4980 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4981 unsigned f = 1, t = 1;
4982 _cleanup_lookup_paths_free_ LookupPaths paths = {};
4984 if (arg_scope != UNIT_FILE_SYSTEM)
4987 if (!streq(verb, "enable") &&
4988 !streq(verb, "disable") &&
4989 !streq(verb, "is-enabled"))
4992 /* Processes all SysV units, and reshuffles the array so that
4993 * afterwards only the native units remain */
4995 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
5000 for (f = 0; args[f]; f++) {
5002 _cleanup_free_ char *p = NULL, *q = NULL;
5003 bool found_native = false, found_sysv;
5005 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
5013 if (!endswith(name, ".service"))
5016 if (path_is_absolute(name))
5019 STRV_FOREACH(k, paths.unit_path) {
5020 if (!isempty(arg_root))
5021 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
5023 asprintf(&p, "%s/%s", *k, name);
5030 found_native = access(p, F_OK) >= 0;
5041 if (!isempty(arg_root))
5042 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
5044 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
5050 p[strlen(p) - sizeof(".service") + 1] = 0;
5051 found_sysv = access(p, F_OK) >= 0;
5056 /* Mark this entry, so that we don't try enabling it as native unit */
5057 args[f] = (char*) "";
5059 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
5061 if (!isempty(arg_root))
5062 argv[c++] = q = strappend("--root=", arg_root);
5064 argv[c++] = basename(p);
5066 streq(verb, "enable") ? "on" :
5067 streq(verb, "disable") ? "off" : "--level=5";
5070 l = strv_join((char**)argv, " ");
5076 log_info("Executing %s", l);
5081 log_error("Failed to fork: %m");
5084 } else if (pid == 0) {
5087 execv(argv[0], (char**) argv);
5088 _exit(EXIT_FAILURE);
5091 j = wait_for_terminate(pid, &status);
5093 log_error("Failed to wait for child: %s", strerror(-r));
5098 if (status.si_code == CLD_EXITED) {
5099 if (streq(verb, "is-enabled")) {
5100 if (status.si_status == 0) {
5109 } else if (status.si_status != 0) {
5120 /* Drop all SysV units */
5121 for (f = 0, t = 0; args[f]; f++) {
5123 if (isempty(args[f]))
5126 args[t++] = args[f];
5135 static int mangle_names(char **original_names, char ***mangled_names) {
5136 char **i, **l, **name;
5138 l = new(char*, strv_length(original_names) + 1);
5143 STRV_FOREACH(name, original_names) {
5145 /* When enabling units qualified path names are OK,
5146 * too, hence allow them explicitly. */
5151 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5167 static int enable_unit(sd_bus *bus, char **args) {
5168 _cleanup_strv_free_ char **names = NULL;
5169 const char *verb = args[0];
5170 UnitFileChange *changes = NULL;
5171 unsigned n_changes = 0;
5172 int carries_install_info = -1;
5178 r = mangle_names(args+1, &names);
5182 r = enable_sysv_units(verb, names);
5186 /* If the operation was fully executed by the SysV compat,
5187 * let's finish early */
5188 if (strv_isempty(names))
5191 if (!bus || avoid_bus()) {
5192 if (streq(verb, "enable")) {
5193 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5194 carries_install_info = r;
5195 } else if (streq(verb, "disable"))
5196 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5197 else if (streq(verb, "reenable")) {
5198 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5199 carries_install_info = r;
5200 } else if (streq(verb, "link"))
5201 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5202 else if (streq(verb, "preset")) {
5203 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5204 carries_install_info = r;
5205 } else if (streq(verb, "mask"))
5206 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5207 else if (streq(verb, "unmask"))
5208 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5210 assert_not_reached("Unknown verb");
5213 log_error("Operation failed: %s", strerror(-r));
5218 dump_unit_file_changes(changes, n_changes);
5222 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5223 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5224 int expect_carries_install_info = false;
5225 bool send_force = true;
5228 if (streq(verb, "enable")) {
5229 method = "EnableUnitFiles";
5230 expect_carries_install_info = true;
5231 } else if (streq(verb, "disable")) {
5232 method = "DisableUnitFiles";
5234 } else if (streq(verb, "reenable")) {
5235 method = "ReenableUnitFiles";
5236 expect_carries_install_info = true;
5237 } else if (streq(verb, "link"))
5238 method = "LinkUnitFiles";
5239 else if (streq(verb, "preset")) {
5240 method = "PresetUnitFiles";
5241 expect_carries_install_info = true;
5242 } else if (streq(verb, "mask"))
5243 method = "MaskUnitFiles";
5244 else if (streq(verb, "unmask")) {
5245 method = "UnmaskUnitFiles";
5248 assert_not_reached("Unknown verb");
5250 r = sd_bus_message_new_method_call(
5253 "org.freedesktop.systemd1",
5254 "/org/freedesktop/systemd1",
5255 "org.freedesktop.systemd1.Manager",
5258 return bus_log_create_error(r);
5260 r = sd_bus_message_append_strv(m, names);
5262 return bus_log_create_error(r);
5264 r = sd_bus_message_append(m, "b", arg_runtime);
5266 return bus_log_create_error(r);
5269 r = sd_bus_message_append(m, "b", arg_force);
5271 return bus_log_create_error(r);
5274 r = sd_bus_call(bus, m, 0, &error, &reply);
5276 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5280 if (expect_carries_install_info) {
5281 r = sd_bus_message_read(reply, "b", &carries_install_info);
5283 return bus_log_parse_error(r);
5286 r = deserialize_and_dump_unit_file_changes(reply);
5290 /* Try to reload if enabled */
5292 r = daemon_reload(bus, args);
5297 if (carries_install_info == 0)
5298 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5299 "using systemctl.\n"
5300 "Possible reasons for having this kind of units are:\n"
5301 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5302 " .wants/ or .requires/ directory.\n"
5303 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5304 " a requirement dependency on it.\n"
5305 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5306 " D-Bus, udev, scripted systemctl call, ...).\n");
5309 unit_file_changes_free(changes, n_changes);
5314 static int unit_is_enabled(sd_bus *bus, char **args) {
5316 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5317 _cleanup_strv_free_ char **names = NULL;
5322 r = mangle_names(args+1, &names);
5326 r = enable_sysv_units(args[0], names);
5332 if (!bus || avoid_bus()) {
5334 STRV_FOREACH(name, names) {
5335 UnitFileState state;
5337 state = unit_file_get_state(arg_scope, arg_root, *name);
5339 log_error("Failed to get unit file state for %s: %s", *name, strerror(-state));
5343 if (state == UNIT_FILE_ENABLED ||
5344 state == UNIT_FILE_ENABLED_RUNTIME ||
5345 state == UNIT_FILE_STATIC)
5349 puts(unit_file_state_to_string(state));
5353 STRV_FOREACH(name, names) {
5354 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5357 r = sd_bus_call_method(
5359 "org.freedesktop.systemd1",
5360 "/org/freedesktop/systemd1",
5361 "org.freedesktop.systemd1.Manager",
5367 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5371 r = sd_bus_message_read(reply, "s", &s);
5373 return bus_log_parse_error(r);
5375 if (streq(s, "enabled") ||
5376 streq(s, "enabled-runtime") ||
5388 static int systemctl_help(void) {
5390 pager_open_if_enabled();
5392 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
5393 "Query or send control commands to the systemd manager.\n\n"
5394 " -h --help Show this help\n"
5395 " --version Show package version\n"
5396 " --system Connect to system manager\n"
5397 " --user Connect to user service manager\n"
5398 " -H --host=[USER@]HOST\n"
5399 " Operate on remote host\n"
5400 " -M --machine=CONTAINER\n"
5401 " Operate on local container\n"
5402 " -t --type=TYPE List only units of a particular type\n"
5403 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
5404 " -p --property=NAME Show only properties by this name\n"
5405 " -a --all Show all loaded units/properties, including dead/empty\n"
5406 " ones. To list all units installed on the system, use\n"
5407 " the 'list-unit-files' command instead.\n"
5408 " -l --full Don't ellipsize unit names on output\n"
5409 " -r --recursive Show unit list of host and local containers\n"
5410 " --reverse Show reverse dependencies with 'list-dependencies'\n"
5411 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
5412 " queueing a new job\n"
5413 " --show-types When showing sockets, explicitly show their type\n"
5414 " -i --ignore-inhibitors\n"
5415 " When shutting down or sleeping, ignore inhibitors\n"
5416 " --kill-who=WHO Who to send signal to\n"
5417 " -s --signal=SIGNAL Which signal to send\n"
5418 " -q --quiet Suppress output\n"
5419 " --no-block Do not wait until operation finished\n"
5420 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5421 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
5423 " --no-legend Do not print a legend (column headers and hints)\n"
5424 " --no-pager Do not pipe output into a pager\n"
5425 " --no-ask-password\n"
5426 " Do not ask for system passwords\n"
5427 " --global Enable/disable unit files globally\n"
5428 " --runtime Enable unit files only temporarily until next reboot\n"
5429 " -f --force When enabling unit files, override existing symlinks\n"
5430 " When shutting down, execute action immediately\n"
5431 " --root=PATH Enable unit files in the specified root directory\n"
5432 " -n --lines=INTEGER Number of journal entries to show\n"
5433 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
5434 " verbose, export, json, json-pretty, json-sse, cat)\n"
5435 " --plain Print unit dependencies as a list instead of a tree\n\n"
5437 " list-units [PATTERN...] List loaded units\n"
5438 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
5439 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
5440 " start NAME... Start (activate) one or more units\n"
5441 " stop NAME... Stop (deactivate) one or more units\n"
5442 " reload NAME... Reload one or more units\n"
5443 " restart NAME... Start or restart one or more units\n"
5444 " try-restart NAME... Restart one or more units if active\n"
5445 " reload-or-restart NAME... Reload one or more units if possible,\n"
5446 " otherwise start or restart\n"
5447 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
5448 " otherwise restart if active\n"
5449 " isolate NAME Start one unit and stop all others\n"
5450 " kill NAME... Send signal to processes of a unit\n"
5451 " is-active PATTERN... Check whether units are active\n"
5452 " is-failed PATTERN... Check whether units are failed\n"
5453 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
5454 " show [PATTERN...|JOB...] Show properties of one or more\n"
5455 " units/jobs or the manager\n"
5456 " cat PATTERN... Show files and drop-ins of one or more units\n"
5457 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
5458 " help PATTERN...|PID... Show manual for one or more units\n"
5459 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
5461 " list-dependencies [NAME] Recursively show units which are required\n"
5462 " or wanted by this unit or by which this\n"
5463 " unit is required or wanted\n\n"
5464 "Unit File Commands:\n"
5465 " list-unit-files [PATTERN...] List installed unit files\n"
5466 " enable NAME... Enable one or more unit files\n"
5467 " disable NAME... Disable one or more unit files\n"
5468 " reenable NAME... Reenable one or more unit files\n"
5469 " preset NAME... Enable/disable one or more unit files\n"
5470 " based on preset configuration\n"
5471 " is-enabled NAME... Check whether unit files are enabled\n\n"
5472 " mask NAME... Mask one or more units\n"
5473 " unmask NAME... Unmask one or more units\n"
5474 " link PATH... Link one or more units files into\n"
5475 " the search path\n"
5476 " get-default Get the name of the default target\n"
5477 " set-default NAME Set the default target\n\n"
5478 "Machine Commands:\n"
5479 " list-machines [PATTERN...] List local containers and host\n\n"
5481 " list-jobs [PATTERN...] List jobs\n"
5482 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
5483 "Snapshot Commands:\n"
5484 " snapshot [NAME] Create a snapshot\n"
5485 " delete NAME... Remove one or more snapshots\n\n"
5486 "Environment Commands:\n"
5487 " show-environment Dump environment\n"
5488 " set-environment NAME=VALUE... Set one or more environment variables\n"
5489 " unset-environment NAME... Unset one or more environment variables\n"
5490 " import-environment NAME... Import all, one or more environment variables\n\n"
5491 "Manager Lifecycle Commands:\n"
5492 " daemon-reload Reload systemd manager configuration\n"
5493 " daemon-reexec Reexecute systemd manager\n\n"
5494 "System Commands:\n"
5495 " default Enter system default mode\n"
5496 " rescue Enter system rescue mode\n"
5497 " emergency Enter system emergency mode\n"
5498 " halt Shut down and halt the system\n"
5499 " poweroff Shut down and power-off the system\n"
5500 " reboot [ARG] Shut down and reboot the system\n"
5501 " kexec Shut down and reboot the system with kexec\n"
5502 " exit Request user instance exit\n"
5503 " switch-root ROOT [INIT] Change to a different root file system\n"
5504 " suspend Suspend the system\n"
5505 " hibernate Hibernate the system\n"
5506 " hybrid-sleep Hibernate and suspend the system\n",
5507 program_invocation_short_name);
5512 static int halt_help(void) {
5514 printf("%s [OPTIONS...]%s\n\n"
5515 "%s the system.\n\n"
5516 " --help Show this help\n"
5517 " --halt Halt the machine\n"
5518 " -p --poweroff Switch off the machine\n"
5519 " --reboot Reboot the machine\n"
5520 " -f --force Force immediate halt/power-off/reboot\n"
5521 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
5522 " -d --no-wtmp Don't write wtmp record\n"
5523 " --no-wall Don't send wall message before halt/power-off/reboot\n",
5524 program_invocation_short_name,
5525 arg_action == ACTION_REBOOT ? " [ARG]" : "",
5526 arg_action == ACTION_REBOOT ? "Reboot" :
5527 arg_action == ACTION_POWEROFF ? "Power off" :
5533 static int shutdown_help(void) {
5535 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
5536 "Shut down the system.\n\n"
5537 " --help Show this help\n"
5538 " -H --halt Halt the machine\n"
5539 " -P --poweroff Power-off the machine\n"
5540 " -r --reboot Reboot the machine\n"
5541 " -h Equivalent to --poweroff, overridden by --halt\n"
5542 " -k Don't halt/power-off/reboot, just send warnings\n"
5543 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5544 " -c Cancel a pending shutdown\n",
5545 program_invocation_short_name);
5550 static int telinit_help(void) {
5552 printf("%s [OPTIONS...] {COMMAND}\n\n"
5553 "Send control commands to the init daemon.\n\n"
5554 " --help Show this help\n"
5555 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
5557 " 0 Power-off the machine\n"
5558 " 6 Reboot the machine\n"
5559 " 2, 3, 4, 5 Start runlevelX.target unit\n"
5560 " 1, s, S Enter rescue mode\n"
5561 " q, Q Reload init daemon configuration\n"
5562 " u, U Reexecute init daemon\n",
5563 program_invocation_short_name);
5568 static int runlevel_help(void) {
5570 printf("%s [OPTIONS...]\n\n"
5571 "Prints the previous and current runlevel of the init system.\n\n"
5572 " --help Show this help\n",
5573 program_invocation_short_name);
5578 static int help_types(void) {
5582 puts("Available unit types:");
5583 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
5584 t = unit_type_to_string(i);
5592 static int systemctl_parse_argv(int argc, char *argv[]) {
5601 ARG_IGNORE_DEPENDENCIES,
5613 ARG_NO_ASK_PASSWORD,
5622 static const struct option options[] = {
5623 { "help", no_argument, NULL, 'h' },
5624 { "version", no_argument, NULL, ARG_VERSION },
5625 { "type", required_argument, NULL, 't' },
5626 { "property", required_argument, NULL, 'p' },
5627 { "all", no_argument, NULL, 'a' },
5628 { "reverse", no_argument, NULL, ARG_REVERSE },
5629 { "after", no_argument, NULL, ARG_AFTER },
5630 { "before", no_argument, NULL, ARG_BEFORE },
5631 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
5632 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
5633 { "full", no_argument, NULL, 'l' },
5634 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
5635 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
5636 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
5637 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
5638 { "ignore-inhibitors", no_argument, NULL, 'i' },
5639 { "user", no_argument, NULL, ARG_USER },
5640 { "system", no_argument, NULL, ARG_SYSTEM },
5641 { "global", no_argument, NULL, ARG_GLOBAL },
5642 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
5643 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
5644 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
5645 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5646 { "quiet", no_argument, NULL, 'q' },
5647 { "root", required_argument, NULL, ARG_ROOT },
5648 { "force", no_argument, NULL, ARG_FORCE },
5649 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
5650 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
5651 { "signal", required_argument, NULL, 's' },
5652 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
5653 { "host", required_argument, NULL, 'H' },
5654 { "machine", required_argument, NULL, 'M' },
5655 { "runtime", no_argument, NULL, ARG_RUNTIME },
5656 { "lines", required_argument, NULL, 'n' },
5657 { "output", required_argument, NULL, 'o' },
5658 { "plain", no_argument, NULL, ARG_PLAIN },
5659 { "state", required_argument, NULL, ARG_STATE },
5660 { "recursive", no_argument, NULL, 'r' },
5669 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0) {
5674 return systemctl_help();
5677 puts(PACKAGE_STRING);
5678 puts(SYSTEMD_FEATURES);
5685 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5686 _cleanup_free_ char *type;
5688 type = strndup(word, size);
5692 if (streq(type, "help")) {
5697 if (unit_type_from_string(type) >= 0) {
5698 if (strv_push(&arg_types, type))
5704 /* It's much nicer to use --state= for
5705 * load states, but let's support this
5706 * in --types= too for compatibility
5707 * with old versions */
5708 if (unit_load_state_from_string(optarg) >= 0) {
5709 if (strv_push(&arg_states, type) < 0)
5715 log_error("Unknown unit type or load state '%s'.", type);
5716 log_info("Use -t help to see a list of allowed values.");
5724 /* Make sure that if the empty property list
5725 was specified, we won't show any properties. */
5726 if (isempty(optarg) && !arg_properties) {
5727 arg_properties = new0(char*, 1);
5728 if (!arg_properties)
5734 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5737 prop = strndup(word, size);
5741 if (strv_consume(&arg_properties, prop) < 0)
5746 /* If the user asked for a particular
5747 * property, show it to him, even if it is
5759 arg_dependency = DEPENDENCY_REVERSE;
5763 arg_dependency = DEPENDENCY_AFTER;
5767 arg_dependency = DEPENDENCY_BEFORE;
5770 case ARG_SHOW_TYPES:
5771 arg_show_types = true;
5775 arg_job_mode = optarg;
5779 arg_job_mode = "fail";
5782 case ARG_IRREVERSIBLE:
5783 arg_job_mode = "replace-irreversibly";
5786 case ARG_IGNORE_DEPENDENCIES:
5787 arg_job_mode = "ignore-dependencies";
5791 arg_scope = UNIT_FILE_USER;
5795 arg_scope = UNIT_FILE_SYSTEM;
5799 arg_scope = UNIT_FILE_GLOBAL;
5803 arg_no_block = true;
5807 arg_no_legend = true;
5811 arg_no_pager = true;
5827 if (strv_extend(&arg_states, "failed") < 0)
5845 arg_no_reload = true;
5849 arg_kill_who = optarg;
5853 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5854 log_error("Failed to parse signal string %s.", optarg);
5859 case ARG_NO_ASK_PASSWORD:
5860 arg_ask_password = false;
5864 arg_transport = BUS_TRANSPORT_REMOTE;
5869 arg_transport = BUS_TRANSPORT_CONTAINER;
5878 if (safe_atou(optarg, &arg_lines) < 0) {
5879 log_error("Failed to parse lines '%s'", optarg);
5885 arg_output = output_mode_from_string(optarg);
5886 if (arg_output < 0) {
5887 log_error("Unknown output '%s'.", optarg);
5893 arg_ignore_inhibitors = true;
5904 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5907 s = strndup(word, size);
5911 if (strv_consume(&arg_states, s) < 0)
5918 if (geteuid() != 0) {
5919 log_error("--recursive requires root priviliges.");
5923 arg_recursive = true;
5930 assert_not_reached("Unhandled option");
5934 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
5935 log_error("Cannot access user instance remotely.");
5942 static int halt_parse_argv(int argc, char *argv[]) {
5951 static const struct option options[] = {
5952 { "help", no_argument, NULL, ARG_HELP },
5953 { "halt", no_argument, NULL, ARG_HALT },
5954 { "poweroff", no_argument, NULL, 'p' },
5955 { "reboot", no_argument, NULL, ARG_REBOOT },
5956 { "force", no_argument, NULL, 'f' },
5957 { "wtmp-only", no_argument, NULL, 'w' },
5958 { "no-wtmp", no_argument, NULL, 'd' },
5959 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5968 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5969 if (runlevel == '0' || runlevel == '6')
5972 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5979 arg_action = ACTION_HALT;
5983 if (arg_action != ACTION_REBOOT)
5984 arg_action = ACTION_POWEROFF;
5988 arg_action = ACTION_REBOOT;
6010 /* Compatibility nops */
6017 assert_not_reached("Unhandled option");
6021 if (arg_action == ACTION_REBOOT && argc == optind + 1) {
6022 r = write_string_file(REBOOT_PARAM_FILE, argv[optind]);
6024 log_error("Failed to write reboot param to "
6025 REBOOT_PARAM_FILE": %s", strerror(-r));
6028 } else if (optind < argc) {
6029 log_error("Too many arguments.");
6036 static int parse_time_spec(const char *t, usec_t *_u) {
6040 if (streq(t, "now"))
6042 else if (!strchr(t, ':')) {
6045 if (safe_atou64(t, &u) < 0)
6048 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
6057 hour = strtol(t, &e, 10);
6058 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
6061 minute = strtol(e+1, &e, 10);
6062 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
6065 n = now(CLOCK_REALTIME);
6066 s = (time_t) (n / USEC_PER_SEC);
6068 assert_se(localtime_r(&s, &tm));
6070 tm.tm_hour = (int) hour;
6071 tm.tm_min = (int) minute;
6074 assert_se(s = mktime(&tm));
6076 *_u = (usec_t) s * USEC_PER_SEC;
6079 *_u += USEC_PER_DAY;
6085 static int shutdown_parse_argv(int argc, char *argv[]) {
6092 static const struct option options[] = {
6093 { "help", no_argument, NULL, ARG_HELP },
6094 { "halt", no_argument, NULL, 'H' },
6095 { "poweroff", no_argument, NULL, 'P' },
6096 { "reboot", no_argument, NULL, 'r' },
6097 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
6098 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6107 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
6111 return shutdown_help();
6114 arg_action = ACTION_HALT;
6118 arg_action = ACTION_POWEROFF;
6123 arg_action = ACTION_KEXEC;
6125 arg_action = ACTION_REBOOT;
6129 arg_action = ACTION_KEXEC;
6133 if (arg_action != ACTION_HALT)
6134 arg_action = ACTION_POWEROFF;
6147 /* Compatibility nops */
6151 arg_action = ACTION_CANCEL_SHUTDOWN;
6158 assert_not_reached("Unhandled option");
6162 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
6163 r = parse_time_spec(argv[optind], &arg_when);
6165 log_error("Failed to parse time specification: %s", argv[optind]);
6169 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
6171 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
6172 /* No time argument for shutdown cancel */
6173 arg_wall = argv + optind;
6174 else if (argc > optind + 1)
6175 /* We skip the time argument */
6176 arg_wall = argv + optind + 1;
6183 static int telinit_parse_argv(int argc, char *argv[]) {
6190 static const struct option options[] = {
6191 { "help", no_argument, NULL, ARG_HELP },
6192 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6196 static const struct {
6200 { '0', ACTION_POWEROFF },
6201 { '6', ACTION_REBOOT },
6202 { '1', ACTION_RESCUE },
6203 { '2', ACTION_RUNLEVEL2 },
6204 { '3', ACTION_RUNLEVEL3 },
6205 { '4', ACTION_RUNLEVEL4 },
6206 { '5', ACTION_RUNLEVEL5 },
6207 { 's', ACTION_RESCUE },
6208 { 'S', ACTION_RESCUE },
6209 { 'q', ACTION_RELOAD },
6210 { 'Q', ACTION_RELOAD },
6211 { 'u', ACTION_REEXEC },
6212 { 'U', ACTION_REEXEC }
6221 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
6225 return telinit_help();
6235 assert_not_reached("Unhandled option");
6239 if (optind >= argc) {
6244 if (optind + 1 < argc) {
6245 log_error("Too many arguments.");
6249 if (strlen(argv[optind]) != 1) {
6250 log_error("Expected single character argument.");
6254 for (i = 0; i < ELEMENTSOF(table); i++)
6255 if (table[i].from == argv[optind][0])
6258 if (i >= ELEMENTSOF(table)) {
6259 log_error("Unknown command '%s'.", argv[optind]);
6263 arg_action = table[i].to;
6270 static int runlevel_parse_argv(int argc, char *argv[]) {
6276 static const struct option options[] = {
6277 { "help", no_argument, NULL, ARG_HELP },
6286 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
6290 return runlevel_help();
6296 assert_not_reached("Unhandled option");
6300 if (optind < argc) {
6301 log_error("Too many arguments.");
6308 static int parse_argv(int argc, char *argv[]) {
6312 if (program_invocation_short_name) {
6314 if (strstr(program_invocation_short_name, "halt")) {
6315 arg_action = ACTION_HALT;
6316 return halt_parse_argv(argc, argv);
6317 } else if (strstr(program_invocation_short_name, "poweroff")) {
6318 arg_action = ACTION_POWEROFF;
6319 return halt_parse_argv(argc, argv);
6320 } else if (strstr(program_invocation_short_name, "reboot")) {
6322 arg_action = ACTION_KEXEC;
6324 arg_action = ACTION_REBOOT;
6325 return halt_parse_argv(argc, argv);
6326 } else if (strstr(program_invocation_short_name, "shutdown")) {
6327 arg_action = ACTION_POWEROFF;
6328 return shutdown_parse_argv(argc, argv);
6329 } else if (strstr(program_invocation_short_name, "init")) {
6331 if (sd_booted() > 0) {
6332 arg_action = _ACTION_INVALID;
6333 return telinit_parse_argv(argc, argv);
6335 /* Hmm, so some other init system is
6336 * running, we need to forward this
6337 * request to it. For now we simply
6338 * guess that it is Upstart. */
6340 execv(TELINIT, argv);
6342 log_error("Couldn't find an alternative telinit implementation to spawn.");
6346 } else if (strstr(program_invocation_short_name, "runlevel")) {
6347 arg_action = ACTION_RUNLEVEL;
6348 return runlevel_parse_argv(argc, argv);
6352 arg_action = ACTION_SYSTEMCTL;
6353 return systemctl_parse_argv(argc, argv);
6356 _pure_ static int action_to_runlevel(void) {
6358 static const char table[_ACTION_MAX] = {
6359 [ACTION_HALT] = '0',
6360 [ACTION_POWEROFF] = '0',
6361 [ACTION_REBOOT] = '6',
6362 [ACTION_RUNLEVEL2] = '2',
6363 [ACTION_RUNLEVEL3] = '3',
6364 [ACTION_RUNLEVEL4] = '4',
6365 [ACTION_RUNLEVEL5] = '5',
6366 [ACTION_RESCUE] = '1'
6369 assert(arg_action < _ACTION_MAX);
6371 return table[arg_action];
6374 static int talk_initctl(void) {
6376 struct init_request request = {
6377 .magic = INIT_MAGIC,
6379 .cmd = INIT_CMD_RUNLVL
6382 _cleanup_close_ int fd = -1;
6386 rl = action_to_runlevel();
6390 request.runlevel = rl;
6392 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
6394 if (errno == ENOENT)
6397 log_error("Failed to open "INIT_FIFO": %m");
6402 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
6404 log_error("Failed to write to "INIT_FIFO": %m");
6405 return errno > 0 ? -errno : -EIO;
6411 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
6413 static const struct {
6421 int (* const dispatch)(sd_bus *bus, char **args);
6427 { "list-units", MORE, 0, list_units },
6428 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
6429 { "list-sockets", MORE, 1, list_sockets },
6430 { "list-timers", MORE, 1, list_timers },
6431 { "list-jobs", MORE, 1, list_jobs },
6432 { "list-machines", MORE, 1, list_machines },
6433 { "clear-jobs", EQUAL, 1, daemon_reload },
6434 { "cancel", MORE, 2, cancel_job },
6435 { "start", MORE, 2, start_unit },
6436 { "stop", MORE, 2, start_unit },
6437 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6438 { "reload", MORE, 2, start_unit },
6439 { "restart", MORE, 2, start_unit },
6440 { "try-restart", MORE, 2, start_unit },
6441 { "reload-or-restart", MORE, 2, start_unit },
6442 { "reload-or-try-restart", MORE, 2, start_unit },
6443 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
6444 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6445 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
6446 { "isolate", EQUAL, 2, start_unit },
6447 { "kill", MORE, 2, kill_unit },
6448 { "is-active", MORE, 2, check_unit_active },
6449 { "check", MORE, 2, check_unit_active },
6450 { "is-failed", MORE, 2, check_unit_failed },
6451 { "show", MORE, 1, show },
6452 { "cat", MORE, 2, cat },
6453 { "status", MORE, 1, show },
6454 { "help", MORE, 2, show },
6455 { "snapshot", LESS, 2, snapshot },
6456 { "delete", MORE, 2, delete_snapshot },
6457 { "daemon-reload", EQUAL, 1, daemon_reload },
6458 { "daemon-reexec", EQUAL, 1, daemon_reload },
6459 { "show-environment", EQUAL, 1, show_environment },
6460 { "set-environment", MORE, 2, set_environment },
6461 { "unset-environment", MORE, 2, set_environment },
6462 { "import-environment", MORE, 1, import_environment},
6463 { "halt", EQUAL, 1, start_special, FORCE },
6464 { "poweroff", EQUAL, 1, start_special, FORCE },
6465 { "reboot", EQUAL, 1, start_special, FORCE },
6466 { "kexec", EQUAL, 1, start_special },
6467 { "suspend", EQUAL, 1, start_special },
6468 { "hibernate", EQUAL, 1, start_special },
6469 { "hybrid-sleep", EQUAL, 1, start_special },
6470 { "default", EQUAL, 1, start_special },
6471 { "rescue", EQUAL, 1, start_special },
6472 { "emergency", EQUAL, 1, start_special },
6473 { "exit", EQUAL, 1, start_special },
6474 { "reset-failed", MORE, 1, reset_failed },
6475 { "enable", MORE, 2, enable_unit, NOBUS },
6476 { "disable", MORE, 2, enable_unit, NOBUS },
6477 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
6478 { "reenable", MORE, 2, enable_unit, NOBUS },
6479 { "preset", MORE, 2, enable_unit, NOBUS },
6480 { "mask", MORE, 2, enable_unit, NOBUS },
6481 { "unmask", MORE, 2, enable_unit, NOBUS },
6482 { "link", MORE, 2, enable_unit, NOBUS },
6483 { "switch-root", MORE, 2, switch_root },
6484 { "list-dependencies", LESS, 2, list_dependencies },
6485 { "set-default", EQUAL, 2, set_default, NOBUS },
6486 { "get-default", EQUAL, 1, get_default, NOBUS },
6487 { "set-property", MORE, 3, set_property },
6496 left = argc - optind;
6498 /* Special rule: no arguments (left == 0) means "list-units" */
6500 if (streq(argv[optind], "help") && !argv[optind+1]) {
6501 log_error("This command expects one or more "
6502 "unit names. Did you mean --help?");
6506 for (; verb->verb; verb++)
6507 if (streq(argv[optind], verb->verb))
6510 log_error("Unknown operation '%s'.", argv[optind]);
6515 switch (verb->argc_cmp) {
6518 if (left != verb->argc) {
6519 log_error("Invalid number of arguments.");
6526 if (left < verb->argc) {
6527 log_error("Too few arguments.");
6534 if (left > verb->argc) {
6535 log_error("Too many arguments.");
6542 assert_not_reached("Unknown comparison operator.");
6545 /* Require a bus connection for all operations but
6547 if (verb->bus == NOBUS) {
6548 if (!bus && !avoid_bus()) {
6549 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6554 if (running_in_chroot() > 0) {
6555 log_info("Running in chroot, ignoring request.");
6559 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
6560 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6565 return verb->dispatch(bus, argv + optind);
6568 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
6570 struct sd_shutdown_command c = {
6577 union sockaddr_union sockaddr = {
6578 .un.sun_family = AF_UNIX,
6579 .un.sun_path = "/run/systemd/shutdownd",
6582 struct iovec iovec[2] = {{
6583 .iov_base = (char*) &c,
6584 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
6587 struct msghdr msghdr = {
6588 .msg_name = &sockaddr,
6589 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
6590 + strlen("/run/systemd/shutdownd"),
6595 _cleanup_close_ int fd;
6597 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
6601 if (!isempty(message)) {
6602 iovec[1].iov_base = (char*) message;
6603 iovec[1].iov_len = strlen(message);
6604 msghdr.msg_iovlen++;
6607 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
6613 static int reload_with_fallback(sd_bus *bus) {
6616 /* First, try systemd via D-Bus. */
6617 if (daemon_reload(bus, NULL) >= 0)
6621 /* Nothing else worked, so let's try signals */
6622 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
6624 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
6625 log_error("kill() failed: %m");
6632 static int start_with_fallback(sd_bus *bus) {
6635 /* First, try systemd via D-Bus. */
6636 if (start_unit(bus, NULL) >= 0)
6640 /* Nothing else worked, so let's try
6642 if (talk_initctl() > 0)
6645 log_error("Failed to talk to init daemon.");
6649 warn_wall(arg_action);
6653 static int halt_now(enum action a) {
6655 /* Make sure C-A-D is handled by the kernel from this
6657 reboot(RB_ENABLE_CAD);
6662 log_info("Halting.");
6663 reboot(RB_HALT_SYSTEM);
6666 case ACTION_POWEROFF:
6667 log_info("Powering off.");
6668 reboot(RB_POWER_OFF);
6671 case ACTION_REBOOT: {
6672 _cleanup_free_ char *param = NULL;
6674 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
6675 log_info("Rebooting with argument '%s'.", param);
6676 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
6677 LINUX_REBOOT_CMD_RESTART2, param);
6680 log_info("Rebooting.");
6681 reboot(RB_AUTOBOOT);
6686 assert_not_reached("Unknown action.");
6690 static int halt_main(sd_bus *bus) {
6693 r = check_inhibitors(bus, arg_action);
6697 if (geteuid() != 0) {
6698 /* Try logind if we are a normal user and no special
6699 * mode applies. Maybe PolicyKit allows us to shutdown
6702 if (arg_when <= 0 &&
6705 (arg_action == ACTION_POWEROFF ||
6706 arg_action == ACTION_REBOOT)) {
6707 r = reboot_with_logind(bus, arg_action);
6712 log_error("Must be root.");
6717 _cleanup_free_ char *m;
6719 m = strv_join(arg_wall, " ");
6723 r = send_shutdownd(arg_when,
6724 arg_action == ACTION_HALT ? 'H' :
6725 arg_action == ACTION_POWEROFF ? 'P' :
6726 arg_action == ACTION_KEXEC ? 'K' :
6733 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6735 char date[FORMAT_TIMESTAMP_MAX];
6737 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6738 format_timestamp(date, sizeof(date), arg_when));
6743 if (!arg_dry && !arg_force)
6744 return start_with_fallback(bus);
6747 if (sd_booted() > 0)
6748 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6750 r = utmp_put_shutdown();
6752 log_warning("Failed to write utmp record: %s", strerror(-r));
6759 r = halt_now(arg_action);
6760 log_error("Failed to reboot: %s", strerror(-r));
6765 static int runlevel_main(void) {
6766 int r, runlevel, previous;
6768 r = utmp_get_runlevel(&runlevel, &previous);
6775 previous <= 0 ? 'N' : previous,
6776 runlevel <= 0 ? 'N' : runlevel);
6781 int main(int argc, char*argv[]) {
6782 _cleanup_bus_unref_ sd_bus *bus = NULL;
6785 setlocale(LC_ALL, "");
6786 log_parse_environment();
6789 /* Explicitly not on_tty() to avoid setting cached value.
6790 * This becomes relevant for piping output which might be
6792 original_stdout_is_tty = isatty(STDOUT_FILENO);
6794 r = parse_argv(argc, argv);
6798 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6799 * let's shortcut this */
6800 if (arg_action == ACTION_RUNLEVEL) {
6801 r = runlevel_main();
6805 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6806 log_info("Running in chroot, ignoring request.");
6812 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
6814 /* systemctl_main() will print an error message for the bus
6815 * connection, but only if it needs to */
6817 switch (arg_action) {
6819 case ACTION_SYSTEMCTL:
6820 r = systemctl_main(bus, argc, argv, r);
6824 case ACTION_POWEROFF:
6830 case ACTION_RUNLEVEL2:
6831 case ACTION_RUNLEVEL3:
6832 case ACTION_RUNLEVEL4:
6833 case ACTION_RUNLEVEL5:
6835 case ACTION_EMERGENCY:
6836 case ACTION_DEFAULT:
6837 r = start_with_fallback(bus);
6842 r = reload_with_fallback(bus);
6845 case ACTION_CANCEL_SHUTDOWN: {
6846 _cleanup_free_ char *m = NULL;
6849 m = strv_join(arg_wall, " ");
6856 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6858 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6862 case ACTION_RUNLEVEL:
6863 case _ACTION_INVALID:
6865 assert_not_reached("Unknown action");
6870 ask_password_agent_close();
6871 polkit_agent_close();
6873 strv_free(arg_types);
6874 strv_free(arg_states);
6875 strv_free(arg_properties);
6877 return r < 0 ? EXIT_FAILURE : r;