1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Marc-Antoine Perennou
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/reboot.h>
24 #include <linux/reboot.h>
25 #include <sys/syscall.h>
32 #include <sys/ioctl.h>
36 #include <sys/socket.h>
39 #include <sys/prctl.h>
42 #include "sd-daemon.h"
43 #include "sd-shutdown.h"
50 #include "utmp-wtmp.h"
53 #include "path-util.h"
55 #include "cgroup-show.h"
56 #include "cgroup-util.h"
58 #include "path-lookup.h"
59 #include "conf-parser.h"
60 #include "exit-status.h"
62 #include "unit-name.h"
64 #include "spawn-ask-password-agent.h"
65 #include "spawn-polkit-agent.h"
67 #include "logs-show.h"
68 #include "socket-util.h"
73 #include "bus-message.h"
74 #include "bus-error.h"
75 #include "bus-common-errors.h"
79 static char **arg_types = NULL;
80 static char **arg_states = NULL;
81 static char **arg_properties = NULL;
82 static bool arg_all = false;
83 static enum dependency {
89 } arg_dependency = DEPENDENCY_FORWARD;
90 static const char *arg_job_mode = "replace";
91 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
92 static bool arg_no_block = false;
93 static bool arg_no_legend = false;
94 static bool arg_no_pager = false;
95 static bool arg_no_wtmp = false;
96 static bool arg_no_wall = false;
97 static bool arg_no_reload = false;
98 static bool arg_show_types = false;
99 static bool arg_ignore_inhibitors = false;
100 static bool arg_dry = false;
101 static bool arg_quiet = false;
102 static bool arg_full = false;
103 static bool arg_recursive = false;
104 static int arg_force = 0;
105 static bool arg_ask_password = true;
106 static bool arg_runtime = false;
107 static UnitFilePresetMode arg_preset_mode = UNIT_FILE_PRESET_FULL;
108 static char **arg_wall = NULL;
109 static const char *arg_kill_who = NULL;
110 static int arg_signal = SIGTERM;
111 static const char *arg_root = NULL;
112 static usec_t arg_when = 0;
134 ACTION_CANCEL_SHUTDOWN,
136 } arg_action = ACTION_SYSTEMCTL;
137 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
138 static char *arg_host = NULL;
139 static unsigned arg_lines = 10;
140 static OutputMode arg_output = OUTPUT_SHORT;
141 static bool arg_plain = false;
143 static bool original_stdout_is_tty;
145 static int daemon_reload(sd_bus *bus, char **args);
146 static int halt_now(enum action a);
147 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet);
149 static char** strv_skip_first(char **strv) {
150 if (strv_length(strv) > 0)
155 static void pager_open_if_enabled(void) {
163 static void ask_password_agent_open_if_enabled(void) {
165 /* Open the password agent as a child process if necessary */
167 if (!arg_ask_password)
170 if (arg_scope != UNIT_FILE_SYSTEM)
173 if (arg_transport != BUS_TRANSPORT_LOCAL)
176 ask_password_agent_open();
179 static void polkit_agent_open_if_enabled(void) {
181 /* Open the polkit agent as a child process if necessary */
183 if (!arg_ask_password)
186 if (arg_scope != UNIT_FILE_SYSTEM)
189 if (arg_transport != BUS_TRANSPORT_LOCAL)
195 static OutputFlags get_output_flags(void) {
197 arg_all * OUTPUT_SHOW_ALL |
198 arg_full * OUTPUT_FULL_WIDTH |
199 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
200 on_tty() * OUTPUT_COLOR |
201 !arg_quiet * OUTPUT_WARN_CUTOFF;
204 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
207 if (!sd_bus_error_is_set(error))
210 if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) ||
211 sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
212 sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
213 sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
214 return EXIT_NOPERMISSION;
216 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
217 return EXIT_NOTINSTALLED;
219 if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
220 sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED))
221 return EXIT_NOTIMPLEMENTED;
223 if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
224 return EXIT_NOTCONFIGURED;
232 static void warn_wall(enum action a) {
233 static const char *table[_ACTION_MAX] = {
234 [ACTION_HALT] = "The system is going down for system halt NOW!",
235 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
236 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
237 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
238 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
239 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
240 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
247 _cleanup_free_ char *p;
249 p = strv_join(arg_wall, " ");
256 utmp_wall(p, NULL, NULL);
264 utmp_wall(table[a], NULL, NULL);
267 static bool avoid_bus(void) {
269 if (running_in_chroot() > 0)
272 if (sd_booted() <= 0)
275 if (!isempty(arg_root))
278 if (arg_scope == UNIT_FILE_GLOBAL)
284 static int compare_unit_info(const void *a, const void *b) {
285 const UnitInfo *u = a, *v = b;
289 /* First, order by machine */
290 if (!u->machine && v->machine)
292 if (u->machine && !v->machine)
294 if (u->machine && v->machine) {
295 r = strcasecmp(u->machine, v->machine);
300 /* Second, order by unit type */
301 d1 = strrchr(u->id, '.');
302 d2 = strrchr(v->id, '.');
304 r = strcasecmp(d1, d2);
309 /* Third, order by name */
310 return strcasecmp(u->id, v->id);
313 static bool output_show_unit(const UnitInfo *u, char **patterns) {
314 if (!strv_isempty(patterns)) {
317 STRV_FOREACH(pattern, patterns)
318 if (fnmatch(*pattern, u->id, FNM_NOESCAPE) == 0)
327 dot = strrchr(u->id, '.');
331 if (!strv_find(arg_types, dot+1))
341 if (streq(u->active_state, "inactive") || u->following[0])
347 static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
348 unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
350 unsigned n_shown = 0;
353 max_id_len = strlen("UNIT");
354 load_len = strlen("LOAD");
355 active_len = strlen("ACTIVE");
356 sub_len = strlen("SUB");
357 job_len = strlen("JOB");
360 for (u = unit_infos; u < unit_infos + c; u++) {
361 max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0));
362 load_len = MAX(load_len, strlen(u->load_state));
363 active_len = MAX(active_len, strlen(u->active_state));
364 sub_len = MAX(sub_len, strlen(u->sub_state));
366 if (u->job_id != 0) {
367 job_len = MAX(job_len, strlen(u->job_type));
371 if (!arg_no_legend &&
372 (streq(u->active_state, "failed") ||
373 STR_IN_SET(u->load_state, "error", "not-found", "masked")))
377 if (!arg_full && original_stdout_is_tty) {
380 id_len = MIN(max_id_len, 25u);
381 basic_len = circle_len + 5 + id_len + 5 + active_len + sub_len;
384 basic_len += job_len + 1;
386 if (basic_len < (unsigned) columns()) {
387 unsigned extra_len, incr;
388 extra_len = columns() - basic_len;
390 /* Either UNIT already got 25, or is fully satisfied.
391 * Grant up to 25 to DESC now. */
392 incr = MIN(extra_len, 25u);
396 /* split the remaining space between UNIT and DESC,
397 * but do not give UNIT more than it needs. */
399 incr = MIN(extra_len / 2, max_id_len - id_len);
401 desc_len += extra_len - incr;
407 for (u = unit_infos; u < unit_infos + c; u++) {
408 _cleanup_free_ char *e = NULL, *j = NULL;
409 const char *on_loaded = "", *off_loaded = "";
410 const char *on_active = "", *off_active = "";
411 const char *on_circle = "", *off_circle = "";
415 if (!n_shown && !arg_no_legend) {
420 printf("%-*s %-*s %-*s %-*s ",
423 active_len, "ACTIVE",
427 printf("%-*s ", job_len, "JOB");
429 if (!arg_full && arg_no_pager)
430 printf("%.*s\n", desc_len, "DESCRIPTION");
432 printf("%s\n", "DESCRIPTION");
437 if (STR_IN_SET(u->load_state, "error", "not-found", "masked") && !arg_plain) {
438 on_loaded = ansi_highlight_red();
439 on_circle = ansi_highlight_yellow();
440 off_loaded = off_circle = ansi_highlight_off();
442 } else if (streq(u->active_state, "failed") && !arg_plain) {
443 on_circle = on_active = ansi_highlight_red();
444 off_circle = off_active = ansi_highlight_off();
449 j = strjoin(u->machine, ":", u->id, NULL);
458 e = ellipsize(id, id_len, 33);
466 printf("%s%s%s ", on_circle, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_circle);
468 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
469 on_active, id_len, id, off_active,
470 on_loaded, load_len, u->load_state, off_loaded,
471 on_active, active_len, u->active_state,
472 sub_len, u->sub_state, off_active,
473 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
476 printf("%.*s\n", desc_len, u->description);
478 printf("%s\n", u->description);
481 if (!arg_no_legend) {
482 const char *on, *off;
486 "LOAD = Reflects whether the unit definition was properly loaded.\n"
487 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
488 "SUB = The low-level unit activation state, values depend on unit type.");
489 puts(job_count ? "JOB = Pending job for the unit.\n" : "");
490 on = ansi_highlight();
491 off = ansi_highlight_off();
493 on = ansi_highlight_red();
494 off = ansi_highlight_off();
498 printf("%s%u loaded units listed.%s\n"
499 "To show all installed unit files use 'systemctl list-unit-files'.\n",
502 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
503 "To show all installed unit files use 'systemctl list-unit-files'.\n",
510 static int get_unit_list(
514 UnitInfo **unit_infos,
516 sd_bus_message **_reply) {
518 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
519 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
520 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
529 r = sd_bus_message_new_method_call(
532 "org.freedesktop.systemd1",
533 "/org/freedesktop/systemd1",
534 "org.freedesktop.systemd1.Manager",
535 "ListUnitsFiltered");
538 return bus_log_create_error(r);
540 r = sd_bus_message_append_strv(m, arg_states);
542 return bus_log_create_error(r);
544 r = sd_bus_call(bus, m, 0, &error, &reply);
546 log_error("Failed to list units: %s", bus_error_message(&error, r));
550 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
552 return bus_log_parse_error(r);
554 while ((r = bus_parse_unit_info(reply, &u)) > 0) {
557 if (!output_show_unit(&u, patterns))
560 if (!GREEDY_REALLOC(*unit_infos, size, c+1))
563 (*unit_infos)[c++] = u;
566 return bus_log_parse_error(r);
568 r = sd_bus_message_exit_container(reply);
570 return bus_log_parse_error(r);
578 static void message_set_freep(Set **set) {
581 while ((m = set_steal_first(*set)))
582 sd_bus_message_unref(m);
587 static int get_unit_list_recursive(
590 UnitInfo **_unit_infos,
594 _cleanup_free_ UnitInfo *unit_infos = NULL;
595 _cleanup_(message_set_freep) Set *replies;
596 sd_bus_message *reply;
604 replies = set_new(NULL);
608 c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
612 r = set_put(replies, reply);
614 sd_bus_message_unref(reply);
619 _cleanup_strv_free_ char **machines = NULL;
622 r = sd_get_machine_names(&machines);
626 STRV_FOREACH(i, machines) {
627 _cleanup_bus_close_unref_ sd_bus *container = NULL;
630 r = sd_bus_open_system_machine(&container, *i);
632 log_error_errno(r, "Failed to connect to container %s: %m", *i);
636 k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
642 r = set_put(replies, reply);
644 sd_bus_message_unref(reply);
649 *_machines = machines;
654 *_unit_infos = unit_infos;
663 static int list_units(sd_bus *bus, char **args) {
664 _cleanup_free_ UnitInfo *unit_infos = NULL;
665 _cleanup_(message_set_freep) Set *replies = NULL;
666 _cleanup_strv_free_ char **machines = NULL;
669 pager_open_if_enabled();
671 r = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
675 qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
676 return output_units_list(unit_infos, r);
679 static int get_triggered_units(
684 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
687 r = sd_bus_get_property_strv(
689 "org.freedesktop.systemd1",
691 "org.freedesktop.systemd1.Unit",
697 log_error("Failed to determine triggers: %s", bus_error_message(&error, r));
702 static int get_listening(
704 const char* unit_path,
707 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
708 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
709 const char *type, *path;
712 r = sd_bus_get_property(
714 "org.freedesktop.systemd1",
716 "org.freedesktop.systemd1.Socket",
722 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r));
726 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
728 return bus_log_parse_error(r);
730 while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
732 r = strv_extend(listening, type);
736 r = strv_extend(listening, path);
743 return bus_log_parse_error(r);
745 r = sd_bus_message_exit_container(reply);
747 return bus_log_parse_error(r);
759 /* Note: triggered is a list here, although it almost certainly
760 * will always be one unit. Nevertheless, dbus API allows for multiple
761 * values, so let's follow that. */
764 /* The strv above is shared. free is set only in the first one. */
768 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
774 if (!a->machine && b->machine)
776 if (a->machine && !b->machine)
778 if (a->machine && b->machine) {
779 o = strcasecmp(a->machine, b->machine);
784 o = strcmp(a->path, b->path);
786 o = strcmp(a->type, b->type);
791 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
792 struct socket_info *s;
793 unsigned pathlen = strlen("LISTEN"),
794 typelen = strlen("TYPE") * arg_show_types,
795 socklen = strlen("UNIT"),
796 servlen = strlen("ACTIVATES");
797 const char *on, *off;
799 for (s = socket_infos; s < socket_infos + cs; s++) {
803 socklen = MAX(socklen, strlen(s->id));
805 typelen = MAX(typelen, strlen(s->type));
806 pathlen = MAX(pathlen, strlen(s->path) + (s->machine ? strlen(s->machine)+1 : 0));
808 STRV_FOREACH(a, s->triggered)
809 tmp += strlen(*a) + 2*(a != s->triggered);
810 servlen = MAX(servlen, tmp);
815 printf("%-*s %-*.*s%-*s %s\n",
817 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
821 for (s = socket_infos; s < socket_infos + cs; s++) {
822 _cleanup_free_ char *j = NULL;
827 j = strjoin(s->machine, ":", s->path, NULL);
835 printf("%-*s %-*s %-*s",
836 pathlen, path, typelen, s->type, socklen, s->id);
839 pathlen, path, socklen, s->id);
840 STRV_FOREACH(a, s->triggered)
842 a == s->triggered ? "" : ",", *a);
846 on = ansi_highlight();
847 off = ansi_highlight_off();
851 on = ansi_highlight_red();
852 off = ansi_highlight_off();
855 if (!arg_no_legend) {
856 printf("%s%u sockets listed.%s\n", on, cs, off);
858 printf("Pass --all to see loaded but inactive sockets, too.\n");
864 static int list_sockets(sd_bus *bus, char **args) {
865 _cleanup_(message_set_freep) Set *replies = NULL;
866 _cleanup_strv_free_ char **machines = NULL;
867 _cleanup_free_ UnitInfo *unit_infos = NULL;
868 _cleanup_free_ struct socket_info *socket_infos = NULL;
870 struct socket_info *s;
875 pager_open_if_enabled();
877 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
881 for (u = unit_infos; u < unit_infos + n; u++) {
882 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
885 if (!endswith(u->id, ".socket"))
888 r = get_triggered_units(bus, u->unit_path, &triggered);
892 c = get_listening(bus, u->unit_path, &listening);
898 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
903 for (i = 0; i < c; i++)
904 socket_infos[cs + i] = (struct socket_info) {
905 .machine = u->machine,
907 .type = listening[i*2],
908 .path = listening[i*2 + 1],
909 .triggered = triggered,
910 .own_triggered = i==0,
913 /* from this point on we will cleanup those socket_infos */
916 listening = triggered = NULL; /* avoid cleanup */
919 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
920 (__compar_fn_t) socket_info_compare);
922 output_sockets_list(socket_infos, cs);
925 assert(cs == 0 || socket_infos);
926 for (s = socket_infos; s < socket_infos + cs; s++) {
929 if (s->own_triggered)
930 strv_free(s->triggered);
936 static int get_next_elapse(
939 dual_timestamp *next) {
941 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
949 r = sd_bus_get_property_trivial(
951 "org.freedesktop.systemd1",
953 "org.freedesktop.systemd1.Timer",
954 "NextElapseUSecMonotonic",
959 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
963 r = sd_bus_get_property_trivial(
965 "org.freedesktop.systemd1",
967 "org.freedesktop.systemd1.Timer",
968 "NextElapseUSecRealtime",
973 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
981 static int get_last_trigger(
986 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
993 r = sd_bus_get_property_trivial(
995 "org.freedesktop.systemd1",
997 "org.freedesktop.systemd1.Timer",
1003 log_error("Failed to get last trigger time: %s", bus_error_message(&error, r));
1011 const char* machine;
1014 usec_t last_trigger;
1018 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
1024 if (!a->machine && b->machine)
1026 if (a->machine && !b->machine)
1028 if (a->machine && b->machine) {
1029 o = strcasecmp(a->machine, b->machine);
1034 if (a->next_elapse < b->next_elapse)
1036 if (a->next_elapse > b->next_elapse)
1039 return strcmp(a->id, b->id);
1042 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
1043 struct timer_info *t;
1045 nextlen = strlen("NEXT"),
1046 leftlen = strlen("LEFT"),
1047 lastlen = strlen("LAST"),
1048 passedlen = strlen("PASSED"),
1049 unitlen = strlen("UNIT"),
1050 activatelen = strlen("ACTIVATES");
1052 const char *on, *off;
1054 assert(timer_infos || n == 0);
1056 for (t = timer_infos; t < timer_infos + n; t++) {
1060 if (t->next_elapse > 0) {
1061 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1063 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
1064 nextlen = MAX(nextlen, strlen(tstamp) + 1);
1066 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
1067 leftlen = MAX(leftlen, strlen(trel));
1070 if (t->last_trigger > 0) {
1071 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1073 format_timestamp(tstamp, sizeof(tstamp), t->last_trigger);
1074 lastlen = MAX(lastlen, strlen(tstamp) + 1);
1076 format_timestamp_relative(trel, sizeof(trel), t->last_trigger);
1077 passedlen = MAX(passedlen, strlen(trel));
1080 unitlen = MAX(unitlen, strlen(t->id) + (t->machine ? strlen(t->machine)+1 : 0));
1082 STRV_FOREACH(a, t->triggered)
1083 ul += strlen(*a) + 2*(a != t->triggered);
1085 activatelen = MAX(activatelen, ul);
1090 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1094 passedlen, "PASSED",
1098 for (t = timer_infos; t < timer_infos + n; t++) {
1099 _cleanup_free_ char *j = NULL;
1101 char tstamp1[FORMAT_TIMESTAMP_MAX] = "n/a", trel1[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1102 char tstamp2[FORMAT_TIMESTAMP_MAX] = "n/a", trel2[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1105 format_timestamp(tstamp1, sizeof(tstamp1), t->next_elapse);
1106 format_timestamp_relative(trel1, sizeof(trel1), t->next_elapse);
1108 format_timestamp(tstamp2, sizeof(tstamp2), t->last_trigger);
1109 format_timestamp_relative(trel2, sizeof(trel2), t->last_trigger);
1112 j = strjoin(t->machine, ":", t->id, NULL);
1119 printf("%-*s %-*s %-*s %-*s %-*s",
1120 nextlen, tstamp1, leftlen, trel1, lastlen, tstamp2, passedlen, trel2, unitlen, unit);
1122 STRV_FOREACH(a, t->triggered)
1124 a == t->triggered ? "" : ",", *a);
1128 on = ansi_highlight();
1129 off = ansi_highlight_off();
1133 on = ansi_highlight_red();
1134 off = ansi_highlight_off();
1137 if (!arg_no_legend) {
1138 printf("%s%u timers listed.%s\n", on, n, off);
1140 printf("Pass --all to see loaded but inactive timers, too.\n");
1146 static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
1152 if (next->monotonic != USEC_INFINITY && next->monotonic > 0) {
1155 if (next->monotonic > nw->monotonic)
1156 converted = nw->realtime + (next->monotonic - nw->monotonic);
1158 converted = nw->realtime - (nw->monotonic - next->monotonic);
1160 if (next->realtime != USEC_INFINITY && next->realtime > 0)
1161 next_elapse = MIN(converted, next->realtime);
1163 next_elapse = converted;
1166 next_elapse = next->realtime;
1171 static int list_timers(sd_bus *bus, char **args) {
1172 _cleanup_(message_set_freep) Set *replies = NULL;
1173 _cleanup_strv_free_ char **machines = NULL;
1174 _cleanup_free_ struct timer_info *timer_infos = NULL;
1175 _cleanup_free_ UnitInfo *unit_infos = NULL;
1176 struct timer_info *t;
1183 pager_open_if_enabled();
1185 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
1189 dual_timestamp_get(&nw);
1191 for (u = unit_infos; u < unit_infos + n; u++) {
1192 _cleanup_strv_free_ char **triggered = NULL;
1193 dual_timestamp next = {};
1196 if (!endswith(u->id, ".timer"))
1199 r = get_triggered_units(bus, u->unit_path, &triggered);
1203 r = get_next_elapse(bus, u->unit_path, &next);
1207 get_last_trigger(bus, u->unit_path, &last);
1209 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
1214 m = calc_next_elapse(&nw, &next);
1216 timer_infos[c++] = (struct timer_info) {
1217 .machine = u->machine,
1220 .last_trigger = last,
1221 .triggered = triggered,
1224 triggered = NULL; /* avoid cleanup */
1227 qsort_safe(timer_infos, c, sizeof(struct timer_info),
1228 (__compar_fn_t) timer_info_compare);
1230 output_timers_list(timer_infos, c);
1233 for (t = timer_infos; t < timer_infos + c; t++)
1234 strv_free(t->triggered);
1239 static int compare_unit_file_list(const void *a, const void *b) {
1240 const char *d1, *d2;
1241 const UnitFileList *u = a, *v = b;
1243 d1 = strrchr(u->path, '.');
1244 d2 = strrchr(v->path, '.');
1249 r = strcasecmp(d1, d2);
1254 return strcasecmp(basename(u->path), basename(v->path));
1257 static bool output_show_unit_file(const UnitFileList *u, char **patterns) {
1258 if (!strv_isempty(patterns)) {
1261 STRV_FOREACH(pattern, patterns)
1262 if (fnmatch(*pattern, basename(u->path), FNM_NOESCAPE) == 0)
1268 if (!strv_isempty(arg_types)) {
1271 dot = strrchr(u->path, '.');
1275 if (!strv_find(arg_types, dot+1))
1279 if (!strv_isempty(arg_states)) {
1280 if (!strv_find(arg_states, unit_file_state_to_string(u->state)))
1287 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
1288 unsigned max_id_len, id_cols, state_cols;
1289 const UnitFileList *u;
1291 max_id_len = strlen("UNIT FILE");
1292 state_cols = strlen("STATE");
1294 for (u = units; u < units + c; u++) {
1295 max_id_len = MAX(max_id_len, strlen(basename(u->path)));
1296 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1300 unsigned basic_cols;
1302 id_cols = MIN(max_id_len, 25u);
1303 basic_cols = 1 + id_cols + state_cols;
1304 if (basic_cols < (unsigned) columns())
1305 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1307 id_cols = max_id_len;
1310 printf("%-*s %-*s\n",
1311 id_cols, "UNIT FILE",
1312 state_cols, "STATE");
1314 for (u = units; u < units + c; u++) {
1315 _cleanup_free_ char *e = NULL;
1316 const char *on, *off;
1319 if (u->state == UNIT_FILE_MASKED ||
1320 u->state == UNIT_FILE_MASKED_RUNTIME ||
1321 u->state == UNIT_FILE_DISABLED ||
1322 u->state == UNIT_FILE_INVALID) {
1323 on = ansi_highlight_red();
1324 off = ansi_highlight_off();
1325 } else if (u->state == UNIT_FILE_ENABLED) {
1326 on = ansi_highlight_green();
1327 off = ansi_highlight_off();
1331 id = basename(u->path);
1333 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1335 printf("%-*s %s%-*s%s\n",
1336 id_cols, e ? e : id,
1337 on, state_cols, unit_file_state_to_string(u->state), off);
1341 printf("\n%u unit files listed.\n", c);
1344 static int list_unit_files(sd_bus *bus, char **args) {
1345 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1346 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1347 _cleanup_free_ UnitFileList *units = NULL;
1355 pager_open_if_enabled();
1363 h = hashmap_new(&string_hash_ops);
1367 r = unit_file_get_list(arg_scope, arg_root, h);
1369 unit_file_list_free(h);
1370 log_error_errno(r, "Failed to get unit file list: %m");
1374 n_units = hashmap_size(h);
1376 units = new(UnitFileList, n_units);
1377 if (!units && n_units > 0) {
1378 unit_file_list_free(h);
1382 HASHMAP_FOREACH(u, h, i) {
1383 if (!output_show_unit_file(u, strv_skip_first(args)))
1390 assert(c <= n_units);
1393 r = sd_bus_call_method(
1395 "org.freedesktop.systemd1",
1396 "/org/freedesktop/systemd1",
1397 "org.freedesktop.systemd1.Manager",
1403 log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1407 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1409 return bus_log_parse_error(r);
1411 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1413 if (!GREEDY_REALLOC(units, size, c + 1))
1416 units[c] = (struct UnitFileList) {
1418 unit_file_state_from_string(state)
1421 if (output_show_unit_file(&units[c], strv_skip_first(args)))
1426 return bus_log_parse_error(r);
1428 r = sd_bus_message_exit_container(reply);
1430 return bus_log_parse_error(r);
1433 qsort_safe(units, c, sizeof(UnitFileList), compare_unit_file_list);
1434 output_unit_file_list(units, c);
1437 for (unit = units; unit < units + c; unit++)
1444 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1445 _cleanup_free_ char *n = NULL;
1446 size_t max_len = MAX(columns(),20u);
1452 for (i = level - 1; i >= 0; i--) {
1454 if (len > max_len - 3 && !arg_full) {
1455 printf("%s...\n",max_len % 2 ? "" : " ");
1458 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERTICAL : DRAW_TREE_SPACE));
1462 if (len > max_len - 3 && !arg_full) {
1463 printf("%s...\n",max_len % 2 ? "" : " ");
1467 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
1471 printf("%s\n", name);
1475 n = ellipsize(name, max_len-len, 100);
1483 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1485 static const char *dependencies[_DEPENDENCY_MAX] = {
1486 [DEPENDENCY_FORWARD] = "Requires\0"
1487 "RequiresOverridable\0"
1489 "RequisiteOverridable\0"
1492 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1493 "RequiredByOverridable\0"
1497 [DEPENDENCY_AFTER] = "After\0",
1498 [DEPENDENCY_BEFORE] = "Before\0",
1501 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1502 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1503 _cleanup_strv_free_ char **ret = NULL;
1504 _cleanup_free_ char *path = NULL;
1510 assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
1512 path = unit_dbus_path_from_name(name);
1516 r = sd_bus_call_method(
1518 "org.freedesktop.systemd1",
1520 "org.freedesktop.DBus.Properties",
1524 "s", "org.freedesktop.systemd1.Unit");
1526 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1530 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1532 return bus_log_parse_error(r);
1534 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1537 r = sd_bus_message_read(reply, "s", &prop);
1539 return bus_log_parse_error(r);
1541 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1542 r = sd_bus_message_skip(reply, "v");
1544 return bus_log_parse_error(r);
1547 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1549 return bus_log_parse_error(r);
1551 r = bus_message_read_strv_extend(reply, &ret);
1553 return bus_log_parse_error(r);
1555 r = sd_bus_message_exit_container(reply);
1557 return bus_log_parse_error(r);
1560 r = sd_bus_message_exit_container(reply);
1562 return bus_log_parse_error(r);
1566 return bus_log_parse_error(r);
1568 r = sd_bus_message_exit_container(reply);
1570 return bus_log_parse_error(r);
1578 static int list_dependencies_compare(const void *_a, const void *_b) {
1579 const char **a = (const char**) _a, **b = (const char**) _b;
1581 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1583 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1586 return strcasecmp(*a, *b);
1589 static int list_dependencies_one(
1594 unsigned int branches) {
1596 _cleanup_strv_free_ char **deps = NULL;
1604 r = strv_extend(units, name);
1608 r = list_dependencies_get_dependencies(bus, name, &deps);
1612 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1614 STRV_FOREACH(c, deps) {
1615 if (strv_contains(*units, *c)) {
1617 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1630 state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true);
1631 on = state > 0 ? ansi_highlight_green() : ansi_highlight_red();
1632 printf("%s%s%s ", on, draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1635 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1639 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1640 r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1647 strv_remove(*units, name);
1652 static int list_dependencies(sd_bus *bus, char **args) {
1653 _cleanup_strv_free_ char **units = NULL;
1654 _cleanup_free_ char *unit = NULL;
1660 unit = unit_name_mangle(args[1], MANGLE_NOGLOB);
1665 u = SPECIAL_DEFAULT_TARGET;
1667 pager_open_if_enabled();
1671 return list_dependencies_one(bus, u, 0, &units, 0);
1674 struct machine_info {
1678 char *control_group;
1679 uint32_t n_failed_units;
1684 static const struct bus_properties_map machine_info_property_map[] = {
1685 { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
1686 { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
1687 { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
1688 { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
1689 { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
1693 static void free_machines_list(struct machine_info *machine_infos, int n) {
1699 for (i = 0; i < n; i++) {
1700 free(machine_infos[i].name);
1701 free(machine_infos[i].state);
1702 free(machine_infos[i].control_group);
1705 free(machine_infos);
1708 static int compare_machine_info(const void *a, const void *b) {
1709 const struct machine_info *u = a, *v = b;
1711 if (u->is_host != v->is_host)
1712 return u->is_host > v->is_host ? -1 : 1;
1714 return strcasecmp(u->name, v->name);
1717 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1718 _cleanup_bus_close_unref_ sd_bus *container = NULL;
1724 r = sd_bus_open_system_machine(&container, mi->name);
1731 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi);
1738 static bool output_show_machine(const char *name, char **patterns) {
1743 if (strv_isempty(patterns))
1746 STRV_FOREACH(i, patterns)
1747 if (fnmatch(*i, name, FNM_NOESCAPE) == 0)
1753 static int get_machine_list(
1755 struct machine_info **_machine_infos,
1758 struct machine_info *machine_infos = NULL;
1759 _cleanup_strv_free_ char **m = NULL;
1760 _cleanup_free_ char *hn = NULL;
1765 hn = gethostname_malloc();
1769 if (output_show_machine(hn, patterns)) {
1770 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1773 machine_infos[c].is_host = true;
1774 machine_infos[c].name = hn;
1777 get_machine_properties(bus, &machine_infos[c]);
1781 sd_get_machine_names(&m);
1782 STRV_FOREACH(i, m) {
1783 _cleanup_free_ char *class = NULL;
1785 if (!output_show_machine(*i, patterns))
1788 sd_machine_get_class(*i, &class);
1789 if (!streq_ptr(class, "container"))
1792 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1793 free_machines_list(machine_infos, c);
1797 machine_infos[c].is_host = false;
1798 machine_infos[c].name = strdup(*i);
1799 if (!machine_infos[c].name) {
1800 free_machines_list(machine_infos, c);
1804 get_machine_properties(NULL, &machine_infos[c]);
1808 *_machine_infos = machine_infos;
1812 static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1813 struct machine_info *m;
1816 namelen = sizeof("NAME") - 1,
1817 statelen = sizeof("STATE") - 1,
1818 failedlen = sizeof("FAILED") - 1,
1819 jobslen = sizeof("JOBS") - 1;
1821 assert(machine_infos || n == 0);
1823 for (m = machine_infos; m < machine_infos + n; m++) {
1824 namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
1825 statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
1826 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
1827 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
1829 if (!arg_plain && !streq_ptr(m->state, "running"))
1833 if (!arg_no_legend) {
1837 printf("%-*s %-*s %-*s %-*s\n",
1840 failedlen, "FAILED",
1844 for (m = machine_infos; m < machine_infos + n; m++) {
1845 const char *on_state = "", *off_state = "";
1846 const char *on_failed = "", *off_failed = "";
1847 bool circle = false;
1849 if (streq_ptr(m->state, "degraded")) {
1850 on_state = ansi_highlight_red();
1851 off_state = ansi_highlight_off();
1853 } else if (!streq_ptr(m->state, "running")) {
1854 on_state = ansi_highlight_yellow();
1855 off_state = ansi_highlight_off();
1859 if (m->n_failed_units > 0) {
1860 on_failed = ansi_highlight_red();
1861 off_failed = ansi_highlight_off();
1863 on_failed = off_failed = "";
1866 printf("%s%s%s ", on_state, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_state);
1869 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1870 (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
1871 on_state, statelen, strna(m->state), off_state,
1872 on_failed, failedlen, m->n_failed_units, off_failed,
1873 jobslen, m->n_jobs);
1875 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1876 namelen, strna(m->name),
1877 on_state, statelen, strna(m->state), off_state,
1878 on_failed, failedlen, m->n_failed_units, off_failed,
1879 jobslen, m->n_jobs);
1883 printf("\n%u machines listed.\n", n);
1886 static int list_machines(sd_bus *bus, char **args) {
1887 struct machine_info *machine_infos = NULL;
1892 if (geteuid() != 0) {
1893 log_error("Must be root.");
1897 pager_open_if_enabled();
1899 r = get_machine_list(bus, &machine_infos, strv_skip_first(args));
1903 qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
1904 output_machines_list(machine_infos, r);
1905 free_machines_list(machine_infos, r);
1910 static int get_default(sd_bus *bus, char **args) {
1911 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1912 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1913 _cleanup_free_ char *_path = NULL;
1917 if (!bus || avoid_bus()) {
1918 r = unit_file_get_default(arg_scope, arg_root, &_path);
1920 return log_error_errno(r, "Failed to get default target: %m");
1924 r = sd_bus_call_method(
1926 "org.freedesktop.systemd1",
1927 "/org/freedesktop/systemd1",
1928 "org.freedesktop.systemd1.Manager",
1934 log_error("Failed to get default target: %s", bus_error_message(&error, -r));
1938 r = sd_bus_message_read(reply, "s", &path);
1940 return bus_log_parse_error(r);
1944 printf("%s\n", path);
1949 static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) {
1952 assert(changes || n_changes == 0);
1954 for (i = 0; i < n_changes; i++) {
1955 if (changes[i].type == UNIT_FILE_SYMLINK)
1956 log_info("Created symlink from %s to %s.", changes[i].path, changes[i].source);
1958 log_info("Removed symlink %s.", changes[i].path);
1962 static int set_default(sd_bus *bus, char **args) {
1963 _cleanup_free_ char *unit = NULL;
1964 UnitFileChange *changes = NULL;
1965 unsigned n_changes = 0;
1968 unit = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
1972 if (!bus || avoid_bus()) {
1973 r = unit_file_set_default(arg_scope, arg_root, unit, true, &changes, &n_changes);
1975 return log_error_errno(r, "Failed to set default target: %m");
1978 dump_unit_file_changes(changes, n_changes);
1982 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1983 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1985 r = sd_bus_message_new_method_call(
1988 "org.freedesktop.systemd1",
1989 "/org/freedesktop/systemd1",
1990 "org.freedesktop.systemd1.Manager",
1991 "SetDefaultTarget");
1993 return bus_log_create_error(r);
1995 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
1997 return bus_log_create_error(r);
1999 r = sd_bus_message_append(m, "sb", unit, 1);
2001 return bus_log_create_error(r);
2003 r = sd_bus_call(bus, m, 0, &error, &reply);
2005 log_error("Failed to set default target: %s", bus_error_message(&error, -r));
2009 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
2013 /* Try to reload if enabled */
2015 r = daemon_reload(bus, args);
2020 unit_file_changes_free(changes, n_changes);
2027 const char *name, *type, *state;
2030 static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
2031 unsigned id_len, unit_len, type_len, state_len;
2032 const struct job_info *j;
2033 const char *on, *off;
2034 bool shorten = false;
2036 assert(n == 0 || jobs);
2039 if (!arg_no_legend) {
2040 on = ansi_highlight_green();
2041 off = ansi_highlight_off();
2043 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
2048 pager_open_if_enabled();
2050 id_len = strlen("JOB");
2051 unit_len = strlen("UNIT");
2052 type_len = strlen("TYPE");
2053 state_len = strlen("STATE");
2055 for (j = jobs; j < jobs + n; j++) {
2056 uint32_t id = j->id;
2057 assert(j->name && j->type && j->state);
2059 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
2060 unit_len = MAX(unit_len, strlen(j->name));
2061 type_len = MAX(type_len, strlen(j->type));
2062 state_len = MAX(state_len, strlen(j->state));
2065 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
2066 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
2071 printf("%*s %-*s %-*s %-*s\n",
2075 state_len, "STATE");
2077 for (j = jobs; j < jobs + n; j++) {
2078 _cleanup_free_ char *e = NULL;
2080 if (streq(j->state, "running")) {
2081 on = ansi_highlight();
2082 off = ansi_highlight_off();
2086 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
2087 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2089 on, unit_len, e ? e : j->name, off,
2091 on, state_len, j->state, off);
2094 if (!arg_no_legend) {
2095 on = ansi_highlight();
2096 off = ansi_highlight_off();
2098 printf("\n%s%u jobs listed%s.\n", on, n, off);
2102 static bool output_show_job(struct job_info *job, char **patterns) {
2107 if (strv_isempty(patterns))
2110 STRV_FOREACH(pattern, patterns)
2111 if (fnmatch(*pattern, job->name, FNM_NOESCAPE) == 0)
2116 static int list_jobs(sd_bus *bus, char **args) {
2117 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2118 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2119 const char *name, *type, *state, *job_path, *unit_path;
2120 _cleanup_free_ struct job_info *jobs = NULL;
2125 bool skipped = false;
2127 r = sd_bus_call_method(
2129 "org.freedesktop.systemd1",
2130 "/org/freedesktop/systemd1",
2131 "org.freedesktop.systemd1.Manager",
2137 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
2141 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2143 return bus_log_parse_error(r);
2145 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
2146 struct job_info job = { id, name, type, state };
2148 if (!output_show_job(&job, strv_skip_first(args))) {
2153 if (!GREEDY_REALLOC(jobs, size, c + 1))
2159 return bus_log_parse_error(r);
2161 r = sd_bus_message_exit_container(reply);
2163 return bus_log_parse_error(r);
2165 output_jobs_list(jobs, c, skipped);
2169 static int cancel_job(sd_bus *bus, char **args) {
2170 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2176 if (strv_length(args) <= 1)
2177 return daemon_reload(bus, args);
2179 STRV_FOREACH(name, args+1) {
2180 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2184 q = safe_atou32(*name, &id);
2186 return log_error_errno(q, "Failed to parse job id \"%s\": %m", *name);
2188 q = sd_bus_message_new_method_call(
2191 "org.freedesktop.systemd1",
2192 "/org/freedesktop/systemd1",
2193 "org.freedesktop.systemd1.Manager",
2196 return bus_log_create_error(q);
2198 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2200 return bus_log_create_error(1);
2202 q = sd_bus_message_append(m, "u", id);
2204 return bus_log_create_error(q);
2206 q = sd_bus_call(bus, m, 0, &error, NULL);
2208 log_error("Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, q));
2217 static int need_daemon_reload(sd_bus *bus, const char *unit) {
2218 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2222 /* We ignore all errors here, since this is used to show a
2225 /* We don't use unit_dbus_path_from_name() directly since we
2226 * don't want to load the unit if it isn't loaded. */
2228 r = sd_bus_call_method(
2230 "org.freedesktop.systemd1",
2231 "/org/freedesktop/systemd1",
2232 "org.freedesktop.systemd1.Manager",
2240 r = sd_bus_message_read(reply, "o", &path);
2244 r = sd_bus_get_property_trivial(
2246 "org.freedesktop.systemd1",
2248 "org.freedesktop.systemd1.Unit",
2258 static void warn_unit_file_changed(const char *name) {
2259 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2260 ansi_highlight_red(),
2261 ansi_highlight_off(),
2263 arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2266 static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **unit_path) {
2273 STRV_FOREACH(p, lp->unit_path) {
2274 _cleanup_free_ char *path;
2276 path = path_join(arg_root, *p, unit_name);
2280 if (access(path, F_OK) == 0) {
2290 static int unit_find_paths(sd_bus *bus,
2291 const char *unit_name,
2292 bool avoid_bus_cache,
2294 char **fragment_path,
2295 char ***dropin_paths) {
2297 _cleanup_free_ char *path = NULL;
2298 _cleanup_strv_free_ char **dropins = NULL;
2302 * Finds where the unit is defined on disk. Returns 0 if the unit
2303 * is not found. Returns 1 if it is found, and sets
2304 * - the path to the unit in *path, if it exists on disk,
2305 * - and a strv of existing drop-ins in *dropins,
2306 * if the arg is not NULL and any dropins were found.
2310 assert(fragment_path);
2313 if (!avoid_bus_cache && !unit_name_is_template(unit_name)) {
2314 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2315 _cleanup_bus_message_unref_ sd_bus_message *unit_load_error = NULL;
2316 _cleanup_free_ char *unit = NULL;
2317 _cleanup_strv_free_ char **load_error = NULL;
2318 char *unit_load_error_name, *unit_load_error_message;
2320 unit = unit_dbus_path_from_name(unit_name);
2324 if (need_daemon_reload(bus, unit_name) > 0)
2325 warn_unit_file_changed(unit_name);
2327 r = sd_bus_get_property(
2329 "org.freedesktop.systemd1",
2331 "org.freedesktop.systemd1.Unit",
2337 return log_error_errno(r, "Failed to get LoadError: %s", bus_error_message(&error, r));
2339 r = sd_bus_message_read(
2342 &unit_load_error_name,
2343 &unit_load_error_message);
2345 return bus_log_parse_error(r);
2347 if (!isempty(unit_load_error_name)) {
2348 log_error("Unit %s is not loaded: %s", unit_name, unit_load_error_message);
2352 r = sd_bus_get_property_string(
2354 "org.freedesktop.systemd1",
2356 "org.freedesktop.systemd1.Unit",
2361 return log_error_errno(r, "Failed to get FragmentPath: %s", bus_error_message(&error, r));
2364 r = sd_bus_get_property_strv(
2366 "org.freedesktop.systemd1",
2368 "org.freedesktop.systemd1.Unit",
2373 return log_error_errno(r, "Failed to get DropInPaths: %s", bus_error_message(&error, r));
2376 _cleanup_set_free_ Set *names;
2378 names = set_new(NULL);
2382 r = set_put(names, unit_name);
2386 r = unit_file_find_path(lp, unit_name, &path);
2391 _cleanup_free_ char *template;
2393 template = unit_name_template(unit_name);
2397 if (!streq(template, unit_name)) {
2398 r = unit_file_find_path(lp, template, &path);
2405 r = unit_file_find_dropin_paths(lp->unit_path, NULL, names, &dropins);
2413 if (!isempty(path)) {
2414 *fragment_path = path;
2419 if (dropin_paths && !strv_isempty(dropins)) {
2420 *dropin_paths = dropins;
2426 log_error("No files found for %s.", unit_name);
2431 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2432 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2433 _cleanup_free_ char *n = NULL, *state = NULL;
2439 n = unit_name_mangle(name, MANGLE_NOGLOB);
2443 /* We don't use unit_dbus_path_from_name() directly since we
2444 * don't want to load the unit if it isn't loaded. */
2446 r = sd_bus_call_method(
2448 "org.freedesktop.systemd1",
2449 "/org/freedesktop/systemd1",
2450 "org.freedesktop.systemd1.Manager",
2461 r = sd_bus_message_read(reply, "o", &path);
2463 return bus_log_parse_error(r);
2465 r = sd_bus_get_property_string(
2467 "org.freedesktop.systemd1",
2469 "org.freedesktop.systemd1.Unit",
2482 return nulstr_contains(good_states, state);
2485 static int check_triggering_units(
2489 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2490 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2491 _cleanup_strv_free_ char **triggered_by = NULL;
2492 bool print_warning_label = true;
2496 n = unit_name_mangle(name, MANGLE_NOGLOB);
2500 path = unit_dbus_path_from_name(n);
2504 r = sd_bus_get_property_string(
2506 "org.freedesktop.systemd1",
2508 "org.freedesktop.systemd1.Unit",
2513 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2517 if (streq(state, "masked"))
2520 r = sd_bus_get_property_strv(
2522 "org.freedesktop.systemd1",
2524 "org.freedesktop.systemd1.Unit",
2529 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2533 STRV_FOREACH(i, triggered_by) {
2534 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2536 return log_error_errno(r, "Failed to check unit: %m");
2541 if (print_warning_label) {
2542 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2543 print_warning_label = false;
2546 log_warning(" %s", *i);
2552 static const struct {
2555 } unit_actions[] = {
2556 { "start", "StartUnit" },
2557 { "stop", "StopUnit" },
2558 { "condstop", "StopUnit" },
2559 { "reload", "ReloadUnit" },
2560 { "restart", "RestartUnit" },
2561 { "try-restart", "TryRestartUnit" },
2562 { "condrestart", "TryRestartUnit" },
2563 { "reload-or-restart", "ReloadOrRestartUnit" },
2564 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2565 { "condreload", "ReloadOrTryRestartUnit" },
2566 { "force-reload", "ReloadOrTryRestartUnit" }
2569 static const char *verb_to_method(const char *verb) {
2572 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2573 if (streq_ptr(unit_actions[i].verb, verb))
2574 return unit_actions[i].method;
2579 static const char *method_to_verb(const char *method) {
2582 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2583 if (streq_ptr(unit_actions[i].method, method))
2584 return unit_actions[i].verb;
2589 static int start_unit_one(
2594 sd_bus_error *error,
2595 BusWaitForJobs *w) {
2597 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2606 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2608 r = sd_bus_message_new_method_call(
2611 "org.freedesktop.systemd1",
2612 "/org/freedesktop/systemd1",
2613 "org.freedesktop.systemd1.Manager",
2616 return bus_log_create_error(r);
2618 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2620 return bus_log_create_error(r);
2622 r = sd_bus_message_append(m, "ss", name, mode);
2624 return bus_log_create_error(r);
2626 r = sd_bus_call(bus, m, 0, error, &reply);
2630 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2631 /* There's always a fallback possible for
2632 * legacy actions. */
2633 return -EADDRNOTAVAIL;
2635 verb = method_to_verb(method);
2637 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2641 r = sd_bus_message_read(reply, "o", &path);
2643 return bus_log_parse_error(r);
2645 if (need_daemon_reload(bus, name) > 0)
2646 warn_unit_file_changed(name);
2649 log_debug("Adding %s to the set", path);
2650 r = bus_wait_for_jobs_add(w, path);
2658 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2660 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2664 STRV_FOREACH(name, names) {
2668 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2670 t = unit_name_mangle(*name, MANGLE_GLOB);
2674 if (string_is_glob(t))
2675 r = strv_consume(&globs, t);
2677 r = strv_consume(&mangled, t);
2682 /* Query the manager only if any of the names are a glob, since
2683 * this is fairly expensive */
2684 if (!strv_isempty(globs)) {
2685 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2686 _cleanup_free_ UnitInfo *unit_infos = NULL;
2689 return log_error_errno(ENOTSUP, "Unit name globbing without bus is not implemented.");
2691 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2695 for (i = 0; i < r; i++)
2696 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2701 mangled = NULL; /* do not free */
2706 static const struct {
2710 } action_table[_ACTION_MAX] = {
2711 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2712 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2713 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2714 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2715 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
2716 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
2717 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
2718 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
2719 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2720 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2721 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2722 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2723 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2724 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2725 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2728 static enum action verb_to_action(const char *verb) {
2731 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2732 if (streq_ptr(action_table[i].verb, verb))
2735 return _ACTION_INVALID;
2738 static int start_unit(sd_bus *bus, char **args) {
2739 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
2740 const char *method, *mode, *one_name, *suffix = NULL;
2741 _cleanup_strv_free_ char **names = NULL;
2747 ask_password_agent_open_if_enabled();
2748 polkit_agent_open_if_enabled();
2750 if (arg_action == ACTION_SYSTEMCTL) {
2752 method = verb_to_method(args[0]);
2753 action = verb_to_action(args[0]);
2755 if (streq(args[0], "isolate")) {
2759 mode = action_table[action].mode ?: arg_job_mode;
2761 one_name = action_table[action].target;
2763 assert(arg_action < ELEMENTSOF(action_table));
2764 assert(action_table[arg_action].target);
2766 method = "StartUnit";
2768 mode = action_table[arg_action].mode;
2769 one_name = action_table[arg_action].target;
2773 names = strv_new(one_name, NULL);
2775 r = expand_names(bus, args + 1, suffix, &names);
2777 log_error_errno(r, "Failed to expand names: %m");
2780 if (!arg_no_block) {
2781 r = bus_wait_for_jobs_new(bus, &w);
2783 return log_error_errno(r, "Could not watch jobs: %m");
2786 STRV_FOREACH(name, names) {
2787 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2790 q = start_unit_one(bus, method, *name, mode, &error, w);
2791 if (r >= 0 && q < 0)
2792 r = translate_bus_error_to_exit_status(q, &error);
2795 if (!arg_no_block) {
2798 q = bus_wait_for_jobs(w, arg_quiet);
2802 /* When stopping units, warn if they can still be triggered by
2803 * another active unit (socket, path, timer) */
2804 if (!arg_quiet && streq(method, "StopUnit"))
2805 STRV_FOREACH(name, names)
2806 check_triggering_units(bus, *name);
2812 /* Ask systemd-logind, which might grant access to unprivileged users
2813 * through PolicyKit */
2814 static int reboot_with_logind(sd_bus *bus, enum action a) {
2816 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2823 polkit_agent_open_if_enabled();
2831 case ACTION_POWEROFF:
2832 method = "PowerOff";
2835 case ACTION_SUSPEND:
2839 case ACTION_HIBERNATE:
2840 method = "Hibernate";
2843 case ACTION_HYBRID_SLEEP:
2844 method = "HybridSleep";
2851 r = sd_bus_call_method(
2853 "org.freedesktop.login1",
2854 "/org/freedesktop/login1",
2855 "org.freedesktop.login1.Manager",
2859 "b", arg_ask_password);
2861 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2869 static int check_inhibitors(sd_bus *bus, enum action a) {
2871 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2872 _cleanup_strv_free_ char **sessions = NULL;
2873 const char *what, *who, *why, *mode;
2882 if (arg_ignore_inhibitors || arg_force > 0)
2894 r = sd_bus_call_method(
2896 "org.freedesktop.login1",
2897 "/org/freedesktop/login1",
2898 "org.freedesktop.login1.Manager",
2904 /* If logind is not around, then there are no inhibitors... */
2907 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2909 return bus_log_parse_error(r);
2911 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2912 _cleanup_free_ char *comm = NULL, *user = NULL;
2913 _cleanup_strv_free_ char **sv = NULL;
2915 if (!streq(mode, "block"))
2918 sv = strv_split(what, ":");
2922 if (!strv_contains(sv,
2924 a == ACTION_POWEROFF ||
2925 a == ACTION_REBOOT ||
2926 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2929 get_process_comm(pid, &comm);
2930 user = uid_to_name(uid);
2932 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
2933 who, pid, strna(comm), strna(user), why);
2938 return bus_log_parse_error(r);
2940 r = sd_bus_message_exit_container(reply);
2942 return bus_log_parse_error(r);
2944 /* Check for current sessions */
2945 sd_get_sessions(&sessions);
2946 STRV_FOREACH(s, sessions) {
2947 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2949 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2952 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2955 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2958 sd_session_get_tty(*s, &tty);
2959 sd_session_get_seat(*s, &seat);
2960 sd_session_get_service(*s, &service);
2961 user = uid_to_name(uid);
2963 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2970 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2971 action_table[a].verb);
2979 static int start_special(sd_bus *bus, char **args) {
2985 a = verb_to_action(args[0]);
2987 r = check_inhibitors(bus, a);
2991 if (arg_force >= 2 && geteuid() != 0) {
2992 log_error("Must be root.");
2996 if (a == ACTION_REBOOT) {
2997 r = update_reboot_param_file(args[1]);
3002 if (arg_force >= 2 &&
3003 (a == ACTION_HALT ||
3004 a == ACTION_POWEROFF ||
3005 a == ACTION_REBOOT))
3008 if (arg_force >= 1 &&
3009 (a == ACTION_HALT ||
3010 a == ACTION_POWEROFF ||
3011 a == ACTION_REBOOT ||
3012 a == ACTION_KEXEC ||
3014 return daemon_reload(bus, args);
3016 /* first try logind, to allow authentication with polkit */
3017 if (geteuid() != 0 &&
3018 (a == ACTION_POWEROFF ||
3019 a == ACTION_REBOOT ||
3020 a == ACTION_SUSPEND ||
3021 a == ACTION_HIBERNATE ||
3022 a == ACTION_HYBRID_SLEEP)) {
3023 r = reboot_with_logind(bus, a);
3024 if (r >= 0 || IN_SET(r, -ENOTSUP, -EINPROGRESS))
3028 r = start_unit(bus, args);
3029 if (r == EXIT_SUCCESS)
3035 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
3036 _cleanup_strv_free_ char **names = NULL;
3043 r = expand_names(bus, args, NULL, &names);
3045 return log_error_errno(r, "Failed to expand names: %m");
3047 STRV_FOREACH(name, names) {
3050 state = check_one_unit(bus, *name, good_states, arg_quiet);
3060 static int check_unit_active(sd_bus *bus, char **args) {
3061 /* According to LSB: 3, "program is not running" */
3062 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
3065 static int check_unit_failed(sd_bus *bus, char **args) {
3066 return check_unit_generic(bus, 1, "failed\0", args + 1);
3069 static int kill_unit(sd_bus *bus, char **args) {
3070 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3071 _cleanup_strv_free_ char **names = NULL;
3078 polkit_agent_open_if_enabled();
3081 arg_kill_who = "all";
3083 r = expand_names(bus, args + 1, NULL, &names);
3085 log_error_errno(r, "Failed to expand names: %m");
3087 STRV_FOREACH(name, names) {
3088 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3090 q = sd_bus_message_new_method_call(
3093 "org.freedesktop.systemd1",
3094 "/org/freedesktop/systemd1",
3095 "org.freedesktop.systemd1.Manager",
3098 return bus_log_create_error(q);
3100 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
3102 return bus_log_create_error(q);
3104 q = sd_bus_message_append(m, "ssi", *names, arg_kill_who, arg_signal);
3106 return bus_log_create_error(q);
3108 q = sd_bus_call(bus, m, 0, &error, NULL);
3110 log_error("Failed to kill unit %s: %s", *names, bus_error_message(&error, q));
3119 typedef struct ExecStatusInfo {
3127 usec_t start_timestamp;
3128 usec_t exit_timestamp;
3133 LIST_FIELDS(struct ExecStatusInfo, exec);
3136 static void exec_status_info_free(ExecStatusInfo *i) {
3145 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3146 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3149 int32_t code, status;
3155 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3157 return bus_log_parse_error(r);
3161 r = sd_bus_message_read(m, "s", &path);
3163 return bus_log_parse_error(r);
3165 i->path = strdup(path);
3169 r = sd_bus_message_read_strv(m, &i->argv);
3171 return bus_log_parse_error(r);
3173 r = sd_bus_message_read(m,
3176 &start_timestamp, &start_timestamp_monotonic,
3177 &exit_timestamp, &exit_timestamp_monotonic,
3181 return bus_log_parse_error(r);
3184 i->start_timestamp = (usec_t) start_timestamp;
3185 i->exit_timestamp = (usec_t) exit_timestamp;
3186 i->pid = (pid_t) pid;
3190 r = sd_bus_message_exit_container(m);
3192 return bus_log_parse_error(r);
3197 typedef struct UnitStatusInfo {
3199 const char *load_state;
3200 const char *active_state;
3201 const char *sub_state;
3202 const char *unit_file_state;
3203 const char *unit_file_preset;
3205 const char *description;
3206 const char *following;
3208 char **documentation;
3210 const char *fragment_path;
3211 const char *source_path;
3212 const char *control_group;
3214 char **dropin_paths;
3216 const char *load_error;
3219 usec_t inactive_exit_timestamp;
3220 usec_t inactive_exit_timestamp_monotonic;
3221 usec_t active_enter_timestamp;
3222 usec_t active_exit_timestamp;
3223 usec_t inactive_enter_timestamp;
3225 bool need_daemon_reload;
3230 const char *status_text;
3231 const char *pid_file;
3235 usec_t start_timestamp;
3236 usec_t exit_timestamp;
3238 int exit_code, exit_status;
3240 usec_t condition_timestamp;
3241 bool condition_result;
3242 bool failed_condition_trigger;
3243 bool failed_condition_negate;
3244 const char *failed_condition;
3245 const char *failed_condition_parameter;
3247 usec_t assert_timestamp;
3249 bool failed_assert_trigger;
3250 bool failed_assert_negate;
3251 const char *failed_assert;
3252 const char *failed_assert_parameter;
3255 unsigned n_accepted;
3256 unsigned n_connections;
3259 /* Pairs of type, path */
3263 const char *sysfs_path;
3265 /* Mount, Automount */
3272 uint64_t memory_current;
3273 uint64_t memory_limit;
3275 LIST_HEAD(ExecStatusInfo, exec);
3278 static void print_status_info(
3283 const char *active_on, *active_off, *on, *off, *ss;
3285 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3286 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3292 /* This shows pretty information about a unit. See
3293 * print_property() for a low-level property printer */
3295 if (streq_ptr(i->active_state, "failed")) {
3296 active_on = ansi_highlight_red();
3297 active_off = ansi_highlight_off();
3298 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3299 active_on = ansi_highlight_green();
3300 active_off = ansi_highlight_off();
3302 active_on = active_off = "";
3304 printf("%s%s%s %s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3306 if (i->description && !streq_ptr(i->id, i->description))
3307 printf(" - %s", i->description);
3312 printf(" Follow: unit currently follows state of %s\n", i->following);
3314 if (streq_ptr(i->load_state, "error")) {
3315 on = ansi_highlight_red();
3316 off = ansi_highlight_off();
3320 path = i->source_path ? i->source_path : i->fragment_path;
3323 printf(" Loaded: %s%s%s (Reason: %s)\n",
3324 on, strna(i->load_state), off, i->load_error);
3325 else if (path && !isempty(i->unit_file_state) && !isempty(i->unit_file_preset))
3326 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3327 on, strna(i->load_state), off, path, i->unit_file_state, i->unit_file_preset);
3328 else if (path && !isempty(i->unit_file_state))
3329 printf(" Loaded: %s%s%s (%s; %s)\n",
3330 on, strna(i->load_state), off, path, i->unit_file_state);
3332 printf(" Loaded: %s%s%s (%s)\n",
3333 on, strna(i->load_state), off, path);
3335 printf(" Loaded: %s%s%s\n",
3336 on, strna(i->load_state), off);
3338 if (!strv_isempty(i->dropin_paths)) {
3339 _cleanup_free_ char *dir = NULL;
3343 STRV_FOREACH(dropin, i->dropin_paths) {
3344 if (! dir || last) {
3345 printf(dir ? " " : " Drop-In: ");
3350 if (path_get_parent(*dropin, &dir) < 0) {
3355 printf("%s\n %s", dir,
3356 draw_special_char(DRAW_TREE_RIGHT));
3359 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3361 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3365 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3367 printf(" Active: %s%s (%s)%s",
3368 active_on, strna(i->active_state), ss, active_off);
3370 printf(" Active: %s%s%s",
3371 active_on, strna(i->active_state), active_off);
3373 if (!isempty(i->result) && !streq(i->result, "success"))
3374 printf(" (Result: %s)", i->result);
3376 timestamp = (streq_ptr(i->active_state, "active") ||
3377 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
3378 (streq_ptr(i->active_state, "inactive") ||
3379 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
3380 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
3381 i->active_exit_timestamp;
3383 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3384 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3387 printf(" since %s; %s\n", s2, s1);
3389 printf(" since %s\n", s2);
3393 if (!i->condition_result && i->condition_timestamp > 0) {
3394 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3395 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3397 printf("Condition: start %scondition failed%s at %s%s%s\n",
3398 ansi_highlight_yellow(), ansi_highlight_off(),
3399 s2, s1 ? "; " : "", s1 ? s1 : "");
3400 if (i->failed_condition_trigger)
3401 printf(" none of the trigger conditions were met\n");
3402 else if (i->failed_condition)
3403 printf(" %s=%s%s was not met\n",
3404 i->failed_condition,
3405 i->failed_condition_negate ? "!" : "",
3406 i->failed_condition_parameter);
3409 if (!i->assert_result && i->assert_timestamp > 0) {
3410 s1 = format_timestamp_relative(since1, sizeof(since1), i->assert_timestamp);
3411 s2 = format_timestamp(since2, sizeof(since2), i->assert_timestamp);
3413 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3414 ansi_highlight_red(), ansi_highlight_off(),
3415 s2, s1 ? "; " : "", s1 ? s1 : "");
3416 if (i->failed_assert_trigger)
3417 printf(" none of the trigger assertions were met\n");
3418 else if (i->failed_assert)
3419 printf(" %s=%s%s was not met\n",
3421 i->failed_assert_negate ? "!" : "",
3422 i->failed_assert_parameter);
3426 printf(" Device: %s\n", i->sysfs_path);
3428 printf(" Where: %s\n", i->where);
3430 printf(" What: %s\n", i->what);
3432 STRV_FOREACH(t, i->documentation)
3433 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3435 STRV_FOREACH_PAIR(t, t2, i->listen)
3436 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3439 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3441 LIST_FOREACH(exec, p, i->exec) {
3442 _cleanup_free_ char *argv = NULL;
3445 /* Only show exited processes here */
3449 argv = strv_join(p->argv, " ");
3450 printf(" Process: "PID_FMT" %s=%s ", p->pid, p->name, strna(argv));
3452 good = is_clean_exit_lsb(p->code, p->status, NULL);
3454 on = ansi_highlight_red();
3455 off = ansi_highlight_off();
3459 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3461 if (p->code == CLD_EXITED) {
3464 printf("status=%i", p->status);
3466 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3471 printf("signal=%s", signal_to_string(p->status));
3473 printf(")%s\n", off);
3475 if (i->main_pid == p->pid &&
3476 i->start_timestamp == p->start_timestamp &&
3477 i->exit_timestamp == p->start_timestamp)
3478 /* Let's not show this twice */
3481 if (p->pid == i->control_pid)
3485 if (i->main_pid > 0 || i->control_pid > 0) {
3486 if (i->main_pid > 0) {
3487 printf(" Main PID: "PID_FMT, i->main_pid);
3490 _cleanup_free_ char *comm = NULL;
3491 get_process_comm(i->main_pid, &comm);
3493 printf(" (%s)", comm);
3494 } else if (i->exit_code > 0) {
3495 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3497 if (i->exit_code == CLD_EXITED) {
3500 printf("status=%i", i->exit_status);
3502 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3507 printf("signal=%s", signal_to_string(i->exit_status));
3511 if (i->control_pid > 0)
3515 if (i->control_pid > 0) {
3516 _cleanup_free_ char *c = NULL;
3518 printf(" %8s: "PID_FMT, i->main_pid ? "" : " Control", i->control_pid);
3520 get_process_comm(i->control_pid, &c);
3529 printf(" Status: \"%s\"\n", i->status_text);
3530 if (i->status_errno > 0)
3531 printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
3533 if (i->memory_current != (uint64_t) -1) {
3534 char buf[FORMAT_BYTES_MAX];
3536 printf(" Memory: %s", format_bytes(buf, sizeof(buf), i->memory_current));
3538 if (i->memory_limit != (uint64_t) -1)
3539 printf(" (limit: %s)\n", format_bytes(buf, sizeof(buf), i->memory_limit));
3544 if (i->control_group &&
3545 (i->main_pid > 0 || i->control_pid > 0 ||
3546 ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_MACHINE) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3549 printf(" CGroup: %s\n", i->control_group);
3551 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_MACHINE) {
3554 static const char prefix[] = " ";
3557 if (c > sizeof(prefix) - 1)
3558 c -= sizeof(prefix) - 1;
3562 if (i->main_pid > 0)
3563 extra[k++] = i->main_pid;
3565 if (i->control_pid > 0)
3566 extra[k++] = i->control_pid;
3568 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, get_output_flags());
3572 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3573 show_journal_by_unit(
3578 i->inactive_exit_timestamp_monotonic,
3581 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
3582 SD_JOURNAL_LOCAL_ONLY,
3583 arg_scope == UNIT_FILE_SYSTEM,
3587 if (i->need_daemon_reload)
3588 warn_unit_file_changed(i->id);
3591 static void show_unit_help(UnitStatusInfo *i) {
3596 if (!i->documentation) {
3597 log_info("Documentation for %s not known.", i->id);
3601 STRV_FOREACH(p, i->documentation)
3602 if (startswith(*p, "man:"))
3603 show_man_page(*p + 4, false);
3605 log_info("Can't show: %s", *p);
3608 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3615 switch (contents[0]) {
3617 case SD_BUS_TYPE_STRING: {
3620 r = sd_bus_message_read(m, "s", &s);
3622 return bus_log_parse_error(r);
3625 if (streq(name, "Id"))
3627 else if (streq(name, "LoadState"))
3629 else if (streq(name, "ActiveState"))
3630 i->active_state = s;
3631 else if (streq(name, "SubState"))
3633 else if (streq(name, "Description"))
3635 else if (streq(name, "FragmentPath"))
3636 i->fragment_path = s;
3637 else if (streq(name, "SourcePath"))
3640 else if (streq(name, "DefaultControlGroup")) {
3642 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3644 i->control_group = e;
3647 else if (streq(name, "ControlGroup"))
3648 i->control_group = s;
3649 else if (streq(name, "StatusText"))
3651 else if (streq(name, "PIDFile"))
3653 else if (streq(name, "SysFSPath"))
3655 else if (streq(name, "Where"))
3657 else if (streq(name, "What"))
3659 else if (streq(name, "Following"))
3661 else if (streq(name, "UnitFileState"))
3662 i->unit_file_state = s;
3663 else if (streq(name, "UnitFilePreset"))
3664 i->unit_file_preset = s;
3665 else if (streq(name, "Result"))
3672 case SD_BUS_TYPE_BOOLEAN: {
3675 r = sd_bus_message_read(m, "b", &b);
3677 return bus_log_parse_error(r);
3679 if (streq(name, "Accept"))
3681 else if (streq(name, "NeedDaemonReload"))
3682 i->need_daemon_reload = b;
3683 else if (streq(name, "ConditionResult"))
3684 i->condition_result = b;
3685 else if (streq(name, "AssertResult"))
3686 i->assert_result = b;
3691 case SD_BUS_TYPE_UINT32: {
3694 r = sd_bus_message_read(m, "u", &u);
3696 return bus_log_parse_error(r);
3698 if (streq(name, "MainPID")) {
3700 i->main_pid = (pid_t) u;
3703 } else if (streq(name, "ControlPID"))
3704 i->control_pid = (pid_t) u;
3705 else if (streq(name, "ExecMainPID")) {
3707 i->main_pid = (pid_t) u;
3708 } else if (streq(name, "NAccepted"))
3710 else if (streq(name, "NConnections"))
3711 i->n_connections = u;
3716 case SD_BUS_TYPE_INT32: {
3719 r = sd_bus_message_read(m, "i", &j);
3721 return bus_log_parse_error(r);
3723 if (streq(name, "ExecMainCode"))
3724 i->exit_code = (int) j;
3725 else if (streq(name, "ExecMainStatus"))
3726 i->exit_status = (int) j;
3727 else if (streq(name, "StatusErrno"))
3728 i->status_errno = (int) j;
3733 case SD_BUS_TYPE_UINT64: {
3736 r = sd_bus_message_read(m, "t", &u);
3738 return bus_log_parse_error(r);
3740 if (streq(name, "ExecMainStartTimestamp"))
3741 i->start_timestamp = (usec_t) u;
3742 else if (streq(name, "ExecMainExitTimestamp"))
3743 i->exit_timestamp = (usec_t) u;
3744 else if (streq(name, "ActiveEnterTimestamp"))
3745 i->active_enter_timestamp = (usec_t) u;
3746 else if (streq(name, "InactiveEnterTimestamp"))
3747 i->inactive_enter_timestamp = (usec_t) u;
3748 else if (streq(name, "InactiveExitTimestamp"))
3749 i->inactive_exit_timestamp = (usec_t) u;
3750 else if (streq(name, "InactiveExitTimestampMonotonic"))
3751 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3752 else if (streq(name, "ActiveExitTimestamp"))
3753 i->active_exit_timestamp = (usec_t) u;
3754 else if (streq(name, "ConditionTimestamp"))
3755 i->condition_timestamp = (usec_t) u;
3756 else if (streq(name, "AssertTimestamp"))
3757 i->assert_timestamp = (usec_t) u;
3758 else if (streq(name, "MemoryCurrent"))
3759 i->memory_current = u;
3760 else if (streq(name, "MemoryLimit"))
3761 i->memory_limit = u;
3766 case SD_BUS_TYPE_ARRAY:
3768 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3769 _cleanup_free_ ExecStatusInfo *info = NULL;
3771 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3773 return bus_log_parse_error(r);
3775 info = new0(ExecStatusInfo, 1);
3779 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3781 info->name = strdup(name);
3785 LIST_PREPEND(exec, i->exec, info);
3787 info = new0(ExecStatusInfo, 1);
3793 return bus_log_parse_error(r);
3795 r = sd_bus_message_exit_container(m);
3797 return bus_log_parse_error(r);
3801 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3802 const char *type, *path;
3804 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3806 return bus_log_parse_error(r);
3808 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3810 r = strv_extend(&i->listen, type);
3814 r = strv_extend(&i->listen, path);
3819 return bus_log_parse_error(r);
3821 r = sd_bus_message_exit_container(m);
3823 return bus_log_parse_error(r);
3827 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3829 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3831 return bus_log_parse_error(r);
3833 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3835 r = sd_bus_message_read_strv(m, &i->documentation);
3837 return bus_log_parse_error(r);
3839 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3840 const char *cond, *param;
3841 int trigger, negate;
3844 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3846 return bus_log_parse_error(r);
3848 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3849 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3850 if (state < 0 && (!trigger || !i->failed_condition)) {
3851 i->failed_condition = cond;
3852 i->failed_condition_trigger = trigger;
3853 i->failed_condition_negate = negate;
3854 i->failed_condition_parameter = param;
3858 return bus_log_parse_error(r);
3860 r = sd_bus_message_exit_container(m);
3862 return bus_log_parse_error(r);
3864 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Asserts")) {
3865 const char *cond, *param;
3866 int trigger, negate;
3869 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3871 return bus_log_parse_error(r);
3873 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3874 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3875 if (state < 0 && (!trigger || !i->failed_assert)) {
3876 i->failed_assert = cond;
3877 i->failed_assert_trigger = trigger;
3878 i->failed_assert_negate = negate;
3879 i->failed_assert_parameter = param;
3883 return bus_log_parse_error(r);
3885 r = sd_bus_message_exit_container(m);
3887 return bus_log_parse_error(r);
3894 case SD_BUS_TYPE_STRUCT_BEGIN:
3896 if (streq(name, "LoadError")) {
3897 const char *n, *message;
3899 r = sd_bus_message_read(m, "(ss)", &n, &message);
3901 return bus_log_parse_error(r);
3903 if (!isempty(message))
3904 i->load_error = message;
3917 r = sd_bus_message_skip(m, contents);
3919 return bus_log_parse_error(r);
3924 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3930 /* This is a low-level property printer, see
3931 * print_status_info() for the nicer output */
3933 if (arg_properties && !strv_find(arg_properties, name)) {
3934 /* skip what we didn't read */
3935 r = sd_bus_message_skip(m, contents);
3939 switch (contents[0]) {
3941 case SD_BUS_TYPE_STRUCT_BEGIN:
3943 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3946 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3948 return bus_log_parse_error(r);
3951 printf("%s=%"PRIu32"\n", name, u);
3953 printf("%s=\n", name);
3957 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3960 r = sd_bus_message_read(m, "(so)", &s, NULL);
3962 return bus_log_parse_error(r);
3964 if (arg_all || !isempty(s))
3965 printf("%s=%s\n", name, s);
3969 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3970 const char *a = NULL, *b = NULL;
3972 r = sd_bus_message_read(m, "(ss)", &a, &b);
3974 return bus_log_parse_error(r);
3976 if (arg_all || !isempty(a) || !isempty(b))
3977 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3980 } else if (streq_ptr(name, "SystemCallFilter")) {
3981 _cleanup_strv_free_ char **l = NULL;
3984 r = sd_bus_message_enter_container(m, 'r', "bas");
3986 return bus_log_parse_error(r);
3988 r = sd_bus_message_read(m, "b", &whitelist);
3990 return bus_log_parse_error(r);
3992 r = sd_bus_message_read_strv(m, &l);
3994 return bus_log_parse_error(r);
3996 r = sd_bus_message_exit_container(m);
3998 return bus_log_parse_error(r);
4000 if (arg_all || whitelist || !strv_isempty(l)) {
4004 fputs(name, stdout);
4010 STRV_FOREACH(i, l) {
4018 fputc('\n', stdout);
4026 case SD_BUS_TYPE_ARRAY:
4028 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
4032 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
4034 return bus_log_parse_error(r);
4036 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
4037 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
4040 return bus_log_parse_error(r);
4042 r = sd_bus_message_exit_container(m);
4044 return bus_log_parse_error(r);
4048 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
4049 const char *type, *path;
4051 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4053 return bus_log_parse_error(r);
4055 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4056 printf("%s=%s\n", type, path);
4058 return bus_log_parse_error(r);
4060 r = sd_bus_message_exit_container(m);
4062 return bus_log_parse_error(r);
4066 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
4067 const char *type, *path;
4069 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4071 return bus_log_parse_error(r);
4073 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4074 printf("Listen%s=%s\n", type, path);
4076 return bus_log_parse_error(r);
4078 r = sd_bus_message_exit_container(m);
4080 return bus_log_parse_error(r);
4084 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
4086 uint64_t value, next_elapse;
4088 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
4090 return bus_log_parse_error(r);
4092 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
4093 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
4095 printf("%s={ value=%s ; next_elapse=%s }\n",
4097 format_timespan(timespan1, sizeof(timespan1), value, 0),
4098 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
4101 return bus_log_parse_error(r);
4103 r = sd_bus_message_exit_container(m);
4105 return bus_log_parse_error(r);
4109 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
4110 ExecStatusInfo info = {};
4112 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
4114 return bus_log_parse_error(r);
4116 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
4117 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
4118 _cleanup_free_ char *tt;
4120 tt = strv_join(info.argv, " ");
4122 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",
4126 yes_no(info.ignore),
4127 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
4128 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
4130 sigchld_code_to_string(info.code),
4132 info.code == CLD_EXITED ? "" : "/",
4133 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
4136 strv_free(info.argv);
4140 r = sd_bus_message_exit_container(m);
4142 return bus_log_parse_error(r);
4146 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
4147 const char *path, *rwm;
4149 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4151 return bus_log_parse_error(r);
4153 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
4154 printf("%s=%s %s\n", name, strna(path), strna(rwm));
4156 return bus_log_parse_error(r);
4158 r = sd_bus_message_exit_container(m);
4160 return bus_log_parse_error(r);
4164 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
4168 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4170 return bus_log_parse_error(r);
4172 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4173 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
4175 return bus_log_parse_error(r);
4177 r = sd_bus_message_exit_container(m);
4179 return bus_log_parse_error(r);
4183 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
4187 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4189 return bus_log_parse_error(r);
4191 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4192 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
4194 return bus_log_parse_error(r);
4196 r = sd_bus_message_exit_container(m);
4198 return bus_log_parse_error(r);
4206 r = bus_print_property(name, m, arg_all);
4208 return bus_log_parse_error(r);
4211 r = sd_bus_message_skip(m, contents);
4213 return bus_log_parse_error(r);
4216 printf("%s=[unprintable]\n", name);
4222 static int show_one(
4226 bool show_properties,
4230 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4231 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4232 UnitStatusInfo info = {
4233 .memory_current = (uint64_t) -1,
4234 .memory_limit = (uint64_t) -1,
4242 log_debug("Showing one %s", path);
4244 r = sd_bus_call_method(
4246 "org.freedesktop.systemd1",
4248 "org.freedesktop.DBus.Properties",
4254 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4258 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4260 return bus_log_parse_error(r);
4267 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4268 const char *name, *contents;
4270 r = sd_bus_message_read(reply, "s", &name);
4272 return bus_log_parse_error(r);
4274 r = sd_bus_message_peek_type(reply, NULL, &contents);
4276 return bus_log_parse_error(r);
4278 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4280 return bus_log_parse_error(r);
4282 if (show_properties)
4283 r = print_property(name, reply, contents);
4285 r = status_property(name, reply, &info, contents);
4289 r = sd_bus_message_exit_container(reply);
4291 return bus_log_parse_error(r);
4293 r = sd_bus_message_exit_container(reply);
4295 return bus_log_parse_error(r);
4298 return bus_log_parse_error(r);
4300 r = sd_bus_message_exit_container(reply);
4302 return bus_log_parse_error(r);
4306 if (!show_properties) {
4307 if (streq(verb, "help"))
4308 show_unit_help(&info);
4310 print_status_info(&info, ellipsized);
4313 strv_free(info.documentation);
4314 strv_free(info.dropin_paths);
4315 strv_free(info.listen);
4317 if (!streq_ptr(info.active_state, "active") &&
4318 !streq_ptr(info.active_state, "reloading") &&
4319 streq(verb, "status")) {
4320 /* According to LSB: "program not running" */
4321 /* 0: program is running or service is OK
4322 * 1: program is dead and /run PID file exists
4323 * 2: program is dead and /run/lock lock file exists
4324 * 3: program is not running
4325 * 4: program or service status is unknown
4327 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4333 while ((p = info.exec)) {
4334 LIST_REMOVE(exec, info.exec, p);
4335 exec_status_info_free(p);
4341 static int get_unit_dbus_path_by_pid(
4346 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4347 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4351 r = sd_bus_call_method(
4353 "org.freedesktop.systemd1",
4354 "/org/freedesktop/systemd1",
4355 "org.freedesktop.systemd1.Manager",
4361 log_error("Failed to get unit for PID %"PRIu32": %s", pid, bus_error_message(&error, r));
4365 r = sd_bus_message_read(reply, "o", &u);
4367 return bus_log_parse_error(r);
4377 static int show_all(
4380 bool show_properties,
4384 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4385 _cleanup_free_ UnitInfo *unit_infos = NULL;
4390 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4394 pager_open_if_enabled();
4398 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4400 for (u = unit_infos; u < unit_infos + c; u++) {
4401 _cleanup_free_ char *p = NULL;
4403 p = unit_dbus_path_from_name(u->id);
4407 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4410 else if (r > 0 && ret == 0)
4417 static int show_system_status(sd_bus *bus) {
4418 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4419 _cleanup_free_ char *hn = NULL;
4420 struct machine_info mi = {};
4421 const char *on, *off;
4424 hn = gethostname_malloc();
4428 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4430 return log_error_errno(r, "Failed to read server status: %m");
4432 if (streq_ptr(mi.state, "degraded")) {
4433 on = ansi_highlight_red();
4434 off = ansi_highlight_off();
4435 } else if (!streq_ptr(mi.state, "running")) {
4436 on = ansi_highlight_yellow();
4437 off = ansi_highlight_off();
4441 printf("%s%s%s %s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4443 printf(" State: %s%s%s\n",
4444 on, strna(mi.state), off);
4446 printf(" Jobs: %u queued\n", mi.n_jobs);
4447 printf(" Failed: %u units\n", mi.n_failed_units);
4449 printf(" Since: %s; %s\n",
4450 format_timestamp(since2, sizeof(since2), mi.timestamp),
4451 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4453 printf(" CGroup: %s\n", mi.control_group ?: "/");
4454 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_MACHINE) {
4455 static const char prefix[] = " ";
4459 if (c > sizeof(prefix) - 1)
4460 c -= sizeof(prefix) - 1;
4464 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, get_output_flags());
4468 free(mi.control_group);
4473 static int show(sd_bus *bus, char **args) {
4474 bool show_properties, show_status, new_line = false;
4475 bool ellipsized = false;
4481 show_properties = streq(args[0], "show");
4482 show_status = streq(args[0], "status");
4484 if (show_properties)
4485 pager_open_if_enabled();
4487 /* If no argument is specified inspect the manager itself */
4489 if (show_properties && strv_length(args) <= 1)
4490 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4492 if (show_status && strv_length(args) <= 1) {
4494 pager_open_if_enabled();
4495 show_system_status(bus);
4499 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4501 _cleanup_free_ char **patterns = NULL;
4504 STRV_FOREACH(name, args + 1) {
4505 _cleanup_free_ char *unit = NULL;
4508 if (safe_atou32(*name, &id) < 0) {
4509 if (strv_push(&patterns, *name) < 0)
4513 } else if (show_properties) {
4514 /* Interpret as job id */
4515 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4519 /* Interpret as PID */
4520 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4527 r = show_one(args[0], bus, unit, show_properties,
4528 &new_line, &ellipsized);
4531 else if (r > 0 && ret == 0)
4535 if (!strv_isempty(patterns)) {
4536 _cleanup_strv_free_ char **names = NULL;
4538 r = expand_names(bus, patterns, NULL, &names);
4540 log_error_errno(r, "Failed to expand names: %m");
4542 STRV_FOREACH(name, names) {
4543 _cleanup_free_ char *unit;
4545 unit = unit_dbus_path_from_name(*name);
4549 r = show_one(args[0], bus, unit, show_properties,
4550 &new_line, &ellipsized);
4553 else if (r > 0 && ret == 0)
4559 if (ellipsized && !arg_quiet)
4560 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4565 static int init_home_and_lookup_paths(char **user_home, char **user_runtime, LookupPaths *lp) {
4569 assert(user_runtime);
4572 if (arg_scope == UNIT_FILE_USER) {
4573 r = user_config_home(user_home);
4575 return log_error_errno(r, "Failed to query XDG_CONFIG_HOME: %m");
4577 return log_error_errno(ENOTDIR, "Cannot find units: $XDG_CONFIG_HOME and $HOME are not set.");
4579 r = user_runtime_dir(user_runtime);
4581 return log_error_errno(r, "Failed to query XDG_CONFIG_HOME: %m");
4583 return log_error_errno(ENOTDIR, "Cannot find units: $XDG_RUNTIME_DIR is not set.");
4586 r = lookup_paths_init_from_scope(lp, arg_scope, arg_root);
4588 return log_error_errno(r, "Failed to query unit lookup paths: %m");
4593 static int cat(sd_bus *bus, char **args) {
4594 _cleanup_free_ char *user_home = NULL;
4595 _cleanup_free_ char *user_runtime = NULL;
4596 _cleanup_lookup_paths_free_ LookupPaths lp = {};
4597 _cleanup_strv_free_ char **names = NULL;
4599 bool first = true, avoid_bus_cache;
4604 if (arg_transport != BUS_TRANSPORT_LOCAL) {
4605 log_error("Cannot remotely cat units");
4609 r = init_home_and_lookup_paths(&user_home, &user_runtime, &lp);
4613 r = expand_names(bus, args + 1, NULL, &names);
4615 return log_error_errno(r, "Failed to expand names: %m");
4617 avoid_bus_cache = !bus || avoid_bus();
4619 pager_open_if_enabled();
4621 STRV_FOREACH(name, names) {
4622 _cleanup_free_ char *fragment_path = NULL;
4623 _cleanup_strv_free_ char **dropin_paths = NULL;
4626 r = unit_find_paths(bus, *name, avoid_bus_cache, &lp, &fragment_path, &dropin_paths);
4637 if (fragment_path) {
4638 printf("%s# %s%s\n",
4639 ansi_highlight_blue(),
4641 ansi_highlight_off());
4644 r = copy_file_fd(fragment_path, STDOUT_FILENO, false);
4646 log_warning_errno(r, "Failed to cat %s: %m", fragment_path);
4651 STRV_FOREACH(path, dropin_paths) {
4652 printf("%s%s# %s%s\n",
4653 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4654 ansi_highlight_blue(),
4656 ansi_highlight_off());
4659 r = copy_file_fd(*path, STDOUT_FILENO, false);
4661 log_warning_errno(r, "Failed to cat %s: %m", *path);
4667 return r < 0 ? r : 0;
4670 static int set_property(sd_bus *bus, char **args) {
4671 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4672 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4673 _cleanup_free_ char *n = NULL;
4677 polkit_agent_open_if_enabled();
4679 r = sd_bus_message_new_method_call(
4682 "org.freedesktop.systemd1",
4683 "/org/freedesktop/systemd1",
4684 "org.freedesktop.systemd1.Manager",
4685 "SetUnitProperties");
4687 return bus_log_create_error(r);
4689 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4691 return bus_log_create_error(r);
4693 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4697 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4699 return bus_log_create_error(r);
4701 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4703 return bus_log_create_error(r);
4705 STRV_FOREACH(i, args + 2) {
4706 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4708 return bus_log_create_error(r);
4710 r = bus_append_unit_property_assignment(m, *i);
4714 r = sd_bus_message_close_container(m);
4716 return bus_log_create_error(r);
4719 r = sd_bus_message_close_container(m);
4721 return bus_log_create_error(r);
4723 r = sd_bus_call(bus, m, 0, &error, NULL);
4725 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4732 static int snapshot(sd_bus *bus, char **args) {
4733 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4734 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
4735 _cleanup_free_ char *n = NULL, *id = NULL;
4739 polkit_agent_open_if_enabled();
4741 if (strv_length(args) > 1)
4742 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4748 r = sd_bus_message_new_method_call(
4751 "org.freedesktop.systemd1",
4752 "/org/freedesktop/systemd1",
4753 "org.freedesktop.systemd1.Manager",
4756 return bus_log_create_error(r);
4758 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4760 return bus_log_create_error(r);
4762 r = sd_bus_message_append(m, "sb", n, false);
4764 return bus_log_create_error(r);
4766 r = sd_bus_call(bus, m, 0, &error, &reply);
4768 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4772 r = sd_bus_message_read(reply, "o", &path);
4774 return bus_log_parse_error(r);
4776 r = sd_bus_get_property_string(
4778 "org.freedesktop.systemd1",
4780 "org.freedesktop.systemd1.Unit",
4785 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4795 static int delete_snapshot(sd_bus *bus, char **args) {
4796 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4797 _cleanup_strv_free_ char **names = NULL;
4803 polkit_agent_open_if_enabled();
4805 r = expand_names(bus, args + 1, ".snapshot", &names);
4807 log_error_errno(r, "Failed to expand names: %m");
4809 STRV_FOREACH(name, names) {
4810 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4813 q = sd_bus_message_new_method_call(
4816 "org.freedesktop.systemd1",
4817 "/org/freedesktop/systemd1",
4818 "org.freedesktop.systemd1.Manager",
4821 return bus_log_create_error(q);
4823 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4825 return bus_log_create_error(q);
4827 q = sd_bus_message_append(m, "s", *name);
4829 return bus_log_create_error(q);
4831 q = sd_bus_call(bus, m, 0, &error, NULL);
4833 log_error("Failed to remove snapshot %s: %s", *name, bus_error_message(&error, q));
4842 static int daemon_reload(sd_bus *bus, char **args) {
4843 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4844 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4848 polkit_agent_open_if_enabled();
4850 if (arg_action == ACTION_RELOAD)
4852 else if (arg_action == ACTION_REEXEC)
4853 method = "Reexecute";
4855 assert(arg_action == ACTION_SYSTEMCTL);
4858 streq(args[0], "clear-jobs") ||
4859 streq(args[0], "cancel") ? "ClearJobs" :
4860 streq(args[0], "daemon-reexec") ? "Reexecute" :
4861 streq(args[0], "reset-failed") ? "ResetFailed" :
4862 streq(args[0], "halt") ? "Halt" :
4863 streq(args[0], "poweroff") ? "PowerOff" :
4864 streq(args[0], "reboot") ? "Reboot" :
4865 streq(args[0], "kexec") ? "KExec" :
4866 streq(args[0], "exit") ? "Exit" :
4867 /* "daemon-reload" */ "Reload";
4870 r = sd_bus_message_new_method_call(
4873 "org.freedesktop.systemd1",
4874 "/org/freedesktop/systemd1",
4875 "org.freedesktop.systemd1.Manager",
4878 return bus_log_create_error(r);
4880 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4882 return bus_log_create_error(r);
4884 r = sd_bus_call(bus, m, 0, &error, NULL);
4885 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4886 /* There's always a fallback possible for
4887 * legacy actions. */
4889 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4890 /* On reexecution, we expect a disconnect, not a
4894 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4896 return r < 0 ? r : 0;
4899 static int reset_failed(sd_bus *bus, char **args) {
4900 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4901 _cleanup_strv_free_ char **names = NULL;
4905 if (strv_length(args) <= 1)
4906 return daemon_reload(bus, args);
4908 polkit_agent_open_if_enabled();
4910 r = expand_names(bus, args + 1, NULL, &names);
4912 log_error_errno(r, "Failed to expand names: %m");
4914 STRV_FOREACH(name, names) {
4915 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4917 q = sd_bus_message_new_method_call(
4920 "org.freedesktop.systemd1",
4921 "/org/freedesktop/systemd1",
4922 "org.freedesktop.systemd1.Manager",
4925 return bus_log_create_error(q);
4927 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4929 return bus_log_create_error(q);
4931 q = sd_bus_message_append(m, "s", *name);
4933 return bus_log_create_error(q);
4935 q = sd_bus_call(bus, m, 0, &error, NULL);
4937 log_error("Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q));
4946 static int show_environment(sd_bus *bus, char **args) {
4947 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4948 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4952 pager_open_if_enabled();
4954 r = sd_bus_get_property(
4956 "org.freedesktop.systemd1",
4957 "/org/freedesktop/systemd1",
4958 "org.freedesktop.systemd1.Manager",
4964 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4968 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4970 return bus_log_parse_error(r);
4972 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4975 return bus_log_parse_error(r);
4977 r = sd_bus_message_exit_container(reply);
4979 return bus_log_parse_error(r);
4984 static int switch_root(sd_bus *bus, char **args) {
4985 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4986 _cleanup_free_ char *cmdline_init = NULL;
4987 const char *root, *init;
4991 l = strv_length(args);
4992 if (l < 2 || l > 3) {
4993 log_error("Wrong number of arguments.");
5002 r = parse_env_file("/proc/cmdline", WHITESPACE,
5003 "init", &cmdline_init,
5006 log_debug_errno(r, "Failed to parse /proc/cmdline: %m");
5008 init = cmdline_init;
5015 const char *root_systemd_path = NULL, *root_init_path = NULL;
5017 root_systemd_path = strjoina(root, "/" SYSTEMD_BINARY_PATH);
5018 root_init_path = strjoina(root, "/", init);
5020 /* If the passed init is actually the same as the
5021 * systemd binary, then let's suppress it. */
5022 if (files_same(root_init_path, root_systemd_path) > 0)
5026 log_debug("Switching root - root: %s; init: %s", root, strna(init));
5028 r = sd_bus_call_method(
5030 "org.freedesktop.systemd1",
5031 "/org/freedesktop/systemd1",
5032 "org.freedesktop.systemd1.Manager",
5038 log_error("Failed to switch root: %s", bus_error_message(&error, r));
5045 static int set_environment(sd_bus *bus, char **args) {
5046 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5047 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
5054 method = streq(args[0], "set-environment")
5056 : "UnsetEnvironment";
5058 r = sd_bus_message_new_method_call(
5061 "org.freedesktop.systemd1",
5062 "/org/freedesktop/systemd1",
5063 "org.freedesktop.systemd1.Manager",
5066 return bus_log_create_error(r);
5068 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5070 return bus_log_create_error(r);
5072 r = sd_bus_message_append_strv(m, args + 1);
5074 return bus_log_create_error(r);
5076 r = sd_bus_call(bus, m, 0, &error, NULL);
5078 log_error("Failed to set environment: %s", bus_error_message(&error, r));
5085 static int import_environment(sd_bus *bus, char **args) {
5086 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5087 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
5093 r = sd_bus_message_new_method_call(
5096 "org.freedesktop.systemd1",
5097 "/org/freedesktop/systemd1",
5098 "org.freedesktop.systemd1.Manager",
5101 return bus_log_create_error(r);
5103 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5105 return bus_log_create_error(r);
5107 if (strv_isempty(args + 1))
5108 r = sd_bus_message_append_strv(m, environ);
5112 r = sd_bus_message_open_container(m, 'a', "s");
5114 return bus_log_create_error(r);
5116 STRV_FOREACH(a, args + 1) {
5118 if (!env_name_is_valid(*a)) {
5119 log_error("Not a valid environment variable name: %s", *a);
5123 STRV_FOREACH(b, environ) {
5126 eq = startswith(*b, *a);
5127 if (eq && *eq == '=') {
5129 r = sd_bus_message_append(m, "s", *b);
5131 return bus_log_create_error(r);
5138 r = sd_bus_message_close_container(m);
5141 return bus_log_create_error(r);
5143 r = sd_bus_call(bus, m, 0, &error, NULL);
5145 log_error("Failed to import environment: %s", bus_error_message(&error, r));
5152 static int enable_sysv_units(const char *verb, char **args) {
5155 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
5157 _cleanup_lookup_paths_free_ LookupPaths paths = {};
5159 if (arg_scope != UNIT_FILE_SYSTEM)
5162 if (!streq(verb, "enable") &&
5163 !streq(verb, "disable") &&
5164 !streq(verb, "is-enabled"))
5167 /* Processes all SysV units, and reshuffles the array so that
5168 * afterwards only the native units remain */
5170 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, arg_root, NULL, NULL, NULL);
5177 _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL;
5178 bool found_native = false, found_sysv;
5180 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
5188 if (!endswith(name, ".service"))
5191 if (path_is_absolute(name))
5194 STRV_FOREACH(k, paths.unit_path) {
5195 _cleanup_free_ char *path = NULL;
5197 path = path_join(arg_root, *k, name);
5201 found_native = access(path, F_OK) >= 0;
5209 p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name);
5213 p[strlen(p) - strlen(".service")] = 0;
5214 found_sysv = access(p, F_OK) >= 0;
5218 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
5220 if (!isempty(arg_root))
5221 argv[c++] = q = strappend("--root=", arg_root);
5223 argv[c++] = basename(p);
5225 streq(verb, "enable") ? "on" :
5226 streq(verb, "disable") ? "off" : "--level=5";
5229 l = strv_join((char**)argv, " ");
5233 log_info("Executing %s", l);
5237 return log_error_errno(errno, "Failed to fork: %m");
5238 else if (pid == 0) {
5241 execv(argv[0], (char**) argv);
5242 _exit(EXIT_FAILURE);
5245 j = wait_for_terminate(pid, &status);
5247 log_error_errno(r, "Failed to wait for child: %m");
5251 if (status.si_code == CLD_EXITED) {
5252 if (streq(verb, "is-enabled")) {
5253 if (status.si_status == 0) {
5262 } else if (status.si_status != 0)
5267 /* Remove this entry, so that we don't try enabling it as native unit */
5270 assert(args[f] == name);
5271 strv_remove(args, name);
5278 static int mangle_names(char **original_names, char ***mangled_names) {
5279 char **i, **l, **name;
5281 l = new(char*, strv_length(original_names) + 1);
5286 STRV_FOREACH(name, original_names) {
5288 /* When enabling units qualified path names are OK,
5289 * too, hence allow them explicitly. */
5294 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5310 static int enable_unit(sd_bus *bus, char **args) {
5311 _cleanup_strv_free_ char **names = NULL;
5312 const char *verb = args[0];
5313 UnitFileChange *changes = NULL;
5314 unsigned n_changes = 0;
5315 int carries_install_info = -1;
5321 r = mangle_names(args+1, &names);
5325 r = enable_sysv_units(verb, names);
5329 /* If the operation was fully executed by the SysV compat,
5330 * let's finish early */
5331 if (strv_isempty(names))
5334 if (!bus || avoid_bus()) {
5335 if (streq(verb, "enable")) {
5336 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5337 carries_install_info = r;
5338 } else if (streq(verb, "disable"))
5339 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5340 else if (streq(verb, "reenable")) {
5341 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5342 carries_install_info = r;
5343 } else if (streq(verb, "link"))
5344 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5345 else if (streq(verb, "preset")) {
5346 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_preset_mode, arg_force, &changes, &n_changes);
5347 carries_install_info = r;
5348 } else if (streq(verb, "mask"))
5349 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5350 else if (streq(verb, "unmask"))
5351 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5353 assert_not_reached("Unknown verb");
5356 log_error_errno(r, "Operation failed: %m");
5361 dump_unit_file_changes(changes, n_changes);
5365 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5366 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5367 int expect_carries_install_info = false;
5368 bool send_force = true, send_preset_mode = false;
5371 polkit_agent_open_if_enabled();
5373 if (streq(verb, "enable")) {
5374 method = "EnableUnitFiles";
5375 expect_carries_install_info = true;
5376 } else if (streq(verb, "disable")) {
5377 method = "DisableUnitFiles";
5379 } else if (streq(verb, "reenable")) {
5380 method = "ReenableUnitFiles";
5381 expect_carries_install_info = true;
5382 } else if (streq(verb, "link"))
5383 method = "LinkUnitFiles";
5384 else if (streq(verb, "preset")) {
5386 if (arg_preset_mode != UNIT_FILE_PRESET_FULL) {
5387 method = "PresetUnitFilesWithMode";
5388 send_preset_mode = true;
5390 method = "PresetUnitFiles";
5392 expect_carries_install_info = true;
5393 } else if (streq(verb, "mask"))
5394 method = "MaskUnitFiles";
5395 else if (streq(verb, "unmask")) {
5396 method = "UnmaskUnitFiles";
5399 assert_not_reached("Unknown verb");
5401 r = sd_bus_message_new_method_call(
5404 "org.freedesktop.systemd1",
5405 "/org/freedesktop/systemd1",
5406 "org.freedesktop.systemd1.Manager",
5409 return bus_log_create_error(r);
5411 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5413 return bus_log_create_error(r);
5415 r = sd_bus_message_append_strv(m, names);
5417 return bus_log_create_error(r);
5419 if (send_preset_mode) {
5420 r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode));
5422 return bus_log_create_error(r);
5425 r = sd_bus_message_append(m, "b", arg_runtime);
5427 return bus_log_create_error(r);
5430 r = sd_bus_message_append(m, "b", arg_force);
5432 return bus_log_create_error(r);
5435 r = sd_bus_call(bus, m, 0, &error, &reply);
5437 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5441 if (expect_carries_install_info) {
5442 r = sd_bus_message_read(reply, "b", &carries_install_info);
5444 return bus_log_parse_error(r);
5447 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
5451 /* Try to reload if enabled */
5453 r = daemon_reload(bus, args);
5458 if (carries_install_info == 0)
5459 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5460 "using systemctl.\n"
5461 "Possible reasons for having this kind of units are:\n"
5462 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5463 " .wants/ or .requires/ directory.\n"
5464 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5465 " a requirement dependency on it.\n"
5466 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5467 " D-Bus, udev, scripted systemctl call, ...).\n");
5470 unit_file_changes_free(changes, n_changes);
5475 static int add_dependency(sd_bus *bus, char **args) {
5476 _cleanup_strv_free_ char **names = NULL;
5477 _cleanup_free_ char *target = NULL;
5478 const char *verb = args[0];
5485 target = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
5489 r = mangle_names(args+2, &names);
5493 if (streq(verb, "add-wants"))
5495 else if (streq(verb, "add-requires"))
5496 dep = UNIT_REQUIRES;
5498 assert_not_reached("Unknown verb");
5500 if (!bus || avoid_bus()) {
5501 UnitFileChange *changes = NULL;
5502 unsigned n_changes = 0;
5504 r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes);
5507 return log_error_errno(r, "Can't add dependency: %m");
5510 dump_unit_file_changes(changes, n_changes);
5512 unit_file_changes_free(changes, n_changes);
5515 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5516 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5518 polkit_agent_open_if_enabled();
5520 r = sd_bus_message_new_method_call(
5523 "org.freedesktop.systemd1",
5524 "/org/freedesktop/systemd1",
5525 "org.freedesktop.systemd1.Manager",
5526 "AddDependencyUnitFiles");
5528 return bus_log_create_error(r);
5530 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5532 return bus_log_create_error(r);
5534 r = sd_bus_message_append_strv(m, names);
5536 return bus_log_create_error(r);
5538 r = sd_bus_message_append(m, "ssbb", target, unit_dependency_to_string(dep), arg_runtime, arg_force);
5540 return bus_log_create_error(r);
5542 r = sd_bus_call(bus, m, 0, &error, &reply);
5544 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5548 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
5553 r = daemon_reload(bus, args);
5561 static int preset_all(sd_bus *bus, char **args) {
5562 UnitFileChange *changes = NULL;
5563 unsigned n_changes = 0;
5566 if (!bus || avoid_bus()) {
5568 r = unit_file_preset_all(arg_scope, arg_runtime, arg_root, arg_preset_mode, arg_force, &changes, &n_changes);
5570 log_error_errno(r, "Operation failed: %m");
5575 dump_unit_file_changes(changes, n_changes);
5580 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
5581 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5583 polkit_agent_open_if_enabled();
5585 r = sd_bus_message_new_method_call(
5588 "org.freedesktop.systemd1",
5589 "/org/freedesktop/systemd1",
5590 "org.freedesktop.systemd1.Manager",
5591 "PresetAllUnitFiles");
5593 return bus_log_create_error(r);
5595 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5597 return bus_log_create_error(r);
5599 r = sd_bus_message_append(
5602 unit_file_preset_mode_to_string(arg_preset_mode),
5606 return bus_log_create_error(r);
5608 r = sd_bus_call(bus, m, 0, &error, &reply);
5610 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5614 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
5619 r = daemon_reload(bus, args);
5625 unit_file_changes_free(changes, n_changes);
5630 static int unit_is_enabled(sd_bus *bus, char **args) {
5632 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5633 _cleanup_strv_free_ char **names = NULL;
5638 r = mangle_names(args+1, &names);
5642 r = enable_sysv_units(args[0], names);
5648 if (!bus || avoid_bus()) {
5650 STRV_FOREACH(name, names) {
5651 UnitFileState state;
5653 state = unit_file_get_state(arg_scope, arg_root, *name);
5655 return log_error_errno(state, "Failed to get unit file state for %s: %m", *name);
5657 if (state == UNIT_FILE_ENABLED ||
5658 state == UNIT_FILE_ENABLED_RUNTIME ||
5659 state == UNIT_FILE_STATIC ||
5660 state == UNIT_FILE_INDIRECT)
5664 puts(unit_file_state_to_string(state));
5668 STRV_FOREACH(name, names) {
5669 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5672 r = sd_bus_call_method(
5674 "org.freedesktop.systemd1",
5675 "/org/freedesktop/systemd1",
5676 "org.freedesktop.systemd1.Manager",
5682 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5686 r = sd_bus_message_read(reply, "s", &s);
5688 return bus_log_parse_error(r);
5690 if (STR_IN_SET(s, "enabled", "enabled-runtime", "static", "indirect"))
5701 static int is_system_running(sd_bus *bus, char **args) {
5702 _cleanup_free_ char *state = NULL;
5705 r = sd_bus_get_property_string(
5707 "org.freedesktop.systemd1",
5708 "/org/freedesktop/systemd1",
5709 "org.freedesktop.systemd1.Manager",
5722 return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE;
5725 static int create_edit_temp_file(const char *new_path, const char *original_path, char **ret_tmp_fn) {
5730 assert(original_path);
5733 r = tempfn_random(new_path, &t);
5735 return log_error_errno(r, "Failed to determine temporary filename for \"%s\": %m", new_path);
5737 r = mkdir_parents(new_path, 0755);
5739 log_error_errno(r, "Failed to create directories for \"%s\": %m", new_path);
5744 r = copy_file(original_path, t, 0, 0644, 0);
5748 log_error_errno(r, "Failed to create temporary file \"%s\": %m", t);
5753 log_error_errno(r, "Failed to copy \"%s\" to \"%s\": %m", original_path, t);
5763 static int get_file_to_edit(const char *name, const char *user_home, const char *user_runtime, char **ret_path) {
5764 _cleanup_free_ char *path = NULL, *path2 = NULL, *run = NULL;
5766 switch (arg_scope) {
5767 case UNIT_FILE_SYSTEM:
5768 path = path_join(arg_root, SYSTEM_CONFIG_UNIT_PATH, name);
5770 run = path_join(arg_root, "/run/systemd/system/", name);
5772 case UNIT_FILE_GLOBAL:
5773 path = path_join(arg_root, USER_CONFIG_UNIT_PATH, name);
5775 run = path_join(arg_root, "/run/systemd/user/", name);
5777 case UNIT_FILE_USER:
5779 assert(user_runtime);
5781 path = path_join(arg_root, user_home, name);
5783 path2 = path_join(arg_root, USER_CONFIG_UNIT_PATH, name);
5786 run = path_join(arg_root, user_runtime, name);
5790 assert_not_reached("Invalid scope");
5792 if (!path || (arg_runtime && !run))
5796 if (access(path, F_OK) >= 0)
5797 return log_error_errno(EEXIST, "Refusing to create \"%s\" because it would be overriden by \"%s\" anyway.",
5799 if (path2 && access(path2, F_OK) >= 0)
5800 return log_error_errno(EEXIST, "Refusing to create \"%s\" because it would be overriden by \"%s\" anyway.",
5813 static int unit_file_create_dropin(const char *unit_name, const char *user_home, const char *user_runtime, char **ret_new_path, char **ret_tmp_path) {
5814 char *tmp_new_path, *ending;
5819 assert(ret_new_path);
5820 assert(ret_tmp_path);
5822 ending = strjoina(unit_name, ".d/override.conf");
5823 r = get_file_to_edit(ending, user_home, user_runtime, &tmp_new_path);
5827 r = create_edit_temp_file(tmp_new_path, tmp_new_path, &tmp_tmp_path);
5833 *ret_new_path = tmp_new_path;
5834 *ret_tmp_path = tmp_tmp_path;
5839 static int unit_file_create_copy(const char *unit_name,
5840 const char *fragment_path,
5841 const char *user_home,
5842 const char *user_runtime,
5843 char **ret_new_path,
5844 char **ret_tmp_path) {
5849 assert(fragment_path);
5851 assert(ret_new_path);
5852 assert(ret_tmp_path);
5854 r = get_file_to_edit(unit_name, user_home, user_runtime, &tmp_new_path);
5858 if (!path_equal(fragment_path, tmp_new_path) && access(tmp_new_path, F_OK) == 0) {
5861 r = ask_char(&response, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path, fragment_path);
5866 if (response != 'y') {
5867 log_warning("%s ignored", unit_name);
5873 r = create_edit_temp_file(tmp_new_path, fragment_path, &tmp_tmp_path);
5875 log_error_errno(r, "Failed to create temporary file for \"%s\": %m", tmp_new_path);
5880 *ret_new_path = tmp_new_path;
5881 *ret_tmp_path = tmp_tmp_path;
5886 static int run_editor(char **paths) {
5894 log_error_errno(errno, "Failed to fork: %m");
5900 char **backup_editors = STRV_MAKE("nano", "vim", "vi");
5902 char **tmp_path, **original_path, **p;
5906 argc = strv_length(paths)/2 + 1;
5907 args = newa(const char*, argc + 1);
5910 STRV_FOREACH_PAIR(original_path, tmp_path, paths) {
5911 args[i] = *tmp_path;
5916 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
5917 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
5918 * we try to execute well known editors
5920 editor = getenv("SYSTEMD_EDITOR");
5922 editor = getenv("EDITOR");
5924 editor = getenv("VISUAL");
5926 if (!isempty(editor)) {
5928 execvp(editor, (char* const*) args);
5931 STRV_FOREACH(p, backup_editors) {
5933 execvp(*p, (char* const*) args);
5934 /* We do not fail if the editor doesn't exist
5935 * because we want to try each one of them before
5938 if (errno != ENOENT) {
5939 log_error("Failed to execute %s: %m", editor);
5940 _exit(EXIT_FAILURE);
5944 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR or $EDITOR or $VISUAL.");
5945 _exit(EXIT_FAILURE);
5948 r = wait_for_terminate_and_warn("editor", pid, true);
5950 return log_error_errno(r, "Failed to wait for child: %m");
5955 static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
5956 _cleanup_free_ char *user_home = NULL;
5957 _cleanup_free_ char *user_runtime = NULL;
5958 _cleanup_lookup_paths_free_ LookupPaths lp = {};
5959 bool avoid_bus_cache;
5966 r = init_home_and_lookup_paths(&user_home, &user_runtime, &lp);
5970 avoid_bus_cache = !bus || avoid_bus();
5972 STRV_FOREACH(name, names) {
5973 _cleanup_free_ char *path = NULL;
5974 char *new_path, *tmp_path;
5976 r = unit_find_paths(bus, *name, avoid_bus_cache, &lp, &path, NULL);
5982 // FIXME: support units with path==NULL (no FragmentPath)
5983 log_error("No fragment exists for %s.", *name);
5988 r = unit_file_create_copy(*name, path, user_home, user_runtime, &new_path, &tmp_path);
5990 r = unit_file_create_dropin(*name, user_home, user_runtime, &new_path, &tmp_path);
5994 r = strv_push_pair(paths, new_path, tmp_path);
6002 static int edit(sd_bus *bus, char **args) {
6003 _cleanup_strv_free_ char **names = NULL;
6004 _cleanup_strv_free_ char **paths = NULL;
6005 char **original, **tmp;
6011 log_error("Cannot edit units if not on a tty");
6015 if (arg_transport != BUS_TRANSPORT_LOCAL) {
6016 log_error("Cannot remotely edit units");
6020 r = expand_names(bus, args + 1, NULL, &names);
6022 return log_error_errno(r, "Failed to expand names: %m");
6024 r = find_paths_to_edit(bus, names, &paths);
6028 if (strv_isempty(paths))
6031 r = run_editor(paths);
6035 STRV_FOREACH_PAIR(original, tmp, paths) {
6036 /* If the temporary file is empty we ignore it.
6037 * It's useful if the user wants to cancel its modification
6039 if (null_or_empty_path(*tmp)) {
6040 log_warning("Editing \"%s\" canceled: temporary file is empty", *original);
6043 r = rename(*tmp, *original);
6045 r = log_error_errno(errno, "Failed to rename \"%s\" to \"%s\": %m", *tmp, *original);
6050 if (!arg_no_reload && bus && !avoid_bus())
6051 r = daemon_reload(bus, args);
6054 STRV_FOREACH_PAIR(original, tmp, paths)
6055 unlink_noerrno(*tmp);
6060 static void systemctl_help(void) {
6062 pager_open_if_enabled();
6064 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
6065 "Query or send control commands to the systemd manager.\n\n"
6066 " -h --help Show this help\n"
6067 " --version Show package version\n"
6068 " --system Connect to system manager\n"
6069 " --user Connect to user service manager\n"
6070 " -H --host=[USER@]HOST\n"
6071 " Operate on remote host\n"
6072 " -M --machine=CONTAINER\n"
6073 " Operate on local container\n"
6074 " -t --type=TYPE List units of a particular type\n"
6075 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
6076 " -p --property=NAME Show only properties by this name\n"
6077 " -a --all Show all loaded units/properties, including dead/empty\n"
6078 " ones. To list all units installed on the system, use\n"
6079 " the 'list-unit-files' command instead.\n"
6080 " -l --full Don't ellipsize unit names on output\n"
6081 " -r --recursive Show unit list of host and local containers\n"
6082 " --reverse Show reverse dependencies with 'list-dependencies'\n"
6083 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
6084 " queueing a new job\n"
6085 " --show-types When showing sockets, explicitly show their type\n"
6086 " -i --ignore-inhibitors\n"
6087 " When shutting down or sleeping, ignore inhibitors\n"
6088 " --kill-who=WHO Who to send signal to\n"
6089 " -s --signal=SIGNAL Which signal to send\n"
6090 " -q --quiet Suppress output\n"
6091 " --no-block Do not wait until operation finished\n"
6092 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6093 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
6094 " --no-legend Do not print a legend (column headers and hints)\n"
6095 " --no-pager Do not pipe output into a pager\n"
6096 " --no-ask-password\n"
6097 " Do not ask for system passwords\n"
6098 " --global Enable/disable unit files globally\n"
6099 " --runtime Enable unit files only temporarily until next reboot\n"
6100 " -f --force When enabling unit files, override existing symlinks\n"
6101 " When shutting down, execute action immediately\n"
6102 " --preset-mode= Apply only enable, only disable, or all presets\n"
6103 " --root=PATH Enable unit files in the specified root directory\n"
6104 " -n --lines=INTEGER Number of journal entries to show\n"
6105 " -o --output=STRING Change journal output mode (short, short-iso,\n"
6106 " short-precise, short-monotonic, verbose,\n"
6107 " export, json, json-pretty, json-sse, cat)\n"
6108 " --plain Print unit dependencies as a list instead of a tree\n\n"
6110 " list-units [PATTERN...] List loaded units\n"
6111 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
6112 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
6113 " start NAME... Start (activate) one or more units\n"
6114 " stop NAME... Stop (deactivate) one or more units\n"
6115 " reload NAME... Reload one or more units\n"
6116 " restart NAME... Start or restart one or more units\n"
6117 " try-restart NAME... Restart one or more units if active\n"
6118 " reload-or-restart NAME... Reload one or more units if possible,\n"
6119 " otherwise start or restart\n"
6120 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
6121 " otherwise restart if active\n"
6122 " isolate NAME Start one unit and stop all others\n"
6123 " kill NAME... Send signal to processes of a unit\n"
6124 " is-active PATTERN... Check whether units are active\n"
6125 " is-failed PATTERN... Check whether units are failed\n"
6126 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
6127 " show [PATTERN...|JOB...] Show properties of one or more\n"
6128 " units/jobs or the manager\n"
6129 " cat PATTERN... Show files and drop-ins of one or more units\n"
6130 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
6131 " help PATTERN...|PID... Show manual for one or more units\n"
6132 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
6134 " list-dependencies [NAME] Recursively show units which are required\n"
6135 " or wanted by this unit or by which this\n"
6136 " unit is required or wanted\n\n"
6137 "Unit File Commands:\n"
6138 " list-unit-files [PATTERN...] List installed unit files\n"
6139 " enable NAME... Enable one or more unit files\n"
6140 " disable NAME... Disable one or more unit files\n"
6141 " reenable NAME... Reenable one or more unit files\n"
6142 " preset NAME... Enable/disable one or more unit files\n"
6143 " based on preset configuration\n"
6144 " preset-all Enable/disable all unit files based on\n"
6145 " preset configuration\n"
6146 " is-enabled NAME... Check whether unit files are enabled\n"
6147 " mask NAME... Mask one or more units\n"
6148 " unmask NAME... Unmask one or more units\n"
6149 " link PATH... Link one or more units files into\n"
6150 " the search path\n"
6151 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6152 " on specified one or more units\n"
6153 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6154 " on specified one or more units\n"
6155 " edit NAME... Edit one or more unit files\n"
6156 " get-default Get the name of the default target\n"
6157 " set-default NAME Set the default target\n\n"
6158 "Machine Commands:\n"
6159 " list-machines [PATTERN...] List local containers and host\n\n"
6161 " list-jobs [PATTERN...] List jobs\n"
6162 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
6163 "Snapshot Commands:\n"
6164 " snapshot [NAME] Create a snapshot\n"
6165 " delete NAME... Remove one or more snapshots\n\n"
6166 "Environment Commands:\n"
6167 " show-environment Dump environment\n"
6168 " set-environment NAME=VALUE... Set one or more environment variables\n"
6169 " unset-environment NAME... Unset one or more environment variables\n"
6170 " import-environment [NAME...] Import all or some environment variables\n\n"
6171 "Manager Lifecycle Commands:\n"
6172 " daemon-reload Reload systemd manager configuration\n"
6173 " daemon-reexec Reexecute systemd manager\n\n"
6174 "System Commands:\n"
6175 " is-system-running Check whether system is fully running\n"
6176 " default Enter system default mode\n"
6177 " rescue Enter system rescue mode\n"
6178 " emergency Enter system emergency mode\n"
6179 " halt Shut down and halt the system\n"
6180 " poweroff Shut down and power-off the system\n"
6181 " reboot [ARG] Shut down and reboot the system\n"
6182 " kexec Shut down and reboot the system with kexec\n"
6183 " exit Request user instance exit\n"
6184 " switch-root ROOT [INIT] Change to a different root file system\n"
6185 " suspend Suspend the system\n"
6186 " hibernate Hibernate the system\n"
6187 " hybrid-sleep Hibernate and suspend the system\n",
6188 program_invocation_short_name);
6191 static void halt_help(void) {
6192 printf("%s [OPTIONS...]%s\n\n"
6193 "%s the system.\n\n"
6194 " --help Show this help\n"
6195 " --halt Halt the machine\n"
6196 " -p --poweroff Switch off the machine\n"
6197 " --reboot Reboot the machine\n"
6198 " -f --force Force immediate halt/power-off/reboot\n"
6199 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
6200 " -d --no-wtmp Don't write wtmp record\n"
6201 " --no-wall Don't send wall message before halt/power-off/reboot\n",
6202 program_invocation_short_name,
6203 arg_action == ACTION_REBOOT ? " [ARG]" : "",
6204 arg_action == ACTION_REBOOT ? "Reboot" :
6205 arg_action == ACTION_POWEROFF ? "Power off" :
6209 static void shutdown_help(void) {
6210 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
6211 "Shut down the system.\n\n"
6212 " --help Show this help\n"
6213 " -H --halt Halt the machine\n"
6214 " -P --poweroff Power-off the machine\n"
6215 " -r --reboot Reboot the machine\n"
6216 " -h Equivalent to --poweroff, overridden by --halt\n"
6217 " -k Don't halt/power-off/reboot, just send warnings\n"
6218 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6219 " -c Cancel a pending shutdown\n",
6220 program_invocation_short_name);
6223 static void telinit_help(void) {
6224 printf("%s [OPTIONS...] {COMMAND}\n\n"
6225 "Send control commands to the init daemon.\n\n"
6226 " --help Show this help\n"
6227 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
6229 " 0 Power-off the machine\n"
6230 " 6 Reboot the machine\n"
6231 " 2, 3, 4, 5 Start runlevelX.target unit\n"
6232 " 1, s, S Enter rescue mode\n"
6233 " q, Q Reload init daemon configuration\n"
6234 " u, U Reexecute init daemon\n",
6235 program_invocation_short_name);
6238 static void runlevel_help(void) {
6239 printf("%s [OPTIONS...]\n\n"
6240 "Prints the previous and current runlevel of the init system.\n\n"
6241 " --help Show this help\n",
6242 program_invocation_short_name);
6245 static void help_types(void) {
6250 puts("Available unit types:");
6251 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
6252 t = unit_type_to_string(i);
6258 static int systemctl_parse_argv(int argc, char *argv[]) {
6267 ARG_IGNORE_DEPENDENCIES,
6279 ARG_NO_ASK_PASSWORD,
6289 static const struct option options[] = {
6290 { "help", no_argument, NULL, 'h' },
6291 { "version", no_argument, NULL, ARG_VERSION },
6292 { "type", required_argument, NULL, 't' },
6293 { "property", required_argument, NULL, 'p' },
6294 { "all", no_argument, NULL, 'a' },
6295 { "reverse", no_argument, NULL, ARG_REVERSE },
6296 { "after", no_argument, NULL, ARG_AFTER },
6297 { "before", no_argument, NULL, ARG_BEFORE },
6298 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
6299 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
6300 { "full", no_argument, NULL, 'l' },
6301 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
6302 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
6303 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
6304 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
6305 { "ignore-inhibitors", no_argument, NULL, 'i' },
6306 { "user", no_argument, NULL, ARG_USER },
6307 { "system", no_argument, NULL, ARG_SYSTEM },
6308 { "global", no_argument, NULL, ARG_GLOBAL },
6309 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
6310 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
6311 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
6312 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6313 { "quiet", no_argument, NULL, 'q' },
6314 { "root", required_argument, NULL, ARG_ROOT },
6315 { "force", no_argument, NULL, ARG_FORCE },
6316 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
6317 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
6318 { "signal", required_argument, NULL, 's' },
6319 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
6320 { "host", required_argument, NULL, 'H' },
6321 { "machine", required_argument, NULL, 'M' },
6322 { "runtime", no_argument, NULL, ARG_RUNTIME },
6323 { "lines", required_argument, NULL, 'n' },
6324 { "output", required_argument, NULL, 'o' },
6325 { "plain", no_argument, NULL, ARG_PLAIN },
6326 { "state", required_argument, NULL, ARG_STATE },
6327 { "recursive", no_argument, NULL, 'r' },
6328 { "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
6337 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
6346 puts(PACKAGE_STRING);
6347 puts(SYSTEMD_FEATURES);
6351 const char *word, *state;
6354 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6355 _cleanup_free_ char *type;
6357 type = strndup(word, size);
6361 if (streq(type, "help")) {
6366 if (unit_type_from_string(type) >= 0) {
6367 if (strv_push(&arg_types, type))
6373 /* It's much nicer to use --state= for
6374 * load states, but let's support this
6375 * in --types= too for compatibility
6376 * with old versions */
6377 if (unit_load_state_from_string(optarg) >= 0) {
6378 if (strv_push(&arg_states, type) < 0)
6384 log_error("Unknown unit type or load state '%s'.", type);
6385 log_info("Use -t help to see a list of allowed values.");
6393 /* Make sure that if the empty property list
6394 was specified, we won't show any properties. */
6395 if (isempty(optarg) && !arg_properties) {
6396 arg_properties = new0(char*, 1);
6397 if (!arg_properties)
6400 const char *word, *state;
6403 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6406 prop = strndup(word, size);
6410 if (strv_consume(&arg_properties, prop) < 0)
6415 /* If the user asked for a particular
6416 * property, show it to him, even if it is
6428 arg_dependency = DEPENDENCY_REVERSE;
6432 arg_dependency = DEPENDENCY_AFTER;
6436 arg_dependency = DEPENDENCY_BEFORE;
6439 case ARG_SHOW_TYPES:
6440 arg_show_types = true;
6444 arg_job_mode = optarg;
6448 arg_job_mode = "fail";
6451 case ARG_IRREVERSIBLE:
6452 arg_job_mode = "replace-irreversibly";
6455 case ARG_IGNORE_DEPENDENCIES:
6456 arg_job_mode = "ignore-dependencies";
6460 arg_scope = UNIT_FILE_USER;
6464 arg_scope = UNIT_FILE_SYSTEM;
6468 arg_scope = UNIT_FILE_GLOBAL;
6472 arg_no_block = true;
6476 arg_no_legend = true;
6480 arg_no_pager = true;
6496 if (strv_extend(&arg_states, "failed") < 0)
6514 arg_no_reload = true;
6518 arg_kill_who = optarg;
6522 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
6523 log_error("Failed to parse signal string %s.", optarg);
6528 case ARG_NO_ASK_PASSWORD:
6529 arg_ask_password = false;
6533 arg_transport = BUS_TRANSPORT_REMOTE;
6538 arg_transport = BUS_TRANSPORT_MACHINE;
6547 if (safe_atou(optarg, &arg_lines) < 0) {
6548 log_error("Failed to parse lines '%s'", optarg);
6554 arg_output = output_mode_from_string(optarg);
6555 if (arg_output < 0) {
6556 log_error("Unknown output '%s'.", optarg);
6562 arg_ignore_inhibitors = true;
6570 const char *word, *state;
6573 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6576 s = strndup(word, size);
6580 if (strv_consume(&arg_states, s) < 0)
6587 if (geteuid() != 0) {
6588 log_error("--recursive requires root privileges.");
6592 arg_recursive = true;
6595 case ARG_PRESET_MODE:
6597 arg_preset_mode = unit_file_preset_mode_from_string(optarg);
6598 if (arg_preset_mode < 0) {
6599 log_error("Failed to parse preset mode: %s.", optarg);
6609 assert_not_reached("Unhandled option");
6612 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
6613 log_error("Cannot access user instance remotely.");
6620 static int halt_parse_argv(int argc, char *argv[]) {
6629 static const struct option options[] = {
6630 { "help", no_argument, NULL, ARG_HELP },
6631 { "halt", no_argument, NULL, ARG_HALT },
6632 { "poweroff", no_argument, NULL, 'p' },
6633 { "reboot", no_argument, NULL, ARG_REBOOT },
6634 { "force", no_argument, NULL, 'f' },
6635 { "wtmp-only", no_argument, NULL, 'w' },
6636 { "no-wtmp", no_argument, NULL, 'd' },
6637 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6646 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
6647 if (runlevel == '0' || runlevel == '6')
6650 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
6658 arg_action = ACTION_HALT;
6662 if (arg_action != ACTION_REBOOT)
6663 arg_action = ACTION_POWEROFF;
6667 arg_action = ACTION_REBOOT;
6689 /* Compatibility nops */
6696 assert_not_reached("Unhandled option");
6699 if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
6700 r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL);
6703 } else if (optind < argc) {
6704 log_error("Too many arguments.");
6711 static int parse_time_spec(const char *t, usec_t *_u) {
6715 if (streq(t, "now"))
6717 else if (!strchr(t, ':')) {
6720 if (safe_atou64(t, &u) < 0)
6723 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
6732 hour = strtol(t, &e, 10);
6733 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
6736 minute = strtol(e+1, &e, 10);
6737 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
6740 n = now(CLOCK_REALTIME);
6741 s = (time_t) (n / USEC_PER_SEC);
6743 assert_se(localtime_r(&s, &tm));
6745 tm.tm_hour = (int) hour;
6746 tm.tm_min = (int) minute;
6749 assert_se(s = mktime(&tm));
6751 *_u = (usec_t) s * USEC_PER_SEC;
6754 *_u += USEC_PER_DAY;
6760 static int shutdown_parse_argv(int argc, char *argv[]) {
6767 static const struct option options[] = {
6768 { "help", no_argument, NULL, ARG_HELP },
6769 { "halt", no_argument, NULL, 'H' },
6770 { "poweroff", no_argument, NULL, 'P' },
6771 { "reboot", no_argument, NULL, 'r' },
6772 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
6773 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6782 while ((c = getopt_long(argc, argv, "HPrhkKt:afFc", options, NULL)) >= 0)
6790 arg_action = ACTION_HALT;
6794 arg_action = ACTION_POWEROFF;
6799 arg_action = ACTION_KEXEC;
6801 arg_action = ACTION_REBOOT;
6805 arg_action = ACTION_KEXEC;
6809 if (arg_action != ACTION_HALT)
6810 arg_action = ACTION_POWEROFF;
6825 /* Compatibility nops */
6829 arg_action = ACTION_CANCEL_SHUTDOWN;
6836 assert_not_reached("Unhandled option");
6839 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
6840 r = parse_time_spec(argv[optind], &arg_when);
6842 log_error("Failed to parse time specification: %s", argv[optind]);
6846 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
6848 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
6849 /* No time argument for shutdown cancel */
6850 arg_wall = argv + optind;
6851 else if (argc > optind + 1)
6852 /* We skip the time argument */
6853 arg_wall = argv + optind + 1;
6860 static int telinit_parse_argv(int argc, char *argv[]) {
6867 static const struct option options[] = {
6868 { "help", no_argument, NULL, ARG_HELP },
6869 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6873 static const struct {
6877 { '0', ACTION_POWEROFF },
6878 { '6', ACTION_REBOOT },
6879 { '1', ACTION_RESCUE },
6880 { '2', ACTION_RUNLEVEL2 },
6881 { '3', ACTION_RUNLEVEL3 },
6882 { '4', ACTION_RUNLEVEL4 },
6883 { '5', ACTION_RUNLEVEL5 },
6884 { 's', ACTION_RESCUE },
6885 { 'S', ACTION_RESCUE },
6886 { 'q', ACTION_RELOAD },
6887 { 'Q', ACTION_RELOAD },
6888 { 'u', ACTION_REEXEC },
6889 { 'U', ACTION_REEXEC }
6898 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6913 assert_not_reached("Unhandled option");
6916 if (optind >= argc) {
6917 log_error("%s: required argument missing.",
6918 program_invocation_short_name);
6922 if (optind + 1 < argc) {
6923 log_error("Too many arguments.");
6927 if (strlen(argv[optind]) != 1) {
6928 log_error("Expected single character argument.");
6932 for (i = 0; i < ELEMENTSOF(table); i++)
6933 if (table[i].from == argv[optind][0])
6936 if (i >= ELEMENTSOF(table)) {
6937 log_error("Unknown command '%s'.", argv[optind]);
6941 arg_action = table[i].to;
6948 static int runlevel_parse_argv(int argc, char *argv[]) {
6954 static const struct option options[] = {
6955 { "help", no_argument, NULL, ARG_HELP },
6964 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6975 assert_not_reached("Unhandled option");
6978 if (optind < argc) {
6979 log_error("Too many arguments.");
6986 static int parse_argv(int argc, char *argv[]) {
6990 if (program_invocation_short_name) {
6992 if (strstr(program_invocation_short_name, "halt")) {
6993 arg_action = ACTION_HALT;
6994 return halt_parse_argv(argc, argv);
6995 } else if (strstr(program_invocation_short_name, "poweroff")) {
6996 arg_action = ACTION_POWEROFF;
6997 return halt_parse_argv(argc, argv);
6998 } else if (strstr(program_invocation_short_name, "reboot")) {
7000 arg_action = ACTION_KEXEC;
7002 arg_action = ACTION_REBOOT;
7003 return halt_parse_argv(argc, argv);
7004 } else if (strstr(program_invocation_short_name, "shutdown")) {
7005 arg_action = ACTION_POWEROFF;
7006 return shutdown_parse_argv(argc, argv);
7007 } else if (strstr(program_invocation_short_name, "init")) {
7009 if (sd_booted() > 0) {
7010 arg_action = _ACTION_INVALID;
7011 return telinit_parse_argv(argc, argv);
7013 /* Hmm, so some other init system is
7014 * running, we need to forward this
7015 * request to it. For now we simply
7016 * guess that it is Upstart. */
7018 execv(TELINIT, argv);
7020 log_error("Couldn't find an alternative telinit implementation to spawn.");
7024 } else if (strstr(program_invocation_short_name, "runlevel")) {
7025 arg_action = ACTION_RUNLEVEL;
7026 return runlevel_parse_argv(argc, argv);
7030 arg_action = ACTION_SYSTEMCTL;
7031 return systemctl_parse_argv(argc, argv);
7034 _pure_ static int action_to_runlevel(void) {
7036 static const char table[_ACTION_MAX] = {
7037 [ACTION_HALT] = '0',
7038 [ACTION_POWEROFF] = '0',
7039 [ACTION_REBOOT] = '6',
7040 [ACTION_RUNLEVEL2] = '2',
7041 [ACTION_RUNLEVEL3] = '3',
7042 [ACTION_RUNLEVEL4] = '4',
7043 [ACTION_RUNLEVEL5] = '5',
7044 [ACTION_RESCUE] = '1'
7047 assert(arg_action < _ACTION_MAX);
7049 return table[arg_action];
7052 static int talk_initctl(void) {
7054 struct init_request request = {
7055 .magic = INIT_MAGIC,
7057 .cmd = INIT_CMD_RUNLVL
7060 _cleanup_close_ int fd = -1;
7064 rl = action_to_runlevel();
7068 request.runlevel = rl;
7070 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
7072 if (errno == ENOENT)
7075 log_error_errno(errno, "Failed to open "INIT_FIFO": %m");
7079 r = loop_write(fd, &request, sizeof(request), false);
7081 return log_error_errno(r, "Failed to write to "INIT_FIFO": %m");
7086 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
7088 static const struct {
7096 int (* const dispatch)(sd_bus *bus, char **args);
7102 { "list-units", MORE, 0, list_units },
7103 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
7104 { "list-sockets", MORE, 1, list_sockets },
7105 { "list-timers", MORE, 1, list_timers },
7106 { "list-jobs", MORE, 1, list_jobs },
7107 { "list-machines", MORE, 1, list_machines },
7108 { "clear-jobs", EQUAL, 1, daemon_reload },
7109 { "cancel", MORE, 2, cancel_job },
7110 { "start", MORE, 2, start_unit },
7111 { "stop", MORE, 2, start_unit },
7112 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
7113 { "reload", MORE, 2, start_unit },
7114 { "restart", MORE, 2, start_unit },
7115 { "try-restart", MORE, 2, start_unit },
7116 { "reload-or-restart", MORE, 2, start_unit },
7117 { "reload-or-try-restart", MORE, 2, start_unit },
7118 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
7119 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
7120 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
7121 { "isolate", EQUAL, 2, start_unit },
7122 { "kill", MORE, 2, kill_unit },
7123 { "is-active", MORE, 2, check_unit_active },
7124 { "check", MORE, 2, check_unit_active },
7125 { "is-failed", MORE, 2, check_unit_failed },
7126 { "show", MORE, 1, show },
7127 { "cat", MORE, 2, cat, NOBUS },
7128 { "status", MORE, 1, show },
7129 { "help", MORE, 2, show },
7130 { "snapshot", LESS, 2, snapshot },
7131 { "delete", MORE, 2, delete_snapshot },
7132 { "daemon-reload", EQUAL, 1, daemon_reload },
7133 { "daemon-reexec", EQUAL, 1, daemon_reload },
7134 { "show-environment", EQUAL, 1, show_environment },
7135 { "set-environment", MORE, 2, set_environment },
7136 { "unset-environment", MORE, 2, set_environment },
7137 { "import-environment", MORE, 1, import_environment},
7138 { "halt", EQUAL, 1, start_special, FORCE },
7139 { "poweroff", EQUAL, 1, start_special, FORCE },
7140 { "reboot", MORE, 1, start_special, FORCE },
7141 { "kexec", EQUAL, 1, start_special },
7142 { "suspend", EQUAL, 1, start_special },
7143 { "hibernate", EQUAL, 1, start_special },
7144 { "hybrid-sleep", EQUAL, 1, start_special },
7145 { "default", EQUAL, 1, start_special },
7146 { "rescue", EQUAL, 1, start_special },
7147 { "emergency", EQUAL, 1, start_special },
7148 { "exit", EQUAL, 1, start_special },
7149 { "reset-failed", MORE, 1, reset_failed },
7150 { "enable", MORE, 2, enable_unit, NOBUS },
7151 { "disable", MORE, 2, enable_unit, NOBUS },
7152 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
7153 { "reenable", MORE, 2, enable_unit, NOBUS },
7154 { "preset", MORE, 2, enable_unit, NOBUS },
7155 { "preset-all", EQUAL, 1, preset_all, NOBUS },
7156 { "mask", MORE, 2, enable_unit, NOBUS },
7157 { "unmask", MORE, 2, enable_unit, NOBUS },
7158 { "link", MORE, 2, enable_unit, NOBUS },
7159 { "switch-root", MORE, 2, switch_root },
7160 { "list-dependencies", LESS, 2, list_dependencies },
7161 { "set-default", EQUAL, 2, set_default, NOBUS },
7162 { "get-default", EQUAL, 1, get_default, NOBUS },
7163 { "set-property", MORE, 3, set_property },
7164 { "is-system-running", EQUAL, 1, is_system_running },
7165 { "add-wants", MORE, 3, add_dependency, NOBUS },
7166 { "add-requires", MORE, 3, add_dependency, NOBUS },
7167 { "edit", MORE, 2, edit, NOBUS },
7176 left = argc - optind;
7178 /* Special rule: no arguments (left == 0) means "list-units" */
7180 if (streq(argv[optind], "help") && !argv[optind+1]) {
7181 log_error("This command expects one or more "
7182 "unit names. Did you mean --help?");
7186 for (; verb->verb; verb++)
7187 if (streq(argv[optind], verb->verb))
7190 log_error("Unknown operation '%s'.", argv[optind]);
7195 switch (verb->argc_cmp) {
7198 if (left != verb->argc) {
7199 log_error("Invalid number of arguments.");
7206 if (left < verb->argc) {
7207 log_error("Too few arguments.");
7214 if (left > verb->argc) {
7215 log_error("Too many arguments.");
7222 assert_not_reached("Unknown comparison operator.");
7225 /* Require a bus connection for all operations but
7227 if (verb->bus == NOBUS) {
7228 if (!bus && !avoid_bus()) {
7229 log_error_errno(bus_error, "Failed to get D-Bus connection: %m");
7234 if (running_in_chroot() > 0) {
7235 log_info("Running in chroot, ignoring request.");
7239 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
7240 log_error_errno(bus_error, "Failed to get D-Bus connection: %m");
7245 return verb->dispatch(bus, argv + optind);
7248 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
7250 struct sd_shutdown_command c = {
7257 union sockaddr_union sockaddr = {
7258 .un.sun_family = AF_UNIX,
7259 .un.sun_path = "/run/systemd/shutdownd",
7262 struct iovec iovec[2] = {{
7263 .iov_base = (char*) &c,
7264 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
7267 struct msghdr msghdr = {
7268 .msg_name = &sockaddr,
7269 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
7270 + strlen("/run/systemd/shutdownd"),
7275 _cleanup_close_ int fd;
7277 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
7281 if (!isempty(message)) {
7282 iovec[1].iov_base = (char*) message;
7283 iovec[1].iov_len = strlen(message);
7284 msghdr.msg_iovlen++;
7287 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
7293 static int reload_with_fallback(sd_bus *bus) {
7296 /* First, try systemd via D-Bus. */
7297 if (daemon_reload(bus, NULL) >= 0)
7301 /* Nothing else worked, so let's try signals */
7302 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
7304 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0)
7305 return log_error_errno(errno, "kill() failed: %m");
7310 static int start_with_fallback(sd_bus *bus) {
7313 /* First, try systemd via D-Bus. */
7314 if (start_unit(bus, NULL) >= 0)
7318 /* Nothing else worked, so let's try
7320 if (talk_initctl() > 0)
7323 log_error("Failed to talk to init daemon.");
7327 warn_wall(arg_action);
7331 static int halt_now(enum action a) {
7333 /* The kernel will automaticall flush ATA disks and suchlike
7334 * on reboot(), but the file systems need to be synce'd
7335 * explicitly in advance. */
7338 /* Make sure C-A-D is handled by the kernel from this point
7340 reboot(RB_ENABLE_CAD);
7345 log_info("Halting.");
7346 reboot(RB_HALT_SYSTEM);
7349 case ACTION_POWEROFF:
7350 log_info("Powering off.");
7351 reboot(RB_POWER_OFF);
7354 case ACTION_REBOOT: {
7355 _cleanup_free_ char *param = NULL;
7357 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
7358 log_info("Rebooting with argument '%s'.", param);
7359 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
7360 LINUX_REBOOT_CMD_RESTART2, param);
7363 log_info("Rebooting.");
7364 reboot(RB_AUTOBOOT);
7369 assert_not_reached("Unknown action.");
7373 static int halt_main(sd_bus *bus) {
7376 r = check_inhibitors(bus, arg_action);
7380 if (geteuid() != 0) {
7381 /* Try logind if we are a normal user and no special
7382 * mode applies. Maybe PolicyKit allows us to shutdown
7385 if (arg_when <= 0 &&
7388 (arg_action == ACTION_POWEROFF ||
7389 arg_action == ACTION_REBOOT)) {
7390 r = reboot_with_logind(bus, arg_action);
7395 log_error("Must be root.");
7400 _cleanup_free_ char *m;
7402 m = strv_join(arg_wall, " ");
7406 r = send_shutdownd(arg_when,
7407 arg_action == ACTION_HALT ? 'H' :
7408 arg_action == ACTION_POWEROFF ? 'P' :
7409 arg_action == ACTION_KEXEC ? 'K' :
7416 log_warning_errno(r, "Failed to talk to shutdownd, proceeding with immediate shutdown: %m");
7418 char date[FORMAT_TIMESTAMP_MAX];
7420 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
7421 format_timestamp(date, sizeof(date), arg_when));
7426 if (!arg_dry && !arg_force)
7427 return start_with_fallback(bus);
7430 if (sd_booted() > 0)
7431 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7433 r = utmp_put_shutdown();
7435 log_warning_errno(r, "Failed to write utmp record: %m");
7442 r = halt_now(arg_action);
7443 log_error_errno(r, "Failed to reboot: %m");
7448 static int runlevel_main(void) {
7449 int r, runlevel, previous;
7451 r = utmp_get_runlevel(&runlevel, &previous);
7458 previous <= 0 ? 'N' : previous,
7459 runlevel <= 0 ? 'N' : runlevel);
7464 int main(int argc, char*argv[]) {
7465 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
7468 setlocale(LC_ALL, "");
7469 log_parse_environment();
7472 /* Explicitly not on_tty() to avoid setting cached value.
7473 * This becomes relevant for piping output which might be
7475 original_stdout_is_tty = isatty(STDOUT_FILENO);
7477 r = parse_argv(argc, argv);
7481 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
7482 * let's shortcut this */
7483 if (arg_action == ACTION_RUNLEVEL) {
7484 r = runlevel_main();
7488 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
7489 log_info("Running in chroot, ignoring request.");
7494 /* Increase max number of open files to 16K if we can, we
7495 * might needs this when browsing journal files, which might
7496 * be split up into many files. */
7497 setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(16384));
7500 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
7502 /* systemctl_main() will print an error message for the bus
7503 * connection, but only if it needs to */
7505 switch (arg_action) {
7507 case ACTION_SYSTEMCTL:
7508 r = systemctl_main(bus, argc, argv, r);
7512 case ACTION_POWEROFF:
7518 case ACTION_RUNLEVEL2:
7519 case ACTION_RUNLEVEL3:
7520 case ACTION_RUNLEVEL4:
7521 case ACTION_RUNLEVEL5:
7523 case ACTION_EMERGENCY:
7524 case ACTION_DEFAULT:
7525 r = start_with_fallback(bus);
7530 r = reload_with_fallback(bus);
7533 case ACTION_CANCEL_SHUTDOWN: {
7534 _cleanup_free_ char *m = NULL;
7537 m = strv_join(arg_wall, " ");
7544 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
7546 log_warning_errno(r, "Failed to talk to shutdownd, shutdown hasn't been cancelled: %m");
7550 case ACTION_RUNLEVEL:
7551 case _ACTION_INVALID:
7553 assert_not_reached("Unknown action");
7558 ask_password_agent_close();
7559 polkit_agent_close();
7561 strv_free(arg_types);
7562 strv_free(arg_states);
7563 strv_free(arg_properties);
7565 return r < 0 ? EXIT_FAILURE : r;