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 UnitFilePresetMode arg_preset_mode = UNIT_FILE_PRESET_FULL;
105 static char **arg_wall = NULL;
106 static const char *arg_kill_who = NULL;
107 static int arg_signal = SIGTERM;
108 static const char *arg_root = NULL;
109 static usec_t arg_when = 0;
131 ACTION_CANCEL_SHUTDOWN,
133 } arg_action = ACTION_SYSTEMCTL;
134 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
135 static char *arg_host = NULL;
136 static unsigned arg_lines = 10;
137 static OutputMode arg_output = OUTPUT_SHORT;
138 static bool arg_plain = false;
140 static const struct {
144 { "start", "StartUnit" },
145 { "stop", "StopUnit" },
146 { "condstop", "StopUnit" },
147 { "reload", "ReloadUnit" },
148 { "restart", "RestartUnit" },
149 { "try-restart", "TryRestartUnit" },
150 { "condrestart", "TryRestartUnit" },
151 { "reload-or-restart", "ReloadOrRestartUnit" },
152 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
153 { "condreload", "ReloadOrTryRestartUnit" },
154 { "force-reload", "ReloadOrTryRestartUnit" }
157 static bool original_stdout_is_tty;
159 static int daemon_reload(sd_bus *bus, char **args);
160 static int halt_now(enum action a);
161 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet);
163 static char** strv_skip_first(char **strv) {
164 if (strv_length(strv) > 0)
169 static void pager_open_if_enabled(void) {
177 static void ask_password_agent_open_if_enabled(void) {
179 /* Open the password agent as a child process if necessary */
181 if (!arg_ask_password)
184 if (arg_scope != UNIT_FILE_SYSTEM)
187 if (arg_transport != BUS_TRANSPORT_LOCAL)
190 ask_password_agent_open();
194 static void polkit_agent_open_if_enabled(void) {
196 /* Open the polkit agent as a child process if necessary */
198 if (!arg_ask_password)
201 if (arg_scope != UNIT_FILE_SYSTEM)
204 if (arg_transport != BUS_TRANSPORT_LOCAL)
211 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
214 if (!sd_bus_error_is_set(error))
217 if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) ||
218 sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
219 sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
220 sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
221 return EXIT_NOPERMISSION;
223 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
224 return EXIT_NOTINSTALLED;
226 if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
227 sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED))
228 return EXIT_NOTIMPLEMENTED;
230 if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
231 return EXIT_NOTCONFIGURED;
239 static void warn_wall(enum action a) {
240 static const char *table[_ACTION_MAX] = {
241 [ACTION_HALT] = "The system is going down for system halt NOW!",
242 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
243 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
244 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
245 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
246 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
247 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
254 _cleanup_free_ char *p;
256 p = strv_join(arg_wall, " ");
263 utmp_wall(p, NULL, NULL);
271 utmp_wall(table[a], NULL, NULL);
274 static bool avoid_bus(void) {
276 if (running_in_chroot() > 0)
279 if (sd_booted() <= 0)
282 if (!isempty(arg_root))
285 if (arg_scope == UNIT_FILE_GLOBAL)
291 static int compare_unit_info(const void *a, const void *b) {
292 const UnitInfo *u = a, *v = b;
296 /* First, order by machine */
297 if (!u->machine && v->machine)
299 if (u->machine && !v->machine)
301 if (u->machine && v->machine) {
302 r = strcasecmp(u->machine, v->machine);
307 /* Second, order by unit type */
308 d1 = strrchr(u->id, '.');
309 d2 = strrchr(v->id, '.');
311 r = strcasecmp(d1, d2);
316 /* Third, order by name */
317 return strcasecmp(u->id, v->id);
320 static bool output_show_unit(const UnitInfo *u, char **patterns) {
323 if (!strv_isempty(patterns)) {
326 STRV_FOREACH(pattern, patterns)
327 if (fnmatch(*pattern, u->id, FNM_NOESCAPE) == 0)
332 return (!arg_types || ((dot = strrchr(u->id, '.')) &&
333 strv_find(arg_types, dot+1))) &&
334 (arg_all || !(streq(u->active_state, "inactive")
335 || u->following[0]) || u->job_id > 0);
338 static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
339 unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
341 unsigned n_shown = 0;
344 max_id_len = strlen("UNIT");
345 load_len = strlen("LOAD");
346 active_len = strlen("ACTIVE");
347 sub_len = strlen("SUB");
348 job_len = strlen("JOB");
351 for (u = unit_infos; u < unit_infos + c; u++) {
352 max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0));
353 load_len = MAX(load_len, strlen(u->load_state));
354 active_len = MAX(active_len, strlen(u->active_state));
355 sub_len = MAX(sub_len, strlen(u->sub_state));
357 if (u->job_id != 0) {
358 job_len = MAX(job_len, strlen(u->job_type));
362 if (!arg_no_legend &&
363 (streq(u->active_state, "failed") ||
364 STR_IN_SET(u->load_state, "error", "not-found", "masked")))
368 if (!arg_full && original_stdout_is_tty) {
371 id_len = MIN(max_id_len, 25u);
372 basic_len = circle_len + 5 + id_len + 5 + active_len + sub_len;
375 basic_len += job_len + 1;
377 if (basic_len < (unsigned) columns()) {
378 unsigned extra_len, incr;
379 extra_len = columns() - basic_len;
381 /* Either UNIT already got 25, or is fully satisfied.
382 * Grant up to 25 to DESC now. */
383 incr = MIN(extra_len, 25u);
387 /* split the remaining space between UNIT and DESC,
388 * but do not give UNIT more than it needs. */
390 incr = MIN(extra_len / 2, max_id_len - id_len);
392 desc_len += extra_len - incr;
398 for (u = unit_infos; u < unit_infos + c; u++) {
399 _cleanup_free_ char *e = NULL, *j = NULL;
400 const char *on_loaded = "", *off_loaded = "";
401 const char *on_active = "", *off_active = "";
402 const char *on_circle = "", *off_circle = "";
406 if (!n_shown && !arg_no_legend) {
411 printf("%-*s %-*s %-*s %-*s ",
414 active_len, "ACTIVE",
418 printf("%-*s ", job_len, "JOB");
420 if (!arg_full && arg_no_pager)
421 printf("%.*s\n", desc_len, "DESCRIPTION");
423 printf("%s\n", "DESCRIPTION");
428 if (STR_IN_SET(u->load_state, "error", "not-found", "masked")) {
429 on_loaded = ansi_highlight_red();
430 on_circle = ansi_highlight_yellow();
431 off_loaded = off_circle = ansi_highlight_off();
435 if (streq(u->active_state, "failed")) {
436 on_circle = on_active = ansi_highlight_red();
437 off_circle = off_active = ansi_highlight_off();
442 j = strjoin(u->machine, ":", u->id, NULL);
451 e = ellipsize(id, id_len, 33);
459 printf("%s%s%s ", on_circle, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_circle);
461 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
462 on_active, id_len, id, off_active,
463 on_loaded, load_len, u->load_state, off_loaded,
464 on_active, active_len, u->active_state,
465 sub_len, u->sub_state, off_active,
466 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
469 printf("%.*s\n", desc_len, u->description);
471 printf("%s\n", u->description);
474 if (!arg_no_legend) {
475 const char *on, *off;
479 "LOAD = Reflects whether the unit definition was properly loaded.\n"
480 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
481 "SUB = The low-level unit activation state, values depend on unit type.");
482 puts(job_count ? "JOB = Pending job for the unit.\n" : "");
483 on = ansi_highlight();
484 off = ansi_highlight_off();
486 on = ansi_highlight_red();
487 off = ansi_highlight_off();
491 printf("%s%u loaded units listed.%s\n"
492 "To show all installed unit files use 'systemctl list-unit-files'.\n",
495 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
496 "To show all installed unit files use 'systemctl list-unit-files'.\n",
503 static int get_unit_list(
507 UnitInfo **unit_infos,
509 sd_bus_message **_reply) {
511 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
512 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
513 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
522 r = sd_bus_message_new_method_call(
525 "org.freedesktop.systemd1",
526 "/org/freedesktop/systemd1",
527 "org.freedesktop.systemd1.Manager",
528 "ListUnitsFiltered");
531 return bus_log_create_error(r);
533 r = sd_bus_message_append_strv(m, arg_states);
535 return bus_log_create_error(r);
537 r = sd_bus_call(bus, m, 0, &error, &reply);
539 log_error("Failed to list units: %s", bus_error_message(&error, r));
543 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
545 return bus_log_parse_error(r);
547 while ((r = bus_parse_unit_info(reply, &u)) > 0) {
550 if (!output_show_unit(&u, patterns))
553 if (!GREEDY_REALLOC(*unit_infos, size, c+1))
556 (*unit_infos)[c++] = u;
559 return bus_log_parse_error(r);
561 r = sd_bus_message_exit_container(reply);
563 return bus_log_parse_error(r);
571 static void message_set_freep(Set **set) {
574 while ((m = set_steal_first(*set)))
575 sd_bus_message_unref(m);
580 static int get_unit_list_recursive(
583 UnitInfo **_unit_infos,
587 _cleanup_free_ UnitInfo *unit_infos = NULL;
588 _cleanup_(message_set_freep) Set *replies;
589 sd_bus_message *reply;
597 replies = set_new(NULL);
601 c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
605 r = set_put(replies, reply);
607 sd_bus_message_unref(reply);
612 _cleanup_strv_free_ char **machines = NULL;
615 r = sd_get_machine_names(&machines);
619 STRV_FOREACH(i, machines) {
620 _cleanup_bus_close_unref_ sd_bus *container = NULL;
623 r = sd_bus_open_system_container(&container, *i);
625 log_error("Failed to connect to container %s: %s", *i, strerror(-r));
629 k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
635 r = set_put(replies, reply);
637 sd_bus_message_unref(reply);
642 *_machines = machines;
647 *_unit_infos = unit_infos;
656 static int list_units(sd_bus *bus, char **args) {
657 _cleanup_free_ UnitInfo *unit_infos = NULL;
658 _cleanup_(message_set_freep) Set *replies = NULL;
659 _cleanup_strv_free_ char **machines = NULL;
662 pager_open_if_enabled();
664 r = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
668 qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
669 return output_units_list(unit_infos, r);
672 static int get_triggered_units(
677 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
680 r = sd_bus_get_property_strv(
682 "org.freedesktop.systemd1",
684 "org.freedesktop.systemd1.Unit",
690 log_error("Failed to determine triggers: %s", bus_error_message(&error, r));
695 static int get_listening(
697 const char* unit_path,
700 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
701 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
702 const char *type, *path;
705 r = sd_bus_get_property(
707 "org.freedesktop.systemd1",
709 "org.freedesktop.systemd1.Socket",
715 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r));
719 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
721 return bus_log_parse_error(r);
723 while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
725 r = strv_extend(listening, type);
729 r = strv_extend(listening, path);
736 return bus_log_parse_error(r);
738 r = sd_bus_message_exit_container(reply);
740 return bus_log_parse_error(r);
752 /* Note: triggered is a list here, although it almost certainly
753 * will always be one unit. Nevertheless, dbus API allows for multiple
754 * values, so let's follow that.*/
757 /* The strv above is shared. free is set only in the first one. */
761 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
767 if (!a->machine && b->machine)
769 if (a->machine && !b->machine)
771 if (a->machine && b->machine) {
772 o = strcasecmp(a->machine, b->machine);
777 o = strcmp(a->path, b->path);
779 o = strcmp(a->type, b->type);
784 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
785 struct socket_info *s;
786 unsigned pathlen = strlen("LISTEN"),
787 typelen = strlen("TYPE") * arg_show_types,
788 socklen = strlen("UNIT"),
789 servlen = strlen("ACTIVATES");
790 const char *on, *off;
792 for (s = socket_infos; s < socket_infos + cs; s++) {
796 socklen = MAX(socklen, strlen(s->id));
798 typelen = MAX(typelen, strlen(s->type));
799 pathlen = MAX(pathlen, strlen(s->path) + (s->machine ? strlen(s->machine)+1 : 0));
801 STRV_FOREACH(a, s->triggered)
802 tmp += strlen(*a) + 2*(a != s->triggered);
803 servlen = MAX(servlen, tmp);
808 printf("%-*s %-*.*s%-*s %s\n",
810 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
814 for (s = socket_infos; s < socket_infos + cs; s++) {
815 _cleanup_free_ char *j = NULL;
820 j = strjoin(s->machine, ":", s->path, NULL);
828 printf("%-*s %-*s %-*s",
829 pathlen, path, typelen, s->type, socklen, s->id);
832 pathlen, path, socklen, s->id);
833 STRV_FOREACH(a, s->triggered)
835 a == s->triggered ? "" : ",", *a);
839 on = ansi_highlight();
840 off = ansi_highlight_off();
844 on = ansi_highlight_red();
845 off = ansi_highlight_off();
848 if (!arg_no_legend) {
849 printf("%s%u sockets listed.%s\n", on, cs, off);
851 printf("Pass --all to see loaded but inactive sockets, too.\n");
857 static int list_sockets(sd_bus *bus, char **args) {
858 _cleanup_(message_set_freep) Set *replies = NULL;
859 _cleanup_strv_free_ char **machines = NULL;
860 _cleanup_free_ UnitInfo *unit_infos = NULL;
861 _cleanup_free_ struct socket_info *socket_infos = NULL;
863 struct socket_info *s;
868 pager_open_if_enabled();
870 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
874 for (u = unit_infos; u < unit_infos + n; u++) {
875 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
878 if (!endswith(u->id, ".socket"))
881 r = get_triggered_units(bus, u->unit_path, &triggered);
885 c = get_listening(bus, u->unit_path, &listening);
891 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
896 for (i = 0; i < c; i++)
897 socket_infos[cs + i] = (struct socket_info) {
898 .machine = u->machine,
900 .type = listening[i*2],
901 .path = listening[i*2 + 1],
902 .triggered = triggered,
903 .own_triggered = i==0,
906 /* from this point on we will cleanup those socket_infos */
909 listening = triggered = NULL; /* avoid cleanup */
912 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
913 (__compar_fn_t) socket_info_compare);
915 output_sockets_list(socket_infos, cs);
918 assert(cs == 0 || socket_infos);
919 for (s = socket_infos; s < socket_infos + cs; s++) {
922 if (s->own_triggered)
923 strv_free(s->triggered);
929 static int get_next_elapse(
932 dual_timestamp *next) {
934 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
942 r = sd_bus_get_property_trivial(
944 "org.freedesktop.systemd1",
946 "org.freedesktop.systemd1.Timer",
947 "NextElapseUSecMonotonic",
952 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
956 r = sd_bus_get_property_trivial(
958 "org.freedesktop.systemd1",
960 "org.freedesktop.systemd1.Timer",
961 "NextElapseUSecRealtime",
966 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
974 static int get_last_trigger(
979 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
986 r = sd_bus_get_property_trivial(
988 "org.freedesktop.systemd1",
990 "org.freedesktop.systemd1.Timer",
996 log_error("Failed to get last trigger time: %s", bus_error_message(&error, r));
1004 const char* machine;
1007 usec_t last_trigger;
1011 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
1017 if (!a->machine && b->machine)
1019 if (a->machine && !b->machine)
1021 if (a->machine && b->machine) {
1022 o = strcasecmp(a->machine, b->machine);
1027 if (a->next_elapse < b->next_elapse)
1029 if (a->next_elapse > b->next_elapse)
1032 return strcmp(a->id, b->id);
1035 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
1036 struct timer_info *t;
1038 nextlen = strlen("NEXT"),
1039 leftlen = strlen("LEFT"),
1040 lastlen = strlen("LAST"),
1041 passedlen = strlen("PASSED"),
1042 unitlen = strlen("UNIT"),
1043 activatelen = strlen("ACTIVATES");
1045 const char *on, *off;
1047 assert(timer_infos || n == 0);
1049 for (t = timer_infos; t < timer_infos + n; t++) {
1053 if (t->next_elapse > 0) {
1054 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1056 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
1057 nextlen = MAX(nextlen, strlen(tstamp) + 1);
1059 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
1060 leftlen = MAX(leftlen, strlen(trel));
1063 if (t->last_trigger > 0) {
1064 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1066 format_timestamp(tstamp, sizeof(tstamp), t->last_trigger);
1067 lastlen = MAX(lastlen, strlen(tstamp) + 1);
1069 format_timestamp_relative(trel, sizeof(trel), t->last_trigger);
1070 passedlen = MAX(passedlen, strlen(trel));
1073 unitlen = MAX(unitlen, strlen(t->id) + (t->machine ? strlen(t->machine)+1 : 0));
1075 STRV_FOREACH(a, t->triggered)
1076 ul += strlen(*a) + 2*(a != t->triggered);
1078 activatelen = MAX(activatelen, ul);
1083 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1087 passedlen, "PASSED",
1091 for (t = timer_infos; t < timer_infos + n; t++) {
1092 _cleanup_free_ char *j = NULL;
1094 char tstamp1[FORMAT_TIMESTAMP_MAX] = "n/a", trel1[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1095 char tstamp2[FORMAT_TIMESTAMP_MAX] = "n/a", trel2[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1098 format_timestamp(tstamp1, sizeof(tstamp1), t->next_elapse);
1099 format_timestamp_relative(trel1, sizeof(trel1), t->next_elapse);
1101 format_timestamp(tstamp2, sizeof(tstamp2), t->last_trigger);
1102 format_timestamp_relative(trel2, sizeof(trel2), t->last_trigger);
1105 j = strjoin(t->machine, ":", t->id, NULL);
1112 printf("%-*s %-*s %-*s %-*s %-*s",
1113 nextlen, tstamp1, leftlen, trel1, lastlen, tstamp2, passedlen, trel2, unitlen, unit);
1115 STRV_FOREACH(a, t->triggered)
1117 a == t->triggered ? "" : ",", *a);
1121 on = ansi_highlight();
1122 off = ansi_highlight_off();
1126 on = ansi_highlight_red();
1127 off = ansi_highlight_off();
1130 if (!arg_no_legend) {
1131 printf("%s%u timers listed.%s\n", on, n, off);
1133 printf("Pass --all to see loaded but inactive timers, too.\n");
1139 static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
1145 if (next->monotonic != USEC_INFINITY && next->monotonic > 0) {
1148 if (next->monotonic > nw->monotonic)
1149 converted = nw->realtime + (next->monotonic - nw->monotonic);
1151 converted = nw->realtime - (nw->monotonic - next->monotonic);
1153 if (next->realtime != USEC_INFINITY && next->realtime > 0)
1154 next_elapse = MIN(converted, next->realtime);
1156 next_elapse = converted;
1159 next_elapse = next->realtime;
1164 static int list_timers(sd_bus *bus, char **args) {
1165 _cleanup_(message_set_freep) Set *replies = NULL;
1166 _cleanup_strv_free_ char **machines = NULL;
1167 _cleanup_free_ struct timer_info *timer_infos = NULL;
1168 _cleanup_free_ UnitInfo *unit_infos = NULL;
1169 struct timer_info *t;
1176 pager_open_if_enabled();
1178 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
1182 dual_timestamp_get(&nw);
1184 for (u = unit_infos; u < unit_infos + n; u++) {
1185 _cleanup_strv_free_ char **triggered = NULL;
1186 dual_timestamp next = {};
1189 if (!endswith(u->id, ".timer"))
1192 r = get_triggered_units(bus, u->unit_path, &triggered);
1196 r = get_next_elapse(bus, u->unit_path, &next);
1200 get_last_trigger(bus, u->unit_path, &last);
1202 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
1207 m = calc_next_elapse(&nw, &next);
1209 timer_infos[c++] = (struct timer_info) {
1210 .machine = u->machine,
1213 .last_trigger = last,
1214 .triggered = triggered,
1217 triggered = NULL; /* avoid cleanup */
1220 qsort_safe(timer_infos, c, sizeof(struct timer_info),
1221 (__compar_fn_t) timer_info_compare);
1223 output_timers_list(timer_infos, c);
1226 for (t = timer_infos; t < timer_infos + c; t++)
1227 strv_free(t->triggered);
1232 static int compare_unit_file_list(const void *a, const void *b) {
1233 const char *d1, *d2;
1234 const UnitFileList *u = a, *v = b;
1236 d1 = strrchr(u->path, '.');
1237 d2 = strrchr(v->path, '.');
1242 r = strcasecmp(d1, d2);
1247 return strcasecmp(basename(u->path), basename(v->path));
1250 static bool output_show_unit_file(const UnitFileList *u, char **patterns) {
1253 if (!strv_isempty(patterns)) {
1256 STRV_FOREACH(pattern, patterns)
1257 if (fnmatch(*pattern, basename(u->path), FNM_NOESCAPE) == 0)
1262 return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
1265 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
1266 unsigned max_id_len, id_cols, state_cols;
1267 const UnitFileList *u;
1269 max_id_len = strlen("UNIT FILE");
1270 state_cols = strlen("STATE");
1272 for (u = units; u < units + c; u++) {
1273 max_id_len = MAX(max_id_len, strlen(basename(u->path)));
1274 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1278 unsigned basic_cols;
1280 id_cols = MIN(max_id_len, 25u);
1281 basic_cols = 1 + id_cols + state_cols;
1282 if (basic_cols < (unsigned) columns())
1283 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1285 id_cols = max_id_len;
1288 printf("%-*s %-*s\n",
1289 id_cols, "UNIT FILE",
1290 state_cols, "STATE");
1292 for (u = units; u < units + c; u++) {
1293 _cleanup_free_ char *e = NULL;
1294 const char *on, *off;
1297 if (u->state == UNIT_FILE_MASKED ||
1298 u->state == UNIT_FILE_MASKED_RUNTIME ||
1299 u->state == UNIT_FILE_DISABLED ||
1300 u->state == UNIT_FILE_INVALID) {
1301 on = ansi_highlight_red();
1302 off = ansi_highlight_off();
1303 } else if (u->state == UNIT_FILE_ENABLED) {
1304 on = ansi_highlight_green();
1305 off = ansi_highlight_off();
1309 id = basename(u->path);
1311 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1313 printf("%-*s %s%-*s%s\n",
1314 id_cols, e ? e : id,
1315 on, state_cols, unit_file_state_to_string(u->state), off);
1319 printf("\n%u unit files listed.\n", c);
1322 static int list_unit_files(sd_bus *bus, char **args) {
1323 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1324 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1325 _cleanup_free_ UnitFileList *units = NULL;
1333 pager_open_if_enabled();
1341 h = hashmap_new(&string_hash_ops);
1345 r = unit_file_get_list(arg_scope, arg_root, h);
1347 unit_file_list_free(h);
1348 log_error("Failed to get unit file list: %s", strerror(-r));
1352 n_units = hashmap_size(h);
1354 units = new(UnitFileList, n_units);
1355 if (!units && n_units > 0) {
1356 unit_file_list_free(h);
1360 HASHMAP_FOREACH(u, h, i) {
1361 if (!output_show_unit_file(u, strv_skip_first(args)))
1368 assert(c <= n_units);
1371 r = sd_bus_call_method(
1373 "org.freedesktop.systemd1",
1374 "/org/freedesktop/systemd1",
1375 "org.freedesktop.systemd1.Manager",
1381 log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1385 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1387 return bus_log_parse_error(r);
1389 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1391 if (!GREEDY_REALLOC(units, size, c + 1))
1394 units[c] = (struct UnitFileList) {
1396 unit_file_state_from_string(state)
1399 if (output_show_unit_file(&units[c], strv_skip_first(args)))
1404 return bus_log_parse_error(r);
1406 r = sd_bus_message_exit_container(reply);
1408 return bus_log_parse_error(r);
1411 qsort_safe(units, c, sizeof(UnitFileList), compare_unit_file_list);
1412 output_unit_file_list(units, c);
1415 for (unit = units; unit < units + c; unit++)
1422 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1423 _cleanup_free_ char *n = NULL;
1424 size_t max_len = MAX(columns(),20u);
1430 for (i = level - 1; i >= 0; i--) {
1432 if (len > max_len - 3 && !arg_full) {
1433 printf("%s...\n",max_len % 2 ? "" : " ");
1436 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERTICAL : DRAW_TREE_SPACE));
1440 if (len > max_len - 3 && !arg_full) {
1441 printf("%s...\n",max_len % 2 ? "" : " ");
1445 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
1449 printf("%s\n", name);
1453 n = ellipsize(name, max_len-len, 100);
1461 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1463 static const char *dependencies[_DEPENDENCY_MAX] = {
1464 [DEPENDENCY_FORWARD] = "Requires\0"
1465 "RequiresOverridable\0"
1467 "RequisiteOverridable\0"
1469 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1470 "RequiredByOverridable\0"
1473 [DEPENDENCY_AFTER] = "After\0",
1474 [DEPENDENCY_BEFORE] = "Before\0",
1477 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1478 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1479 _cleanup_strv_free_ char **ret = NULL;
1480 _cleanup_free_ char *path = NULL;
1486 assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
1488 path = unit_dbus_path_from_name(name);
1492 r = sd_bus_call_method(
1494 "org.freedesktop.systemd1",
1496 "org.freedesktop.DBus.Properties",
1500 "s", "org.freedesktop.systemd1.Unit");
1502 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1506 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1508 return bus_log_parse_error(r);
1510 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1513 r = sd_bus_message_read(reply, "s", &prop);
1515 return bus_log_parse_error(r);
1517 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1518 r = sd_bus_message_skip(reply, "v");
1520 return bus_log_parse_error(r);
1523 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1525 return bus_log_parse_error(r);
1527 r = bus_message_read_strv_extend(reply, &ret);
1529 return bus_log_parse_error(r);
1531 r = sd_bus_message_exit_container(reply);
1533 return bus_log_parse_error(r);
1536 r = sd_bus_message_exit_container(reply);
1538 return bus_log_parse_error(r);
1542 return bus_log_parse_error(r);
1544 r = sd_bus_message_exit_container(reply);
1546 return bus_log_parse_error(r);
1554 static int list_dependencies_compare(const void *_a, const void *_b) {
1555 const char **a = (const char**) _a, **b = (const char**) _b;
1557 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1559 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1562 return strcasecmp(*a, *b);
1565 static int list_dependencies_one(
1570 unsigned int branches) {
1572 _cleanup_strv_free_ char **deps = NULL;
1580 r = strv_extend(units, name);
1584 r = list_dependencies_get_dependencies(bus, name, &deps);
1588 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1590 STRV_FOREACH(c, deps) {
1593 if (strv_contains(*units, *c)) {
1595 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1602 state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true);
1604 printf("%s%s%s ", ansi_highlight_green(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1606 printf("%s%s%s ", ansi_highlight_red(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1608 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1612 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1613 r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1620 strv_remove(*units, name);
1625 static int list_dependencies(sd_bus *bus, char **args) {
1626 _cleanup_strv_free_ char **units = NULL;
1627 _cleanup_free_ char *unit = NULL;
1633 unit = unit_name_mangle(args[1], MANGLE_NOGLOB);
1638 u = SPECIAL_DEFAULT_TARGET;
1640 pager_open_if_enabled();
1644 return list_dependencies_one(bus, u, 0, &units, 0);
1647 struct machine_info {
1651 char *control_group;
1652 uint32_t n_failed_units;
1657 static const struct bus_properties_map machine_info_property_map[] = {
1658 { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
1659 { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
1660 { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
1661 { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
1662 { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
1666 static void free_machines_list(struct machine_info *machine_infos, int n) {
1672 for (i = 0; i < n; i++) {
1673 free(machine_infos[i].name);
1674 free(machine_infos[i].state);
1675 free(machine_infos[i].control_group);
1678 free(machine_infos);
1681 static int compare_machine_info(const void *a, const void *b) {
1682 const struct machine_info *u = a, *v = b;
1684 if (u->is_host != v->is_host)
1685 return u->is_host > v->is_host ? -1 : 1;
1687 return strcasecmp(u->name, v->name);
1690 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1691 _cleanup_bus_close_unref_ sd_bus *container = NULL;
1697 r = sd_bus_open_system_container(&container, mi->name);
1704 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi);
1711 static bool output_show_machine(const char *name, char **patterns) {
1716 if (strv_isempty(patterns))
1719 STRV_FOREACH(i, patterns)
1720 if (fnmatch(*i, name, FNM_NOESCAPE) == 0)
1726 static int get_machine_list(
1728 struct machine_info **_machine_infos,
1731 struct machine_info *machine_infos = NULL;
1732 _cleanup_strv_free_ char **m = NULL;
1733 _cleanup_free_ char *hn = NULL;
1738 hn = gethostname_malloc();
1742 if (output_show_machine(hn, patterns)) {
1743 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1746 machine_infos[c].is_host = true;
1747 machine_infos[c].name = hn;
1750 get_machine_properties(bus, &machine_infos[c]);
1754 sd_get_machine_names(&m);
1755 STRV_FOREACH(i, m) {
1756 _cleanup_free_ char *class = NULL;
1758 if (!output_show_machine(*i, patterns))
1761 sd_machine_get_class(*i, &class);
1762 if (!streq_ptr(class, "container"))
1765 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1766 free_machines_list(machine_infos, c);
1770 machine_infos[c].is_host = false;
1771 machine_infos[c].name = strdup(*i);
1772 if (!machine_infos[c].name) {
1773 free_machines_list(machine_infos, c);
1777 get_machine_properties(NULL, &machine_infos[c]);
1781 *_machine_infos = machine_infos;
1785 static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1786 struct machine_info *m;
1789 namelen = sizeof("NAME") - 1,
1790 statelen = sizeof("STATE") - 1,
1791 failedlen = sizeof("FAILED") - 1,
1792 jobslen = sizeof("JOBS") - 1;
1794 assert(machine_infos || n == 0);
1796 for (m = machine_infos; m < machine_infos + n; m++) {
1797 namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
1798 statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
1799 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
1800 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
1802 if (!arg_no_legend && !streq_ptr(m->state, "running"))
1806 if (!arg_no_legend) {
1810 printf("%-*s %-*s %-*s %-*s\n",
1813 failedlen, "FAILED",
1817 for (m = machine_infos; m < machine_infos + n; m++) {
1818 const char *on_state = "", *off_state = "";
1819 const char *on_failed = "", *off_failed = "";
1820 bool circle = false;
1822 if (streq_ptr(m->state, "degraded")) {
1823 on_state = ansi_highlight_red();
1824 off_state = ansi_highlight_off();
1826 } else if (!streq_ptr(m->state, "running")) {
1827 on_state = ansi_highlight_yellow();
1828 off_state = ansi_highlight_off();
1832 if (m->n_failed_units > 0) {
1833 on_failed = ansi_highlight_red();
1834 off_failed = ansi_highlight_off();
1836 on_failed = off_failed = "";
1839 printf("%s%s%s ", on_state, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_state);
1842 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1843 (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
1844 on_state, statelen, strna(m->state), off_state,
1845 on_failed, failedlen, m->n_failed_units, off_failed,
1846 jobslen, m->n_jobs);
1848 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1849 namelen, strna(m->name),
1850 on_state, statelen, strna(m->state), off_state,
1851 on_failed, failedlen, m->n_failed_units, off_failed,
1852 jobslen, m->n_jobs);
1856 printf("\n%u machines listed.\n", n);
1859 static int list_machines(sd_bus *bus, char **args) {
1860 struct machine_info *machine_infos = NULL;
1865 if (geteuid() != 0) {
1866 log_error("Must be root.");
1870 pager_open_if_enabled();
1872 r = get_machine_list(bus, &machine_infos, strv_skip_first(args));
1876 qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
1877 output_machines_list(machine_infos, r);
1878 free_machines_list(machine_infos, r);
1883 static int get_default(sd_bus *bus, char **args) {
1884 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1885 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1886 _cleanup_free_ char *_path = NULL;
1890 if (!bus || avoid_bus()) {
1891 r = unit_file_get_default(arg_scope, arg_root, &_path);
1893 log_error("Failed to get default target: %s", strerror(-r));
1899 r = sd_bus_call_method(
1901 "org.freedesktop.systemd1",
1902 "/org/freedesktop/systemd1",
1903 "org.freedesktop.systemd1.Manager",
1909 log_error("Failed to get default target: %s", bus_error_message(&error, -r));
1913 r = sd_bus_message_read(reply, "s", &path);
1915 return bus_log_parse_error(r);
1919 printf("%s\n", path);
1924 static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) {
1927 assert(changes || n_changes == 0);
1929 for (i = 0; i < n_changes; i++) {
1930 if (changes[i].type == UNIT_FILE_SYMLINK)
1931 log_info("Created symlink from %s to %s.", changes[i].path, changes[i].source);
1933 log_info("Removed symlink %s.", changes[i].path);
1937 static int deserialize_and_dump_unit_file_changes(sd_bus_message *m) {
1938 const char *type, *path, *source;
1941 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1943 return bus_log_parse_error(r);
1945 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1947 if (streq(type, "symlink"))
1948 log_info("Created symlink from %s to %s.", path, source);
1950 log_info("Removed symlink %s.", path);
1954 return bus_log_parse_error(r);
1956 r = sd_bus_message_exit_container(m);
1958 return bus_log_parse_error(r);
1963 static int set_default(sd_bus *bus, char **args) {
1964 _cleanup_free_ char *unit = NULL;
1965 UnitFileChange *changes = NULL;
1966 unsigned n_changes = 0;
1969 unit = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
1973 if (!bus || avoid_bus()) {
1974 r = unit_file_set_default(arg_scope, arg_root, unit, true, &changes, &n_changes);
1976 log_error("Failed to set default target: %s", strerror(-r));
1981 dump_unit_file_changes(changes, n_changes);
1985 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1986 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1988 r = sd_bus_call_method(
1990 "org.freedesktop.systemd1",
1991 "/org/freedesktop/systemd1",
1992 "org.freedesktop.systemd1.Manager",
1998 log_error("Failed to set default target: %s", bus_error_message(&error, -r));
2002 r = deserialize_and_dump_unit_file_changes(reply);
2006 /* Try to reload if enabled */
2008 r = daemon_reload(bus, args);
2013 unit_file_changes_free(changes, n_changes);
2020 const char *name, *type, *state;
2023 static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
2024 unsigned id_len, unit_len, type_len, state_len;
2025 const struct job_info *j;
2026 const char *on, *off;
2027 bool shorten = false;
2029 assert(n == 0 || jobs);
2032 on = ansi_highlight_green();
2033 off = ansi_highlight_off();
2035 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
2039 pager_open_if_enabled();
2041 id_len = strlen("JOB");
2042 unit_len = strlen("UNIT");
2043 type_len = strlen("TYPE");
2044 state_len = strlen("STATE");
2046 for (j = jobs; j < jobs + n; j++) {
2047 uint32_t id = j->id;
2048 assert(j->name && j->type && j->state);
2050 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
2051 unit_len = MAX(unit_len, strlen(j->name));
2052 type_len = MAX(type_len, strlen(j->type));
2053 state_len = MAX(state_len, strlen(j->state));
2056 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
2057 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
2062 printf("%*s %-*s %-*s %-*s\n",
2066 state_len, "STATE");
2068 for (j = jobs; j < jobs + n; j++) {
2069 _cleanup_free_ char *e = NULL;
2071 if (streq(j->state, "running")) {
2072 on = ansi_highlight();
2073 off = ansi_highlight_off();
2077 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
2078 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2080 on, unit_len, e ? e : j->name, off,
2082 on, state_len, j->state, off);
2085 if (!arg_no_legend) {
2086 on = ansi_highlight();
2087 off = ansi_highlight_off();
2089 printf("\n%s%u jobs listed%s.\n", on, n, off);
2093 static bool output_show_job(struct job_info *job, char **patterns) {
2098 if (strv_isempty(patterns))
2101 STRV_FOREACH(pattern, patterns)
2102 if (fnmatch(*pattern, job->name, FNM_NOESCAPE) == 0)
2107 static int list_jobs(sd_bus *bus, char **args) {
2108 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2109 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2110 const char *name, *type, *state, *job_path, *unit_path;
2111 _cleanup_free_ struct job_info *jobs = NULL;
2116 bool skipped = false;
2118 r = sd_bus_call_method(
2120 "org.freedesktop.systemd1",
2121 "/org/freedesktop/systemd1",
2122 "org.freedesktop.systemd1.Manager",
2128 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
2132 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2134 return bus_log_parse_error(r);
2136 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
2137 struct job_info job = { id, name, type, state };
2139 if (!output_show_job(&job, strv_skip_first(args))) {
2144 if (!GREEDY_REALLOC(jobs, size, c + 1))
2150 return bus_log_parse_error(r);
2152 r = sd_bus_message_exit_container(reply);
2154 return bus_log_parse_error(r);
2156 output_jobs_list(jobs, c, skipped);
2160 static int cancel_job(sd_bus *bus, char **args) {
2161 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2166 if (strv_length(args) <= 1)
2167 return daemon_reload(bus, args);
2169 STRV_FOREACH(name, args+1) {
2173 r = safe_atou32(*name, &id);
2175 log_error("Failed to parse job id \"%s\": %s", *name, strerror(-r));
2179 r = sd_bus_call_method(
2181 "org.freedesktop.systemd1",
2182 "/org/freedesktop/systemd1",
2183 "org.freedesktop.systemd1.Manager",
2189 log_error("Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, r));
2197 static int need_daemon_reload(sd_bus *bus, const char *unit) {
2198 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2202 /* We ignore all errors here, since this is used to show a
2205 /* We don't use unit_dbus_path_from_name() directly since we
2206 * don't want to load the unit if it isn't loaded. */
2208 r = sd_bus_call_method(
2210 "org.freedesktop.systemd1",
2211 "/org/freedesktop/systemd1",
2212 "org.freedesktop.systemd1.Manager",
2220 r = sd_bus_message_read(reply, "o", &path);
2224 r = sd_bus_get_property_trivial(
2226 "org.freedesktop.systemd1",
2228 "org.freedesktop.systemd1.Unit",
2238 typedef struct WaitData {
2245 static int wait_filter(sd_bus *bus, sd_bus_message *m, void *data, sd_bus_error *error) {
2252 log_debug("Got D-Bus request: %s.%s() on %s",
2253 sd_bus_message_get_interface(m),
2254 sd_bus_message_get_member(m),
2255 sd_bus_message_get_path(m));
2257 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
2258 log_error("Warning! D-Bus connection terminated.");
2260 } else if (sd_bus_message_is_signal(m, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
2262 const char *path, *result, *unit;
2266 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
2268 ret = set_remove(d->set, (char*) path);
2274 if (!isempty(result))
2275 d->result = strdup(result);
2278 d->name = strdup(unit);
2283 r = sd_bus_message_read(m, "uos", &id, &path, &result);
2285 ret = set_remove(d->set, (char*) path);
2292 d->result = strdup(result);
2298 bus_log_parse_error(r);
2304 static int enable_wait_for_jobs(sd_bus *bus) {
2309 r = sd_bus_add_match(
2313 "sender='org.freedesktop.systemd1',"
2314 "interface='org.freedesktop.systemd1.Manager',"
2315 "member='JobRemoved',"
2316 "path='/org/freedesktop/systemd1'",
2319 log_error("Failed to add match");
2323 /* This is slightly dirty, since we don't undo the match registrations. */
2327 static int bus_process_wait(sd_bus *bus) {
2331 r = sd_bus_process(bus, NULL);
2336 r = sd_bus_wait(bus, (uint64_t) -1);
2342 static int check_wait_response(WaitData *d) {
2348 if (streq(d->result, "timeout"))
2349 log_error("Job for %s timed out.", strna(d->name));
2350 else if (streq(d->result, "canceled"))
2351 log_error("Job for %s canceled.", strna(d->name));
2352 else if (streq(d->result, "dependency"))
2353 log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
2354 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
2358 quotes = chars_intersect(d->name, SHELL_NEED_QUOTES);
2360 log_error("Job for %s failed. See \"systemctl status %s%s%s\" and \"journalctl -xe\" for details.",
2362 quotes ? "'" : "", d->name, quotes ? "'" : "");
2364 log_error("Job failed. See \"journalctl -xe\" for details.");
2368 if (streq(d->result, "timeout"))
2370 else if (streq(d->result, "canceled"))
2372 else if (streq(d->result, "dependency"))
2374 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2380 static int wait_for_jobs(sd_bus *bus, Set *s) {
2381 _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
2382 WaitData d = { .set = s };
2388 q = sd_bus_add_filter(bus, &slot, wait_filter, &d);
2392 while (!set_isempty(s)) {
2393 q = bus_process_wait(bus);
2395 log_error("Failed to wait for response: %s", strerror(-q));
2400 q = check_wait_response(&d);
2401 /* Return the first error as it is most likely to be
2403 if (q < 0 && r == 0)
2405 log_debug("Got result %s/%s for job %s",
2406 strna(d.result), strerror(-q), strna(d.name));
2419 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2420 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2421 _cleanup_free_ char *n = NULL, *state = NULL;
2427 n = unit_name_mangle(name, MANGLE_NOGLOB);
2431 /* We don't use unit_dbus_path_from_name() directly since we
2432 * don't want to load the unit if it isn't loaded. */
2434 r = sd_bus_call_method(
2436 "org.freedesktop.systemd1",
2437 "/org/freedesktop/systemd1",
2438 "org.freedesktop.systemd1.Manager",
2449 r = sd_bus_message_read(reply, "o", &path);
2451 return bus_log_parse_error(r);
2453 r = sd_bus_get_property_string(
2455 "org.freedesktop.systemd1",
2457 "org.freedesktop.systemd1.Unit",
2470 return nulstr_contains(good_states, state);
2473 static int check_triggering_units(
2477 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2478 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2479 _cleanup_strv_free_ char **triggered_by = NULL;
2480 bool print_warning_label = true;
2484 n = unit_name_mangle(name, MANGLE_NOGLOB);
2488 path = unit_dbus_path_from_name(n);
2492 r = sd_bus_get_property_string(
2494 "org.freedesktop.systemd1",
2496 "org.freedesktop.systemd1.Unit",
2501 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2505 if (streq(state, "masked"))
2508 r = sd_bus_get_property_strv(
2510 "org.freedesktop.systemd1",
2512 "org.freedesktop.systemd1.Unit",
2517 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2521 STRV_FOREACH(i, triggered_by) {
2522 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2524 log_error("Failed to check unit: %s", strerror(-r));
2531 if (print_warning_label) {
2532 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2533 print_warning_label = false;
2536 log_warning(" %s", *i);
2542 static const char *verb_to_method(const char *verb) {
2545 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2546 if (streq_ptr(unit_actions[i].verb, verb))
2547 return unit_actions[i].method;
2552 static const char *method_to_verb(const char *method) {
2555 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2556 if (streq_ptr(unit_actions[i].method, method))
2557 return unit_actions[i].verb;
2562 static int start_unit_one(
2567 sd_bus_error *error,
2570 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2579 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2580 r = sd_bus_call_method(
2582 "org.freedesktop.systemd1",
2583 "/org/freedesktop/systemd1",
2584 "org.freedesktop.systemd1.Manager",
2592 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2593 /* There's always a fallback possible for
2594 * legacy actions. */
2595 return -EADDRNOTAVAIL;
2597 verb = method_to_verb(method);
2599 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2603 r = sd_bus_message_read(reply, "o", &path);
2605 return bus_log_parse_error(r);
2607 if (need_daemon_reload(bus, name) > 0)
2608 log_warning("Warning: Unit file of %s changed on disk, 'systemctl%s daemon-reload' recommended.",
2609 name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2618 log_debug("Adding %s to the set", p);
2619 r = set_consume(s, p);
2627 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2629 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2633 STRV_FOREACH(name, names) {
2637 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2639 t = unit_name_mangle(*name, MANGLE_GLOB);
2643 if (string_is_glob(t))
2644 r = strv_consume(&globs, t);
2646 r = strv_consume(&mangled, t);
2651 /* Query the manager only if any of the names are a glob, since
2652 * this is fairly expensive */
2653 if (!strv_isempty(globs)) {
2654 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2655 _cleanup_free_ UnitInfo *unit_infos = NULL;
2657 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2661 for (i = 0; i < r; i++)
2662 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2667 mangled = NULL; /* do not free */
2672 static const struct {
2676 } action_table[_ACTION_MAX] = {
2677 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2678 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2679 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2680 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2681 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
2682 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
2683 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
2684 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
2685 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2686 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2687 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2688 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2689 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2690 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2691 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2694 static enum action verb_to_action(const char *verb) {
2697 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2698 if (streq_ptr(action_table[i].verb, verb))
2701 return _ACTION_INVALID;
2704 static int start_unit(sd_bus *bus, char **args) {
2705 _cleanup_set_free_free_ Set *s = NULL;
2706 _cleanup_strv_free_ char **names = NULL;
2707 const char *method, *mode, *one_name;
2713 ask_password_agent_open_if_enabled();
2715 if (arg_action == ACTION_SYSTEMCTL) {
2717 method = verb_to_method(args[0]);
2718 action = verb_to_action(args[0]);
2720 mode = streq(args[0], "isolate") ? "isolate" :
2721 action_table[action].mode ?: arg_job_mode;
2723 one_name = action_table[action].target;
2725 assert(arg_action < ELEMENTSOF(action_table));
2726 assert(action_table[arg_action].target);
2728 method = "StartUnit";
2730 mode = action_table[arg_action].mode;
2731 one_name = action_table[arg_action].target;
2735 names = strv_new(one_name, NULL);
2737 r = expand_names(bus, args + 1, NULL, &names);
2739 log_error("Failed to expand names: %s", strerror(-r));
2742 if (!arg_no_block) {
2743 r = enable_wait_for_jobs(bus);
2745 log_error("Could not watch jobs: %s", strerror(-r));
2749 s = set_new(&string_hash_ops);
2754 STRV_FOREACH(name, names) {
2755 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2758 q = start_unit_one(bus, method, *name, mode, &error, s);
2759 if (r >= 0 && q < 0)
2760 r = translate_bus_error_to_exit_status(q, &error);
2763 if (!arg_no_block) {
2766 q = wait_for_jobs(bus, s);
2770 /* When stopping units, warn if they can still be triggered by
2771 * another active unit (socket, path, timer) */
2772 if (!arg_quiet && streq(method, "StopUnit"))
2773 STRV_FOREACH(name, names)
2774 check_triggering_units(bus, *name);
2780 /* Ask systemd-logind, which might grant access to unprivileged users
2781 * through PolicyKit */
2782 static int reboot_with_logind(sd_bus *bus, enum action a) {
2784 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2791 polkit_agent_open_if_enabled();
2799 case ACTION_POWEROFF:
2800 method = "PowerOff";
2803 case ACTION_SUSPEND:
2807 case ACTION_HIBERNATE:
2808 method = "Hibernate";
2811 case ACTION_HYBRID_SLEEP:
2812 method = "HybridSleep";
2819 r = sd_bus_call_method(
2821 "org.freedesktop.login1",
2822 "/org/freedesktop/login1",
2823 "org.freedesktop.login1.Manager",
2829 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2837 static int check_inhibitors(sd_bus *bus, enum action a) {
2839 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2840 _cleanup_strv_free_ char **sessions = NULL;
2841 const char *what, *who, *why, *mode;
2850 if (arg_ignore_inhibitors || arg_force > 0)
2862 r = sd_bus_call_method(
2864 "org.freedesktop.login1",
2865 "/org/freedesktop/login1",
2866 "org.freedesktop.login1.Manager",
2872 /* If logind is not around, then there are no inhibitors... */
2875 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2877 return bus_log_parse_error(r);
2879 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2880 _cleanup_free_ char *comm = NULL, *user = NULL;
2881 _cleanup_strv_free_ char **sv = NULL;
2883 if (!streq(mode, "block"))
2886 sv = strv_split(what, ":");
2890 if (!strv_contains(sv,
2892 a == ACTION_POWEROFF ||
2893 a == ACTION_REBOOT ||
2894 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2897 get_process_comm(pid, &comm);
2898 user = uid_to_name(uid);
2900 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
2901 who, pid, strna(comm), strna(user), why);
2906 return bus_log_parse_error(r);
2908 r = sd_bus_message_exit_container(reply);
2910 return bus_log_parse_error(r);
2912 /* Check for current sessions */
2913 sd_get_sessions(&sessions);
2914 STRV_FOREACH(s, sessions) {
2915 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2917 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2920 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2923 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2926 sd_session_get_tty(*s, &tty);
2927 sd_session_get_seat(*s, &seat);
2928 sd_session_get_service(*s, &service);
2929 user = uid_to_name(uid);
2931 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2938 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2939 action_table[a].verb);
2947 static int start_special(sd_bus *bus, char **args) {
2953 a = verb_to_action(args[0]);
2955 r = check_inhibitors(bus, a);
2959 if (arg_force >= 2 && geteuid() != 0) {
2960 log_error("Must be root.");
2964 if (arg_force >= 2 &&
2965 (a == ACTION_HALT ||
2966 a == ACTION_POWEROFF ||
2967 a == ACTION_REBOOT))
2970 if (arg_force >= 1 &&
2971 (a == ACTION_HALT ||
2972 a == ACTION_POWEROFF ||
2973 a == ACTION_REBOOT ||
2974 a == ACTION_KEXEC ||
2976 return daemon_reload(bus, args);
2978 /* first try logind, to allow authentication with polkit */
2979 if (geteuid() != 0 &&
2980 (a == ACTION_POWEROFF ||
2981 a == ACTION_REBOOT ||
2982 a == ACTION_SUSPEND ||
2983 a == ACTION_HIBERNATE ||
2984 a == ACTION_HYBRID_SLEEP)) {
2985 r = reboot_with_logind(bus, a);
2990 r = start_unit(bus, args);
2991 if (r == EXIT_SUCCESS)
2997 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
2998 _cleanup_strv_free_ char **names = NULL;
3005 r = expand_names(bus, args, NULL, &names);
3007 log_error("Failed to expand names: %s", strerror(-r));
3011 STRV_FOREACH(name, names) {
3014 state = check_one_unit(bus, *name, good_states, arg_quiet);
3024 static int check_unit_active(sd_bus *bus, char **args) {
3025 /* According to LSB: 3, "program is not running" */
3026 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
3029 static int check_unit_failed(sd_bus *bus, char **args) {
3030 return check_unit_generic(bus, 1, "failed\0", args + 1);
3033 static int kill_unit(sd_bus *bus, char **args) {
3034 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3035 _cleanup_strv_free_ char **names = NULL;
3043 arg_kill_who = "all";
3045 r = expand_names(bus, args + 1, NULL, &names);
3047 log_error("Failed to expand names: %s", strerror(-r));
3049 STRV_FOREACH(name, names) {
3050 q = sd_bus_call_method(
3052 "org.freedesktop.systemd1",
3053 "/org/freedesktop/systemd1",
3054 "org.freedesktop.systemd1.Manager",
3058 "ssi", *names, arg_kill_who, arg_signal);
3060 log_error("Failed to kill unit %s: %s",
3061 *names, bus_error_message(&error, r));
3070 typedef struct ExecStatusInfo {
3078 usec_t start_timestamp;
3079 usec_t exit_timestamp;
3084 LIST_FIELDS(struct ExecStatusInfo, exec);
3087 static void exec_status_info_free(ExecStatusInfo *i) {
3096 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3097 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3100 int32_t code, status;
3106 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3108 return bus_log_parse_error(r);
3112 r = sd_bus_message_read(m, "s", &path);
3114 return bus_log_parse_error(r);
3116 i->path = strdup(path);
3120 r = sd_bus_message_read_strv(m, &i->argv);
3122 return bus_log_parse_error(r);
3124 r = sd_bus_message_read(m,
3127 &start_timestamp, &start_timestamp_monotonic,
3128 &exit_timestamp, &exit_timestamp_monotonic,
3132 return bus_log_parse_error(r);
3135 i->start_timestamp = (usec_t) start_timestamp;
3136 i->exit_timestamp = (usec_t) exit_timestamp;
3137 i->pid = (pid_t) pid;
3141 r = sd_bus_message_exit_container(m);
3143 return bus_log_parse_error(r);
3148 typedef struct UnitStatusInfo {
3150 const char *load_state;
3151 const char *active_state;
3152 const char *sub_state;
3153 const char *unit_file_state;
3155 const char *description;
3156 const char *following;
3158 char **documentation;
3160 const char *fragment_path;
3161 const char *source_path;
3162 const char *control_group;
3164 char **dropin_paths;
3166 const char *load_error;
3169 usec_t inactive_exit_timestamp;
3170 usec_t inactive_exit_timestamp_monotonic;
3171 usec_t active_enter_timestamp;
3172 usec_t active_exit_timestamp;
3173 usec_t inactive_enter_timestamp;
3175 bool need_daemon_reload;
3180 const char *status_text;
3181 const char *pid_file;
3185 usec_t start_timestamp;
3186 usec_t exit_timestamp;
3188 int exit_code, exit_status;
3190 usec_t condition_timestamp;
3191 bool condition_result;
3192 bool failed_condition_trigger;
3193 bool failed_condition_negate;
3194 const char *failed_condition;
3195 const char *failed_condition_param;
3198 unsigned n_accepted;
3199 unsigned n_connections;
3202 /* Pairs of type, path */
3206 const char *sysfs_path;
3208 /* Mount, Automount */
3214 LIST_HEAD(ExecStatusInfo, exec);
3217 static void print_status_info(
3222 const char *active_on, *active_off, *on, *off, *ss;
3224 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3225 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3228 arg_all * OUTPUT_SHOW_ALL |
3229 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
3230 on_tty() * OUTPUT_COLOR |
3231 !arg_quiet * OUTPUT_WARN_CUTOFF |
3232 arg_full * OUTPUT_FULL_WIDTH;
3237 /* This shows pretty information about a unit. See
3238 * print_property() for a low-level property printer */
3240 if (streq_ptr(i->active_state, "failed")) {
3241 active_on = ansi_highlight_red();
3242 active_off = ansi_highlight_off();
3243 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3244 active_on = ansi_highlight_green();
3245 active_off = ansi_highlight_off();
3247 active_on = active_off = "";
3249 printf("%s%s%s %s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3251 if (i->description && !streq_ptr(i->id, i->description))
3252 printf(" - %s", i->description);
3257 printf(" Follow: unit currently follows state of %s\n", i->following);
3259 if (streq_ptr(i->load_state, "error")) {
3260 on = ansi_highlight_red();
3261 off = ansi_highlight_off();
3265 path = i->source_path ? i->source_path : i->fragment_path;
3268 printf(" Loaded: %s%s%s (Reason: %s)\n",
3269 on, strna(i->load_state), off, i->load_error);
3270 else if (path && i->unit_file_state)
3271 printf(" Loaded: %s%s%s (%s; %s)\n",
3272 on, strna(i->load_state), off, path, i->unit_file_state);
3274 printf(" Loaded: %s%s%s (%s)\n",
3275 on, strna(i->load_state), off, path);
3277 printf(" Loaded: %s%s%s\n",
3278 on, strna(i->load_state), off);
3280 if (!strv_isempty(i->dropin_paths)) {
3281 _cleanup_free_ char *dir = NULL;
3285 STRV_FOREACH(dropin, i->dropin_paths) {
3286 if (! dir || last) {
3287 printf(dir ? " " : " Drop-In: ");
3292 if (path_get_parent(*dropin, &dir) < 0) {
3297 printf("%s\n %s", dir,
3298 draw_special_char(DRAW_TREE_RIGHT));
3301 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3303 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3307 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3309 printf(" Active: %s%s (%s)%s",
3310 active_on, strna(i->active_state), ss, active_off);
3312 printf(" Active: %s%s%s",
3313 active_on, strna(i->active_state), active_off);
3315 if (!isempty(i->result) && !streq(i->result, "success"))
3316 printf(" (Result: %s)", i->result);
3318 timestamp = (streq_ptr(i->active_state, "active") ||
3319 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
3320 (streq_ptr(i->active_state, "inactive") ||
3321 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
3322 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
3323 i->active_exit_timestamp;
3325 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3326 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3329 printf(" since %s; %s\n", s2, s1);
3331 printf(" since %s\n", s2);
3335 if (!i->condition_result && i->condition_timestamp > 0) {
3336 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3337 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3339 printf(" start condition failed at %s%s%s\n",
3340 s2, s1 ? "; " : "", s1 ? s1 : "");
3341 if (i->failed_condition_trigger)
3342 printf(" none of the trigger conditions were met\n");
3343 else if (i->failed_condition)
3344 printf(" %s=%s%s was not met\n",
3345 i->failed_condition,
3346 i->failed_condition_negate ? "!" : "",
3347 i->failed_condition_param);
3351 printf(" Device: %s\n", i->sysfs_path);
3353 printf(" Where: %s\n", i->where);
3355 printf(" What: %s\n", i->what);
3357 STRV_FOREACH(t, i->documentation)
3358 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3360 STRV_FOREACH_PAIR(t, t2, i->listen)
3361 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3364 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3366 LIST_FOREACH(exec, p, i->exec) {
3367 _cleanup_free_ char *argv = NULL;
3370 /* Only show exited processes here */
3374 argv = strv_join(p->argv, " ");
3375 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
3377 good = is_clean_exit_lsb(p->code, p->status, NULL);
3379 on = ansi_highlight_red();
3380 off = ansi_highlight_off();
3384 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3386 if (p->code == CLD_EXITED) {
3389 printf("status=%i", p->status);
3391 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3396 printf("signal=%s", signal_to_string(p->status));
3398 printf(")%s\n", off);
3400 if (i->main_pid == p->pid &&
3401 i->start_timestamp == p->start_timestamp &&
3402 i->exit_timestamp == p->start_timestamp)
3403 /* Let's not show this twice */
3406 if (p->pid == i->control_pid)
3410 if (i->main_pid > 0 || i->control_pid > 0) {
3411 if (i->main_pid > 0) {
3412 printf(" Main PID: "PID_FMT, i->main_pid);
3415 _cleanup_free_ char *comm = NULL;
3416 get_process_comm(i->main_pid, &comm);
3418 printf(" (%s)", comm);
3419 } else if (i->exit_code > 0) {
3420 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3422 if (i->exit_code == CLD_EXITED) {
3425 printf("status=%i", i->exit_status);
3427 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3432 printf("signal=%s", signal_to_string(i->exit_status));
3436 if (i->control_pid > 0)
3440 if (i->control_pid > 0) {
3441 _cleanup_free_ char *c = NULL;
3443 printf(" %8s: "PID_FMT, i->main_pid ? "" : " Control", i->control_pid);
3445 get_process_comm(i->control_pid, &c);
3454 printf(" Status: \"%s\"\n", i->status_text);
3455 if (i->status_errno > 0)
3456 printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
3458 if (i->control_group &&
3459 (i->main_pid > 0 || i->control_pid > 0 ||
3460 ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_CONTAINER) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3463 printf(" CGroup: %s\n", i->control_group);
3465 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
3468 static const char prefix[] = " ";
3471 if (c > sizeof(prefix) - 1)
3472 c -= sizeof(prefix) - 1;
3476 if (i->main_pid > 0)
3477 extra[k++] = i->main_pid;
3479 if (i->control_pid > 0)
3480 extra[k++] = i->control_pid;
3482 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, flags);
3486 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3487 show_journal_by_unit(stdout,
3491 i->inactive_exit_timestamp_monotonic,
3494 flags | OUTPUT_BEGIN_NEWLINE,
3495 arg_scope == UNIT_FILE_SYSTEM,
3499 if (i->need_daemon_reload)
3500 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
3501 ansi_highlight_red(),
3502 ansi_highlight_off(),
3503 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
3506 static void show_unit_help(UnitStatusInfo *i) {
3511 if (!i->documentation) {
3512 log_info("Documentation for %s not known.", i->id);
3516 STRV_FOREACH(p, i->documentation)
3517 if (startswith(*p, "man:"))
3518 show_man_page(*p + 4, false);
3520 log_info("Can't show: %s", *p);
3523 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3530 switch (contents[0]) {
3532 case SD_BUS_TYPE_STRING: {
3535 r = sd_bus_message_read(m, "s", &s);
3537 return bus_log_parse_error(r);
3540 if (streq(name, "Id"))
3542 else if (streq(name, "LoadState"))
3544 else if (streq(name, "ActiveState"))
3545 i->active_state = s;
3546 else if (streq(name, "SubState"))
3548 else if (streq(name, "Description"))
3550 else if (streq(name, "FragmentPath"))
3551 i->fragment_path = s;
3552 else if (streq(name, "SourcePath"))
3555 else if (streq(name, "DefaultControlGroup")) {
3557 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3559 i->control_group = e;
3562 else if (streq(name, "ControlGroup"))
3563 i->control_group = s;
3564 else if (streq(name, "StatusText"))
3566 else if (streq(name, "PIDFile"))
3568 else if (streq(name, "SysFSPath"))
3570 else if (streq(name, "Where"))
3572 else if (streq(name, "What"))
3574 else if (streq(name, "Following"))
3576 else if (streq(name, "UnitFileState"))
3577 i->unit_file_state = s;
3578 else if (streq(name, "Result"))
3585 case SD_BUS_TYPE_BOOLEAN: {
3588 r = sd_bus_message_read(m, "b", &b);
3590 return bus_log_parse_error(r);
3592 if (streq(name, "Accept"))
3594 else if (streq(name, "NeedDaemonReload"))
3595 i->need_daemon_reload = b;
3596 else if (streq(name, "ConditionResult"))
3597 i->condition_result = b;
3602 case SD_BUS_TYPE_UINT32: {
3605 r = sd_bus_message_read(m, "u", &u);
3607 return bus_log_parse_error(r);
3609 if (streq(name, "MainPID")) {
3611 i->main_pid = (pid_t) u;
3614 } else if (streq(name, "ControlPID"))
3615 i->control_pid = (pid_t) u;
3616 else if (streq(name, "ExecMainPID")) {
3618 i->main_pid = (pid_t) u;
3619 } else if (streq(name, "NAccepted"))
3621 else if (streq(name, "NConnections"))
3622 i->n_connections = u;
3627 case SD_BUS_TYPE_INT32: {
3630 r = sd_bus_message_read(m, "i", &j);
3632 return bus_log_parse_error(r);
3634 if (streq(name, "ExecMainCode"))
3635 i->exit_code = (int) j;
3636 else if (streq(name, "ExecMainStatus"))
3637 i->exit_status = (int) j;
3638 else if (streq(name, "StatusErrno"))
3639 i->status_errno = (int) j;
3644 case SD_BUS_TYPE_UINT64: {
3647 r = sd_bus_message_read(m, "t", &u);
3649 return bus_log_parse_error(r);
3651 if (streq(name, "ExecMainStartTimestamp"))
3652 i->start_timestamp = (usec_t) u;
3653 else if (streq(name, "ExecMainExitTimestamp"))
3654 i->exit_timestamp = (usec_t) u;
3655 else if (streq(name, "ActiveEnterTimestamp"))
3656 i->active_enter_timestamp = (usec_t) u;
3657 else if (streq(name, "InactiveEnterTimestamp"))
3658 i->inactive_enter_timestamp = (usec_t) u;
3659 else if (streq(name, "InactiveExitTimestamp"))
3660 i->inactive_exit_timestamp = (usec_t) u;
3661 else if (streq(name, "InactiveExitTimestampMonotonic"))
3662 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3663 else if (streq(name, "ActiveExitTimestamp"))
3664 i->active_exit_timestamp = (usec_t) u;
3665 else if (streq(name, "ConditionTimestamp"))
3666 i->condition_timestamp = (usec_t) u;
3671 case SD_BUS_TYPE_ARRAY:
3673 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3674 _cleanup_free_ ExecStatusInfo *info = NULL;
3676 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3678 return bus_log_parse_error(r);
3680 info = new0(ExecStatusInfo, 1);
3684 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3686 info->name = strdup(name);
3690 LIST_PREPEND(exec, i->exec, info);
3692 info = new0(ExecStatusInfo, 1);
3698 return bus_log_parse_error(r);
3700 r = sd_bus_message_exit_container(m);
3702 return bus_log_parse_error(r);
3706 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3707 const char *type, *path;
3709 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3711 return bus_log_parse_error(r);
3713 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3715 r = strv_extend(&i->listen, type);
3719 r = strv_extend(&i->listen, path);
3724 return bus_log_parse_error(r);
3726 r = sd_bus_message_exit_container(m);
3728 return bus_log_parse_error(r);
3732 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3734 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3736 return bus_log_parse_error(r);
3738 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3740 r = sd_bus_message_read_strv(m, &i->documentation);
3742 return bus_log_parse_error(r);
3744 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3745 const char *cond, *param;
3746 int trigger, negate;
3749 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3751 return bus_log_parse_error(r);
3753 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3754 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3755 if (state < 0 && (!trigger || !i->failed_condition)) {
3756 i->failed_condition = cond;
3757 i->failed_condition_trigger = trigger;
3758 i->failed_condition_negate = negate;
3759 i->failed_condition_param = param;
3763 return bus_log_parse_error(r);
3765 r = sd_bus_message_exit_container(m);
3767 return bus_log_parse_error(r);
3774 case SD_BUS_TYPE_STRUCT_BEGIN:
3776 if (streq(name, "LoadError")) {
3777 const char *n, *message;
3779 r = sd_bus_message_read(m, "(ss)", &n, &message);
3781 return bus_log_parse_error(r);
3783 if (!isempty(message))
3784 i->load_error = message;
3797 r = sd_bus_message_skip(m, contents);
3799 return bus_log_parse_error(r);
3804 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3810 /* This is a low-level property printer, see
3811 * print_status_info() for the nicer output */
3813 if (arg_properties && !strv_find(arg_properties, name)) {
3814 /* skip what we didn't read */
3815 r = sd_bus_message_skip(m, contents);
3819 switch (contents[0]) {
3821 case SD_BUS_TYPE_STRUCT_BEGIN:
3823 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3826 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3828 return bus_log_parse_error(r);
3831 printf("%s=%"PRIu32"\n", name, u);
3833 printf("%s=\n", name);
3837 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3840 r = sd_bus_message_read(m, "(so)", &s, NULL);
3842 return bus_log_parse_error(r);
3844 if (arg_all || !isempty(s))
3845 printf("%s=%s\n", name, s);
3849 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3850 const char *a = NULL, *b = NULL;
3852 r = sd_bus_message_read(m, "(ss)", &a, &b);
3854 return bus_log_parse_error(r);
3856 if (arg_all || !isempty(a) || !isempty(b))
3857 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3860 } else if (streq_ptr(name, "SystemCallFilter")) {
3861 _cleanup_strv_free_ char **l = NULL;
3864 r = sd_bus_message_enter_container(m, 'r', "bas");
3866 return bus_log_parse_error(r);
3868 r = sd_bus_message_read(m, "b", &whitelist);
3870 return bus_log_parse_error(r);
3872 r = sd_bus_message_read_strv(m, &l);
3874 return bus_log_parse_error(r);
3876 r = sd_bus_message_exit_container(m);
3878 return bus_log_parse_error(r);
3880 if (arg_all || whitelist || !strv_isempty(l)) {
3884 fputs(name, stdout);
3890 STRV_FOREACH(i, l) {
3898 fputc('\n', stdout);
3906 case SD_BUS_TYPE_ARRAY:
3908 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
3912 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
3914 return bus_log_parse_error(r);
3916 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
3917 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3920 return bus_log_parse_error(r);
3922 r = sd_bus_message_exit_container(m);
3924 return bus_log_parse_error(r);
3928 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
3929 const char *type, *path;
3931 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3933 return bus_log_parse_error(r);
3935 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3936 printf("%s=%s\n", type, path);
3938 return bus_log_parse_error(r);
3940 r = sd_bus_message_exit_container(m);
3942 return bus_log_parse_error(r);
3946 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3947 const char *type, *path;
3949 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3951 return bus_log_parse_error(r);
3953 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3954 printf("Listen%s=%s\n", type, path);
3956 return bus_log_parse_error(r);
3958 r = sd_bus_message_exit_container(m);
3960 return bus_log_parse_error(r);
3964 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
3966 uint64_t value, next_elapse;
3968 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
3970 return bus_log_parse_error(r);
3972 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
3973 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3975 printf("%s={ value=%s ; next_elapse=%s }\n",
3977 format_timespan(timespan1, sizeof(timespan1), value, 0),
3978 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3981 return bus_log_parse_error(r);
3983 r = sd_bus_message_exit_container(m);
3985 return bus_log_parse_error(r);
3989 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3990 ExecStatusInfo info = {};
3992 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3994 return bus_log_parse_error(r);
3996 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
3997 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3998 _cleanup_free_ char *tt;
4000 tt = strv_join(info.argv, " ");
4002 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }\n",
4006 yes_no(info.ignore),
4007 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
4008 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
4010 sigchld_code_to_string(info.code),
4012 info.code == CLD_EXITED ? "" : "/",
4013 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
4016 strv_free(info.argv);
4020 r = sd_bus_message_exit_container(m);
4022 return bus_log_parse_error(r);
4026 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
4027 const char *path, *rwm;
4029 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4031 return bus_log_parse_error(r);
4033 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
4034 printf("%s=%s %s\n", name, strna(path), strna(rwm));
4036 return bus_log_parse_error(r);
4038 r = sd_bus_message_exit_container(m);
4040 return bus_log_parse_error(r);
4044 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
4048 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4050 return bus_log_parse_error(r);
4052 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4053 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
4055 return bus_log_parse_error(r);
4057 r = sd_bus_message_exit_container(m);
4059 return bus_log_parse_error(r);
4063 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
4067 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4069 return bus_log_parse_error(r);
4071 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4072 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
4074 return bus_log_parse_error(r);
4076 r = sd_bus_message_exit_container(m);
4078 return bus_log_parse_error(r);
4086 r = bus_print_property(name, m, arg_all);
4088 return bus_log_parse_error(r);
4091 r = sd_bus_message_skip(m, contents);
4093 return bus_log_parse_error(r);
4096 printf("%s=[unprintable]\n", name);
4102 static int show_one(
4106 bool show_properties,
4110 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4111 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4112 UnitStatusInfo info = {};
4119 log_debug("Showing one %s", path);
4121 r = sd_bus_call_method(
4123 "org.freedesktop.systemd1",
4125 "org.freedesktop.DBus.Properties",
4131 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4135 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4137 return bus_log_parse_error(r);
4144 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4145 const char *name, *contents;
4147 r = sd_bus_message_read(reply, "s", &name);
4149 return bus_log_parse_error(r);
4151 r = sd_bus_message_peek_type(reply, NULL, &contents);
4153 return bus_log_parse_error(r);
4155 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4157 return bus_log_parse_error(r);
4159 if (show_properties)
4160 r = print_property(name, reply, contents);
4162 r = status_property(name, reply, &info, contents);
4166 r = sd_bus_message_exit_container(reply);
4168 return bus_log_parse_error(r);
4170 r = sd_bus_message_exit_container(reply);
4172 return bus_log_parse_error(r);
4175 return bus_log_parse_error(r);
4177 r = sd_bus_message_exit_container(reply);
4179 return bus_log_parse_error(r);
4183 if (!show_properties) {
4184 if (streq(verb, "help"))
4185 show_unit_help(&info);
4187 print_status_info(&info, ellipsized);
4190 strv_free(info.documentation);
4191 strv_free(info.dropin_paths);
4192 strv_free(info.listen);
4194 if (!streq_ptr(info.active_state, "active") &&
4195 !streq_ptr(info.active_state, "reloading") &&
4196 streq(verb, "status")) {
4197 /* According to LSB: "program not running" */
4198 /* 0: program is running or service is OK
4199 * 1: program is dead and /run PID file exists
4200 * 2: program is dead and /run/lock lock file exists
4201 * 3: program is not running
4202 * 4: program or service status is unknown
4204 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4210 while ((p = info.exec)) {
4211 LIST_REMOVE(exec, info.exec, p);
4212 exec_status_info_free(p);
4218 static int get_unit_dbus_path_by_pid(
4223 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4224 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4228 r = sd_bus_call_method(
4230 "org.freedesktop.systemd1",
4231 "/org/freedesktop/systemd1",
4232 "org.freedesktop.systemd1.Manager",
4238 log_error("Failed to get unit for PID "PID_FMT": %s", pid, bus_error_message(&error, r));
4242 r = sd_bus_message_read(reply, "o", &u);
4244 return bus_log_parse_error(r);
4254 static int show_all(
4257 bool show_properties,
4261 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4262 _cleanup_free_ UnitInfo *unit_infos = NULL;
4267 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4271 pager_open_if_enabled();
4275 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4277 for (u = unit_infos; u < unit_infos + c; u++) {
4278 _cleanup_free_ char *p = NULL;
4280 p = unit_dbus_path_from_name(u->id);
4284 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4287 else if (r > 0 && ret == 0)
4294 static int show_system_status(sd_bus *bus) {
4295 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4296 _cleanup_free_ char *hn = NULL;
4297 struct machine_info mi = {};
4298 const char *on, *off;
4301 hn = gethostname_malloc();
4305 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4307 log_error("Failed to read server status: %s", strerror(-r));
4311 if (streq_ptr(mi.state, "degraded")) {
4312 on = ansi_highlight_red();
4313 off = ansi_highlight_off();
4314 } else if (!streq_ptr(mi.state, "running")) {
4315 on = ansi_highlight_yellow();
4316 off = ansi_highlight_off();
4320 printf("%s%s%s %s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4322 printf(" State: %s%s%s\n",
4323 on, strna(mi.state), off);
4325 printf(" Jobs: %u queued\n", mi.n_jobs);
4326 printf(" Failed: %u units\n", mi.n_failed_units);
4328 printf(" Since: %s; %s\n",
4329 format_timestamp(since2, sizeof(since2), mi.timestamp),
4330 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4332 printf(" CGroup: %s\n", mi.control_group ?: "/");
4333 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
4335 arg_all * OUTPUT_SHOW_ALL |
4336 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
4337 on_tty() * OUTPUT_COLOR |
4338 !arg_quiet * OUTPUT_WARN_CUTOFF |
4339 arg_full * OUTPUT_FULL_WIDTH;
4341 static const char prefix[] = " ";
4345 if (c > sizeof(prefix) - 1)
4346 c -= sizeof(prefix) - 1;
4350 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
4354 free(mi.control_group);
4359 static int show(sd_bus *bus, char **args) {
4360 bool show_properties, show_status, new_line = false;
4361 bool ellipsized = false;
4367 show_properties = streq(args[0], "show");
4368 show_status = streq(args[0], "status");
4370 if (show_properties)
4371 pager_open_if_enabled();
4373 /* If no argument is specified inspect the manager itself */
4375 if (show_properties && strv_length(args) <= 1)
4376 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4378 if (show_status && strv_length(args) <= 1) {
4380 pager_open_if_enabled();
4381 show_system_status(bus);
4385 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4387 _cleanup_free_ char **patterns = NULL;
4390 STRV_FOREACH(name, args + 1) {
4391 _cleanup_free_ char *unit = NULL;
4394 if (safe_atou32(*name, &id) < 0) {
4395 if (strv_push(&patterns, *name) < 0)
4399 } else if (show_properties) {
4400 /* Interpret as job id */
4401 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4405 /* Interpret as PID */
4406 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4413 r = show_one(args[0], bus, unit, show_properties,
4414 &new_line, &ellipsized);
4417 else if (r > 0 && ret == 0)
4421 if (!strv_isempty(patterns)) {
4422 _cleanup_strv_free_ char **names = NULL;
4424 r = expand_names(bus, patterns, NULL, &names);
4426 log_error("Failed to expand names: %s", strerror(-r));
4428 STRV_FOREACH(name, names) {
4429 _cleanup_free_ char *unit;
4431 unit = unit_dbus_path_from_name(*name);
4435 r = show_one(args[0], bus, unit, show_properties,
4436 &new_line, &ellipsized);
4439 else if (r > 0 && ret == 0)
4445 if (ellipsized && !arg_quiet)
4446 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4451 static int cat(sd_bus *bus, char **args) {
4452 _cleanup_strv_free_ char **names = NULL;
4460 r = expand_names(bus, args + 1, NULL, &names);
4462 log_error("Failed to expand names: %s", strerror(-r));
4464 pager_open_if_enabled();
4466 STRV_FOREACH(name, names) {
4467 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4468 _cleanup_strv_free_ char **dropin_paths = NULL;
4469 _cleanup_free_ char *fragment_path = NULL, *unit = NULL;
4472 unit = unit_dbus_path_from_name(*name);
4476 if (need_daemon_reload(bus, *name) > 0)
4477 log_warning("Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'.",
4478 *name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
4480 r = sd_bus_get_property_string(
4482 "org.freedesktop.systemd1",
4484 "org.freedesktop.systemd1.Unit",
4489 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
4493 r = sd_bus_get_property_strv(
4495 "org.freedesktop.systemd1",
4497 "org.freedesktop.systemd1.Unit",
4502 log_warning("Failed to get DropInPaths: %s", bus_error_message(&error, r));
4511 if (!isempty(fragment_path)) {
4512 printf("%s# %s%s\n",
4513 ansi_highlight_blue(),
4515 ansi_highlight_off());
4518 r = sendfile_full(STDOUT_FILENO, fragment_path);
4520 log_warning("Failed to cat %s: %s", fragment_path, strerror(-r));
4525 STRV_FOREACH(path, dropin_paths) {
4526 printf("%s%s# %s%s\n",
4527 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4528 ansi_highlight_blue(),
4530 ansi_highlight_off());
4533 r = sendfile_full(STDOUT_FILENO, *path);
4535 log_warning("Failed to cat %s: %s", *path, strerror(-r));
4541 return r < 0 ? r : 0;
4544 static int set_property(sd_bus *bus, char **args) {
4545 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4546 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4547 _cleanup_free_ char *n = NULL;
4551 r = sd_bus_message_new_method_call(
4554 "org.freedesktop.systemd1",
4555 "/org/freedesktop/systemd1",
4556 "org.freedesktop.systemd1.Manager",
4557 "SetUnitProperties");
4559 return bus_log_create_error(r);
4561 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4565 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4567 return bus_log_create_error(r);
4569 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4571 return bus_log_create_error(r);
4573 STRV_FOREACH(i, args + 2) {
4574 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4576 return bus_log_create_error(r);
4578 r = bus_append_unit_property_assignment(m, *i);
4582 r = sd_bus_message_close_container(m);
4584 return bus_log_create_error(r);
4587 r = sd_bus_message_close_container(m);
4589 return bus_log_create_error(r);
4591 r = sd_bus_call(bus, m, 0, &error, NULL);
4593 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4600 static int snapshot(sd_bus *bus, char **args) {
4601 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4602 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4603 _cleanup_free_ char *n = NULL, *id = NULL;
4607 if (strv_length(args) > 1)
4608 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4614 r = sd_bus_call_method(
4616 "org.freedesktop.systemd1",
4617 "/org/freedesktop/systemd1",
4618 "org.freedesktop.systemd1.Manager",
4624 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4628 r = sd_bus_message_read(reply, "o", &path);
4630 return bus_log_parse_error(r);
4632 r = sd_bus_get_property_string(
4634 "org.freedesktop.systemd1",
4636 "org.freedesktop.systemd1.Unit",
4641 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4651 static int delete_snapshot(sd_bus *bus, char **args) {
4652 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4653 _cleanup_strv_free_ char **names = NULL;
4659 r = expand_names(bus, args + 1, ".snapshot", &names);
4661 log_error("Failed to expand names: %s", strerror(-r));
4663 STRV_FOREACH(name, names) {
4664 q = sd_bus_call_method(
4666 "org.freedesktop.systemd1",
4667 "/org/freedesktop/systemd1",
4668 "org.freedesktop.systemd1.Manager",
4674 log_error("Failed to remove snapshot %s: %s",
4675 *name, bus_error_message(&error, r));
4684 static int daemon_reload(sd_bus *bus, char **args) {
4685 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4689 if (arg_action == ACTION_RELOAD)
4691 else if (arg_action == ACTION_REEXEC)
4692 method = "Reexecute";
4694 assert(arg_action == ACTION_SYSTEMCTL);
4697 streq(args[0], "clear-jobs") ||
4698 streq(args[0], "cancel") ? "ClearJobs" :
4699 streq(args[0], "daemon-reexec") ? "Reexecute" :
4700 streq(args[0], "reset-failed") ? "ResetFailed" :
4701 streq(args[0], "halt") ? "Halt" :
4702 streq(args[0], "poweroff") ? "PowerOff" :
4703 streq(args[0], "reboot") ? "Reboot" :
4704 streq(args[0], "kexec") ? "KExec" :
4705 streq(args[0], "exit") ? "Exit" :
4706 /* "daemon-reload" */ "Reload";
4709 r = sd_bus_call_method(
4711 "org.freedesktop.systemd1",
4712 "/org/freedesktop/systemd1",
4713 "org.freedesktop.systemd1.Manager",
4719 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4720 /* There's always a fallback possible for
4721 * legacy actions. */
4723 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4724 /* On reexecution, we expect a disconnect, not a
4728 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4730 return r < 0 ? r : 0;
4733 static int reset_failed(sd_bus *bus, char **args) {
4734 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4735 _cleanup_strv_free_ char **names = NULL;
4739 if (strv_length(args) <= 1)
4740 return daemon_reload(bus, args);
4742 r = expand_names(bus, args + 1, NULL, &names);
4744 log_error("Failed to expand names: %s", strerror(-r));
4746 STRV_FOREACH(name, names) {
4747 q = sd_bus_call_method(
4749 "org.freedesktop.systemd1",
4750 "/org/freedesktop/systemd1",
4751 "org.freedesktop.systemd1.Manager",
4757 log_error("Failed to reset failed state of unit %s: %s",
4758 *name, bus_error_message(&error, r));
4767 static int show_environment(sd_bus *bus, char **args) {
4768 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4769 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4773 pager_open_if_enabled();
4775 r = sd_bus_get_property(
4777 "org.freedesktop.systemd1",
4778 "/org/freedesktop/systemd1",
4779 "org.freedesktop.systemd1.Manager",
4785 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4789 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4791 return bus_log_parse_error(r);
4793 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4796 return bus_log_parse_error(r);
4798 r = sd_bus_message_exit_container(reply);
4800 return bus_log_parse_error(r);
4805 static int switch_root(sd_bus *bus, char **args) {
4806 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4807 _cleanup_free_ char *cmdline_init = NULL;
4808 const char *root, *init;
4812 l = strv_length(args);
4813 if (l < 2 || l > 3) {
4814 log_error("Wrong number of arguments.");
4823 r = parse_env_file("/proc/cmdline", WHITESPACE,
4824 "init", &cmdline_init,
4827 log_debug("Failed to parse /proc/cmdline: %s", strerror(-r));
4829 init = cmdline_init;
4836 const char *root_systemd_path = NULL, *root_init_path = NULL;
4838 root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
4839 root_init_path = strappenda(root, "/", init);
4841 /* If the passed init is actually the same as the
4842 * systemd binary, then let's suppress it. */
4843 if (files_same(root_init_path, root_systemd_path) > 0)
4847 log_debug("Switching root - root: %s; init: %s", root, strna(init));
4849 r = sd_bus_call_method(
4851 "org.freedesktop.systemd1",
4852 "/org/freedesktop/systemd1",
4853 "org.freedesktop.systemd1.Manager",
4859 log_error("Failed to switch root: %s", bus_error_message(&error, r));
4866 static int set_environment(sd_bus *bus, char **args) {
4867 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4868 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4875 method = streq(args[0], "set-environment")
4877 : "UnsetEnvironment";
4879 r = sd_bus_message_new_method_call(
4882 "org.freedesktop.systemd1",
4883 "/org/freedesktop/systemd1",
4884 "org.freedesktop.systemd1.Manager",
4887 return bus_log_create_error(r);
4889 r = sd_bus_message_append_strv(m, args + 1);
4891 return bus_log_create_error(r);
4893 r = sd_bus_call(bus, m, 0, &error, NULL);
4895 log_error("Failed to set environment: %s", bus_error_message(&error, r));
4902 static int import_environment(sd_bus *bus, char **args) {
4903 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4904 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4910 r = sd_bus_message_new_method_call(
4913 "org.freedesktop.systemd1",
4914 "/org/freedesktop/systemd1",
4915 "org.freedesktop.systemd1.Manager",
4918 return bus_log_create_error(r);
4920 if (strv_isempty(args + 1))
4921 r = sd_bus_message_append_strv(m, environ);
4925 r = sd_bus_message_open_container(m, 'a', "s");
4927 return bus_log_create_error(r);
4929 STRV_FOREACH(a, args + 1) {
4931 if (!env_name_is_valid(*a)) {
4932 log_error("Not a valid environment variable name: %s", *a);
4936 STRV_FOREACH(b, environ) {
4939 eq = startswith(*b, *a);
4940 if (eq && *eq == '=') {
4942 r = sd_bus_message_append(m, "s", *b);
4944 return bus_log_create_error(r);
4951 r = sd_bus_message_close_container(m);
4954 return bus_log_create_error(r);
4956 r = sd_bus_call(bus, m, 0, &error, NULL);
4958 log_error("Failed to import environment: %s", bus_error_message(&error, r));
4965 static int enable_sysv_units(const char *verb, char **args) {
4968 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4969 unsigned f = 1, t = 1;
4970 _cleanup_lookup_paths_free_ LookupPaths paths = {};
4972 if (arg_scope != UNIT_FILE_SYSTEM)
4975 if (!streq(verb, "enable") &&
4976 !streq(verb, "disable") &&
4977 !streq(verb, "is-enabled"))
4980 /* Processes all SysV units, and reshuffles the array so that
4981 * afterwards only the native units remain */
4983 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, arg_root, NULL, NULL, NULL);
4988 for (f = 0; args[f]; f++) {
4990 _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL;
4991 bool found_native = false, found_sysv;
4993 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
5001 if (!endswith(name, ".service"))
5004 if (path_is_absolute(name))
5007 STRV_FOREACH(k, paths.unit_path) {
5008 _cleanup_free_ char *path = NULL;
5010 path = path_join(arg_root, *k, name);
5014 found_native = access(path, F_OK) >= 0;
5022 p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name);
5026 p[strlen(p) - strlen(".service")] = 0;
5027 found_sysv = access(p, F_OK) >= 0;
5031 /* Mark this entry, so that we don't try enabling it as native unit */
5032 args[f] = (char*) "";
5034 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
5036 if (!isempty(arg_root))
5037 argv[c++] = q = strappend("--root=", arg_root);
5039 argv[c++] = basename(p);
5041 streq(verb, "enable") ? "on" :
5042 streq(verb, "disable") ? "off" : "--level=5";
5045 l = strv_join((char**)argv, " ");
5049 log_info("Executing %s", l);
5053 log_error("Failed to fork: %m");
5055 } else if (pid == 0) {
5058 execv(argv[0], (char**) argv);
5059 _exit(EXIT_FAILURE);
5062 j = wait_for_terminate(pid, &status);
5064 log_error("Failed to wait for child: %s", strerror(-r));
5068 if (status.si_code == CLD_EXITED) {
5069 if (streq(verb, "is-enabled")) {
5070 if (status.si_status == 0) {
5079 } else if (status.si_status != 0)
5085 /* Drop all SysV units */
5086 for (f = 0, t = 0; args[f]; f++) {
5088 if (isempty(args[f]))
5091 args[t++] = args[f];
5100 static int mangle_names(char **original_names, char ***mangled_names) {
5101 char **i, **l, **name;
5103 l = new(char*, strv_length(original_names) + 1);
5108 STRV_FOREACH(name, original_names) {
5110 /* When enabling units qualified path names are OK,
5111 * too, hence allow them explicitly. */
5116 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5132 static int enable_unit(sd_bus *bus, char **args) {
5133 _cleanup_strv_free_ char **names = NULL;
5134 const char *verb = args[0];
5135 UnitFileChange *changes = NULL;
5136 unsigned n_changes = 0;
5137 int carries_install_info = -1;
5143 r = mangle_names(args+1, &names);
5147 r = enable_sysv_units(verb, names);
5151 /* If the operation was fully executed by the SysV compat,
5152 * let's finish early */
5153 if (strv_isempty(names))
5156 if (!bus || avoid_bus()) {
5157 if (streq(verb, "enable")) {
5158 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5159 carries_install_info = r;
5160 } else if (streq(verb, "disable"))
5161 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5162 else if (streq(verb, "reenable")) {
5163 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5164 carries_install_info = r;
5165 } else if (streq(verb, "link"))
5166 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5167 else if (streq(verb, "preset")) {
5168 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_preset_mode, arg_force, &changes, &n_changes);
5169 carries_install_info = r;
5170 } else if (streq(verb, "mask"))
5171 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5172 else if (streq(verb, "unmask"))
5173 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5175 assert_not_reached("Unknown verb");
5178 log_error("Operation failed: %s", strerror(-r));
5183 dump_unit_file_changes(changes, n_changes);
5187 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5188 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5189 int expect_carries_install_info = false;
5190 bool send_force = true, send_preset_mode = false;
5193 if (streq(verb, "enable")) {
5194 method = "EnableUnitFiles";
5195 expect_carries_install_info = true;
5196 } else if (streq(verb, "disable")) {
5197 method = "DisableUnitFiles";
5199 } else if (streq(verb, "reenable")) {
5200 method = "ReenableUnitFiles";
5201 expect_carries_install_info = true;
5202 } else if (streq(verb, "link"))
5203 method = "LinkUnitFiles";
5204 else if (streq(verb, "preset")) {
5206 if (arg_preset_mode != UNIT_FILE_PRESET_FULL) {
5207 method = "PresetUnitFilesWithMode";
5208 send_preset_mode = true;
5210 method = "PresetUnitFiles";
5212 expect_carries_install_info = true;
5213 } else if (streq(verb, "mask"))
5214 method = "MaskUnitFiles";
5215 else if (streq(verb, "unmask")) {
5216 method = "UnmaskUnitFiles";
5219 assert_not_reached("Unknown verb");
5221 r = sd_bus_message_new_method_call(
5224 "org.freedesktop.systemd1",
5225 "/org/freedesktop/systemd1",
5226 "org.freedesktop.systemd1.Manager",
5229 return bus_log_create_error(r);
5231 r = sd_bus_message_append_strv(m, names);
5233 return bus_log_create_error(r);
5235 if (send_preset_mode) {
5236 r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode));
5238 return bus_log_create_error(r);
5241 r = sd_bus_message_append(m, "b", arg_runtime);
5243 return bus_log_create_error(r);
5246 r = sd_bus_message_append(m, "b", arg_force);
5248 return bus_log_create_error(r);
5251 r = sd_bus_call(bus, m, 0, &error, &reply);
5253 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5257 if (expect_carries_install_info) {
5258 r = sd_bus_message_read(reply, "b", &carries_install_info);
5260 return bus_log_parse_error(r);
5263 r = deserialize_and_dump_unit_file_changes(reply);
5267 /* Try to reload if enabled */
5269 r = daemon_reload(bus, args);
5274 if (carries_install_info == 0)
5275 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5276 "using systemctl.\n"
5277 "Possible reasons for having this kind of units are:\n"
5278 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5279 " .wants/ or .requires/ directory.\n"
5280 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5281 " a requirement dependency on it.\n"
5282 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5283 " D-Bus, udev, scripted systemctl call, ...).\n");
5286 unit_file_changes_free(changes, n_changes);
5291 static int add_dependency(sd_bus *bus, char **args) {
5292 _cleanup_strv_free_ char **names = NULL;
5293 _cleanup_free_ char *target = NULL;
5294 const char *verb = args[0];
5301 target = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
5305 r = mangle_names(args+2, &names);
5309 if (streq(verb, "add-wants"))
5311 else if (streq(verb, "add-requires"))
5312 dep = UNIT_REQUIRES;
5314 assert_not_reached("Unknown verb");
5316 if (!bus || avoid_bus()) {
5317 UnitFileChange *changes = NULL;
5318 unsigned n_changes = 0;
5320 r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes);
5323 log_error("Can't add dependency: %s", strerror(-r));
5328 dump_unit_file_changes(changes, n_changes);
5330 unit_file_changes_free(changes, n_changes);
5333 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5334 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5336 r = sd_bus_message_new_method_call(
5339 "org.freedesktop.systemd1",
5340 "/org/freedesktop/systemd1",
5341 "org.freedesktop.systemd1.Manager",
5342 "AddDependencyUnitFiles");
5344 return bus_log_create_error(r);
5346 r = sd_bus_message_append_strv(m, names);
5348 return bus_log_create_error(r);
5350 r = sd_bus_message_append(m, "s", target);
5352 return bus_log_create_error(r);
5354 r = sd_bus_message_append(m, "s", unit_dependency_to_string(dep));
5356 return bus_log_create_error(r);
5358 r = sd_bus_message_append(m, "b", arg_runtime);
5360 return bus_log_create_error(r);
5362 r = sd_bus_message_append(m, "b", arg_force);
5364 return bus_log_create_error(r);
5366 r = sd_bus_call(bus, m, 0, &error, &reply);
5368 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5372 r = deserialize_and_dump_unit_file_changes(reply);
5377 r = daemon_reload(bus, args);
5385 static int preset_all(sd_bus *bus, char **args) {
5386 UnitFileChange *changes = NULL;
5387 unsigned n_changes = 0;
5390 if (!bus || avoid_bus()) {
5392 r = unit_file_preset_all(arg_scope, arg_runtime, arg_root, arg_preset_mode, arg_force, &changes, &n_changes);
5394 log_error("Operation failed: %s", strerror(-r));
5399 dump_unit_file_changes(changes, n_changes);
5404 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5405 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5407 r = sd_bus_call_method(
5409 "org.freedesktop.systemd1",
5410 "/org/freedesktop/systemd1",
5411 "org.freedesktop.systemd1.Manager",
5412 "PresetAllUnitFiles",
5416 unit_file_preset_mode_to_string(arg_preset_mode),
5420 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5424 r = deserialize_and_dump_unit_file_changes(reply);
5429 r = daemon_reload(bus, args);
5435 unit_file_changes_free(changes, n_changes);
5440 static int unit_is_enabled(sd_bus *bus, char **args) {
5442 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5443 _cleanup_strv_free_ char **names = NULL;
5448 r = mangle_names(args+1, &names);
5452 r = enable_sysv_units(args[0], names);
5458 if (!bus || avoid_bus()) {
5460 STRV_FOREACH(name, names) {
5461 UnitFileState state;
5463 state = unit_file_get_state(arg_scope, arg_root, *name);
5465 log_error("Failed to get unit file state for %s: %s", *name, strerror(-state));
5469 if (state == UNIT_FILE_ENABLED ||
5470 state == UNIT_FILE_ENABLED_RUNTIME ||
5471 state == UNIT_FILE_STATIC)
5475 puts(unit_file_state_to_string(state));
5479 STRV_FOREACH(name, names) {
5480 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5483 r = sd_bus_call_method(
5485 "org.freedesktop.systemd1",
5486 "/org/freedesktop/systemd1",
5487 "org.freedesktop.systemd1.Manager",
5493 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5497 r = sd_bus_message_read(reply, "s", &s);
5499 return bus_log_parse_error(r);
5501 if (streq(s, "enabled") ||
5502 streq(s, "enabled-runtime") ||
5514 static int is_system_running(sd_bus *bus, char **args) {
5515 _cleanup_free_ char *state = NULL;
5518 r = sd_bus_get_property_string(
5520 "org.freedesktop.systemd1",
5521 "/org/freedesktop/systemd1",
5522 "org.freedesktop.systemd1.Manager",
5535 return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE;
5538 static void systemctl_help(void) {
5540 pager_open_if_enabled();
5542 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
5543 "Query or send control commands to the systemd manager.\n\n"
5544 " -h --help Show this help\n"
5545 " --version Show package version\n"
5546 " --system Connect to system manager\n"
5547 " --user Connect to user service manager\n"
5548 " -H --host=[USER@]HOST\n"
5549 " Operate on remote host\n"
5550 " -M --machine=CONTAINER\n"
5551 " Operate on local container\n"
5552 " -t --type=TYPE List only units of a particular type\n"
5553 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
5554 " -p --property=NAME Show only properties by this name\n"
5555 " -a --all Show all loaded units/properties, including dead/empty\n"
5556 " ones. To list all units installed on the system, use\n"
5557 " the 'list-unit-files' command instead.\n"
5558 " -l --full Don't ellipsize unit names on output\n"
5559 " -r --recursive Show unit list of host and local containers\n"
5560 " --reverse Show reverse dependencies with 'list-dependencies'\n"
5561 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
5562 " queueing a new job\n"
5563 " --show-types When showing sockets, explicitly show their type\n"
5564 " -i --ignore-inhibitors\n"
5565 " When shutting down or sleeping, ignore inhibitors\n"
5566 " --kill-who=WHO Who to send signal to\n"
5567 " -s --signal=SIGNAL Which signal to send\n"
5568 " -q --quiet Suppress output\n"
5569 " --no-block Do not wait until operation finished\n"
5570 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5571 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
5573 " --no-legend Do not print a legend (column headers and hints)\n"
5574 " --no-pager Do not pipe output into a pager\n"
5575 " --no-ask-password\n"
5576 " Do not ask for system passwords\n"
5577 " --global Enable/disable unit files globally\n"
5578 " --runtime Enable unit files only temporarily until next reboot\n"
5579 " -f --force When enabling unit files, override existing symlinks\n"
5580 " When shutting down, execute action immediately\n"
5581 " --preset-mode= Specifies whether fully apply presets, or only enable,\n"
5582 " or only disable\n"
5583 " --root=PATH Enable unit files in the specified root directory\n"
5584 " -n --lines=INTEGER Number of journal entries to show\n"
5585 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
5586 " verbose, export, json, json-pretty, json-sse, cat)\n"
5587 " --plain Print unit dependencies as a list instead of a tree\n\n"
5589 " list-units [PATTERN...] List loaded units\n"
5590 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
5591 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
5592 " start NAME... Start (activate) one or more units\n"
5593 " stop NAME... Stop (deactivate) one or more units\n"
5594 " reload NAME... Reload one or more units\n"
5595 " restart NAME... Start or restart one or more units\n"
5596 " try-restart NAME... Restart one or more units if active\n"
5597 " reload-or-restart NAME... Reload one or more units if possible,\n"
5598 " otherwise start or restart\n"
5599 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
5600 " otherwise restart if active\n"
5601 " isolate NAME Start one unit and stop all others\n"
5602 " kill NAME... Send signal to processes of a unit\n"
5603 " is-active PATTERN... Check whether units are active\n"
5604 " is-failed PATTERN... Check whether units are failed\n"
5605 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
5606 " show [PATTERN...|JOB...] Show properties of one or more\n"
5607 " units/jobs or the manager\n"
5608 " cat PATTERN... Show files and drop-ins of one or more units\n"
5609 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
5610 " help PATTERN...|PID... Show manual for one or more units\n"
5611 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
5613 " list-dependencies [NAME] Recursively show units which are required\n"
5614 " or wanted by this unit or by which this\n"
5615 " unit is required or wanted\n\n"
5616 "Unit File Commands:\n"
5617 " list-unit-files [PATTERN...] List installed unit files\n"
5618 " enable NAME... Enable one or more unit files\n"
5619 " disable NAME... Disable one or more unit files\n"
5620 " reenable NAME... Reenable one or more unit files\n"
5621 " preset NAME... Enable/disable one or more unit files\n"
5622 " based on preset configuration\n"
5623 " preset-all Enable/disable all unit files based on\n"
5624 " preset configuration\n"
5625 " is-enabled NAME... Check whether unit files are enabled\n\n"
5626 " mask NAME... Mask one or more units\n"
5627 " unmask NAME... Unmask one or more units\n"
5628 " link PATH... Link one or more units files into\n"
5629 " the search path\n"
5630 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
5631 " on specified one or more units\n"
5632 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
5633 " on specified one or more units\n"
5634 " get-default Get the name of the default target\n"
5635 " set-default NAME Set the default target\n\n"
5636 "Machine Commands:\n"
5637 " list-machines [PATTERN...] List local containers and host\n\n"
5639 " list-jobs [PATTERN...] List jobs\n"
5640 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
5641 "Snapshot Commands:\n"
5642 " snapshot [NAME] Create a snapshot\n"
5643 " delete NAME... Remove one or more snapshots\n\n"
5644 "Environment Commands:\n"
5645 " show-environment Dump environment\n"
5646 " set-environment NAME=VALUE... Set one or more environment variables\n"
5647 " unset-environment NAME... Unset one or more environment variables\n"
5648 " import-environment NAME... Import all, one or more environment variables\n\n"
5649 "Manager Lifecycle Commands:\n"
5650 " daemon-reload Reload systemd manager configuration\n"
5651 " daemon-reexec Reexecute systemd manager\n\n"
5652 "System Commands:\n"
5653 " is-system-running Check whether system is fully running\n"
5654 " default Enter system default mode\n"
5655 " rescue Enter system rescue mode\n"
5656 " emergency Enter system emergency mode\n"
5657 " halt Shut down and halt the system\n"
5658 " poweroff Shut down and power-off the system\n"
5659 " reboot [ARG] Shut down and reboot the system\n"
5660 " kexec Shut down and reboot the system with kexec\n"
5661 " exit Request user instance exit\n"
5662 " switch-root ROOT [INIT] Change to a different root file system\n"
5663 " suspend Suspend the system\n"
5664 " hibernate Hibernate the system\n"
5665 " hybrid-sleep Hibernate and suspend the system\n",
5666 program_invocation_short_name);
5669 static void halt_help(void) {
5670 printf("%s [OPTIONS...]%s\n\n"
5671 "%s the system.\n\n"
5672 " --help Show this help\n"
5673 " --halt Halt the machine\n"
5674 " -p --poweroff Switch off the machine\n"
5675 " --reboot Reboot the machine\n"
5676 " -f --force Force immediate halt/power-off/reboot\n"
5677 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
5678 " -d --no-wtmp Don't write wtmp record\n"
5679 " --no-wall Don't send wall message before halt/power-off/reboot\n",
5680 program_invocation_short_name,
5681 arg_action == ACTION_REBOOT ? " [ARG]" : "",
5682 arg_action == ACTION_REBOOT ? "Reboot" :
5683 arg_action == ACTION_POWEROFF ? "Power off" :
5687 static void shutdown_help(void) {
5688 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
5689 "Shut down the system.\n\n"
5690 " --help Show this help\n"
5691 " -H --halt Halt the machine\n"
5692 " -P --poweroff Power-off the machine\n"
5693 " -r --reboot Reboot the machine\n"
5694 " -h Equivalent to --poweroff, overridden by --halt\n"
5695 " -k Don't halt/power-off/reboot, just send warnings\n"
5696 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5697 " -c Cancel a pending shutdown\n",
5698 program_invocation_short_name);
5701 static void telinit_help(void) {
5702 printf("%s [OPTIONS...] {COMMAND}\n\n"
5703 "Send control commands to the init daemon.\n\n"
5704 " --help Show this help\n"
5705 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
5707 " 0 Power-off the machine\n"
5708 " 6 Reboot the machine\n"
5709 " 2, 3, 4, 5 Start runlevelX.target unit\n"
5710 " 1, s, S Enter rescue mode\n"
5711 " q, Q Reload init daemon configuration\n"
5712 " u, U Reexecute init daemon\n",
5713 program_invocation_short_name);
5716 static void runlevel_help(void) {
5717 printf("%s [OPTIONS...]\n\n"
5718 "Prints the previous and current runlevel of the init system.\n\n"
5719 " --help Show this help\n",
5720 program_invocation_short_name);
5723 static void help_types(void) {
5728 puts("Available unit types:");
5729 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
5730 t = unit_type_to_string(i);
5736 static int systemctl_parse_argv(int argc, char *argv[]) {
5745 ARG_IGNORE_DEPENDENCIES,
5757 ARG_NO_ASK_PASSWORD,
5767 static const struct option options[] = {
5768 { "help", no_argument, NULL, 'h' },
5769 { "version", no_argument, NULL, ARG_VERSION },
5770 { "type", required_argument, NULL, 't' },
5771 { "property", required_argument, NULL, 'p' },
5772 { "all", no_argument, NULL, 'a' },
5773 { "reverse", no_argument, NULL, ARG_REVERSE },
5774 { "after", no_argument, NULL, ARG_AFTER },
5775 { "before", no_argument, NULL, ARG_BEFORE },
5776 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
5777 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
5778 { "full", no_argument, NULL, 'l' },
5779 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
5780 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
5781 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
5782 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
5783 { "ignore-inhibitors", no_argument, NULL, 'i' },
5784 { "user", no_argument, NULL, ARG_USER },
5785 { "system", no_argument, NULL, ARG_SYSTEM },
5786 { "global", no_argument, NULL, ARG_GLOBAL },
5787 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
5788 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
5789 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
5790 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5791 { "quiet", no_argument, NULL, 'q' },
5792 { "root", required_argument, NULL, ARG_ROOT },
5793 { "force", no_argument, NULL, ARG_FORCE },
5794 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
5795 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
5796 { "signal", required_argument, NULL, 's' },
5797 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
5798 { "host", required_argument, NULL, 'H' },
5799 { "machine", required_argument, NULL, 'M' },
5800 { "runtime", no_argument, NULL, ARG_RUNTIME },
5801 { "lines", required_argument, NULL, 'n' },
5802 { "output", required_argument, NULL, 'o' },
5803 { "plain", no_argument, NULL, ARG_PLAIN },
5804 { "state", required_argument, NULL, ARG_STATE },
5805 { "recursive", no_argument, NULL, 'r' },
5806 { "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
5815 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
5824 puts(PACKAGE_STRING);
5825 puts(SYSTEMD_FEATURES);
5829 const char *word, *state;
5832 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5833 _cleanup_free_ char *type;
5835 type = strndup(word, size);
5839 if (streq(type, "help")) {
5844 if (unit_type_from_string(type) >= 0) {
5845 if (strv_push(&arg_types, type))
5851 /* It's much nicer to use --state= for
5852 * load states, but let's support this
5853 * in --types= too for compatibility
5854 * with old versions */
5855 if (unit_load_state_from_string(optarg) >= 0) {
5856 if (strv_push(&arg_states, type) < 0)
5862 log_error("Unknown unit type or load state '%s'.", type);
5863 log_info("Use -t help to see a list of allowed values.");
5871 /* Make sure that if the empty property list
5872 was specified, we won't show any properties. */
5873 if (isempty(optarg) && !arg_properties) {
5874 arg_properties = new0(char*, 1);
5875 if (!arg_properties)
5878 const char *word, *state;
5881 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5884 prop = strndup(word, size);
5888 if (strv_consume(&arg_properties, prop) < 0)
5893 /* If the user asked for a particular
5894 * property, show it to him, even if it is
5906 arg_dependency = DEPENDENCY_REVERSE;
5910 arg_dependency = DEPENDENCY_AFTER;
5914 arg_dependency = DEPENDENCY_BEFORE;
5917 case ARG_SHOW_TYPES:
5918 arg_show_types = true;
5922 arg_job_mode = optarg;
5926 arg_job_mode = "fail";
5929 case ARG_IRREVERSIBLE:
5930 arg_job_mode = "replace-irreversibly";
5933 case ARG_IGNORE_DEPENDENCIES:
5934 arg_job_mode = "ignore-dependencies";
5938 arg_scope = UNIT_FILE_USER;
5942 arg_scope = UNIT_FILE_SYSTEM;
5946 arg_scope = UNIT_FILE_GLOBAL;
5950 arg_no_block = true;
5954 arg_no_legend = true;
5958 arg_no_pager = true;
5974 if (strv_extend(&arg_states, "failed") < 0)
5992 arg_no_reload = true;
5996 arg_kill_who = optarg;
6000 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
6001 log_error("Failed to parse signal string %s.", optarg);
6006 case ARG_NO_ASK_PASSWORD:
6007 arg_ask_password = false;
6011 arg_transport = BUS_TRANSPORT_REMOTE;
6016 arg_transport = BUS_TRANSPORT_CONTAINER;
6025 if (safe_atou(optarg, &arg_lines) < 0) {
6026 log_error("Failed to parse lines '%s'", optarg);
6032 arg_output = output_mode_from_string(optarg);
6033 if (arg_output < 0) {
6034 log_error("Unknown output '%s'.", optarg);
6040 arg_ignore_inhibitors = true;
6048 const char *word, *state;
6051 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6054 s = strndup(word, size);
6058 if (strv_consume(&arg_states, s) < 0)
6065 if (geteuid() != 0) {
6066 log_error("--recursive requires root privileges.");
6070 arg_recursive = true;
6073 case ARG_PRESET_MODE:
6075 arg_preset_mode = unit_file_preset_mode_from_string(optarg);
6076 if (arg_preset_mode < 0) {
6077 log_error("Failed to parse preset mode: %s.", optarg);
6087 assert_not_reached("Unhandled option");
6090 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
6091 log_error("Cannot access user instance remotely.");
6098 static int halt_parse_argv(int argc, char *argv[]) {
6107 static const struct option options[] = {
6108 { "help", no_argument, NULL, ARG_HELP },
6109 { "halt", no_argument, NULL, ARG_HALT },
6110 { "poweroff", no_argument, NULL, 'p' },
6111 { "reboot", no_argument, NULL, ARG_REBOOT },
6112 { "force", no_argument, NULL, 'f' },
6113 { "wtmp-only", no_argument, NULL, 'w' },
6114 { "no-wtmp", no_argument, NULL, 'd' },
6115 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6124 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
6125 if (runlevel == '0' || runlevel == '6')
6128 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
6136 arg_action = ACTION_HALT;
6140 if (arg_action != ACTION_REBOOT)
6141 arg_action = ACTION_POWEROFF;
6145 arg_action = ACTION_REBOOT;
6167 /* Compatibility nops */
6174 assert_not_reached("Unhandled option");
6177 if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
6178 r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL);
6181 } else if (optind < argc) {
6182 log_error("Too many arguments.");
6189 static int parse_time_spec(const char *t, usec_t *_u) {
6193 if (streq(t, "now"))
6195 else if (!strchr(t, ':')) {
6198 if (safe_atou64(t, &u) < 0)
6201 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
6210 hour = strtol(t, &e, 10);
6211 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
6214 minute = strtol(e+1, &e, 10);
6215 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
6218 n = now(CLOCK_REALTIME);
6219 s = (time_t) (n / USEC_PER_SEC);
6221 assert_se(localtime_r(&s, &tm));
6223 tm.tm_hour = (int) hour;
6224 tm.tm_min = (int) minute;
6227 assert_se(s = mktime(&tm));
6229 *_u = (usec_t) s * USEC_PER_SEC;
6232 *_u += USEC_PER_DAY;
6238 static int shutdown_parse_argv(int argc, char *argv[]) {
6245 static const struct option options[] = {
6246 { "help", no_argument, NULL, ARG_HELP },
6247 { "halt", no_argument, NULL, 'H' },
6248 { "poweroff", no_argument, NULL, 'P' },
6249 { "reboot", no_argument, NULL, 'r' },
6250 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
6251 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6260 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0)
6268 arg_action = ACTION_HALT;
6272 arg_action = ACTION_POWEROFF;
6277 arg_action = ACTION_KEXEC;
6279 arg_action = ACTION_REBOOT;
6283 arg_action = ACTION_KEXEC;
6287 if (arg_action != ACTION_HALT)
6288 arg_action = ACTION_POWEROFF;
6301 /* Compatibility nops */
6305 arg_action = ACTION_CANCEL_SHUTDOWN;
6312 assert_not_reached("Unhandled option");
6315 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
6316 r = parse_time_spec(argv[optind], &arg_when);
6318 log_error("Failed to parse time specification: %s", argv[optind]);
6322 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
6324 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
6325 /* No time argument for shutdown cancel */
6326 arg_wall = argv + optind;
6327 else if (argc > optind + 1)
6328 /* We skip the time argument */
6329 arg_wall = argv + optind + 1;
6336 static int telinit_parse_argv(int argc, char *argv[]) {
6343 static const struct option options[] = {
6344 { "help", no_argument, NULL, ARG_HELP },
6345 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6349 static const struct {
6353 { '0', ACTION_POWEROFF },
6354 { '6', ACTION_REBOOT },
6355 { '1', ACTION_RESCUE },
6356 { '2', ACTION_RUNLEVEL2 },
6357 { '3', ACTION_RUNLEVEL3 },
6358 { '4', ACTION_RUNLEVEL4 },
6359 { '5', ACTION_RUNLEVEL5 },
6360 { 's', ACTION_RESCUE },
6361 { 'S', ACTION_RESCUE },
6362 { 'q', ACTION_RELOAD },
6363 { 'Q', ACTION_RELOAD },
6364 { 'u', ACTION_REEXEC },
6365 { 'U', ACTION_REEXEC }
6374 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6389 assert_not_reached("Unhandled option");
6392 if (optind >= argc) {
6393 log_error("%s: required argument missing.",
6394 program_invocation_short_name);
6398 if (optind + 1 < argc) {
6399 log_error("Too many arguments.");
6403 if (strlen(argv[optind]) != 1) {
6404 log_error("Expected single character argument.");
6408 for (i = 0; i < ELEMENTSOF(table); i++)
6409 if (table[i].from == argv[optind][0])
6412 if (i >= ELEMENTSOF(table)) {
6413 log_error("Unknown command '%s'.", argv[optind]);
6417 arg_action = table[i].to;
6424 static int runlevel_parse_argv(int argc, char *argv[]) {
6430 static const struct option options[] = {
6431 { "help", no_argument, NULL, ARG_HELP },
6440 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6451 assert_not_reached("Unhandled option");
6454 if (optind < argc) {
6455 log_error("Too many arguments.");
6462 static int parse_argv(int argc, char *argv[]) {
6466 if (program_invocation_short_name) {
6468 if (strstr(program_invocation_short_name, "halt")) {
6469 arg_action = ACTION_HALT;
6470 return halt_parse_argv(argc, argv);
6471 } else if (strstr(program_invocation_short_name, "poweroff")) {
6472 arg_action = ACTION_POWEROFF;
6473 return halt_parse_argv(argc, argv);
6474 } else if (strstr(program_invocation_short_name, "reboot")) {
6476 arg_action = ACTION_KEXEC;
6478 arg_action = ACTION_REBOOT;
6479 return halt_parse_argv(argc, argv);
6480 } else if (strstr(program_invocation_short_name, "shutdown")) {
6481 arg_action = ACTION_POWEROFF;
6482 return shutdown_parse_argv(argc, argv);
6483 } else if (strstr(program_invocation_short_name, "init")) {
6485 if (sd_booted() > 0) {
6486 arg_action = _ACTION_INVALID;
6487 return telinit_parse_argv(argc, argv);
6489 /* Hmm, so some other init system is
6490 * running, we need to forward this
6491 * request to it. For now we simply
6492 * guess that it is Upstart. */
6494 execv(TELINIT, argv);
6496 log_error("Couldn't find an alternative telinit implementation to spawn.");
6500 } else if (strstr(program_invocation_short_name, "runlevel")) {
6501 arg_action = ACTION_RUNLEVEL;
6502 return runlevel_parse_argv(argc, argv);
6506 arg_action = ACTION_SYSTEMCTL;
6507 return systemctl_parse_argv(argc, argv);
6510 _pure_ static int action_to_runlevel(void) {
6512 static const char table[_ACTION_MAX] = {
6513 [ACTION_HALT] = '0',
6514 [ACTION_POWEROFF] = '0',
6515 [ACTION_REBOOT] = '6',
6516 [ACTION_RUNLEVEL2] = '2',
6517 [ACTION_RUNLEVEL3] = '3',
6518 [ACTION_RUNLEVEL4] = '4',
6519 [ACTION_RUNLEVEL5] = '5',
6520 [ACTION_RESCUE] = '1'
6523 assert(arg_action < _ACTION_MAX);
6525 return table[arg_action];
6528 static int talk_initctl(void) {
6530 struct init_request request = {
6531 .magic = INIT_MAGIC,
6533 .cmd = INIT_CMD_RUNLVL
6536 _cleanup_close_ int fd = -1;
6540 rl = action_to_runlevel();
6544 request.runlevel = rl;
6546 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
6548 if (errno == ENOENT)
6551 log_error("Failed to open "INIT_FIFO": %m");
6556 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
6558 log_error("Failed to write to "INIT_FIFO": %m");
6559 return errno > 0 ? -errno : -EIO;
6565 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
6567 static const struct {
6575 int (* const dispatch)(sd_bus *bus, char **args);
6581 { "list-units", MORE, 0, list_units },
6582 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
6583 { "list-sockets", MORE, 1, list_sockets },
6584 { "list-timers", MORE, 1, list_timers },
6585 { "list-jobs", MORE, 1, list_jobs },
6586 { "list-machines", MORE, 1, list_machines },
6587 { "clear-jobs", EQUAL, 1, daemon_reload },
6588 { "cancel", MORE, 2, cancel_job },
6589 { "start", MORE, 2, start_unit },
6590 { "stop", MORE, 2, start_unit },
6591 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6592 { "reload", MORE, 2, start_unit },
6593 { "restart", MORE, 2, start_unit },
6594 { "try-restart", MORE, 2, start_unit },
6595 { "reload-or-restart", MORE, 2, start_unit },
6596 { "reload-or-try-restart", MORE, 2, start_unit },
6597 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
6598 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6599 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
6600 { "isolate", EQUAL, 2, start_unit },
6601 { "kill", MORE, 2, kill_unit },
6602 { "is-active", MORE, 2, check_unit_active },
6603 { "check", MORE, 2, check_unit_active },
6604 { "is-failed", MORE, 2, check_unit_failed },
6605 { "show", MORE, 1, show },
6606 { "cat", MORE, 2, cat },
6607 { "status", MORE, 1, show },
6608 { "help", MORE, 2, show },
6609 { "snapshot", LESS, 2, snapshot },
6610 { "delete", MORE, 2, delete_snapshot },
6611 { "daemon-reload", EQUAL, 1, daemon_reload },
6612 { "daemon-reexec", EQUAL, 1, daemon_reload },
6613 { "show-environment", EQUAL, 1, show_environment },
6614 { "set-environment", MORE, 2, set_environment },
6615 { "unset-environment", MORE, 2, set_environment },
6616 { "import-environment", MORE, 1, import_environment},
6617 { "halt", EQUAL, 1, start_special, FORCE },
6618 { "poweroff", EQUAL, 1, start_special, FORCE },
6619 { "reboot", EQUAL, 1, start_special, FORCE },
6620 { "kexec", EQUAL, 1, start_special },
6621 { "suspend", EQUAL, 1, start_special },
6622 { "hibernate", EQUAL, 1, start_special },
6623 { "hybrid-sleep", EQUAL, 1, start_special },
6624 { "default", EQUAL, 1, start_special },
6625 { "rescue", EQUAL, 1, start_special },
6626 { "emergency", EQUAL, 1, start_special },
6627 { "exit", EQUAL, 1, start_special },
6628 { "reset-failed", MORE, 1, reset_failed },
6629 { "enable", MORE, 2, enable_unit, NOBUS },
6630 { "disable", MORE, 2, enable_unit, NOBUS },
6631 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
6632 { "reenable", MORE, 2, enable_unit, NOBUS },
6633 { "preset", MORE, 2, enable_unit, NOBUS },
6634 { "preset-all", EQUAL, 1, preset_all, NOBUS },
6635 { "mask", MORE, 2, enable_unit, NOBUS },
6636 { "unmask", MORE, 2, enable_unit, NOBUS },
6637 { "link", MORE, 2, enable_unit, NOBUS },
6638 { "switch-root", MORE, 2, switch_root },
6639 { "list-dependencies", LESS, 2, list_dependencies },
6640 { "set-default", EQUAL, 2, set_default, NOBUS },
6641 { "get-default", EQUAL, 1, get_default, NOBUS },
6642 { "set-property", MORE, 3, set_property },
6643 { "is-system-running", EQUAL, 1, is_system_running },
6644 { "add-wants", MORE, 3, add_dependency, NOBUS },
6645 { "add-requires", MORE, 3, add_dependency, NOBUS },
6654 left = argc - optind;
6656 /* Special rule: no arguments (left == 0) means "list-units" */
6658 if (streq(argv[optind], "help") && !argv[optind+1]) {
6659 log_error("This command expects one or more "
6660 "unit names. Did you mean --help?");
6664 for (; verb->verb; verb++)
6665 if (streq(argv[optind], verb->verb))
6668 log_error("Unknown operation '%s'.", argv[optind]);
6673 switch (verb->argc_cmp) {
6676 if (left != verb->argc) {
6677 log_error("Invalid number of arguments.");
6684 if (left < verb->argc) {
6685 log_error("Too few arguments.");
6692 if (left > verb->argc) {
6693 log_error("Too many arguments.");
6700 assert_not_reached("Unknown comparison operator.");
6703 /* Require a bus connection for all operations but
6705 if (verb->bus == NOBUS) {
6706 if (!bus && !avoid_bus()) {
6707 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6712 if (running_in_chroot() > 0) {
6713 log_info("Running in chroot, ignoring request.");
6717 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
6718 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6723 return verb->dispatch(bus, argv + optind);
6726 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
6728 struct sd_shutdown_command c = {
6735 union sockaddr_union sockaddr = {
6736 .un.sun_family = AF_UNIX,
6737 .un.sun_path = "/run/systemd/shutdownd",
6740 struct iovec iovec[2] = {{
6741 .iov_base = (char*) &c,
6742 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
6745 struct msghdr msghdr = {
6746 .msg_name = &sockaddr,
6747 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
6748 + strlen("/run/systemd/shutdownd"),
6753 _cleanup_close_ int fd;
6755 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
6759 if (!isempty(message)) {
6760 iovec[1].iov_base = (char*) message;
6761 iovec[1].iov_len = strlen(message);
6762 msghdr.msg_iovlen++;
6765 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
6771 static int reload_with_fallback(sd_bus *bus) {
6774 /* First, try systemd via D-Bus. */
6775 if (daemon_reload(bus, NULL) >= 0)
6779 /* Nothing else worked, so let's try signals */
6780 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
6782 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
6783 log_error("kill() failed: %m");
6790 static int start_with_fallback(sd_bus *bus) {
6793 /* First, try systemd via D-Bus. */
6794 if (start_unit(bus, NULL) >= 0)
6798 /* Nothing else worked, so let's try
6800 if (talk_initctl() > 0)
6803 log_error("Failed to talk to init daemon.");
6807 warn_wall(arg_action);
6811 static int halt_now(enum action a) {
6813 /* Make sure C-A-D is handled by the kernel from this
6815 reboot(RB_ENABLE_CAD);
6820 log_info("Halting.");
6821 reboot(RB_HALT_SYSTEM);
6824 case ACTION_POWEROFF:
6825 log_info("Powering off.");
6826 reboot(RB_POWER_OFF);
6829 case ACTION_REBOOT: {
6830 _cleanup_free_ char *param = NULL;
6832 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
6833 log_info("Rebooting with argument '%s'.", param);
6834 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
6835 LINUX_REBOOT_CMD_RESTART2, param);
6838 log_info("Rebooting.");
6839 reboot(RB_AUTOBOOT);
6844 assert_not_reached("Unknown action.");
6848 static int halt_main(sd_bus *bus) {
6851 r = check_inhibitors(bus, arg_action);
6855 if (geteuid() != 0) {
6856 /* Try logind if we are a normal user and no special
6857 * mode applies. Maybe PolicyKit allows us to shutdown
6860 if (arg_when <= 0 &&
6863 (arg_action == ACTION_POWEROFF ||
6864 arg_action == ACTION_REBOOT)) {
6865 r = reboot_with_logind(bus, arg_action);
6870 log_error("Must be root.");
6875 _cleanup_free_ char *m;
6877 m = strv_join(arg_wall, " ");
6881 r = send_shutdownd(arg_when,
6882 arg_action == ACTION_HALT ? 'H' :
6883 arg_action == ACTION_POWEROFF ? 'P' :
6884 arg_action == ACTION_KEXEC ? 'K' :
6891 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6893 char date[FORMAT_TIMESTAMP_MAX];
6895 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6896 format_timestamp(date, sizeof(date), arg_when));
6901 if (!arg_dry && !arg_force)
6902 return start_with_fallback(bus);
6905 if (sd_booted() > 0)
6906 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6908 r = utmp_put_shutdown();
6910 log_warning("Failed to write utmp record: %s", strerror(-r));
6917 r = halt_now(arg_action);
6918 log_error("Failed to reboot: %s", strerror(-r));
6923 static int runlevel_main(void) {
6924 int r, runlevel, previous;
6926 r = utmp_get_runlevel(&runlevel, &previous);
6933 previous <= 0 ? 'N' : previous,
6934 runlevel <= 0 ? 'N' : runlevel);
6939 int main(int argc, char*argv[]) {
6940 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
6943 setlocale(LC_ALL, "");
6944 log_parse_environment();
6947 /* Explicitly not on_tty() to avoid setting cached value.
6948 * This becomes relevant for piping output which might be
6950 original_stdout_is_tty = isatty(STDOUT_FILENO);
6952 r = parse_argv(argc, argv);
6956 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6957 * let's shortcut this */
6958 if (arg_action == ACTION_RUNLEVEL) {
6959 r = runlevel_main();
6963 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6964 log_info("Running in chroot, ignoring request.");
6970 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
6972 /* systemctl_main() will print an error message for the bus
6973 * connection, but only if it needs to */
6975 switch (arg_action) {
6977 case ACTION_SYSTEMCTL:
6978 r = systemctl_main(bus, argc, argv, r);
6982 case ACTION_POWEROFF:
6988 case ACTION_RUNLEVEL2:
6989 case ACTION_RUNLEVEL3:
6990 case ACTION_RUNLEVEL4:
6991 case ACTION_RUNLEVEL5:
6993 case ACTION_EMERGENCY:
6994 case ACTION_DEFAULT:
6995 r = start_with_fallback(bus);
7000 r = reload_with_fallback(bus);
7003 case ACTION_CANCEL_SHUTDOWN: {
7004 _cleanup_free_ char *m = NULL;
7007 m = strv_join(arg_wall, " ");
7014 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
7016 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
7020 case ACTION_RUNLEVEL:
7021 case _ACTION_INVALID:
7023 assert_not_reached("Unknown action");
7028 ask_password_agent_close();
7029 polkit_agent_close();
7031 strv_free(arg_types);
7032 strv_free(arg_states);
7033 strv_free(arg_properties);
7035 return r < 0 ? EXIT_FAILURE : r;