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(
2310 "sender='org.freedesktop.systemd1',"
2311 "interface='org.freedesktop.systemd1.Manager',"
2312 "member='JobRemoved',"
2313 "path='/org/freedesktop/systemd1'",
2316 log_error("Failed to add match");
2320 /* This is slightly dirty, since we don't undo the match registrations. */
2324 static int bus_process_wait(sd_bus *bus) {
2328 r = sd_bus_process(bus, NULL);
2333 r = sd_bus_wait(bus, (uint64_t) -1);
2339 static int check_wait_response(WaitData *d) {
2345 if (streq(d->result, "timeout"))
2346 log_error("Job for %s timed out.", strna(d->name));
2347 else if (streq(d->result, "canceled"))
2348 log_error("Job for %s canceled.", strna(d->name));
2349 else if (streq(d->result, "dependency"))
2350 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d->name));
2351 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2352 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d->name), strna(d->name));
2355 if (streq(d->result, "timeout"))
2357 else if (streq(d->result, "canceled"))
2359 else if (streq(d->result, "dependency"))
2361 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2367 static int wait_for_jobs(sd_bus *bus, Set *s) {
2368 _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
2369 WaitData d = { .set = s };
2375 q = sd_bus_add_filter(bus, &slot, wait_filter, &d);
2379 while (!set_isempty(s)) {
2380 q = bus_process_wait(bus);
2382 log_error("Failed to wait for response: %s", strerror(-r));
2387 q = check_wait_response(&d);
2388 /* Return the first error as it is most likely to be
2390 if (q < 0 && r == 0)
2392 log_debug("Got result %s/%s for job %s",
2393 strna(d.result), strerror(-q), strna(d.name));
2406 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2407 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2408 _cleanup_free_ char *n = NULL, *state = NULL;
2414 n = unit_name_mangle(name, MANGLE_NOGLOB);
2418 /* We don't use unit_dbus_path_from_name() directly since we
2419 * don't want to load the unit if it isn't loaded. */
2421 r = sd_bus_call_method(
2423 "org.freedesktop.systemd1",
2424 "/org/freedesktop/systemd1",
2425 "org.freedesktop.systemd1.Manager",
2436 r = sd_bus_message_read(reply, "o", &path);
2438 return bus_log_parse_error(r);
2440 r = sd_bus_get_property_string(
2442 "org.freedesktop.systemd1",
2444 "org.freedesktop.systemd1.Unit",
2457 return nulstr_contains(good_states, state);
2460 static int check_triggering_units(
2464 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2465 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2466 _cleanup_strv_free_ char **triggered_by = NULL;
2467 bool print_warning_label = true;
2471 n = unit_name_mangle(name, MANGLE_NOGLOB);
2475 path = unit_dbus_path_from_name(n);
2479 r = sd_bus_get_property_string(
2481 "org.freedesktop.systemd1",
2483 "org.freedesktop.systemd1.Unit",
2488 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2492 if (streq(state, "masked"))
2495 r = sd_bus_get_property_strv(
2497 "org.freedesktop.systemd1",
2499 "org.freedesktop.systemd1.Unit",
2504 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2508 STRV_FOREACH(i, triggered_by) {
2509 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2511 log_error("Failed to check unit: %s", strerror(-r));
2518 if (print_warning_label) {
2519 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2520 print_warning_label = false;
2523 log_warning(" %s", *i);
2529 static const char *verb_to_method(const char *verb) {
2532 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2533 if (streq_ptr(unit_actions[i].verb, verb))
2534 return unit_actions[i].method;
2539 static const char *method_to_verb(const char *method) {
2542 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2543 if (streq_ptr(unit_actions[i].method, method))
2544 return unit_actions[i].verb;
2549 static int start_unit_one(
2554 sd_bus_error *error,
2557 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2566 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2567 r = sd_bus_call_method(
2569 "org.freedesktop.systemd1",
2570 "/org/freedesktop/systemd1",
2571 "org.freedesktop.systemd1.Manager",
2579 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2580 /* There's always a fallback possible for
2581 * legacy actions. */
2582 return -EADDRNOTAVAIL;
2584 verb = method_to_verb(method);
2586 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2590 r = sd_bus_message_read(reply, "o", &path);
2592 return bus_log_parse_error(r);
2594 if (need_daemon_reload(bus, name) > 0)
2595 log_warning("Warning: Unit file of %s changed on disk, 'systemctl%s daemon-reload' recommended.",
2596 name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2605 log_debug("Adding %s to the set", p);
2606 r = set_consume(s, p);
2614 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2616 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2620 STRV_FOREACH(name, names) {
2624 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2626 t = unit_name_mangle(*name, MANGLE_GLOB);
2630 if (string_is_glob(t))
2631 r = strv_consume(&globs, t);
2633 r = strv_consume(&mangled, t);
2638 /* Query the manager only if any of the names are a glob, since
2639 * this is fairly expensive */
2640 if (!strv_isempty(globs)) {
2641 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2642 _cleanup_free_ UnitInfo *unit_infos = NULL;
2644 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2648 for (i = 0; i < r; i++)
2649 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2654 mangled = NULL; /* do not free */
2659 static const struct {
2663 } action_table[_ACTION_MAX] = {
2664 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2665 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2666 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2667 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2668 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
2669 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
2670 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
2671 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
2672 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2673 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2674 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2675 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2676 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2677 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2678 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2681 static enum action verb_to_action(const char *verb) {
2684 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2685 if (streq_ptr(action_table[i].verb, verb))
2688 return _ACTION_INVALID;
2691 static int start_unit(sd_bus *bus, char **args) {
2692 _cleanup_set_free_free_ Set *s = NULL;
2693 _cleanup_strv_free_ char **names = NULL;
2694 const char *method, *mode, *one_name;
2700 ask_password_agent_open_if_enabled();
2702 if (arg_action == ACTION_SYSTEMCTL) {
2704 method = verb_to_method(args[0]);
2705 action = verb_to_action(args[0]);
2707 mode = streq(args[0], "isolate") ? "isolate" :
2708 action_table[action].mode ?: arg_job_mode;
2710 one_name = action_table[action].target;
2712 assert(arg_action < ELEMENTSOF(action_table));
2713 assert(action_table[arg_action].target);
2715 method = "StartUnit";
2717 mode = action_table[arg_action].mode;
2718 one_name = action_table[arg_action].target;
2722 names = strv_new(one_name, NULL);
2724 r = expand_names(bus, args + 1, NULL, &names);
2726 log_error("Failed to expand names: %s", strerror(-r));
2729 if (!arg_no_block) {
2730 r = enable_wait_for_jobs(bus);
2732 log_error("Could not watch jobs: %s", strerror(-r));
2736 s = set_new(string_hash_func, string_compare_func);
2741 STRV_FOREACH(name, names) {
2742 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2745 q = start_unit_one(bus, method, *name, mode, &error, s);
2746 if (r >= 0 && q < 0)
2747 r = translate_bus_error_to_exit_status(q, &error);
2750 if (!arg_no_block) {
2753 q = wait_for_jobs(bus, s);
2757 /* When stopping units, warn if they can still be triggered by
2758 * another active unit (socket, path, timer) */
2759 if (!arg_quiet && streq(method, "StopUnit"))
2760 STRV_FOREACH(name, names)
2761 check_triggering_units(bus, *name);
2767 /* Ask systemd-logind, which might grant access to unprivileged users
2768 * through PolicyKit */
2769 static int reboot_with_logind(sd_bus *bus, enum action a) {
2771 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2778 polkit_agent_open_if_enabled();
2786 case ACTION_POWEROFF:
2787 method = "PowerOff";
2790 case ACTION_SUSPEND:
2794 case ACTION_HIBERNATE:
2795 method = "Hibernate";
2798 case ACTION_HYBRID_SLEEP:
2799 method = "HybridSleep";
2806 r = sd_bus_call_method(
2808 "org.freedesktop.login1",
2809 "/org/freedesktop/login1",
2810 "org.freedesktop.login1.Manager",
2816 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2824 static int check_inhibitors(sd_bus *bus, enum action a) {
2826 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2827 _cleanup_strv_free_ char **sessions = NULL;
2828 const char *what, *who, *why, *mode;
2837 if (arg_ignore_inhibitors || arg_force > 0)
2849 r = sd_bus_call_method(
2851 "org.freedesktop.login1",
2852 "/org/freedesktop/login1",
2853 "org.freedesktop.login1.Manager",
2859 /* If logind is not around, then there are no inhibitors... */
2862 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2864 return bus_log_parse_error(r);
2866 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2867 _cleanup_free_ char *comm = NULL, *user = NULL;
2868 _cleanup_strv_free_ char **sv = NULL;
2870 if (!streq(mode, "block"))
2873 sv = strv_split(what, ":");
2877 if (!strv_contains(sv,
2879 a == ACTION_POWEROFF ||
2880 a == ACTION_REBOOT ||
2881 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2884 get_process_comm(pid, &comm);
2885 user = uid_to_name(uid);
2887 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
2888 who, pid, strna(comm), strna(user), why);
2893 return bus_log_parse_error(r);
2895 r = sd_bus_message_exit_container(reply);
2897 return bus_log_parse_error(r);
2899 /* Check for current sessions */
2900 sd_get_sessions(&sessions);
2901 STRV_FOREACH(s, sessions) {
2902 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2904 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2907 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2910 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2913 sd_session_get_tty(*s, &tty);
2914 sd_session_get_seat(*s, &seat);
2915 sd_session_get_service(*s, &service);
2916 user = uid_to_name(uid);
2918 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2925 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2926 action_table[a].verb);
2934 static int start_special(sd_bus *bus, char **args) {
2940 a = verb_to_action(args[0]);
2942 r = check_inhibitors(bus, a);
2946 if (arg_force >= 2 && geteuid() != 0) {
2947 log_error("Must be root.");
2951 if (arg_force >= 2 &&
2952 (a == ACTION_HALT ||
2953 a == ACTION_POWEROFF ||
2954 a == ACTION_REBOOT))
2957 if (arg_force >= 1 &&
2958 (a == ACTION_HALT ||
2959 a == ACTION_POWEROFF ||
2960 a == ACTION_REBOOT ||
2961 a == ACTION_KEXEC ||
2963 return daemon_reload(bus, args);
2965 /* first try logind, to allow authentication with polkit */
2966 if (geteuid() != 0 &&
2967 (a == ACTION_POWEROFF ||
2968 a == ACTION_REBOOT ||
2969 a == ACTION_SUSPEND ||
2970 a == ACTION_HIBERNATE ||
2971 a == ACTION_HYBRID_SLEEP)) {
2972 r = reboot_with_logind(bus, a);
2977 r = start_unit(bus, args);
2978 if (r == EXIT_SUCCESS)
2984 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
2985 _cleanup_strv_free_ char **names = NULL;
2992 r = expand_names(bus, args, NULL, &names);
2994 log_error("Failed to expand names: %s", strerror(-r));
2998 STRV_FOREACH(name, names) {
3001 state = check_one_unit(bus, *name, good_states, arg_quiet);
3011 static int check_unit_active(sd_bus *bus, char **args) {
3012 /* According to LSB: 3, "program is not running" */
3013 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
3016 static int check_unit_failed(sd_bus *bus, char **args) {
3017 return check_unit_generic(bus, 1, "failed\0", args + 1);
3020 static int kill_unit(sd_bus *bus, char **args) {
3021 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3022 _cleanup_strv_free_ char **names = NULL;
3030 arg_kill_who = "all";
3032 r = expand_names(bus, args + 1, NULL, &names);
3034 log_error("Failed to expand names: %s", strerror(-r));
3036 STRV_FOREACH(name, names) {
3037 q = sd_bus_call_method(
3039 "org.freedesktop.systemd1",
3040 "/org/freedesktop/systemd1",
3041 "org.freedesktop.systemd1.Manager",
3045 "ssi", *names, arg_kill_who, arg_signal);
3047 log_error("Failed to kill unit %s: %s",
3048 *names, bus_error_message(&error, r));
3057 typedef struct ExecStatusInfo {
3065 usec_t start_timestamp;
3066 usec_t exit_timestamp;
3071 LIST_FIELDS(struct ExecStatusInfo, exec);
3074 static void exec_status_info_free(ExecStatusInfo *i) {
3083 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3084 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3087 int32_t code, status;
3093 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3095 return bus_log_parse_error(r);
3099 r = sd_bus_message_read(m, "s", &path);
3101 return bus_log_parse_error(r);
3103 i->path = strdup(path);
3107 r = sd_bus_message_read_strv(m, &i->argv);
3109 return bus_log_parse_error(r);
3111 r = sd_bus_message_read(m,
3114 &start_timestamp, &start_timestamp_monotonic,
3115 &exit_timestamp, &exit_timestamp_monotonic,
3119 return bus_log_parse_error(r);
3122 i->start_timestamp = (usec_t) start_timestamp;
3123 i->exit_timestamp = (usec_t) exit_timestamp;
3124 i->pid = (pid_t) pid;
3128 r = sd_bus_message_exit_container(m);
3130 return bus_log_parse_error(r);
3135 typedef struct UnitStatusInfo {
3137 const char *load_state;
3138 const char *active_state;
3139 const char *sub_state;
3140 const char *unit_file_state;
3142 const char *description;
3143 const char *following;
3145 char **documentation;
3147 const char *fragment_path;
3148 const char *source_path;
3149 const char *control_group;
3151 char **dropin_paths;
3153 const char *load_error;
3156 usec_t inactive_exit_timestamp;
3157 usec_t inactive_exit_timestamp_monotonic;
3158 usec_t active_enter_timestamp;
3159 usec_t active_exit_timestamp;
3160 usec_t inactive_enter_timestamp;
3162 bool need_daemon_reload;
3167 const char *status_text;
3168 const char *pid_file;
3171 usec_t start_timestamp;
3172 usec_t exit_timestamp;
3174 int exit_code, exit_status;
3176 usec_t condition_timestamp;
3177 bool condition_result;
3178 bool failed_condition_trigger;
3179 bool failed_condition_negate;
3180 const char *failed_condition;
3181 const char *failed_condition_param;
3184 unsigned n_accepted;
3185 unsigned n_connections;
3188 /* Pairs of type, path */
3192 const char *sysfs_path;
3194 /* Mount, Automount */
3200 LIST_HEAD(ExecStatusInfo, exec);
3203 static void print_status_info(
3208 const char *active_on, *active_off, *on, *off, *ss;
3210 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3211 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3214 arg_all * OUTPUT_SHOW_ALL |
3215 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
3216 on_tty() * OUTPUT_COLOR |
3217 !arg_quiet * OUTPUT_WARN_CUTOFF |
3218 arg_full * OUTPUT_FULL_WIDTH;
3223 /* This shows pretty information about a unit. See
3224 * print_property() for a low-level property printer */
3226 if (streq_ptr(i->active_state, "failed")) {
3227 active_on = ansi_highlight_red();
3228 active_off = ansi_highlight_off();
3229 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3230 active_on = ansi_highlight_green();
3231 active_off = ansi_highlight_off();
3233 active_on = active_off = "";
3235 printf("%s%s%s %s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3237 if (i->description && !streq_ptr(i->id, i->description))
3238 printf(" - %s", i->description);
3243 printf(" Follow: unit currently follows state of %s\n", i->following);
3245 if (streq_ptr(i->load_state, "error")) {
3246 on = ansi_highlight_red();
3247 off = ansi_highlight_off();
3251 path = i->source_path ? i->source_path : i->fragment_path;
3254 printf(" Loaded: %s%s%s (Reason: %s)\n",
3255 on, strna(i->load_state), off, i->load_error);
3256 else if (path && i->unit_file_state)
3257 printf(" Loaded: %s%s%s (%s; %s)\n",
3258 on, strna(i->load_state), off, path, i->unit_file_state);
3260 printf(" Loaded: %s%s%s (%s)\n",
3261 on, strna(i->load_state), off, path);
3263 printf(" Loaded: %s%s%s\n",
3264 on, strna(i->load_state), off);
3266 if (!strv_isempty(i->dropin_paths)) {
3267 _cleanup_free_ char *dir = NULL;
3271 STRV_FOREACH(dropin, i->dropin_paths) {
3272 if (! dir || last) {
3273 printf(dir ? " " : " Drop-In: ");
3278 if (path_get_parent(*dropin, &dir) < 0) {
3283 printf("%s\n %s", dir,
3284 draw_special_char(DRAW_TREE_RIGHT));
3287 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3289 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3293 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3295 printf(" Active: %s%s (%s)%s",
3296 active_on, strna(i->active_state), ss, active_off);
3298 printf(" Active: %s%s%s",
3299 active_on, strna(i->active_state), active_off);
3301 if (!isempty(i->result) && !streq(i->result, "success"))
3302 printf(" (Result: %s)", i->result);
3304 timestamp = (streq_ptr(i->active_state, "active") ||
3305 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
3306 (streq_ptr(i->active_state, "inactive") ||
3307 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
3308 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
3309 i->active_exit_timestamp;
3311 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3312 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3315 printf(" since %s; %s\n", s2, s1);
3317 printf(" since %s\n", s2);
3321 if (!i->condition_result && i->condition_timestamp > 0) {
3322 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3323 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3325 printf(" start condition failed at %s%s%s\n",
3326 s2, s1 ? "; " : "", s1 ? s1 : "");
3327 if (i->failed_condition_trigger)
3328 printf(" none of the trigger conditions were met\n");
3329 else if (i->failed_condition)
3330 printf(" %s=%s%s was not met\n",
3331 i->failed_condition,
3332 i->failed_condition_negate ? "!" : "",
3333 i->failed_condition_param);
3337 printf(" Device: %s\n", i->sysfs_path);
3339 printf(" Where: %s\n", i->where);
3341 printf(" What: %s\n", i->what);
3343 STRV_FOREACH(t, i->documentation)
3344 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3346 STRV_FOREACH_PAIR(t, t2, i->listen)
3347 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3350 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3352 LIST_FOREACH(exec, p, i->exec) {
3353 _cleanup_free_ char *argv = NULL;
3356 /* Only show exited processes here */
3360 argv = strv_join(p->argv, " ");
3361 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
3363 good = is_clean_exit_lsb(p->code, p->status, NULL);
3365 on = ansi_highlight_red();
3366 off = ansi_highlight_off();
3370 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3372 if (p->code == CLD_EXITED) {
3375 printf("status=%i", p->status);
3377 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3382 printf("signal=%s", signal_to_string(p->status));
3384 printf(")%s\n", off);
3386 if (i->main_pid == p->pid &&
3387 i->start_timestamp == p->start_timestamp &&
3388 i->exit_timestamp == p->start_timestamp)
3389 /* Let's not show this twice */
3392 if (p->pid == i->control_pid)
3396 if (i->main_pid > 0 || i->control_pid > 0) {
3397 if (i->main_pid > 0) {
3398 printf(" Main PID: %u", (unsigned) i->main_pid);
3401 _cleanup_free_ char *comm = NULL;
3402 get_process_comm(i->main_pid, &comm);
3404 printf(" (%s)", comm);
3405 } else if (i->exit_code > 0) {
3406 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3408 if (i->exit_code == CLD_EXITED) {
3411 printf("status=%i", i->exit_status);
3413 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3418 printf("signal=%s", signal_to_string(i->exit_status));
3422 if (i->control_pid > 0)
3426 if (i->control_pid > 0) {
3427 _cleanup_free_ char *c = NULL;
3429 printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
3431 get_process_comm(i->control_pid, &c);
3440 printf(" Status: \"%s\"\n", i->status_text);
3442 if (i->control_group &&
3443 (i->main_pid > 0 || i->control_pid > 0 ||
3444 ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_CONTAINER) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3447 printf(" CGroup: %s\n", i->control_group);
3449 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
3452 static const char prefix[] = " ";
3455 if (c > sizeof(prefix) - 1)
3456 c -= sizeof(prefix) - 1;
3460 if (i->main_pid > 0)
3461 extra[k++] = i->main_pid;
3463 if (i->control_pid > 0)
3464 extra[k++] = i->control_pid;
3466 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, flags);
3470 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3471 show_journal_by_unit(stdout,
3475 i->inactive_exit_timestamp_monotonic,
3478 flags | OUTPUT_BEGIN_NEWLINE,
3479 arg_scope == UNIT_FILE_SYSTEM,
3483 if (i->need_daemon_reload)
3484 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
3485 ansi_highlight_red(),
3486 ansi_highlight_off(),
3487 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
3490 static void show_unit_help(UnitStatusInfo *i) {
3495 if (!i->documentation) {
3496 log_info("Documentation for %s not known.", i->id);
3500 STRV_FOREACH(p, i->documentation) {
3502 if (startswith(*p, "man:")) {
3503 const char *args[4] = { "man", NULL, NULL, NULL };
3504 _cleanup_free_ char *page = NULL, *section = NULL;
3511 if ((*p)[k-1] == ')')
3512 e = strrchr(*p, '(');
3515 page = strndup((*p) + 4, e - *p - 4);
3516 section = strndup(e + 1, *p + k - e - 2);
3517 if (!page || !section) {
3529 log_error("Failed to fork: %m");
3535 execvp(args[0], (char**) args);
3536 log_error("Failed to execute man: %m");
3537 _exit(EXIT_FAILURE);
3540 wait_for_terminate(pid, NULL);
3542 log_info("Can't show: %s", *p);
3546 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3553 switch (contents[0]) {
3555 case SD_BUS_TYPE_STRING: {
3558 r = sd_bus_message_read(m, "s", &s);
3560 return bus_log_parse_error(r);
3563 if (streq(name, "Id"))
3565 else if (streq(name, "LoadState"))
3567 else if (streq(name, "ActiveState"))
3568 i->active_state = s;
3569 else if (streq(name, "SubState"))
3571 else if (streq(name, "Description"))
3573 else if (streq(name, "FragmentPath"))
3574 i->fragment_path = s;
3575 else if (streq(name, "SourcePath"))
3578 else if (streq(name, "DefaultControlGroup")) {
3580 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3582 i->control_group = e;
3585 else if (streq(name, "ControlGroup"))
3586 i->control_group = s;
3587 else if (streq(name, "StatusText"))
3589 else if (streq(name, "PIDFile"))
3591 else if (streq(name, "SysFSPath"))
3593 else if (streq(name, "Where"))
3595 else if (streq(name, "What"))
3597 else if (streq(name, "Following"))
3599 else if (streq(name, "UnitFileState"))
3600 i->unit_file_state = s;
3601 else if (streq(name, "Result"))
3608 case SD_BUS_TYPE_BOOLEAN: {
3611 r = sd_bus_message_read(m, "b", &b);
3613 return bus_log_parse_error(r);
3615 if (streq(name, "Accept"))
3617 else if (streq(name, "NeedDaemonReload"))
3618 i->need_daemon_reload = b;
3619 else if (streq(name, "ConditionResult"))
3620 i->condition_result = b;
3625 case SD_BUS_TYPE_UINT32: {
3628 r = sd_bus_message_read(m, "u", &u);
3630 return bus_log_parse_error(r);
3632 if (streq(name, "MainPID")) {
3634 i->main_pid = (pid_t) u;
3637 } else if (streq(name, "ControlPID"))
3638 i->control_pid = (pid_t) u;
3639 else if (streq(name, "ExecMainPID")) {
3641 i->main_pid = (pid_t) u;
3642 } else if (streq(name, "NAccepted"))
3644 else if (streq(name, "NConnections"))
3645 i->n_connections = u;
3650 case SD_BUS_TYPE_INT32: {
3653 r = sd_bus_message_read(m, "i", &j);
3655 return bus_log_parse_error(r);
3657 if (streq(name, "ExecMainCode"))
3658 i->exit_code = (int) j;
3659 else if (streq(name, "ExecMainStatus"))
3660 i->exit_status = (int) j;
3665 case SD_BUS_TYPE_UINT64: {
3668 r = sd_bus_message_read(m, "t", &u);
3670 return bus_log_parse_error(r);
3672 if (streq(name, "ExecMainStartTimestamp"))
3673 i->start_timestamp = (usec_t) u;
3674 else if (streq(name, "ExecMainExitTimestamp"))
3675 i->exit_timestamp = (usec_t) u;
3676 else if (streq(name, "ActiveEnterTimestamp"))
3677 i->active_enter_timestamp = (usec_t) u;
3678 else if (streq(name, "InactiveEnterTimestamp"))
3679 i->inactive_enter_timestamp = (usec_t) u;
3680 else if (streq(name, "InactiveExitTimestamp"))
3681 i->inactive_exit_timestamp = (usec_t) u;
3682 else if (streq(name, "InactiveExitTimestampMonotonic"))
3683 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3684 else if (streq(name, "ActiveExitTimestamp"))
3685 i->active_exit_timestamp = (usec_t) u;
3686 else if (streq(name, "ConditionTimestamp"))
3687 i->condition_timestamp = (usec_t) u;
3692 case SD_BUS_TYPE_ARRAY:
3694 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3695 _cleanup_free_ ExecStatusInfo *info = NULL;
3697 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3699 return bus_log_parse_error(r);
3701 info = new0(ExecStatusInfo, 1);
3705 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3707 info->name = strdup(name);
3711 LIST_PREPEND(exec, i->exec, info);
3713 info = new0(ExecStatusInfo, 1);
3719 return bus_log_parse_error(r);
3721 r = sd_bus_message_exit_container(m);
3723 return bus_log_parse_error(r);
3727 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3728 const char *type, *path;
3730 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3732 return bus_log_parse_error(r);
3734 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3736 r = strv_extend(&i->listen, type);
3740 r = strv_extend(&i->listen, path);
3745 return bus_log_parse_error(r);
3747 r = sd_bus_message_exit_container(m);
3749 return bus_log_parse_error(r);
3753 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3755 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3757 return bus_log_parse_error(r);
3759 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3761 r = sd_bus_message_read_strv(m, &i->documentation);
3763 return bus_log_parse_error(r);
3765 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3766 const char *cond, *param;
3767 int trigger, negate;
3770 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3772 return bus_log_parse_error(r);
3774 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3775 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3776 if (state < 0 && (!trigger || !i->failed_condition)) {
3777 i->failed_condition = cond;
3778 i->failed_condition_trigger = trigger;
3779 i->failed_condition_negate = negate;
3780 i->failed_condition_param = param;
3784 return bus_log_parse_error(r);
3786 r = sd_bus_message_exit_container(m);
3788 return bus_log_parse_error(r);
3795 case SD_BUS_TYPE_STRUCT_BEGIN:
3797 if (streq(name, "LoadError")) {
3798 const char *n, *message;
3800 r = sd_bus_message_read(m, "(ss)", &n, &message);
3802 return bus_log_parse_error(r);
3804 if (!isempty(message))
3805 i->load_error = message;
3818 r = sd_bus_message_skip(m, contents);
3820 return bus_log_parse_error(r);
3825 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3831 /* This is a low-level property printer, see
3832 * print_status_info() for the nicer output */
3834 if (arg_properties && !strv_find(arg_properties, name)) {
3835 /* skip what we didn't read */
3836 r = sd_bus_message_skip(m, contents);
3840 switch (contents[0]) {
3842 case SD_BUS_TYPE_STRUCT_BEGIN:
3844 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3847 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3849 return bus_log_parse_error(r);
3852 printf("%s=%u\n", name, (unsigned) u);
3854 printf("%s=\n", name);
3858 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3861 r = sd_bus_message_read(m, "(so)", &s, NULL);
3863 return bus_log_parse_error(r);
3865 if (arg_all || !isempty(s))
3866 printf("%s=%s\n", name, s);
3870 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3871 const char *a = NULL, *b = NULL;
3873 r = sd_bus_message_read(m, "(ss)", &a, &b);
3875 return bus_log_parse_error(r);
3877 if (arg_all || !isempty(a) || !isempty(b))
3878 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3881 } else if (streq_ptr(name, "SystemCallFilter")) {
3882 _cleanup_strv_free_ char **l = NULL;
3885 r = sd_bus_message_enter_container(m, 'r', "bas");
3887 return bus_log_parse_error(r);
3889 r = sd_bus_message_read(m, "b", &whitelist);
3891 return bus_log_parse_error(r);
3893 r = sd_bus_message_read_strv(m, &l);
3895 return bus_log_parse_error(r);
3897 r = sd_bus_message_exit_container(m);
3899 return bus_log_parse_error(r);
3901 if (arg_all || whitelist || !strv_isempty(l)) {
3905 fputs(name, stdout);
3911 STRV_FOREACH(i, l) {
3919 fputc('\n', stdout);
3927 case SD_BUS_TYPE_ARRAY:
3929 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
3933 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
3935 return bus_log_parse_error(r);
3937 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
3938 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3941 return bus_log_parse_error(r);
3943 r = sd_bus_message_exit_container(m);
3945 return bus_log_parse_error(r);
3949 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
3950 const char *type, *path;
3952 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3954 return bus_log_parse_error(r);
3956 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3957 printf("%s=%s\n", type, path);
3959 return bus_log_parse_error(r);
3961 r = sd_bus_message_exit_container(m);
3963 return bus_log_parse_error(r);
3967 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3968 const char *type, *path;
3970 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3972 return bus_log_parse_error(r);
3974 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3975 printf("Listen%s=%s\n", type, path);
3977 return bus_log_parse_error(r);
3979 r = sd_bus_message_exit_container(m);
3981 return bus_log_parse_error(r);
3985 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
3987 uint64_t value, next_elapse;
3989 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
3991 return bus_log_parse_error(r);
3993 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
3994 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3996 printf("%s={ value=%s ; next_elapse=%s }\n",
3998 format_timespan(timespan1, sizeof(timespan1), value, 0),
3999 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
4002 return bus_log_parse_error(r);
4004 r = sd_bus_message_exit_container(m);
4006 return bus_log_parse_error(r);
4010 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
4011 ExecStatusInfo info = {};
4013 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
4015 return bus_log_parse_error(r);
4017 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
4018 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
4019 _cleanup_free_ char *tt;
4021 tt = strv_join(info.argv, " ");
4023 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
4027 yes_no(info.ignore),
4028 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
4029 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
4030 (unsigned) info. pid,
4031 sigchld_code_to_string(info.code),
4033 info.code == CLD_EXITED ? "" : "/",
4034 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
4037 strv_free(info.argv);
4041 r = sd_bus_message_exit_container(m);
4043 return bus_log_parse_error(r);
4047 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
4048 const char *path, *rwm;
4050 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4052 return bus_log_parse_error(r);
4054 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
4055 printf("%s=%s %s\n", name, strna(path), strna(rwm));
4057 return bus_log_parse_error(r);
4059 r = sd_bus_message_exit_container(m);
4061 return bus_log_parse_error(r);
4065 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
4069 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4071 return bus_log_parse_error(r);
4073 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4074 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
4076 return bus_log_parse_error(r);
4078 r = sd_bus_message_exit_container(m);
4080 return bus_log_parse_error(r);
4084 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
4088 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4090 return bus_log_parse_error(r);
4092 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4093 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
4095 return bus_log_parse_error(r);
4097 r = sd_bus_message_exit_container(m);
4099 return bus_log_parse_error(r);
4107 r = bus_print_property(name, m, arg_all);
4109 return bus_log_parse_error(r);
4112 r = sd_bus_message_skip(m, contents);
4114 return bus_log_parse_error(r);
4117 printf("%s=[unprintable]\n", name);
4123 static int show_one(
4127 bool show_properties,
4131 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4132 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4133 UnitStatusInfo info = {};
4140 log_debug("Showing one %s", path);
4142 r = sd_bus_call_method(
4144 "org.freedesktop.systemd1",
4146 "org.freedesktop.DBus.Properties",
4152 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4156 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4158 return bus_log_parse_error(r);
4165 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4166 const char *name, *contents;
4168 r = sd_bus_message_read(reply, "s", &name);
4170 return bus_log_parse_error(r);
4172 r = sd_bus_message_peek_type(reply, NULL, &contents);
4174 return bus_log_parse_error(r);
4176 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4178 return bus_log_parse_error(r);
4180 if (show_properties)
4181 r = print_property(name, reply, contents);
4183 r = status_property(name, reply, &info, contents);
4187 r = sd_bus_message_exit_container(reply);
4189 return bus_log_parse_error(r);
4191 r = sd_bus_message_exit_container(reply);
4193 return bus_log_parse_error(r);
4196 return bus_log_parse_error(r);
4198 r = sd_bus_message_exit_container(reply);
4200 return bus_log_parse_error(r);
4204 if (!show_properties) {
4205 if (streq(verb, "help"))
4206 show_unit_help(&info);
4208 print_status_info(&info, ellipsized);
4211 strv_free(info.documentation);
4212 strv_free(info.dropin_paths);
4213 strv_free(info.listen);
4215 if (!streq_ptr(info.active_state, "active") &&
4216 !streq_ptr(info.active_state, "reloading") &&
4217 streq(verb, "status")) {
4218 /* According to LSB: "program not running" */
4219 /* 0: program is running or service is OK
4220 * 1: program is dead and /run PID file exists
4221 * 2: program is dead and /run/lock lock file exists
4222 * 3: program is not running
4223 * 4: program or service status is unknown
4225 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4231 while ((p = info.exec)) {
4232 LIST_REMOVE(exec, info.exec, p);
4233 exec_status_info_free(p);
4239 static int get_unit_dbus_path_by_pid(
4244 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4245 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4249 r = sd_bus_call_method(
4251 "org.freedesktop.systemd1",
4252 "/org/freedesktop/systemd1",
4253 "org.freedesktop.systemd1.Manager",
4259 log_error("Failed to get unit for PID "PID_FMT": %s", pid, bus_error_message(&error, r));
4263 r = sd_bus_message_read(reply, "o", &u);
4265 return bus_log_parse_error(r);
4275 static int show_all(
4278 bool show_properties,
4282 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4283 _cleanup_free_ UnitInfo *unit_infos = NULL;
4288 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4292 pager_open_if_enabled();
4296 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4298 for (u = unit_infos; u < unit_infos + c; u++) {
4299 _cleanup_free_ char *p = NULL;
4301 p = unit_dbus_path_from_name(u->id);
4305 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4308 else if (r > 0 && ret == 0)
4315 static int show_system_status(sd_bus *bus) {
4316 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4317 _cleanup_free_ char *hn = NULL;
4318 struct machine_info mi = {};
4319 const char *on, *off;
4322 hn = gethostname_malloc();
4326 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4328 log_error("Failed to read server status: %s", strerror(-r));
4332 if (streq_ptr(mi.state, "degraded")) {
4333 on = ansi_highlight_red();
4334 off = ansi_highlight_off();
4335 } else if (!streq_ptr(mi.state, "running")) {
4336 on = ansi_highlight_yellow();
4337 off = ansi_highlight_off();
4341 printf("%s%s%s %s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4343 printf(" State: %s%s%s\n",
4344 on, strna(mi.state), off);
4346 printf(" Jobs: %u queued\n", mi.n_jobs);
4347 printf(" Failed: %u units\n", mi.n_failed_units);
4349 printf(" Since: %s; %s\n",
4350 format_timestamp(since2, sizeof(since2), mi.timestamp),
4351 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4353 printf(" CGroup: %s\n", mi.control_group ?: "/");
4354 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
4356 arg_all * OUTPUT_SHOW_ALL |
4357 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
4358 on_tty() * OUTPUT_COLOR |
4359 !arg_quiet * OUTPUT_WARN_CUTOFF |
4360 arg_full * OUTPUT_FULL_WIDTH;
4362 static const char prefix[] = " ";
4366 if (c > sizeof(prefix) - 1)
4367 c -= sizeof(prefix) - 1;
4371 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
4375 free(mi.control_group);
4380 static int show(sd_bus *bus, char **args) {
4381 bool show_properties, show_status, new_line = false;
4382 bool ellipsized = false;
4388 show_properties = streq(args[0], "show");
4389 show_status = streq(args[0], "status");
4391 if (show_properties)
4392 pager_open_if_enabled();
4394 /* If no argument is specified inspect the manager itself */
4396 if (show_properties && strv_length(args) <= 1)
4397 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4399 if (show_status && strv_length(args) <= 1) {
4401 pager_open_if_enabled();
4402 show_system_status(bus);
4406 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4408 _cleanup_free_ char **patterns = NULL;
4411 STRV_FOREACH(name, args + 1) {
4412 _cleanup_free_ char *unit = NULL;
4415 if (safe_atou32(*name, &id) < 0) {
4416 if (strv_push(&patterns, *name) < 0)
4420 } else if (show_properties) {
4421 /* Interpret as job id */
4422 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4426 /* Interpret as PID */
4427 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4434 r = show_one(args[0], bus, unit, show_properties,
4435 &new_line, &ellipsized);
4438 else if (r > 0 && ret == 0)
4442 if (!strv_isempty(patterns)) {
4443 _cleanup_strv_free_ char **names = NULL;
4445 r = expand_names(bus, patterns, NULL, &names);
4447 log_error("Failed to expand names: %s", strerror(-r));
4449 STRV_FOREACH(name, names) {
4450 _cleanup_free_ char *unit;
4452 unit = unit_dbus_path_from_name(*name);
4456 r = show_one(args[0], bus, unit, show_properties,
4457 &new_line, &ellipsized);
4460 else if (r > 0 && ret == 0)
4466 if (ellipsized && !arg_quiet)
4467 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4472 static int cat(sd_bus *bus, char **args) {
4473 _cleanup_free_ char *unit = NULL;
4474 _cleanup_strv_free_ char **names = NULL;
4482 r = expand_names(bus, args + 1, NULL, &names);
4484 log_error("Failed to expand names: %s", strerror(-r));
4486 pager_open_if_enabled();
4488 STRV_FOREACH(name, names) {
4489 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4490 _cleanup_strv_free_ char **dropin_paths = NULL;
4491 _cleanup_free_ char *fragment_path = NULL;
4494 unit = unit_dbus_path_from_name(*name);
4498 if (need_daemon_reload(bus, *name) > 0)
4499 log_warning("Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'.",
4500 *name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
4502 r = sd_bus_get_property_string(
4504 "org.freedesktop.systemd1",
4506 "org.freedesktop.systemd1.Unit",
4511 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
4515 r = sd_bus_get_property_strv(
4517 "org.freedesktop.systemd1",
4519 "org.freedesktop.systemd1.Unit",
4524 log_warning("Failed to get DropInPaths: %s", bus_error_message(&error, r));
4533 if (!isempty(fragment_path)) {
4534 printf("%s# %s%s\n",
4535 ansi_highlight_blue(),
4537 ansi_highlight_off());
4540 r = sendfile_full(STDOUT_FILENO, fragment_path);
4542 log_warning("Failed to cat %s: %s", fragment_path, strerror(-r));
4547 STRV_FOREACH(path, dropin_paths) {
4548 printf("%s%s# %s%s\n",
4549 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4550 ansi_highlight_blue(),
4552 ansi_highlight_off());
4555 r = sendfile_full(STDOUT_FILENO, *path);
4557 log_warning("Failed to cat %s: %s", *path, strerror(-r));
4563 return r < 0 ? r : 0;
4566 static int set_property(sd_bus *bus, char **args) {
4567 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4568 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4569 _cleanup_free_ char *n = NULL;
4573 r = sd_bus_message_new_method_call(
4576 "org.freedesktop.systemd1",
4577 "/org/freedesktop/systemd1",
4578 "org.freedesktop.systemd1.Manager",
4579 "SetUnitProperties");
4581 return bus_log_create_error(r);
4583 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4587 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4589 return bus_log_create_error(r);
4591 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4593 return bus_log_create_error(r);
4595 STRV_FOREACH(i, args + 2) {
4596 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4598 return bus_log_create_error(r);
4600 r = bus_append_unit_property_assignment(m, *i);
4604 r = sd_bus_message_close_container(m);
4606 return bus_log_create_error(r);
4609 r = sd_bus_message_close_container(m);
4611 return bus_log_create_error(r);
4613 r = sd_bus_call(bus, m, 0, &error, NULL);
4615 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4622 static int snapshot(sd_bus *bus, char **args) {
4623 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4624 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4625 _cleanup_free_ char *n = NULL, *id = NULL;
4629 if (strv_length(args) > 1)
4630 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4636 r = sd_bus_call_method(
4638 "org.freedesktop.systemd1",
4639 "/org/freedesktop/systemd1",
4640 "org.freedesktop.systemd1.Manager",
4646 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4650 r = sd_bus_message_read(reply, "o", &path);
4652 return bus_log_parse_error(r);
4654 r = sd_bus_get_property_string(
4656 "org.freedesktop.systemd1",
4658 "org.freedesktop.systemd1.Unit",
4663 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4673 static int delete_snapshot(sd_bus *bus, char **args) {
4674 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4675 _cleanup_strv_free_ char **names = NULL;
4681 r = expand_names(bus, args + 1, ".snapshot", &names);
4683 log_error("Failed to expand names: %s", strerror(-r));
4685 STRV_FOREACH(name, names) {
4686 q = sd_bus_call_method(
4688 "org.freedesktop.systemd1",
4689 "/org/freedesktop/systemd1",
4690 "org.freedesktop.systemd1.Manager",
4696 log_error("Failed to remove snapshot %s: %s",
4697 *name, bus_error_message(&error, r));
4706 static int daemon_reload(sd_bus *bus, char **args) {
4707 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4711 if (arg_action == ACTION_RELOAD)
4713 else if (arg_action == ACTION_REEXEC)
4714 method = "Reexecute";
4716 assert(arg_action == ACTION_SYSTEMCTL);
4719 streq(args[0], "clear-jobs") ||
4720 streq(args[0], "cancel") ? "ClearJobs" :
4721 streq(args[0], "daemon-reexec") ? "Reexecute" :
4722 streq(args[0], "reset-failed") ? "ResetFailed" :
4723 streq(args[0], "halt") ? "Halt" :
4724 streq(args[0], "poweroff") ? "PowerOff" :
4725 streq(args[0], "reboot") ? "Reboot" :
4726 streq(args[0], "kexec") ? "KExec" :
4727 streq(args[0], "exit") ? "Exit" :
4728 /* "daemon-reload" */ "Reload";
4731 r = sd_bus_call_method(
4733 "org.freedesktop.systemd1",
4734 "/org/freedesktop/systemd1",
4735 "org.freedesktop.systemd1.Manager",
4741 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4742 /* There's always a fallback possible for
4743 * legacy actions. */
4745 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4746 /* On reexecution, we expect a disconnect, not a
4750 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4752 return r < 0 ? r : 0;
4755 static int reset_failed(sd_bus *bus, char **args) {
4756 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4757 _cleanup_strv_free_ char **names = NULL;
4761 if (strv_length(args) <= 1)
4762 return daemon_reload(bus, args);
4764 r = expand_names(bus, args + 1, NULL, &names);
4766 log_error("Failed to expand names: %s", strerror(-r));
4768 STRV_FOREACH(name, names) {
4769 q = sd_bus_call_method(
4771 "org.freedesktop.systemd1",
4772 "/org/freedesktop/systemd1",
4773 "org.freedesktop.systemd1.Manager",
4779 log_error("Failed to reset failed state of unit %s: %s",
4780 *name, bus_error_message(&error, r));
4789 static int show_environment(sd_bus *bus, char **args) {
4790 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4791 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4795 pager_open_if_enabled();
4797 r = sd_bus_get_property(
4799 "org.freedesktop.systemd1",
4800 "/org/freedesktop/systemd1",
4801 "org.freedesktop.systemd1.Manager",
4807 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4811 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4813 return bus_log_parse_error(r);
4815 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4818 return bus_log_parse_error(r);
4820 r = sd_bus_message_exit_container(reply);
4822 return bus_log_parse_error(r);
4827 static int switch_root(sd_bus *bus, char **args) {
4828 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4829 _cleanup_free_ char *cmdline_init = NULL;
4830 const char *root, *init;
4834 l = strv_length(args);
4835 if (l < 2 || l > 3) {
4836 log_error("Wrong number of arguments.");
4845 r = parse_env_file("/proc/cmdline", WHITESPACE,
4846 "init", &cmdline_init,
4849 log_debug("Failed to parse /proc/cmdline: %s", strerror(-r));
4851 init = cmdline_init;
4858 const char *root_systemd_path = NULL, *root_init_path = NULL;
4860 root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
4861 root_init_path = strappenda3(root, "/", init);
4863 /* If the passed init is actually the same as the
4864 * systemd binary, then let's suppress it. */
4865 if (files_same(root_init_path, root_systemd_path) > 0)
4869 log_debug("Switching root - root: %s; init: %s", root, strna(init));
4871 r = sd_bus_call_method(
4873 "org.freedesktop.systemd1",
4874 "/org/freedesktop/systemd1",
4875 "org.freedesktop.systemd1.Manager",
4881 log_error("Failed to switch root: %s", bus_error_message(&error, r));
4888 static int set_environment(sd_bus *bus, char **args) {
4889 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4890 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4897 method = streq(args[0], "set-environment")
4899 : "UnsetEnvironment";
4901 r = sd_bus_message_new_method_call(
4904 "org.freedesktop.systemd1",
4905 "/org/freedesktop/systemd1",
4906 "org.freedesktop.systemd1.Manager",
4909 return bus_log_create_error(r);
4911 r = sd_bus_message_append_strv(m, args + 1);
4913 return bus_log_create_error(r);
4915 r = sd_bus_call(bus, m, 0, &error, NULL);
4917 log_error("Failed to set environment: %s", bus_error_message(&error, r));
4924 static int import_environment(sd_bus *bus, char **args) {
4925 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4926 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4932 r = sd_bus_message_new_method_call(
4935 "org.freedesktop.systemd1",
4936 "/org/freedesktop/systemd1",
4937 "org.freedesktop.systemd1.Manager",
4940 return bus_log_create_error(r);
4942 if (strv_isempty(args + 1))
4943 r = sd_bus_message_append_strv(m, environ);
4947 r = sd_bus_message_open_container(m, 'a', "s");
4949 return bus_log_create_error(r);
4951 STRV_FOREACH(a, args + 1) {
4953 if (!env_name_is_valid(*a)) {
4954 log_error("Not a valid environment variable name: %s", *a);
4958 STRV_FOREACH(b, environ) {
4961 eq = startswith(*b, *a);
4962 if (eq && *eq == '=') {
4964 r = sd_bus_message_append(m, "s", *b);
4966 return bus_log_create_error(r);
4973 r = sd_bus_message_close_container(m);
4976 return bus_log_create_error(r);
4978 r = sd_bus_call(bus, m, 0, &error, NULL);
4980 log_error("Failed to import environment: %s", bus_error_message(&error, r));
4987 static int enable_sysv_units(const char *verb, char **args) {
4990 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4991 unsigned f = 1, t = 1;
4992 _cleanup_lookup_paths_free_ LookupPaths paths = {};
4994 if (arg_scope != UNIT_FILE_SYSTEM)
4997 if (!streq(verb, "enable") &&
4998 !streq(verb, "disable") &&
4999 !streq(verb, "is-enabled"))
5002 /* Processes all SysV units, and reshuffles the array so that
5003 * afterwards only the native units remain */
5005 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, arg_root, NULL, NULL, NULL);
5010 for (f = 0; args[f]; f++) {
5012 _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL;
5013 bool found_native = false, found_sysv;
5015 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
5023 if (!endswith(name, ".service"))
5026 if (path_is_absolute(name))
5029 STRV_FOREACH(k, paths.unit_path) {
5030 _cleanup_free_ char *path = NULL;
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;
5050 if (!isempty(arg_root))
5051 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
5053 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
5059 p[strlen(p) - strlen(".service")] = 0;
5060 found_sysv = access(p, F_OK) >= 0;
5064 /* Mark this entry, so that we don't try enabling it as native unit */
5065 args[f] = (char*) "";
5067 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
5069 if (!isempty(arg_root))
5070 argv[c++] = q = strappend("--root=", arg_root);
5072 argv[c++] = basename(p);
5074 streq(verb, "enable") ? "on" :
5075 streq(verb, "disable") ? "off" : "--level=5";
5078 l = strv_join((char**)argv, " ");
5084 log_info("Executing %s", l);
5088 log_error("Failed to fork: %m");
5091 } else if (pid == 0) {
5094 execv(argv[0], (char**) argv);
5095 _exit(EXIT_FAILURE);
5098 j = wait_for_terminate(pid, &status);
5100 log_error("Failed to wait for child: %s", strerror(-r));
5105 if (status.si_code == CLD_EXITED) {
5106 if (streq(verb, "is-enabled")) {
5107 if (status.si_status == 0) {
5116 } else if (status.si_status != 0) {
5127 /* Drop all SysV units */
5128 for (f = 0, t = 0; args[f]; f++) {
5130 if (isempty(args[f]))
5133 args[t++] = args[f];
5142 static int mangle_names(char **original_names, char ***mangled_names) {
5143 char **i, **l, **name;
5145 l = new(char*, strv_length(original_names) + 1);
5150 STRV_FOREACH(name, original_names) {
5152 /* When enabling units qualified path names are OK,
5153 * too, hence allow them explicitly. */
5158 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5174 static int enable_unit(sd_bus *bus, char **args) {
5175 _cleanup_strv_free_ char **names = NULL;
5176 const char *verb = args[0];
5177 UnitFileChange *changes = NULL;
5178 unsigned n_changes = 0;
5179 int carries_install_info = -1;
5185 r = mangle_names(args+1, &names);
5189 r = enable_sysv_units(verb, names);
5193 /* If the operation was fully executed by the SysV compat,
5194 * let's finish early */
5195 if (strv_isempty(names))
5198 if (!bus || avoid_bus()) {
5199 if (streq(verb, "enable")) {
5200 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5201 carries_install_info = r;
5202 } else if (streq(verb, "disable"))
5203 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5204 else if (streq(verb, "reenable")) {
5205 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5206 carries_install_info = r;
5207 } else if (streq(verb, "link"))
5208 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5209 else if (streq(verb, "preset")) {
5210 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5211 carries_install_info = r;
5212 } else if (streq(verb, "mask"))
5213 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5214 else if (streq(verb, "unmask"))
5215 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5217 assert_not_reached("Unknown verb");
5220 log_error("Operation failed: %s", strerror(-r));
5225 dump_unit_file_changes(changes, n_changes);
5229 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5230 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5231 int expect_carries_install_info = false;
5232 bool send_force = true;
5235 if (streq(verb, "enable")) {
5236 method = "EnableUnitFiles";
5237 expect_carries_install_info = true;
5238 } else if (streq(verb, "disable")) {
5239 method = "DisableUnitFiles";
5241 } else if (streq(verb, "reenable")) {
5242 method = "ReenableUnitFiles";
5243 expect_carries_install_info = true;
5244 } else if (streq(verb, "link"))
5245 method = "LinkUnitFiles";
5246 else if (streq(verb, "preset")) {
5247 method = "PresetUnitFiles";
5248 expect_carries_install_info = true;
5249 } else if (streq(verb, "mask"))
5250 method = "MaskUnitFiles";
5251 else if (streq(verb, "unmask")) {
5252 method = "UnmaskUnitFiles";
5255 assert_not_reached("Unknown verb");
5257 r = sd_bus_message_new_method_call(
5260 "org.freedesktop.systemd1",
5261 "/org/freedesktop/systemd1",
5262 "org.freedesktop.systemd1.Manager",
5265 return bus_log_create_error(r);
5267 r = sd_bus_message_append_strv(m, names);
5269 return bus_log_create_error(r);
5271 r = sd_bus_message_append(m, "b", arg_runtime);
5273 return bus_log_create_error(r);
5276 r = sd_bus_message_append(m, "b", arg_force);
5278 return bus_log_create_error(r);
5281 r = sd_bus_call(bus, m, 0, &error, &reply);
5283 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5287 if (expect_carries_install_info) {
5288 r = sd_bus_message_read(reply, "b", &carries_install_info);
5290 return bus_log_parse_error(r);
5293 r = deserialize_and_dump_unit_file_changes(reply);
5297 /* Try to reload if enabled */
5299 r = daemon_reload(bus, args);
5304 if (carries_install_info == 0)
5305 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5306 "using systemctl.\n"
5307 "Possible reasons for having this kind of units are:\n"
5308 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5309 " .wants/ or .requires/ directory.\n"
5310 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5311 " a requirement dependency on it.\n"
5312 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5313 " D-Bus, udev, scripted systemctl call, ...).\n");
5316 unit_file_changes_free(changes, n_changes);
5321 static int unit_is_enabled(sd_bus *bus, char **args) {
5323 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5324 _cleanup_strv_free_ char **names = NULL;
5329 r = mangle_names(args+1, &names);
5333 r = enable_sysv_units(args[0], names);
5339 if (!bus || avoid_bus()) {
5341 STRV_FOREACH(name, names) {
5342 UnitFileState state;
5344 state = unit_file_get_state(arg_scope, arg_root, *name);
5346 log_error("Failed to get unit file state for %s: %s", *name, strerror(-state));
5350 if (state == UNIT_FILE_ENABLED ||
5351 state == UNIT_FILE_ENABLED_RUNTIME ||
5352 state == UNIT_FILE_STATIC)
5356 puts(unit_file_state_to_string(state));
5360 STRV_FOREACH(name, names) {
5361 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5364 r = sd_bus_call_method(
5366 "org.freedesktop.systemd1",
5367 "/org/freedesktop/systemd1",
5368 "org.freedesktop.systemd1.Manager",
5374 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5378 r = sd_bus_message_read(reply, "s", &s);
5380 return bus_log_parse_error(r);
5382 if (streq(s, "enabled") ||
5383 streq(s, "enabled-runtime") ||
5395 static int systemctl_help(void) {
5397 pager_open_if_enabled();
5399 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
5400 "Query or send control commands to the systemd manager.\n\n"
5401 " -h --help Show this help\n"
5402 " --version Show package version\n"
5403 " --system Connect to system manager\n"
5404 " --user Connect to user service manager\n"
5405 " -H --host=[USER@]HOST\n"
5406 " Operate on remote host\n"
5407 " -M --machine=CONTAINER\n"
5408 " Operate on local container\n"
5409 " -t --type=TYPE List only units of a particular type\n"
5410 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
5411 " -p --property=NAME Show only properties by this name\n"
5412 " -a --all Show all loaded units/properties, including dead/empty\n"
5413 " ones. To list all units installed on the system, use\n"
5414 " the 'list-unit-files' command instead.\n"
5415 " -l --full Don't ellipsize unit names on output\n"
5416 " -r --recursive Show unit list of host and local containers\n"
5417 " --reverse Show reverse dependencies with 'list-dependencies'\n"
5418 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
5419 " queueing a new job\n"
5420 " --show-types When showing sockets, explicitly show their type\n"
5421 " -i --ignore-inhibitors\n"
5422 " When shutting down or sleeping, ignore inhibitors\n"
5423 " --kill-who=WHO Who to send signal to\n"
5424 " -s --signal=SIGNAL Which signal to send\n"
5425 " -q --quiet Suppress output\n"
5426 " --no-block Do not wait until operation finished\n"
5427 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5428 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
5430 " --no-legend Do not print a legend (column headers and hints)\n"
5431 " --no-pager Do not pipe output into a pager\n"
5432 " --no-ask-password\n"
5433 " Do not ask for system passwords\n"
5434 " --global Enable/disable unit files globally\n"
5435 " --runtime Enable unit files only temporarily until next reboot\n"
5436 " -f --force When enabling unit files, override existing symlinks\n"
5437 " When shutting down, execute action immediately\n"
5438 " --root=PATH Enable unit files in the specified root directory\n"
5439 " -n --lines=INTEGER Number of journal entries to show\n"
5440 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
5441 " verbose, export, json, json-pretty, json-sse, cat)\n"
5442 " --plain Print unit dependencies as a list instead of a tree\n\n"
5444 " list-units [PATTERN...] List loaded units\n"
5445 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
5446 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
5447 " start NAME... Start (activate) one or more units\n"
5448 " stop NAME... Stop (deactivate) one or more units\n"
5449 " reload NAME... Reload one or more units\n"
5450 " restart NAME... Start or restart one or more units\n"
5451 " try-restart NAME... Restart one or more units if active\n"
5452 " reload-or-restart NAME... Reload one or more units if possible,\n"
5453 " otherwise start or restart\n"
5454 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
5455 " otherwise restart if active\n"
5456 " isolate NAME Start one unit and stop all others\n"
5457 " kill NAME... Send signal to processes of a unit\n"
5458 " is-active PATTERN... Check whether units are active\n"
5459 " is-failed PATTERN... Check whether units are failed\n"
5460 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
5461 " show [PATTERN...|JOB...] Show properties of one or more\n"
5462 " units/jobs or the manager\n"
5463 " cat PATTERN... Show files and drop-ins of one or more units\n"
5464 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
5465 " help PATTERN...|PID... Show manual for one or more units\n"
5466 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
5468 " list-dependencies [NAME] Recursively show units which are required\n"
5469 " or wanted by this unit or by which this\n"
5470 " unit is required or wanted\n\n"
5471 "Unit File Commands:\n"
5472 " list-unit-files [PATTERN...] List installed unit files\n"
5473 " enable NAME... Enable one or more unit files\n"
5474 " disable NAME... Disable one or more unit files\n"
5475 " reenable NAME... Reenable one or more unit files\n"
5476 " preset NAME... Enable/disable one or more unit files\n"
5477 " based on preset configuration\n"
5478 " is-enabled NAME... Check whether unit files are enabled\n\n"
5479 " mask NAME... Mask one or more units\n"
5480 " unmask NAME... Unmask one or more units\n"
5481 " link PATH... Link one or more units files into\n"
5482 " the search path\n"
5483 " get-default Get the name of the default target\n"
5484 " set-default NAME Set the default target\n\n"
5485 "Machine Commands:\n"
5486 " list-machines [PATTERN...] List local containers and host\n\n"
5488 " list-jobs [PATTERN...] List jobs\n"
5489 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
5490 "Snapshot Commands:\n"
5491 " snapshot [NAME] Create a snapshot\n"
5492 " delete NAME... Remove one or more snapshots\n\n"
5493 "Environment Commands:\n"
5494 " show-environment Dump environment\n"
5495 " set-environment NAME=VALUE... Set one or more environment variables\n"
5496 " unset-environment NAME... Unset one or more environment variables\n"
5497 " import-environment NAME... Import all, one or more environment variables\n\n"
5498 "Manager Lifecycle Commands:\n"
5499 " daemon-reload Reload systemd manager configuration\n"
5500 " daemon-reexec Reexecute systemd manager\n\n"
5501 "System Commands:\n"
5502 " default Enter system default mode\n"
5503 " rescue Enter system rescue mode\n"
5504 " emergency Enter system emergency mode\n"
5505 " halt Shut down and halt the system\n"
5506 " poweroff Shut down and power-off the system\n"
5507 " reboot [ARG] Shut down and reboot the system\n"
5508 " kexec Shut down and reboot the system with kexec\n"
5509 " exit Request user instance exit\n"
5510 " switch-root ROOT [INIT] Change to a different root file system\n"
5511 " suspend Suspend the system\n"
5512 " hibernate Hibernate the system\n"
5513 " hybrid-sleep Hibernate and suspend the system\n",
5514 program_invocation_short_name);
5519 static int halt_help(void) {
5521 printf("%s [OPTIONS...]%s\n\n"
5522 "%s the system.\n\n"
5523 " --help Show this help\n"
5524 " --halt Halt the machine\n"
5525 " -p --poweroff Switch off the machine\n"
5526 " --reboot Reboot the machine\n"
5527 " -f --force Force immediate halt/power-off/reboot\n"
5528 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
5529 " -d --no-wtmp Don't write wtmp record\n"
5530 " --no-wall Don't send wall message before halt/power-off/reboot\n",
5531 program_invocation_short_name,
5532 arg_action == ACTION_REBOOT ? " [ARG]" : "",
5533 arg_action == ACTION_REBOOT ? "Reboot" :
5534 arg_action == ACTION_POWEROFF ? "Power off" :
5540 static int shutdown_help(void) {
5542 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
5543 "Shut down the system.\n\n"
5544 " --help Show this help\n"
5545 " -H --halt Halt the machine\n"
5546 " -P --poweroff Power-off the machine\n"
5547 " -r --reboot Reboot the machine\n"
5548 " -h Equivalent to --poweroff, overridden by --halt\n"
5549 " -k Don't halt/power-off/reboot, just send warnings\n"
5550 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5551 " -c Cancel a pending shutdown\n",
5552 program_invocation_short_name);
5557 static int telinit_help(void) {
5559 printf("%s [OPTIONS...] {COMMAND}\n\n"
5560 "Send control commands to the init daemon.\n\n"
5561 " --help Show this help\n"
5562 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
5564 " 0 Power-off the machine\n"
5565 " 6 Reboot the machine\n"
5566 " 2, 3, 4, 5 Start runlevelX.target unit\n"
5567 " 1, s, S Enter rescue mode\n"
5568 " q, Q Reload init daemon configuration\n"
5569 " u, U Reexecute init daemon\n",
5570 program_invocation_short_name);
5575 static int runlevel_help(void) {
5577 printf("%s [OPTIONS...]\n\n"
5578 "Prints the previous and current runlevel of the init system.\n\n"
5579 " --help Show this help\n",
5580 program_invocation_short_name);
5585 static int help_types(void) {
5589 puts("Available unit types:");
5590 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
5591 t = unit_type_to_string(i);
5599 static int systemctl_parse_argv(int argc, char *argv[]) {
5608 ARG_IGNORE_DEPENDENCIES,
5620 ARG_NO_ASK_PASSWORD,
5629 static const struct option options[] = {
5630 { "help", no_argument, NULL, 'h' },
5631 { "version", no_argument, NULL, ARG_VERSION },
5632 { "type", required_argument, NULL, 't' },
5633 { "property", required_argument, NULL, 'p' },
5634 { "all", no_argument, NULL, 'a' },
5635 { "reverse", no_argument, NULL, ARG_REVERSE },
5636 { "after", no_argument, NULL, ARG_AFTER },
5637 { "before", no_argument, NULL, ARG_BEFORE },
5638 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
5639 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
5640 { "full", no_argument, NULL, 'l' },
5641 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
5642 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
5643 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
5644 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
5645 { "ignore-inhibitors", no_argument, NULL, 'i' },
5646 { "user", no_argument, NULL, ARG_USER },
5647 { "system", no_argument, NULL, ARG_SYSTEM },
5648 { "global", no_argument, NULL, ARG_GLOBAL },
5649 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
5650 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
5651 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
5652 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5653 { "quiet", no_argument, NULL, 'q' },
5654 { "root", required_argument, NULL, ARG_ROOT },
5655 { "force", no_argument, NULL, ARG_FORCE },
5656 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
5657 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
5658 { "signal", required_argument, NULL, 's' },
5659 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
5660 { "host", required_argument, NULL, 'H' },
5661 { "machine", required_argument, NULL, 'M' },
5662 { "runtime", no_argument, NULL, ARG_RUNTIME },
5663 { "lines", required_argument, NULL, 'n' },
5664 { "output", required_argument, NULL, 'o' },
5665 { "plain", no_argument, NULL, ARG_PLAIN },
5666 { "state", required_argument, NULL, ARG_STATE },
5667 { "recursive", no_argument, NULL, 'r' },
5676 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0) {
5681 return systemctl_help();
5684 puts(PACKAGE_STRING);
5685 puts(SYSTEMD_FEATURES);
5692 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5693 _cleanup_free_ char *type;
5695 type = strndup(word, size);
5699 if (streq(type, "help")) {
5704 if (unit_type_from_string(type) >= 0) {
5705 if (strv_push(&arg_types, type))
5711 /* It's much nicer to use --state= for
5712 * load states, but let's support this
5713 * in --types= too for compatibility
5714 * with old versions */
5715 if (unit_load_state_from_string(optarg) >= 0) {
5716 if (strv_push(&arg_states, type) < 0)
5722 log_error("Unknown unit type or load state '%s'.", type);
5723 log_info("Use -t help to see a list of allowed values.");
5731 /* Make sure that if the empty property list
5732 was specified, we won't show any properties. */
5733 if (isempty(optarg) && !arg_properties) {
5734 arg_properties = new0(char*, 1);
5735 if (!arg_properties)
5741 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5744 prop = strndup(word, size);
5748 if (strv_consume(&arg_properties, prop) < 0)
5753 /* If the user asked for a particular
5754 * property, show it to him, even if it is
5766 arg_dependency = DEPENDENCY_REVERSE;
5770 arg_dependency = DEPENDENCY_AFTER;
5774 arg_dependency = DEPENDENCY_BEFORE;
5777 case ARG_SHOW_TYPES:
5778 arg_show_types = true;
5782 arg_job_mode = optarg;
5786 arg_job_mode = "fail";
5789 case ARG_IRREVERSIBLE:
5790 arg_job_mode = "replace-irreversibly";
5793 case ARG_IGNORE_DEPENDENCIES:
5794 arg_job_mode = "ignore-dependencies";
5798 arg_scope = UNIT_FILE_USER;
5802 arg_scope = UNIT_FILE_SYSTEM;
5806 arg_scope = UNIT_FILE_GLOBAL;
5810 arg_no_block = true;
5814 arg_no_legend = true;
5818 arg_no_pager = true;
5834 if (strv_extend(&arg_states, "failed") < 0)
5852 arg_no_reload = true;
5856 arg_kill_who = optarg;
5860 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5861 log_error("Failed to parse signal string %s.", optarg);
5866 case ARG_NO_ASK_PASSWORD:
5867 arg_ask_password = false;
5871 arg_transport = BUS_TRANSPORT_REMOTE;
5876 arg_transport = BUS_TRANSPORT_CONTAINER;
5885 if (safe_atou(optarg, &arg_lines) < 0) {
5886 log_error("Failed to parse lines '%s'", optarg);
5892 arg_output = output_mode_from_string(optarg);
5893 if (arg_output < 0) {
5894 log_error("Unknown output '%s'.", optarg);
5900 arg_ignore_inhibitors = true;
5911 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5914 s = strndup(word, size);
5918 if (strv_consume(&arg_states, s) < 0)
5925 if (geteuid() != 0) {
5926 log_error("--recursive requires root priviliges.");
5930 arg_recursive = true;
5937 assert_not_reached("Unhandled option");
5941 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
5942 log_error("Cannot access user instance remotely.");
5949 static int halt_parse_argv(int argc, char *argv[]) {
5958 static const struct option options[] = {
5959 { "help", no_argument, NULL, ARG_HELP },
5960 { "halt", no_argument, NULL, ARG_HALT },
5961 { "poweroff", no_argument, NULL, 'p' },
5962 { "reboot", no_argument, NULL, ARG_REBOOT },
5963 { "force", no_argument, NULL, 'f' },
5964 { "wtmp-only", no_argument, NULL, 'w' },
5965 { "no-wtmp", no_argument, NULL, 'd' },
5966 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5975 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5976 if (runlevel == '0' || runlevel == '6')
5979 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5986 arg_action = ACTION_HALT;
5990 if (arg_action != ACTION_REBOOT)
5991 arg_action = ACTION_POWEROFF;
5995 arg_action = ACTION_REBOOT;
6017 /* Compatibility nops */
6024 assert_not_reached("Unhandled option");
6028 if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
6029 r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL);
6032 } else if (optind < argc) {
6033 log_error("Too many arguments.");
6040 static int parse_time_spec(const char *t, usec_t *_u) {
6044 if (streq(t, "now"))
6046 else if (!strchr(t, ':')) {
6049 if (safe_atou64(t, &u) < 0)
6052 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
6061 hour = strtol(t, &e, 10);
6062 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
6065 minute = strtol(e+1, &e, 10);
6066 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
6069 n = now(CLOCK_REALTIME);
6070 s = (time_t) (n / USEC_PER_SEC);
6072 assert_se(localtime_r(&s, &tm));
6074 tm.tm_hour = (int) hour;
6075 tm.tm_min = (int) minute;
6078 assert_se(s = mktime(&tm));
6080 *_u = (usec_t) s * USEC_PER_SEC;
6083 *_u += USEC_PER_DAY;
6089 static int shutdown_parse_argv(int argc, char *argv[]) {
6096 static const struct option options[] = {
6097 { "help", no_argument, NULL, ARG_HELP },
6098 { "halt", no_argument, NULL, 'H' },
6099 { "poweroff", no_argument, NULL, 'P' },
6100 { "reboot", no_argument, NULL, 'r' },
6101 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
6102 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6111 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
6115 return shutdown_help();
6118 arg_action = ACTION_HALT;
6122 arg_action = ACTION_POWEROFF;
6127 arg_action = ACTION_KEXEC;
6129 arg_action = ACTION_REBOOT;
6133 arg_action = ACTION_KEXEC;
6137 if (arg_action != ACTION_HALT)
6138 arg_action = ACTION_POWEROFF;
6151 /* Compatibility nops */
6155 arg_action = ACTION_CANCEL_SHUTDOWN;
6162 assert_not_reached("Unhandled option");
6166 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
6167 r = parse_time_spec(argv[optind], &arg_when);
6169 log_error("Failed to parse time specification: %s", argv[optind]);
6173 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
6175 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
6176 /* No time argument for shutdown cancel */
6177 arg_wall = argv + optind;
6178 else if (argc > optind + 1)
6179 /* We skip the time argument */
6180 arg_wall = argv + optind + 1;
6187 static int telinit_parse_argv(int argc, char *argv[]) {
6194 static const struct option options[] = {
6195 { "help", no_argument, NULL, ARG_HELP },
6196 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6200 static const struct {
6204 { '0', ACTION_POWEROFF },
6205 { '6', ACTION_REBOOT },
6206 { '1', ACTION_RESCUE },
6207 { '2', ACTION_RUNLEVEL2 },
6208 { '3', ACTION_RUNLEVEL3 },
6209 { '4', ACTION_RUNLEVEL4 },
6210 { '5', ACTION_RUNLEVEL5 },
6211 { 's', ACTION_RESCUE },
6212 { 'S', ACTION_RESCUE },
6213 { 'q', ACTION_RELOAD },
6214 { 'Q', ACTION_RELOAD },
6215 { 'u', ACTION_REEXEC },
6216 { 'U', ACTION_REEXEC }
6225 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
6229 return telinit_help();
6239 assert_not_reached("Unhandled option");
6243 if (optind >= argc) {
6248 if (optind + 1 < argc) {
6249 log_error("Too many arguments.");
6253 if (strlen(argv[optind]) != 1) {
6254 log_error("Expected single character argument.");
6258 for (i = 0; i < ELEMENTSOF(table); i++)
6259 if (table[i].from == argv[optind][0])
6262 if (i >= ELEMENTSOF(table)) {
6263 log_error("Unknown command '%s'.", argv[optind]);
6267 arg_action = table[i].to;
6274 static int runlevel_parse_argv(int argc, char *argv[]) {
6280 static const struct option options[] = {
6281 { "help", no_argument, NULL, ARG_HELP },
6290 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
6294 return runlevel_help();
6300 assert_not_reached("Unhandled option");
6304 if (optind < argc) {
6305 log_error("Too many arguments.");
6312 static int parse_argv(int argc, char *argv[]) {
6316 if (program_invocation_short_name) {
6318 if (strstr(program_invocation_short_name, "halt")) {
6319 arg_action = ACTION_HALT;
6320 return halt_parse_argv(argc, argv);
6321 } else if (strstr(program_invocation_short_name, "poweroff")) {
6322 arg_action = ACTION_POWEROFF;
6323 return halt_parse_argv(argc, argv);
6324 } else if (strstr(program_invocation_short_name, "reboot")) {
6326 arg_action = ACTION_KEXEC;
6328 arg_action = ACTION_REBOOT;
6329 return halt_parse_argv(argc, argv);
6330 } else if (strstr(program_invocation_short_name, "shutdown")) {
6331 arg_action = ACTION_POWEROFF;
6332 return shutdown_parse_argv(argc, argv);
6333 } else if (strstr(program_invocation_short_name, "init")) {
6335 if (sd_booted() > 0) {
6336 arg_action = _ACTION_INVALID;
6337 return telinit_parse_argv(argc, argv);
6339 /* Hmm, so some other init system is
6340 * running, we need to forward this
6341 * request to it. For now we simply
6342 * guess that it is Upstart. */
6344 execv(TELINIT, argv);
6346 log_error("Couldn't find an alternative telinit implementation to spawn.");
6350 } else if (strstr(program_invocation_short_name, "runlevel")) {
6351 arg_action = ACTION_RUNLEVEL;
6352 return runlevel_parse_argv(argc, argv);
6356 arg_action = ACTION_SYSTEMCTL;
6357 return systemctl_parse_argv(argc, argv);
6360 _pure_ static int action_to_runlevel(void) {
6362 static const char table[_ACTION_MAX] = {
6363 [ACTION_HALT] = '0',
6364 [ACTION_POWEROFF] = '0',
6365 [ACTION_REBOOT] = '6',
6366 [ACTION_RUNLEVEL2] = '2',
6367 [ACTION_RUNLEVEL3] = '3',
6368 [ACTION_RUNLEVEL4] = '4',
6369 [ACTION_RUNLEVEL5] = '5',
6370 [ACTION_RESCUE] = '1'
6373 assert(arg_action < _ACTION_MAX);
6375 return table[arg_action];
6378 static int talk_initctl(void) {
6380 struct init_request request = {
6381 .magic = INIT_MAGIC,
6383 .cmd = INIT_CMD_RUNLVL
6386 _cleanup_close_ int fd = -1;
6390 rl = action_to_runlevel();
6394 request.runlevel = rl;
6396 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
6398 if (errno == ENOENT)
6401 log_error("Failed to open "INIT_FIFO": %m");
6406 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
6408 log_error("Failed to write to "INIT_FIFO": %m");
6409 return errno > 0 ? -errno : -EIO;
6415 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
6417 static const struct {
6425 int (* const dispatch)(sd_bus *bus, char **args);
6431 { "list-units", MORE, 0, list_units },
6432 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
6433 { "list-sockets", MORE, 1, list_sockets },
6434 { "list-timers", MORE, 1, list_timers },
6435 { "list-jobs", MORE, 1, list_jobs },
6436 { "list-machines", MORE, 1, list_machines },
6437 { "clear-jobs", EQUAL, 1, daemon_reload },
6438 { "cancel", MORE, 2, cancel_job },
6439 { "start", MORE, 2, start_unit },
6440 { "stop", MORE, 2, start_unit },
6441 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6442 { "reload", MORE, 2, start_unit },
6443 { "restart", MORE, 2, start_unit },
6444 { "try-restart", MORE, 2, start_unit },
6445 { "reload-or-restart", MORE, 2, start_unit },
6446 { "reload-or-try-restart", MORE, 2, start_unit },
6447 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
6448 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6449 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
6450 { "isolate", EQUAL, 2, start_unit },
6451 { "kill", MORE, 2, kill_unit },
6452 { "is-active", MORE, 2, check_unit_active },
6453 { "check", MORE, 2, check_unit_active },
6454 { "is-failed", MORE, 2, check_unit_failed },
6455 { "show", MORE, 1, show },
6456 { "cat", MORE, 2, cat },
6457 { "status", MORE, 1, show },
6458 { "help", MORE, 2, show },
6459 { "snapshot", LESS, 2, snapshot },
6460 { "delete", MORE, 2, delete_snapshot },
6461 { "daemon-reload", EQUAL, 1, daemon_reload },
6462 { "daemon-reexec", EQUAL, 1, daemon_reload },
6463 { "show-environment", EQUAL, 1, show_environment },
6464 { "set-environment", MORE, 2, set_environment },
6465 { "unset-environment", MORE, 2, set_environment },
6466 { "import-environment", MORE, 1, import_environment},
6467 { "halt", EQUAL, 1, start_special, FORCE },
6468 { "poweroff", EQUAL, 1, start_special, FORCE },
6469 { "reboot", EQUAL, 1, start_special, FORCE },
6470 { "kexec", EQUAL, 1, start_special },
6471 { "suspend", EQUAL, 1, start_special },
6472 { "hibernate", EQUAL, 1, start_special },
6473 { "hybrid-sleep", EQUAL, 1, start_special },
6474 { "default", EQUAL, 1, start_special },
6475 { "rescue", EQUAL, 1, start_special },
6476 { "emergency", EQUAL, 1, start_special },
6477 { "exit", EQUAL, 1, start_special },
6478 { "reset-failed", MORE, 1, reset_failed },
6479 { "enable", MORE, 2, enable_unit, NOBUS },
6480 { "disable", MORE, 2, enable_unit, NOBUS },
6481 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
6482 { "reenable", MORE, 2, enable_unit, NOBUS },
6483 { "preset", MORE, 2, enable_unit, NOBUS },
6484 { "mask", MORE, 2, enable_unit, NOBUS },
6485 { "unmask", MORE, 2, enable_unit, NOBUS },
6486 { "link", MORE, 2, enable_unit, NOBUS },
6487 { "switch-root", MORE, 2, switch_root },
6488 { "list-dependencies", LESS, 2, list_dependencies },
6489 { "set-default", EQUAL, 2, set_default, NOBUS },
6490 { "get-default", EQUAL, 1, get_default, NOBUS },
6491 { "set-property", MORE, 3, set_property },
6500 left = argc - optind;
6502 /* Special rule: no arguments (left == 0) means "list-units" */
6504 if (streq(argv[optind], "help") && !argv[optind+1]) {
6505 log_error("This command expects one or more "
6506 "unit names. Did you mean --help?");
6510 for (; verb->verb; verb++)
6511 if (streq(argv[optind], verb->verb))
6514 log_error("Unknown operation '%s'.", argv[optind]);
6519 switch (verb->argc_cmp) {
6522 if (left != verb->argc) {
6523 log_error("Invalid number of arguments.");
6530 if (left < verb->argc) {
6531 log_error("Too few arguments.");
6538 if (left > verb->argc) {
6539 log_error("Too many arguments.");
6546 assert_not_reached("Unknown comparison operator.");
6549 /* Require a bus connection for all operations but
6551 if (verb->bus == NOBUS) {
6552 if (!bus && !avoid_bus()) {
6553 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6558 if (running_in_chroot() > 0) {
6559 log_info("Running in chroot, ignoring request.");
6563 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
6564 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6569 return verb->dispatch(bus, argv + optind);
6572 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
6574 struct sd_shutdown_command c = {
6581 union sockaddr_union sockaddr = {
6582 .un.sun_family = AF_UNIX,
6583 .un.sun_path = "/run/systemd/shutdownd",
6586 struct iovec iovec[2] = {{
6587 .iov_base = (char*) &c,
6588 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
6591 struct msghdr msghdr = {
6592 .msg_name = &sockaddr,
6593 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
6594 + strlen("/run/systemd/shutdownd"),
6599 _cleanup_close_ int fd;
6601 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
6605 if (!isempty(message)) {
6606 iovec[1].iov_base = (char*) message;
6607 iovec[1].iov_len = strlen(message);
6608 msghdr.msg_iovlen++;
6611 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
6617 static int reload_with_fallback(sd_bus *bus) {
6620 /* First, try systemd via D-Bus. */
6621 if (daemon_reload(bus, NULL) >= 0)
6625 /* Nothing else worked, so let's try signals */
6626 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
6628 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
6629 log_error("kill() failed: %m");
6636 static int start_with_fallback(sd_bus *bus) {
6639 /* First, try systemd via D-Bus. */
6640 if (start_unit(bus, NULL) >= 0)
6644 /* Nothing else worked, so let's try
6646 if (talk_initctl() > 0)
6649 log_error("Failed to talk to init daemon.");
6653 warn_wall(arg_action);
6657 static int halt_now(enum action a) {
6659 /* Make sure C-A-D is handled by the kernel from this
6661 reboot(RB_ENABLE_CAD);
6666 log_info("Halting.");
6667 reboot(RB_HALT_SYSTEM);
6670 case ACTION_POWEROFF:
6671 log_info("Powering off.");
6672 reboot(RB_POWER_OFF);
6675 case ACTION_REBOOT: {
6676 _cleanup_free_ char *param = NULL;
6678 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
6679 log_info("Rebooting with argument '%s'.", param);
6680 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
6681 LINUX_REBOOT_CMD_RESTART2, param);
6684 log_info("Rebooting.");
6685 reboot(RB_AUTOBOOT);
6690 assert_not_reached("Unknown action.");
6694 static int halt_main(sd_bus *bus) {
6697 r = check_inhibitors(bus, arg_action);
6701 if (geteuid() != 0) {
6702 /* Try logind if we are a normal user and no special
6703 * mode applies. Maybe PolicyKit allows us to shutdown
6706 if (arg_when <= 0 &&
6709 (arg_action == ACTION_POWEROFF ||
6710 arg_action == ACTION_REBOOT)) {
6711 r = reboot_with_logind(bus, arg_action);
6716 log_error("Must be root.");
6721 _cleanup_free_ char *m;
6723 m = strv_join(arg_wall, " ");
6727 r = send_shutdownd(arg_when,
6728 arg_action == ACTION_HALT ? 'H' :
6729 arg_action == ACTION_POWEROFF ? 'P' :
6730 arg_action == ACTION_KEXEC ? 'K' :
6737 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6739 char date[FORMAT_TIMESTAMP_MAX];
6741 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6742 format_timestamp(date, sizeof(date), arg_when));
6747 if (!arg_dry && !arg_force)
6748 return start_with_fallback(bus);
6751 if (sd_booted() > 0)
6752 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6754 r = utmp_put_shutdown();
6756 log_warning("Failed to write utmp record: %s", strerror(-r));
6763 r = halt_now(arg_action);
6764 log_error("Failed to reboot: %s", strerror(-r));
6769 static int runlevel_main(void) {
6770 int r, runlevel, previous;
6772 r = utmp_get_runlevel(&runlevel, &previous);
6779 previous <= 0 ? 'N' : previous,
6780 runlevel <= 0 ? 'N' : runlevel);
6785 int main(int argc, char*argv[]) {
6786 _cleanup_bus_unref_ sd_bus *bus = NULL;
6789 setlocale(LC_ALL, "");
6790 log_parse_environment();
6793 /* Explicitly not on_tty() to avoid setting cached value.
6794 * This becomes relevant for piping output which might be
6796 original_stdout_is_tty = isatty(STDOUT_FILENO);
6798 r = parse_argv(argc, argv);
6802 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6803 * let's shortcut this */
6804 if (arg_action == ACTION_RUNLEVEL) {
6805 r = runlevel_main();
6809 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6810 log_info("Running in chroot, ignoring request.");
6816 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
6818 /* systemctl_main() will print an error message for the bus
6819 * connection, but only if it needs to */
6821 switch (arg_action) {
6823 case ACTION_SYSTEMCTL:
6824 r = systemctl_main(bus, argc, argv, r);
6828 case ACTION_POWEROFF:
6834 case ACTION_RUNLEVEL2:
6835 case ACTION_RUNLEVEL3:
6836 case ACTION_RUNLEVEL4:
6837 case ACTION_RUNLEVEL5:
6839 case ACTION_EMERGENCY:
6840 case ACTION_DEFAULT:
6841 r = start_with_fallback(bus);
6846 r = reload_with_fallback(bus);
6849 case ACTION_CANCEL_SHUTDOWN: {
6850 _cleanup_free_ char *m = NULL;
6853 m = strv_join(arg_wall, " ");
6860 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6862 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6866 case ACTION_RUNLEVEL:
6867 case _ACTION_INVALID:
6869 assert_not_reached("Unknown action");
6874 ask_password_agent_close();
6875 polkit_agent_close();
6877 strv_free(arg_types);
6878 strv_free(arg_states);
6879 strv_free(arg_properties);
6881 return r < 0 ? EXIT_FAILURE : r;