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_VERTICAL : 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, true, &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",
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);
4310 else if (r > 0 && ret == 0)
4317 static int show_system_status(sd_bus *bus) {
4318 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4319 _cleanup_free_ char *hn = NULL;
4320 struct machine_info mi = {};
4321 const char *on, *off;
4324 hn = gethostname_malloc();
4328 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4330 log_error("Failed to read server status: %s", strerror(-r));
4334 if (streq_ptr(mi.state, "degraded")) {
4335 on = ansi_highlight_red();
4336 off = ansi_highlight_off();
4337 } else if (!streq_ptr(mi.state, "running")) {
4338 on = ansi_highlight_yellow();
4339 off = ansi_highlight_off();
4343 printf("%s%s%s %s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4345 printf(" State: %s%s%s\n",
4346 on, strna(mi.state), off);
4348 printf(" Jobs: %u queued\n", mi.n_jobs);
4349 printf(" Failed: %u units\n", mi.n_failed_units);
4351 printf(" Since: %s; %s\n",
4352 format_timestamp(since2, sizeof(since2), mi.timestamp),
4353 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4355 printf(" CGroup: %s\n", mi.control_group ?: "/");
4356 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
4358 arg_all * OUTPUT_SHOW_ALL |
4359 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
4360 on_tty() * OUTPUT_COLOR |
4361 !arg_quiet * OUTPUT_WARN_CUTOFF |
4362 arg_full * OUTPUT_FULL_WIDTH;
4364 static const char prefix[] = " ";
4368 if (c > sizeof(prefix) - 1)
4369 c -= sizeof(prefix) - 1;
4373 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
4377 free(mi.control_group);
4382 static int show(sd_bus *bus, char **args) {
4383 bool show_properties, show_status, new_line = false;
4384 bool ellipsized = false;
4390 show_properties = streq(args[0], "show");
4391 show_status = streq(args[0], "status");
4393 if (show_properties)
4394 pager_open_if_enabled();
4396 /* If no argument is specified inspect the manager itself */
4398 if (show_properties && strv_length(args) <= 1)
4399 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4401 if (show_status && strv_length(args) <= 1) {
4403 pager_open_if_enabled();
4404 show_system_status(bus);
4408 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4410 _cleanup_free_ char **patterns = NULL;
4413 STRV_FOREACH(name, args + 1) {
4414 _cleanup_free_ char *unit = NULL;
4417 if (safe_atou32(*name, &id) < 0) {
4418 if (strv_push(&patterns, *name) < 0)
4422 } else if (show_properties) {
4423 /* Interpret as job id */
4424 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4428 /* Interpret as PID */
4429 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4436 r = show_one(args[0], bus, unit, show_properties,
4437 &new_line, &ellipsized);
4440 else if (r > 0 && ret == 0)
4444 if (!strv_isempty(patterns)) {
4445 _cleanup_strv_free_ char **names = NULL;
4447 r = expand_names(bus, patterns, NULL, &names);
4449 log_error("Failed to expand names: %s", strerror(-r));
4451 STRV_FOREACH(name, names) {
4452 _cleanup_free_ char *unit;
4454 unit = unit_dbus_path_from_name(*name);
4458 r = show_one(args[0], bus, unit, show_properties,
4459 &new_line, &ellipsized);
4462 else if (r > 0 && ret == 0)
4468 if (ellipsized && !arg_quiet)
4469 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4474 static int cat(sd_bus *bus, char **args) {
4475 _cleanup_free_ char *unit = NULL;
4476 _cleanup_strv_free_ char **names = NULL;
4484 r = expand_names(bus, args + 1, NULL, &names);
4486 log_error("Failed to expand names: %s", strerror(-r));
4488 pager_open_if_enabled();
4490 STRV_FOREACH(name, names) {
4491 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4492 _cleanup_strv_free_ char **dropin_paths = NULL;
4493 _cleanup_free_ char *fragment_path = NULL;
4496 unit = unit_dbus_path_from_name(*name);
4500 if (need_daemon_reload(bus, *name) > 0)
4501 log_warning("Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'.",
4502 *name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
4504 r = sd_bus_get_property_string(
4506 "org.freedesktop.systemd1",
4508 "org.freedesktop.systemd1.Unit",
4513 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
4517 r = sd_bus_get_property_strv(
4519 "org.freedesktop.systemd1",
4521 "org.freedesktop.systemd1.Unit",
4526 log_warning("Failed to get DropInPaths: %s", bus_error_message(&error, r));
4535 if (!isempty(fragment_path)) {
4536 printf("%s# %s%s\n",
4537 ansi_highlight_blue(),
4539 ansi_highlight_off());
4542 r = sendfile_full(STDOUT_FILENO, fragment_path);
4544 log_warning("Failed to cat %s: %s", fragment_path, strerror(-r));
4549 STRV_FOREACH(path, dropin_paths) {
4550 printf("%s%s# %s%s\n",
4551 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4552 ansi_highlight_blue(),
4554 ansi_highlight_off());
4557 r = sendfile_full(STDOUT_FILENO, *path);
4559 log_warning("Failed to cat %s: %s", *path, strerror(-r));
4565 return r < 0 ? r : 0;
4568 static int set_property(sd_bus *bus, char **args) {
4569 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4570 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4571 _cleanup_free_ char *n = NULL;
4575 r = sd_bus_message_new_method_call(
4578 "org.freedesktop.systemd1",
4579 "/org/freedesktop/systemd1",
4580 "org.freedesktop.systemd1.Manager",
4581 "SetUnitProperties");
4583 return bus_log_create_error(r);
4585 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4589 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4591 return bus_log_create_error(r);
4593 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4595 return bus_log_create_error(r);
4597 STRV_FOREACH(i, args + 2) {
4598 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4600 return bus_log_create_error(r);
4602 r = bus_append_unit_property_assignment(m, *i);
4606 r = sd_bus_message_close_container(m);
4608 return bus_log_create_error(r);
4611 r = sd_bus_message_close_container(m);
4613 return bus_log_create_error(r);
4615 r = sd_bus_call(bus, m, 0, &error, NULL);
4617 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4624 static int snapshot(sd_bus *bus, char **args) {
4625 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4626 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4627 _cleanup_free_ char *n = NULL, *id = NULL;
4631 if (strv_length(args) > 1)
4632 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4638 r = sd_bus_call_method(
4640 "org.freedesktop.systemd1",
4641 "/org/freedesktop/systemd1",
4642 "org.freedesktop.systemd1.Manager",
4648 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4652 r = sd_bus_message_read(reply, "o", &path);
4654 return bus_log_parse_error(r);
4656 r = sd_bus_get_property_string(
4658 "org.freedesktop.systemd1",
4660 "org.freedesktop.systemd1.Unit",
4665 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4675 static int delete_snapshot(sd_bus *bus, char **args) {
4676 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4677 _cleanup_strv_free_ char **names = NULL;
4683 r = expand_names(bus, args + 1, ".snapshot", &names);
4685 log_error("Failed to expand names: %s", strerror(-r));
4687 STRV_FOREACH(name, names) {
4688 q = sd_bus_call_method(
4690 "org.freedesktop.systemd1",
4691 "/org/freedesktop/systemd1",
4692 "org.freedesktop.systemd1.Manager",
4698 log_error("Failed to remove snapshot %s: %s",
4699 *name, bus_error_message(&error, r));
4708 static int daemon_reload(sd_bus *bus, char **args) {
4709 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4713 if (arg_action == ACTION_RELOAD)
4715 else if (arg_action == ACTION_REEXEC)
4716 method = "Reexecute";
4718 assert(arg_action == ACTION_SYSTEMCTL);
4721 streq(args[0], "clear-jobs") ||
4722 streq(args[0], "cancel") ? "ClearJobs" :
4723 streq(args[0], "daemon-reexec") ? "Reexecute" :
4724 streq(args[0], "reset-failed") ? "ResetFailed" :
4725 streq(args[0], "halt") ? "Halt" :
4726 streq(args[0], "poweroff") ? "PowerOff" :
4727 streq(args[0], "reboot") ? "Reboot" :
4728 streq(args[0], "kexec") ? "KExec" :
4729 streq(args[0], "exit") ? "Exit" :
4730 /* "daemon-reload" */ "Reload";
4733 r = sd_bus_call_method(
4735 "org.freedesktop.systemd1",
4736 "/org/freedesktop/systemd1",
4737 "org.freedesktop.systemd1.Manager",
4743 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4744 /* There's always a fallback possible for
4745 * legacy actions. */
4747 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4748 /* On reexecution, we expect a disconnect, not a
4752 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4754 return r < 0 ? r : 0;
4757 static int reset_failed(sd_bus *bus, char **args) {
4758 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4759 _cleanup_strv_free_ char **names = NULL;
4763 if (strv_length(args) <= 1)
4764 return daemon_reload(bus, args);
4766 r = expand_names(bus, args + 1, NULL, &names);
4768 log_error("Failed to expand names: %s", strerror(-r));
4770 STRV_FOREACH(name, names) {
4771 q = sd_bus_call_method(
4773 "org.freedesktop.systemd1",
4774 "/org/freedesktop/systemd1",
4775 "org.freedesktop.systemd1.Manager",
4781 log_error("Failed to reset failed state of unit %s: %s",
4782 *name, bus_error_message(&error, r));
4791 static int show_environment(sd_bus *bus, char **args) {
4792 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4793 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4797 pager_open_if_enabled();
4799 r = sd_bus_get_property(
4801 "org.freedesktop.systemd1",
4802 "/org/freedesktop/systemd1",
4803 "org.freedesktop.systemd1.Manager",
4809 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4813 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4815 return bus_log_parse_error(r);
4817 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4820 return bus_log_parse_error(r);
4822 r = sd_bus_message_exit_container(reply);
4824 return bus_log_parse_error(r);
4829 static int switch_root(sd_bus *bus, char **args) {
4830 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4831 _cleanup_free_ char *cmdline_init = NULL;
4832 const char *root, *init;
4836 l = strv_length(args);
4837 if (l < 2 || l > 3) {
4838 log_error("Wrong number of arguments.");
4847 r = parse_env_file("/proc/cmdline", WHITESPACE,
4848 "init", &cmdline_init,
4851 log_debug("Failed to parse /proc/cmdline: %s", strerror(-r));
4853 init = cmdline_init;
4860 const char *root_systemd_path = NULL, *root_init_path = NULL;
4862 root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
4863 root_init_path = strappenda3(root, "/", init);
4865 /* If the passed init is actually the same as the
4866 * systemd binary, then let's suppress it. */
4867 if (files_same(root_init_path, root_systemd_path) > 0)
4871 log_debug("Switching root - root: %s; init: %s", root, strna(init));
4873 r = sd_bus_call_method(
4875 "org.freedesktop.systemd1",
4876 "/org/freedesktop/systemd1",
4877 "org.freedesktop.systemd1.Manager",
4883 log_error("Failed to switch root: %s", bus_error_message(&error, r));
4890 static int set_environment(sd_bus *bus, char **args) {
4891 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4892 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4899 method = streq(args[0], "set-environment")
4901 : "UnsetEnvironment";
4903 r = sd_bus_message_new_method_call(
4906 "org.freedesktop.systemd1",
4907 "/org/freedesktop/systemd1",
4908 "org.freedesktop.systemd1.Manager",
4911 return bus_log_create_error(r);
4913 r = sd_bus_message_append_strv(m, args + 1);
4915 return bus_log_create_error(r);
4917 r = sd_bus_call(bus, m, 0, &error, NULL);
4919 log_error("Failed to set environment: %s", bus_error_message(&error, r));
4926 static int import_environment(sd_bus *bus, char **args) {
4927 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4928 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4934 r = sd_bus_message_new_method_call(
4937 "org.freedesktop.systemd1",
4938 "/org/freedesktop/systemd1",
4939 "org.freedesktop.systemd1.Manager",
4942 return bus_log_create_error(r);
4944 if (strv_isempty(args + 1))
4945 r = sd_bus_message_append_strv(m, environ);
4949 r = sd_bus_message_open_container(m, 'a', "s");
4951 return bus_log_create_error(r);
4953 STRV_FOREACH(a, args + 1) {
4955 if (!env_name_is_valid(*a)) {
4956 log_error("Not a valid environment variable name: %s", *a);
4960 STRV_FOREACH(b, environ) {
4963 eq = startswith(*b, *a);
4964 if (eq && *eq == '=') {
4966 r = sd_bus_message_append(m, "s", *b);
4968 return bus_log_create_error(r);
4975 r = sd_bus_message_close_container(m);
4978 return bus_log_create_error(r);
4980 r = sd_bus_call(bus, m, 0, &error, NULL);
4982 log_error("Failed to import environment: %s", bus_error_message(&error, r));
4989 static int enable_sysv_units(const char *verb, char **args) {
4992 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4993 unsigned f = 1, t = 1;
4994 _cleanup_lookup_paths_free_ LookupPaths paths = {};
4996 if (arg_scope != UNIT_FILE_SYSTEM)
4999 if (!streq(verb, "enable") &&
5000 !streq(verb, "disable") &&
5001 !streq(verb, "is-enabled"))
5004 /* Processes all SysV units, and reshuffles the array so that
5005 * afterwards only the native units remain */
5007 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
5012 for (f = 0; args[f]; f++) {
5014 _cleanup_free_ char *p = NULL, *q = NULL;
5015 bool found_native = false, found_sysv;
5017 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
5025 if (!endswith(name, ".service"))
5028 if (path_is_absolute(name))
5031 STRV_FOREACH(k, paths.unit_path) {
5032 if (!isempty(arg_root))
5033 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
5035 asprintf(&p, "%s/%s", *k, name);
5042 found_native = access(p, F_OK) >= 0;
5053 if (!isempty(arg_root))
5054 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
5056 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
5062 p[strlen(p) - sizeof(".service") + 1] = 0;
5063 found_sysv = access(p, F_OK) >= 0;
5068 /* Mark this entry, so that we don't try enabling it as native unit */
5069 args[f] = (char*) "";
5071 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
5073 if (!isempty(arg_root))
5074 argv[c++] = q = strappend("--root=", arg_root);
5076 argv[c++] = basename(p);
5078 streq(verb, "enable") ? "on" :
5079 streq(verb, "disable") ? "off" : "--level=5";
5082 l = strv_join((char**)argv, " ");
5088 log_info("Executing %s", l);
5093 log_error("Failed to fork: %m");
5096 } else if (pid == 0) {
5099 execv(argv[0], (char**) argv);
5100 _exit(EXIT_FAILURE);
5103 j = wait_for_terminate(pid, &status);
5105 log_error("Failed to wait for child: %s", strerror(-r));
5110 if (status.si_code == CLD_EXITED) {
5111 if (streq(verb, "is-enabled")) {
5112 if (status.si_status == 0) {
5121 } else if (status.si_status != 0) {
5132 /* Drop all SysV units */
5133 for (f = 0, t = 0; args[f]; f++) {
5135 if (isempty(args[f]))
5138 args[t++] = args[f];
5147 static int mangle_names(char **original_names, char ***mangled_names) {
5148 char **i, **l, **name;
5150 l = new(char*, strv_length(original_names) + 1);
5155 STRV_FOREACH(name, original_names) {
5157 /* When enabling units qualified path names are OK,
5158 * too, hence allow them explicitly. */
5163 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5179 static int enable_unit(sd_bus *bus, char **args) {
5180 _cleanup_strv_free_ char **names = NULL;
5181 const char *verb = args[0];
5182 UnitFileChange *changes = NULL;
5183 unsigned n_changes = 0;
5184 int carries_install_info = -1;
5190 r = mangle_names(args+1, &names);
5194 r = enable_sysv_units(verb, names);
5198 /* If the operation was fully executed by the SysV compat,
5199 * let's finish early */
5200 if (strv_isempty(names))
5203 if (!bus || avoid_bus()) {
5204 if (streq(verb, "enable")) {
5205 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5206 carries_install_info = r;
5207 } else if (streq(verb, "disable"))
5208 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5209 else if (streq(verb, "reenable")) {
5210 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5211 carries_install_info = r;
5212 } else if (streq(verb, "link"))
5213 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5214 else if (streq(verb, "preset")) {
5215 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5216 carries_install_info = r;
5217 } else if (streq(verb, "mask"))
5218 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5219 else if (streq(verb, "unmask"))
5220 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5222 assert_not_reached("Unknown verb");
5225 log_error("Operation failed: %s", strerror(-r));
5230 dump_unit_file_changes(changes, n_changes);
5234 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5235 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5236 int expect_carries_install_info = false;
5237 bool send_force = true;
5240 if (streq(verb, "enable")) {
5241 method = "EnableUnitFiles";
5242 expect_carries_install_info = true;
5243 } else if (streq(verb, "disable")) {
5244 method = "DisableUnitFiles";
5246 } else if (streq(verb, "reenable")) {
5247 method = "ReenableUnitFiles";
5248 expect_carries_install_info = true;
5249 } else if (streq(verb, "link"))
5250 method = "LinkUnitFiles";
5251 else if (streq(verb, "preset")) {
5252 method = "PresetUnitFiles";
5253 expect_carries_install_info = true;
5254 } else if (streq(verb, "mask"))
5255 method = "MaskUnitFiles";
5256 else if (streq(verb, "unmask")) {
5257 method = "UnmaskUnitFiles";
5260 assert_not_reached("Unknown verb");
5262 r = sd_bus_message_new_method_call(
5265 "org.freedesktop.systemd1",
5266 "/org/freedesktop/systemd1",
5267 "org.freedesktop.systemd1.Manager",
5270 return bus_log_create_error(r);
5272 r = sd_bus_message_append_strv(m, names);
5274 return bus_log_create_error(r);
5276 r = sd_bus_message_append(m, "b", arg_runtime);
5278 return bus_log_create_error(r);
5281 r = sd_bus_message_append(m, "b", arg_force);
5283 return bus_log_create_error(r);
5286 r = sd_bus_call(bus, m, 0, &error, &reply);
5288 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5292 if (expect_carries_install_info) {
5293 r = sd_bus_message_read(reply, "b", &carries_install_info);
5295 return bus_log_parse_error(r);
5298 r = deserialize_and_dump_unit_file_changes(reply);
5302 /* Try to reload if enabled */
5304 r = daemon_reload(bus, args);
5309 if (carries_install_info == 0)
5310 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5311 "using systemctl.\n"
5312 "Possible reasons for having this kind of units are:\n"
5313 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5314 " .wants/ or .requires/ directory.\n"
5315 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5316 " a requirement dependency on it.\n"
5317 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5318 " D-Bus, udev, scripted systemctl call, ...).\n");
5321 unit_file_changes_free(changes, n_changes);
5326 static int unit_is_enabled(sd_bus *bus, char **args) {
5328 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5329 _cleanup_strv_free_ char **names = NULL;
5334 r = mangle_names(args+1, &names);
5338 r = enable_sysv_units(args[0], names);
5344 if (!bus || avoid_bus()) {
5346 STRV_FOREACH(name, names) {
5347 UnitFileState state;
5349 state = unit_file_get_state(arg_scope, arg_root, *name);
5351 log_error("Failed to get unit file state for %s: %s", *name, strerror(-state));
5355 if (state == UNIT_FILE_ENABLED ||
5356 state == UNIT_FILE_ENABLED_RUNTIME ||
5357 state == UNIT_FILE_STATIC)
5361 puts(unit_file_state_to_string(state));
5365 STRV_FOREACH(name, names) {
5366 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5369 r = sd_bus_call_method(
5371 "org.freedesktop.systemd1",
5372 "/org/freedesktop/systemd1",
5373 "org.freedesktop.systemd1.Manager",
5379 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5383 r = sd_bus_message_read(reply, "s", &s);
5385 return bus_log_parse_error(r);
5387 if (streq(s, "enabled") ||
5388 streq(s, "enabled-runtime") ||
5400 static int systemctl_help(void) {
5402 pager_open_if_enabled();
5404 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
5405 "Query or send control commands to the systemd manager.\n\n"
5406 " -h --help Show this help\n"
5407 " --version Show package version\n"
5408 " --system Connect to system manager\n"
5409 " --user Connect to user service manager\n"
5410 " -H --host=[USER@]HOST\n"
5411 " Operate on remote host\n"
5412 " -M --machine=CONTAINER\n"
5413 " Operate on local container\n"
5414 " -t --type=TYPE List only units of a particular type\n"
5415 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
5416 " -p --property=NAME Show only properties by this name\n"
5417 " -a --all Show all loaded units/properties, including dead/empty\n"
5418 " ones. To list all units installed on the system, use\n"
5419 " the 'list-unit-files' command instead.\n"
5420 " -l --full Don't ellipsize unit names on output\n"
5421 " -r --recursive Show unit list of host and local containers\n"
5422 " --reverse Show reverse dependencies with 'list-dependencies'\n"
5423 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
5424 " queueing a new job\n"
5425 " --show-types When showing sockets, explicitly show their type\n"
5426 " -i --ignore-inhibitors\n"
5427 " When shutting down or sleeping, ignore inhibitors\n"
5428 " --kill-who=WHO Who to send signal to\n"
5429 " -s --signal=SIGNAL Which signal to send\n"
5430 " -q --quiet Suppress output\n"
5431 " --no-block Do not wait until operation finished\n"
5432 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5433 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
5435 " --no-legend Do not print a legend (column headers and hints)\n"
5436 " --no-pager Do not pipe output into a pager\n"
5437 " --no-ask-password\n"
5438 " Do not ask for system passwords\n"
5439 " --global Enable/disable unit files globally\n"
5440 " --runtime Enable unit files only temporarily until next reboot\n"
5441 " -f --force When enabling unit files, override existing symlinks\n"
5442 " When shutting down, execute action immediately\n"
5443 " --root=PATH Enable unit files in the specified root directory\n"
5444 " -n --lines=INTEGER Number of journal entries to show\n"
5445 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
5446 " verbose, export, json, json-pretty, json-sse, cat)\n"
5447 " --plain Print unit dependencies as a list instead of a tree\n\n"
5449 " list-units [PATTERN...] List loaded units\n"
5450 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
5451 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
5452 " start NAME... Start (activate) one or more units\n"
5453 " stop NAME... Stop (deactivate) one or more units\n"
5454 " reload NAME... Reload one or more units\n"
5455 " restart NAME... Start or restart one or more units\n"
5456 " try-restart NAME... Restart one or more units if active\n"
5457 " reload-or-restart NAME... Reload one or more units if possible,\n"
5458 " otherwise start or restart\n"
5459 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
5460 " otherwise restart if active\n"
5461 " isolate NAME Start one unit and stop all others\n"
5462 " kill NAME... Send signal to processes of a unit\n"
5463 " is-active PATTERN... Check whether units are active\n"
5464 " is-failed PATTERN... Check whether units are failed\n"
5465 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
5466 " show [PATTERN...|JOB...] Show properties of one or more\n"
5467 " units/jobs or the manager\n"
5468 " cat PATTERN... Show files and drop-ins of one or more units\n"
5469 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
5470 " help PATTERN...|PID... Show manual for one or more units\n"
5471 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
5473 " list-dependencies [NAME] Recursively show units which are required\n"
5474 " or wanted by this unit or by which this\n"
5475 " unit is required or wanted\n\n"
5476 "Unit File Commands:\n"
5477 " list-unit-files [PATTERN...] List installed unit files\n"
5478 " enable NAME... Enable one or more unit files\n"
5479 " disable NAME... Disable one or more unit files\n"
5480 " reenable NAME... Reenable one or more unit files\n"
5481 " preset NAME... Enable/disable one or more unit files\n"
5482 " based on preset configuration\n"
5483 " is-enabled NAME... Check whether unit files are enabled\n\n"
5484 " mask NAME... Mask one or more units\n"
5485 " unmask NAME... Unmask one or more units\n"
5486 " link PATH... Link one or more units files into\n"
5487 " the search path\n"
5488 " get-default Get the name of the default target\n"
5489 " set-default NAME Set the default target\n\n"
5490 "Machine Commands:\n"
5491 " list-machines [PATTERN...] List local containers and host\n\n"
5493 " list-jobs [PATTERN...] List jobs\n"
5494 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
5495 "Snapshot Commands:\n"
5496 " snapshot [NAME] Create a snapshot\n"
5497 " delete NAME... Remove one or more snapshots\n\n"
5498 "Environment Commands:\n"
5499 " show-environment Dump environment\n"
5500 " set-environment NAME=VALUE... Set one or more environment variables\n"
5501 " unset-environment NAME... Unset one or more environment variables\n"
5502 " import-environment NAME... Import all, one or more environment variables\n\n"
5503 "Manager Lifecycle Commands:\n"
5504 " daemon-reload Reload systemd manager configuration\n"
5505 " daemon-reexec Reexecute systemd manager\n\n"
5506 "System Commands:\n"
5507 " default Enter system default mode\n"
5508 " rescue Enter system rescue mode\n"
5509 " emergency Enter system emergency mode\n"
5510 " halt Shut down and halt the system\n"
5511 " poweroff Shut down and power-off the system\n"
5512 " reboot [ARG] Shut down and reboot the system\n"
5513 " kexec Shut down and reboot the system with kexec\n"
5514 " exit Request user instance exit\n"
5515 " switch-root ROOT [INIT] Change to a different root file system\n"
5516 " suspend Suspend the system\n"
5517 " hibernate Hibernate the system\n"
5518 " hybrid-sleep Hibernate and suspend the system\n",
5519 program_invocation_short_name);
5524 static int halt_help(void) {
5526 printf("%s [OPTIONS...]%s\n\n"
5527 "%s the system.\n\n"
5528 " --help Show this help\n"
5529 " --halt Halt the machine\n"
5530 " -p --poweroff Switch off the machine\n"
5531 " --reboot Reboot the machine\n"
5532 " -f --force Force immediate halt/power-off/reboot\n"
5533 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
5534 " -d --no-wtmp Don't write wtmp record\n"
5535 " --no-wall Don't send wall message before halt/power-off/reboot\n",
5536 program_invocation_short_name,
5537 arg_action == ACTION_REBOOT ? " [ARG]" : "",
5538 arg_action == ACTION_REBOOT ? "Reboot" :
5539 arg_action == ACTION_POWEROFF ? "Power off" :
5545 static int shutdown_help(void) {
5547 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
5548 "Shut down the system.\n\n"
5549 " --help Show this help\n"
5550 " -H --halt Halt the machine\n"
5551 " -P --poweroff Power-off the machine\n"
5552 " -r --reboot Reboot the machine\n"
5553 " -h Equivalent to --poweroff, overridden by --halt\n"
5554 " -k Don't halt/power-off/reboot, just send warnings\n"
5555 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5556 " -c Cancel a pending shutdown\n",
5557 program_invocation_short_name);
5562 static int telinit_help(void) {
5564 printf("%s [OPTIONS...] {COMMAND}\n\n"
5565 "Send control commands to the init daemon.\n\n"
5566 " --help Show this help\n"
5567 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
5569 " 0 Power-off the machine\n"
5570 " 6 Reboot the machine\n"
5571 " 2, 3, 4, 5 Start runlevelX.target unit\n"
5572 " 1, s, S Enter rescue mode\n"
5573 " q, Q Reload init daemon configuration\n"
5574 " u, U Reexecute init daemon\n",
5575 program_invocation_short_name);
5580 static int runlevel_help(void) {
5582 printf("%s [OPTIONS...]\n\n"
5583 "Prints the previous and current runlevel of the init system.\n\n"
5584 " --help Show this help\n",
5585 program_invocation_short_name);
5590 static int help_types(void) {
5594 puts("Available unit types:");
5595 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
5596 t = unit_type_to_string(i);
5604 static int systemctl_parse_argv(int argc, char *argv[]) {
5613 ARG_IGNORE_DEPENDENCIES,
5625 ARG_NO_ASK_PASSWORD,
5634 static const struct option options[] = {
5635 { "help", no_argument, NULL, 'h' },
5636 { "version", no_argument, NULL, ARG_VERSION },
5637 { "type", required_argument, NULL, 't' },
5638 { "property", required_argument, NULL, 'p' },
5639 { "all", no_argument, NULL, 'a' },
5640 { "reverse", no_argument, NULL, ARG_REVERSE },
5641 { "after", no_argument, NULL, ARG_AFTER },
5642 { "before", no_argument, NULL, ARG_BEFORE },
5643 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
5644 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
5645 { "full", no_argument, NULL, 'l' },
5646 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
5647 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
5648 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
5649 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
5650 { "ignore-inhibitors", no_argument, NULL, 'i' },
5651 { "user", no_argument, NULL, ARG_USER },
5652 { "system", no_argument, NULL, ARG_SYSTEM },
5653 { "global", no_argument, NULL, ARG_GLOBAL },
5654 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
5655 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
5656 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
5657 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5658 { "quiet", no_argument, NULL, 'q' },
5659 { "root", required_argument, NULL, ARG_ROOT },
5660 { "force", no_argument, NULL, ARG_FORCE },
5661 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
5662 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
5663 { "signal", required_argument, NULL, 's' },
5664 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
5665 { "host", required_argument, NULL, 'H' },
5666 { "machine", required_argument, NULL, 'M' },
5667 { "runtime", no_argument, NULL, ARG_RUNTIME },
5668 { "lines", required_argument, NULL, 'n' },
5669 { "output", required_argument, NULL, 'o' },
5670 { "plain", no_argument, NULL, ARG_PLAIN },
5671 { "state", required_argument, NULL, ARG_STATE },
5672 { "recursive", no_argument, NULL, 'r' },
5681 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0) {
5686 return systemctl_help();
5689 puts(PACKAGE_STRING);
5690 puts(SYSTEMD_FEATURES);
5697 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5698 _cleanup_free_ char *type;
5700 type = strndup(word, size);
5704 if (streq(type, "help")) {
5709 if (unit_type_from_string(type) >= 0) {
5710 if (strv_push(&arg_types, type))
5716 /* It's much nicer to use --state= for
5717 * load states, but let's support this
5718 * in --types= too for compatibility
5719 * with old versions */
5720 if (unit_load_state_from_string(optarg) >= 0) {
5721 if (strv_push(&arg_states, type) < 0)
5727 log_error("Unknown unit type or load state '%s'.", type);
5728 log_info("Use -t help to see a list of allowed values.");
5736 /* Make sure that if the empty property list
5737 was specified, we won't show any properties. */
5738 if (isempty(optarg) && !arg_properties) {
5739 arg_properties = new0(char*, 1);
5740 if (!arg_properties)
5746 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5749 prop = strndup(word, size);
5753 if (strv_consume(&arg_properties, prop) < 0)
5758 /* If the user asked for a particular
5759 * property, show it to him, even if it is
5771 arg_dependency = DEPENDENCY_REVERSE;
5775 arg_dependency = DEPENDENCY_AFTER;
5779 arg_dependency = DEPENDENCY_BEFORE;
5782 case ARG_SHOW_TYPES:
5783 arg_show_types = true;
5787 arg_job_mode = optarg;
5791 arg_job_mode = "fail";
5794 case ARG_IRREVERSIBLE:
5795 arg_job_mode = "replace-irreversibly";
5798 case ARG_IGNORE_DEPENDENCIES:
5799 arg_job_mode = "ignore-dependencies";
5803 arg_scope = UNIT_FILE_USER;
5807 arg_scope = UNIT_FILE_SYSTEM;
5811 arg_scope = UNIT_FILE_GLOBAL;
5815 arg_no_block = true;
5819 arg_no_legend = true;
5823 arg_no_pager = true;
5839 if (strv_extend(&arg_states, "failed") < 0)
5857 arg_no_reload = true;
5861 arg_kill_who = optarg;
5865 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5866 log_error("Failed to parse signal string %s.", optarg);
5871 case ARG_NO_ASK_PASSWORD:
5872 arg_ask_password = false;
5876 arg_transport = BUS_TRANSPORT_REMOTE;
5881 arg_transport = BUS_TRANSPORT_CONTAINER;
5890 if (safe_atou(optarg, &arg_lines) < 0) {
5891 log_error("Failed to parse lines '%s'", optarg);
5897 arg_output = output_mode_from_string(optarg);
5898 if (arg_output < 0) {
5899 log_error("Unknown output '%s'.", optarg);
5905 arg_ignore_inhibitors = true;
5916 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5919 s = strndup(word, size);
5923 if (strv_consume(&arg_states, s) < 0)
5930 if (geteuid() != 0) {
5931 log_error("--recursive requires root priviliges.");
5935 arg_recursive = true;
5942 assert_not_reached("Unhandled option");
5946 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
5947 log_error("Cannot access user instance remotely.");
5954 static int halt_parse_argv(int argc, char *argv[]) {
5963 static const struct option options[] = {
5964 { "help", no_argument, NULL, ARG_HELP },
5965 { "halt", no_argument, NULL, ARG_HALT },
5966 { "poweroff", no_argument, NULL, 'p' },
5967 { "reboot", no_argument, NULL, ARG_REBOOT },
5968 { "force", no_argument, NULL, 'f' },
5969 { "wtmp-only", no_argument, NULL, 'w' },
5970 { "no-wtmp", no_argument, NULL, 'd' },
5971 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5980 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5981 if (runlevel == '0' || runlevel == '6')
5984 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5991 arg_action = ACTION_HALT;
5995 if (arg_action != ACTION_REBOOT)
5996 arg_action = ACTION_POWEROFF;
6000 arg_action = ACTION_REBOOT;
6022 /* Compatibility nops */
6029 assert_not_reached("Unhandled option");
6033 if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
6034 r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL);
6037 } else if (optind < argc) {
6038 log_error("Too many arguments.");
6045 static int parse_time_spec(const char *t, usec_t *_u) {
6049 if (streq(t, "now"))
6051 else if (!strchr(t, ':')) {
6054 if (safe_atou64(t, &u) < 0)
6057 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
6066 hour = strtol(t, &e, 10);
6067 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
6070 minute = strtol(e+1, &e, 10);
6071 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
6074 n = now(CLOCK_REALTIME);
6075 s = (time_t) (n / USEC_PER_SEC);
6077 assert_se(localtime_r(&s, &tm));
6079 tm.tm_hour = (int) hour;
6080 tm.tm_min = (int) minute;
6083 assert_se(s = mktime(&tm));
6085 *_u = (usec_t) s * USEC_PER_SEC;
6088 *_u += USEC_PER_DAY;
6094 static int shutdown_parse_argv(int argc, char *argv[]) {
6101 static const struct option options[] = {
6102 { "help", no_argument, NULL, ARG_HELP },
6103 { "halt", no_argument, NULL, 'H' },
6104 { "poweroff", no_argument, NULL, 'P' },
6105 { "reboot", no_argument, NULL, 'r' },
6106 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
6107 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6116 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
6120 return shutdown_help();
6123 arg_action = ACTION_HALT;
6127 arg_action = ACTION_POWEROFF;
6132 arg_action = ACTION_KEXEC;
6134 arg_action = ACTION_REBOOT;
6138 arg_action = ACTION_KEXEC;
6142 if (arg_action != ACTION_HALT)
6143 arg_action = ACTION_POWEROFF;
6156 /* Compatibility nops */
6160 arg_action = ACTION_CANCEL_SHUTDOWN;
6167 assert_not_reached("Unhandled option");
6171 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
6172 r = parse_time_spec(argv[optind], &arg_when);
6174 log_error("Failed to parse time specification: %s", argv[optind]);
6178 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
6180 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
6181 /* No time argument for shutdown cancel */
6182 arg_wall = argv + optind;
6183 else if (argc > optind + 1)
6184 /* We skip the time argument */
6185 arg_wall = argv + optind + 1;
6192 static int telinit_parse_argv(int argc, char *argv[]) {
6199 static const struct option options[] = {
6200 { "help", no_argument, NULL, ARG_HELP },
6201 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6205 static const struct {
6209 { '0', ACTION_POWEROFF },
6210 { '6', ACTION_REBOOT },
6211 { '1', ACTION_RESCUE },
6212 { '2', ACTION_RUNLEVEL2 },
6213 { '3', ACTION_RUNLEVEL3 },
6214 { '4', ACTION_RUNLEVEL4 },
6215 { '5', ACTION_RUNLEVEL5 },
6216 { 's', ACTION_RESCUE },
6217 { 'S', ACTION_RESCUE },
6218 { 'q', ACTION_RELOAD },
6219 { 'Q', ACTION_RELOAD },
6220 { 'u', ACTION_REEXEC },
6221 { 'U', ACTION_REEXEC }
6230 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
6234 return telinit_help();
6244 assert_not_reached("Unhandled option");
6248 if (optind >= argc) {
6253 if (optind + 1 < argc) {
6254 log_error("Too many arguments.");
6258 if (strlen(argv[optind]) != 1) {
6259 log_error("Expected single character argument.");
6263 for (i = 0; i < ELEMENTSOF(table); i++)
6264 if (table[i].from == argv[optind][0])
6267 if (i >= ELEMENTSOF(table)) {
6268 log_error("Unknown command '%s'.", argv[optind]);
6272 arg_action = table[i].to;
6279 static int runlevel_parse_argv(int argc, char *argv[]) {
6285 static const struct option options[] = {
6286 { "help", no_argument, NULL, ARG_HELP },
6295 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
6299 return runlevel_help();
6305 assert_not_reached("Unhandled option");
6309 if (optind < argc) {
6310 log_error("Too many arguments.");
6317 static int parse_argv(int argc, char *argv[]) {
6321 if (program_invocation_short_name) {
6323 if (strstr(program_invocation_short_name, "halt")) {
6324 arg_action = ACTION_HALT;
6325 return halt_parse_argv(argc, argv);
6326 } else if (strstr(program_invocation_short_name, "poweroff")) {
6327 arg_action = ACTION_POWEROFF;
6328 return halt_parse_argv(argc, argv);
6329 } else if (strstr(program_invocation_short_name, "reboot")) {
6331 arg_action = ACTION_KEXEC;
6333 arg_action = ACTION_REBOOT;
6334 return halt_parse_argv(argc, argv);
6335 } else if (strstr(program_invocation_short_name, "shutdown")) {
6336 arg_action = ACTION_POWEROFF;
6337 return shutdown_parse_argv(argc, argv);
6338 } else if (strstr(program_invocation_short_name, "init")) {
6340 if (sd_booted() > 0) {
6341 arg_action = _ACTION_INVALID;
6342 return telinit_parse_argv(argc, argv);
6344 /* Hmm, so some other init system is
6345 * running, we need to forward this
6346 * request to it. For now we simply
6347 * guess that it is Upstart. */
6349 execv(TELINIT, argv);
6351 log_error("Couldn't find an alternative telinit implementation to spawn.");
6355 } else if (strstr(program_invocation_short_name, "runlevel")) {
6356 arg_action = ACTION_RUNLEVEL;
6357 return runlevel_parse_argv(argc, argv);
6361 arg_action = ACTION_SYSTEMCTL;
6362 return systemctl_parse_argv(argc, argv);
6365 _pure_ static int action_to_runlevel(void) {
6367 static const char table[_ACTION_MAX] = {
6368 [ACTION_HALT] = '0',
6369 [ACTION_POWEROFF] = '0',
6370 [ACTION_REBOOT] = '6',
6371 [ACTION_RUNLEVEL2] = '2',
6372 [ACTION_RUNLEVEL3] = '3',
6373 [ACTION_RUNLEVEL4] = '4',
6374 [ACTION_RUNLEVEL5] = '5',
6375 [ACTION_RESCUE] = '1'
6378 assert(arg_action < _ACTION_MAX);
6380 return table[arg_action];
6383 static int talk_initctl(void) {
6385 struct init_request request = {
6386 .magic = INIT_MAGIC,
6388 .cmd = INIT_CMD_RUNLVL
6391 _cleanup_close_ int fd = -1;
6395 rl = action_to_runlevel();
6399 request.runlevel = rl;
6401 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
6403 if (errno == ENOENT)
6406 log_error("Failed to open "INIT_FIFO": %m");
6411 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
6413 log_error("Failed to write to "INIT_FIFO": %m");
6414 return errno > 0 ? -errno : -EIO;
6420 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
6422 static const struct {
6430 int (* const dispatch)(sd_bus *bus, char **args);
6436 { "list-units", MORE, 0, list_units },
6437 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
6438 { "list-sockets", MORE, 1, list_sockets },
6439 { "list-timers", MORE, 1, list_timers },
6440 { "list-jobs", MORE, 1, list_jobs },
6441 { "list-machines", MORE, 1, list_machines },
6442 { "clear-jobs", EQUAL, 1, daemon_reload },
6443 { "cancel", MORE, 2, cancel_job },
6444 { "start", MORE, 2, start_unit },
6445 { "stop", MORE, 2, start_unit },
6446 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6447 { "reload", MORE, 2, start_unit },
6448 { "restart", MORE, 2, start_unit },
6449 { "try-restart", MORE, 2, start_unit },
6450 { "reload-or-restart", MORE, 2, start_unit },
6451 { "reload-or-try-restart", MORE, 2, start_unit },
6452 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
6453 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6454 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
6455 { "isolate", EQUAL, 2, start_unit },
6456 { "kill", MORE, 2, kill_unit },
6457 { "is-active", MORE, 2, check_unit_active },
6458 { "check", MORE, 2, check_unit_active },
6459 { "is-failed", MORE, 2, check_unit_failed },
6460 { "show", MORE, 1, show },
6461 { "cat", MORE, 2, cat },
6462 { "status", MORE, 1, show },
6463 { "help", MORE, 2, show },
6464 { "snapshot", LESS, 2, snapshot },
6465 { "delete", MORE, 2, delete_snapshot },
6466 { "daemon-reload", EQUAL, 1, daemon_reload },
6467 { "daemon-reexec", EQUAL, 1, daemon_reload },
6468 { "show-environment", EQUAL, 1, show_environment },
6469 { "set-environment", MORE, 2, set_environment },
6470 { "unset-environment", MORE, 2, set_environment },
6471 { "import-environment", MORE, 1, import_environment},
6472 { "halt", EQUAL, 1, start_special, FORCE },
6473 { "poweroff", EQUAL, 1, start_special, FORCE },
6474 { "reboot", EQUAL, 1, start_special, FORCE },
6475 { "kexec", EQUAL, 1, start_special },
6476 { "suspend", EQUAL, 1, start_special },
6477 { "hibernate", EQUAL, 1, start_special },
6478 { "hybrid-sleep", EQUAL, 1, start_special },
6479 { "default", EQUAL, 1, start_special },
6480 { "rescue", EQUAL, 1, start_special },
6481 { "emergency", EQUAL, 1, start_special },
6482 { "exit", EQUAL, 1, start_special },
6483 { "reset-failed", MORE, 1, reset_failed },
6484 { "enable", MORE, 2, enable_unit, NOBUS },
6485 { "disable", MORE, 2, enable_unit, NOBUS },
6486 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
6487 { "reenable", MORE, 2, enable_unit, NOBUS },
6488 { "preset", MORE, 2, enable_unit, NOBUS },
6489 { "mask", MORE, 2, enable_unit, NOBUS },
6490 { "unmask", MORE, 2, enable_unit, NOBUS },
6491 { "link", MORE, 2, enable_unit, NOBUS },
6492 { "switch-root", MORE, 2, switch_root },
6493 { "list-dependencies", LESS, 2, list_dependencies },
6494 { "set-default", EQUAL, 2, set_default, NOBUS },
6495 { "get-default", EQUAL, 1, get_default, NOBUS },
6496 { "set-property", MORE, 3, set_property },
6505 left = argc - optind;
6507 /* Special rule: no arguments (left == 0) means "list-units" */
6509 if (streq(argv[optind], "help") && !argv[optind+1]) {
6510 log_error("This command expects one or more "
6511 "unit names. Did you mean --help?");
6515 for (; verb->verb; verb++)
6516 if (streq(argv[optind], verb->verb))
6519 log_error("Unknown operation '%s'.", argv[optind]);
6524 switch (verb->argc_cmp) {
6527 if (left != verb->argc) {
6528 log_error("Invalid number of arguments.");
6535 if (left < verb->argc) {
6536 log_error("Too few arguments.");
6543 if (left > verb->argc) {
6544 log_error("Too many arguments.");
6551 assert_not_reached("Unknown comparison operator.");
6554 /* Require a bus connection for all operations but
6556 if (verb->bus == NOBUS) {
6557 if (!bus && !avoid_bus()) {
6558 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6563 if (running_in_chroot() > 0) {
6564 log_info("Running in chroot, ignoring request.");
6568 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
6569 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6574 return verb->dispatch(bus, argv + optind);
6577 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
6579 struct sd_shutdown_command c = {
6586 union sockaddr_union sockaddr = {
6587 .un.sun_family = AF_UNIX,
6588 .un.sun_path = "/run/systemd/shutdownd",
6591 struct iovec iovec[2] = {{
6592 .iov_base = (char*) &c,
6593 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
6596 struct msghdr msghdr = {
6597 .msg_name = &sockaddr,
6598 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
6599 + strlen("/run/systemd/shutdownd"),
6604 _cleanup_close_ int fd;
6606 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
6610 if (!isempty(message)) {
6611 iovec[1].iov_base = (char*) message;
6612 iovec[1].iov_len = strlen(message);
6613 msghdr.msg_iovlen++;
6616 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
6622 static int reload_with_fallback(sd_bus *bus) {
6625 /* First, try systemd via D-Bus. */
6626 if (daemon_reload(bus, NULL) >= 0)
6630 /* Nothing else worked, so let's try signals */
6631 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
6633 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
6634 log_error("kill() failed: %m");
6641 static int start_with_fallback(sd_bus *bus) {
6644 /* First, try systemd via D-Bus. */
6645 if (start_unit(bus, NULL) >= 0)
6649 /* Nothing else worked, so let's try
6651 if (talk_initctl() > 0)
6654 log_error("Failed to talk to init daemon.");
6658 warn_wall(arg_action);
6662 static int halt_now(enum action a) {
6664 /* Make sure C-A-D is handled by the kernel from this
6666 reboot(RB_ENABLE_CAD);
6671 log_info("Halting.");
6672 reboot(RB_HALT_SYSTEM);
6675 case ACTION_POWEROFF:
6676 log_info("Powering off.");
6677 reboot(RB_POWER_OFF);
6680 case ACTION_REBOOT: {
6681 _cleanup_free_ char *param = NULL;
6683 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
6684 log_info("Rebooting with argument '%s'.", param);
6685 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
6686 LINUX_REBOOT_CMD_RESTART2, param);
6689 log_info("Rebooting.");
6690 reboot(RB_AUTOBOOT);
6695 assert_not_reached("Unknown action.");
6699 static int halt_main(sd_bus *bus) {
6702 r = check_inhibitors(bus, arg_action);
6706 if (geteuid() != 0) {
6707 /* Try logind if we are a normal user and no special
6708 * mode applies. Maybe PolicyKit allows us to shutdown
6711 if (arg_when <= 0 &&
6714 (arg_action == ACTION_POWEROFF ||
6715 arg_action == ACTION_REBOOT)) {
6716 r = reboot_with_logind(bus, arg_action);
6721 log_error("Must be root.");
6726 _cleanup_free_ char *m;
6728 m = strv_join(arg_wall, " ");
6732 r = send_shutdownd(arg_when,
6733 arg_action == ACTION_HALT ? 'H' :
6734 arg_action == ACTION_POWEROFF ? 'P' :
6735 arg_action == ACTION_KEXEC ? 'K' :
6742 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6744 char date[FORMAT_TIMESTAMP_MAX];
6746 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6747 format_timestamp(date, sizeof(date), arg_when));
6752 if (!arg_dry && !arg_force)
6753 return start_with_fallback(bus);
6756 if (sd_booted() > 0)
6757 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6759 r = utmp_put_shutdown();
6761 log_warning("Failed to write utmp record: %s", strerror(-r));
6768 r = halt_now(arg_action);
6769 log_error("Failed to reboot: %s", strerror(-r));
6774 static int runlevel_main(void) {
6775 int r, runlevel, previous;
6777 r = utmp_get_runlevel(&runlevel, &previous);
6784 previous <= 0 ? 'N' : previous,
6785 runlevel <= 0 ? 'N' : runlevel);
6790 int main(int argc, char*argv[]) {
6791 _cleanup_bus_unref_ sd_bus *bus = NULL;
6794 setlocale(LC_ALL, "");
6795 log_parse_environment();
6798 /* Explicitly not on_tty() to avoid setting cached value.
6799 * This becomes relevant for piping output which might be
6801 original_stdout_is_tty = isatty(STDOUT_FILENO);
6803 r = parse_argv(argc, argv);
6807 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6808 * let's shortcut this */
6809 if (arg_action == ACTION_RUNLEVEL) {
6810 r = runlevel_main();
6814 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6815 log_info("Running in chroot, ignoring request.");
6821 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
6823 /* systemctl_main() will print an error message for the bus
6824 * connection, but only if it needs to */
6826 switch (arg_action) {
6828 case ACTION_SYSTEMCTL:
6829 r = systemctl_main(bus, argc, argv, r);
6833 case ACTION_POWEROFF:
6839 case ACTION_RUNLEVEL2:
6840 case ACTION_RUNLEVEL3:
6841 case ACTION_RUNLEVEL4:
6842 case ACTION_RUNLEVEL5:
6844 case ACTION_EMERGENCY:
6845 case ACTION_DEFAULT:
6846 r = start_with_fallback(bus);
6851 r = reload_with_fallback(bus);
6854 case ACTION_CANCEL_SHUTDOWN: {
6855 _cleanup_free_ char *m = NULL;
6858 m = strv_join(arg_wall, " ");
6865 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6867 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6871 case ACTION_RUNLEVEL:
6872 case _ACTION_INVALID:
6874 assert_not_reached("Unknown action");
6879 ask_password_agent_close();
6880 polkit_agent_close();
6882 strv_free(arg_types);
6883 strv_free(arg_states);
6884 strv_free(arg_properties);
6886 return r < 0 ? EXIT_FAILURE : r;