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();
180 static void polkit_agent_open_if_enabled(void) {
182 /* Open the polkit agent as a child process if necessary */
184 if (!arg_ask_password)
187 if (arg_scope != UNIT_FILE_SYSTEM)
190 if (arg_transport != BUS_TRANSPORT_LOCAL)
197 static OutputFlags get_output_flags(void) {
199 arg_all * OUTPUT_SHOW_ALL |
200 arg_full * OUTPUT_FULL_WIDTH |
201 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
202 on_tty() * OUTPUT_COLOR |
203 !arg_quiet * OUTPUT_WARN_CUTOFF;
206 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
209 if (!sd_bus_error_is_set(error))
212 if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) ||
213 sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
214 sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
215 sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
216 return EXIT_NOPERMISSION;
218 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
219 return EXIT_NOTINSTALLED;
221 if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
222 sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED))
223 return EXIT_NOTIMPLEMENTED;
225 if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
226 return EXIT_NOTCONFIGURED;
234 static void warn_wall(enum action a) {
235 static const char *table[_ACTION_MAX] = {
236 [ACTION_HALT] = "The system is going down for system halt NOW!",
237 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
238 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
239 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
240 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
241 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
242 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
249 _cleanup_free_ char *p;
251 p = strv_join(arg_wall, " ");
258 utmp_wall(p, NULL, NULL);
266 utmp_wall(table[a], NULL, NULL);
269 static bool avoid_bus(void) {
271 if (running_in_chroot() > 0)
274 if (sd_booted() <= 0)
277 if (!isempty(arg_root))
280 if (arg_scope == UNIT_FILE_GLOBAL)
286 static int compare_unit_info(const void *a, const void *b) {
287 const UnitInfo *u = a, *v = b;
291 /* First, order by machine */
292 if (!u->machine && v->machine)
294 if (u->machine && !v->machine)
296 if (u->machine && v->machine) {
297 r = strcasecmp(u->machine, v->machine);
302 /* Second, order by unit type */
303 d1 = strrchr(u->id, '.');
304 d2 = strrchr(v->id, '.');
306 r = strcasecmp(d1, d2);
311 /* Third, order by name */
312 return strcasecmp(u->id, v->id);
315 static bool output_show_unit(const UnitInfo *u, char **patterns) {
316 if (!strv_isempty(patterns)) {
319 STRV_FOREACH(pattern, patterns)
320 if (fnmatch(*pattern, u->id, FNM_NOESCAPE) == 0)
329 dot = strrchr(u->id, '.');
333 if (!strv_find(arg_types, dot+1))
343 if (streq(u->active_state, "inactive") || u->following[0])
349 static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
350 unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
352 unsigned n_shown = 0;
355 max_id_len = strlen("UNIT");
356 load_len = strlen("LOAD");
357 active_len = strlen("ACTIVE");
358 sub_len = strlen("SUB");
359 job_len = strlen("JOB");
362 for (u = unit_infos; u < unit_infos + c; u++) {
363 max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0));
364 load_len = MAX(load_len, strlen(u->load_state));
365 active_len = MAX(active_len, strlen(u->active_state));
366 sub_len = MAX(sub_len, strlen(u->sub_state));
368 if (u->job_id != 0) {
369 job_len = MAX(job_len, strlen(u->job_type));
373 if (!arg_no_legend &&
374 (streq(u->active_state, "failed") ||
375 STR_IN_SET(u->load_state, "error", "not-found", "masked")))
379 if (!arg_full && original_stdout_is_tty) {
382 id_len = MIN(max_id_len, 25u);
383 basic_len = circle_len + 5 + id_len + 5 + active_len + sub_len;
386 basic_len += job_len + 1;
388 if (basic_len < (unsigned) columns()) {
389 unsigned extra_len, incr;
390 extra_len = columns() - basic_len;
392 /* Either UNIT already got 25, or is fully satisfied.
393 * Grant up to 25 to DESC now. */
394 incr = MIN(extra_len, 25u);
398 /* split the remaining space between UNIT and DESC,
399 * but do not give UNIT more than it needs. */
401 incr = MIN(extra_len / 2, max_id_len - id_len);
403 desc_len += extra_len - incr;
409 for (u = unit_infos; u < unit_infos + c; u++) {
410 _cleanup_free_ char *e = NULL, *j = NULL;
411 const char *on_loaded = "", *off_loaded = "";
412 const char *on_active = "", *off_active = "";
413 const char *on_circle = "", *off_circle = "";
417 if (!n_shown && !arg_no_legend) {
422 printf("%-*s %-*s %-*s %-*s ",
425 active_len, "ACTIVE",
429 printf("%-*s ", job_len, "JOB");
431 if (!arg_full && arg_no_pager)
432 printf("%.*s\n", desc_len, "DESCRIPTION");
434 printf("%s\n", "DESCRIPTION");
439 if (STR_IN_SET(u->load_state, "error", "not-found", "masked")) {
440 on_loaded = ansi_highlight_red();
441 on_circle = ansi_highlight_yellow();
442 off_loaded = off_circle = ansi_highlight_off();
446 if (streq(u->active_state, "failed")) {
447 on_circle = on_active = ansi_highlight_red();
448 off_circle = off_active = ansi_highlight_off();
453 j = strjoin(u->machine, ":", u->id, NULL);
462 e = ellipsize(id, id_len, 33);
470 printf("%s%s%s ", on_circle, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_circle);
472 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
473 on_active, id_len, id, off_active,
474 on_loaded, load_len, u->load_state, off_loaded,
475 on_active, active_len, u->active_state,
476 sub_len, u->sub_state, off_active,
477 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
480 printf("%.*s\n", desc_len, u->description);
482 printf("%s\n", u->description);
485 if (!arg_no_legend) {
486 const char *on, *off;
490 "LOAD = Reflects whether the unit definition was properly loaded.\n"
491 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
492 "SUB = The low-level unit activation state, values depend on unit type.");
493 puts(job_count ? "JOB = Pending job for the unit.\n" : "");
494 on = ansi_highlight();
495 off = ansi_highlight_off();
497 on = ansi_highlight_red();
498 off = ansi_highlight_off();
502 printf("%s%u loaded units listed.%s\n"
503 "To show all installed unit files use 'systemctl list-unit-files'.\n",
506 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
507 "To show all installed unit files use 'systemctl list-unit-files'.\n",
514 static int get_unit_list(
518 UnitInfo **unit_infos,
520 sd_bus_message **_reply) {
522 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
523 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
524 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
533 r = sd_bus_message_new_method_call(
536 "org.freedesktop.systemd1",
537 "/org/freedesktop/systemd1",
538 "org.freedesktop.systemd1.Manager",
539 "ListUnitsFiltered");
542 return bus_log_create_error(r);
544 r = sd_bus_message_append_strv(m, arg_states);
546 return bus_log_create_error(r);
548 r = sd_bus_call(bus, m, 0, &error, &reply);
550 log_error("Failed to list units: %s", bus_error_message(&error, r));
554 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
556 return bus_log_parse_error(r);
558 while ((r = bus_parse_unit_info(reply, &u)) > 0) {
561 if (!output_show_unit(&u, patterns))
564 if (!GREEDY_REALLOC(*unit_infos, size, c+1))
567 (*unit_infos)[c++] = u;
570 return bus_log_parse_error(r);
572 r = sd_bus_message_exit_container(reply);
574 return bus_log_parse_error(r);
582 static void message_set_freep(Set **set) {
585 while ((m = set_steal_first(*set)))
586 sd_bus_message_unref(m);
591 static int get_unit_list_recursive(
594 UnitInfo **_unit_infos,
598 _cleanup_free_ UnitInfo *unit_infos = NULL;
599 _cleanup_(message_set_freep) Set *replies;
600 sd_bus_message *reply;
608 replies = set_new(NULL);
612 c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
616 r = set_put(replies, reply);
618 sd_bus_message_unref(reply);
623 _cleanup_strv_free_ char **machines = NULL;
626 r = sd_get_machine_names(&machines);
630 STRV_FOREACH(i, machines) {
631 _cleanup_bus_close_unref_ sd_bus *container = NULL;
634 r = sd_bus_open_system_machine(&container, *i);
636 log_error_errno(r, "Failed to connect to container %s: %m", *i);
640 k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
646 r = set_put(replies, reply);
648 sd_bus_message_unref(reply);
653 *_machines = machines;
658 *_unit_infos = unit_infos;
667 static int list_units(sd_bus *bus, char **args) {
668 _cleanup_free_ UnitInfo *unit_infos = NULL;
669 _cleanup_(message_set_freep) Set *replies = NULL;
670 _cleanup_strv_free_ char **machines = NULL;
673 pager_open_if_enabled();
675 r = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
679 qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
680 return output_units_list(unit_infos, r);
683 static int get_triggered_units(
688 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
691 r = sd_bus_get_property_strv(
693 "org.freedesktop.systemd1",
695 "org.freedesktop.systemd1.Unit",
701 log_error("Failed to determine triggers: %s", bus_error_message(&error, r));
706 static int get_listening(
708 const char* unit_path,
711 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
712 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
713 const char *type, *path;
716 r = sd_bus_get_property(
718 "org.freedesktop.systemd1",
720 "org.freedesktop.systemd1.Socket",
726 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r));
730 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
732 return bus_log_parse_error(r);
734 while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
736 r = strv_extend(listening, type);
740 r = strv_extend(listening, path);
747 return bus_log_parse_error(r);
749 r = sd_bus_message_exit_container(reply);
751 return bus_log_parse_error(r);
763 /* Note: triggered is a list here, although it almost certainly
764 * will always be one unit. Nevertheless, dbus API allows for multiple
765 * values, so let's follow that. */
768 /* The strv above is shared. free is set only in the first one. */
772 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
778 if (!a->machine && b->machine)
780 if (a->machine && !b->machine)
782 if (a->machine && b->machine) {
783 o = strcasecmp(a->machine, b->machine);
788 o = strcmp(a->path, b->path);
790 o = strcmp(a->type, b->type);
795 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
796 struct socket_info *s;
797 unsigned pathlen = strlen("LISTEN"),
798 typelen = strlen("TYPE") * arg_show_types,
799 socklen = strlen("UNIT"),
800 servlen = strlen("ACTIVATES");
801 const char *on, *off;
803 for (s = socket_infos; s < socket_infos + cs; s++) {
807 socklen = MAX(socklen, strlen(s->id));
809 typelen = MAX(typelen, strlen(s->type));
810 pathlen = MAX(pathlen, strlen(s->path) + (s->machine ? strlen(s->machine)+1 : 0));
812 STRV_FOREACH(a, s->triggered)
813 tmp += strlen(*a) + 2*(a != s->triggered);
814 servlen = MAX(servlen, tmp);
819 printf("%-*s %-*.*s%-*s %s\n",
821 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
825 for (s = socket_infos; s < socket_infos + cs; s++) {
826 _cleanup_free_ char *j = NULL;
831 j = strjoin(s->machine, ":", s->path, NULL);
839 printf("%-*s %-*s %-*s",
840 pathlen, path, typelen, s->type, socklen, s->id);
843 pathlen, path, socklen, s->id);
844 STRV_FOREACH(a, s->triggered)
846 a == s->triggered ? "" : ",", *a);
850 on = ansi_highlight();
851 off = ansi_highlight_off();
855 on = ansi_highlight_red();
856 off = ansi_highlight_off();
859 if (!arg_no_legend) {
860 printf("%s%u sockets listed.%s\n", on, cs, off);
862 printf("Pass --all to see loaded but inactive sockets, too.\n");
868 static int list_sockets(sd_bus *bus, char **args) {
869 _cleanup_(message_set_freep) Set *replies = NULL;
870 _cleanup_strv_free_ char **machines = NULL;
871 _cleanup_free_ UnitInfo *unit_infos = NULL;
872 _cleanup_free_ struct socket_info *socket_infos = NULL;
874 struct socket_info *s;
879 pager_open_if_enabled();
881 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
885 for (u = unit_infos; u < unit_infos + n; u++) {
886 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
889 if (!endswith(u->id, ".socket"))
892 r = get_triggered_units(bus, u->unit_path, &triggered);
896 c = get_listening(bus, u->unit_path, &listening);
902 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
907 for (i = 0; i < c; i++)
908 socket_infos[cs + i] = (struct socket_info) {
909 .machine = u->machine,
911 .type = listening[i*2],
912 .path = listening[i*2 + 1],
913 .triggered = triggered,
914 .own_triggered = i==0,
917 /* from this point on we will cleanup those socket_infos */
920 listening = triggered = NULL; /* avoid cleanup */
923 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
924 (__compar_fn_t) socket_info_compare);
926 output_sockets_list(socket_infos, cs);
929 assert(cs == 0 || socket_infos);
930 for (s = socket_infos; s < socket_infos + cs; s++) {
933 if (s->own_triggered)
934 strv_free(s->triggered);
940 static int get_next_elapse(
943 dual_timestamp *next) {
945 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
953 r = sd_bus_get_property_trivial(
955 "org.freedesktop.systemd1",
957 "org.freedesktop.systemd1.Timer",
958 "NextElapseUSecMonotonic",
963 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
967 r = sd_bus_get_property_trivial(
969 "org.freedesktop.systemd1",
971 "org.freedesktop.systemd1.Timer",
972 "NextElapseUSecRealtime",
977 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
985 static int get_last_trigger(
990 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
997 r = sd_bus_get_property_trivial(
999 "org.freedesktop.systemd1",
1001 "org.freedesktop.systemd1.Timer",
1007 log_error("Failed to get last trigger time: %s", bus_error_message(&error, r));
1015 const char* machine;
1018 usec_t last_trigger;
1022 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
1028 if (!a->machine && b->machine)
1030 if (a->machine && !b->machine)
1032 if (a->machine && b->machine) {
1033 o = strcasecmp(a->machine, b->machine);
1038 if (a->next_elapse < b->next_elapse)
1040 if (a->next_elapse > b->next_elapse)
1043 return strcmp(a->id, b->id);
1046 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
1047 struct timer_info *t;
1049 nextlen = strlen("NEXT"),
1050 leftlen = strlen("LEFT"),
1051 lastlen = strlen("LAST"),
1052 passedlen = strlen("PASSED"),
1053 unitlen = strlen("UNIT"),
1054 activatelen = strlen("ACTIVATES");
1056 const char *on, *off;
1058 assert(timer_infos || n == 0);
1060 for (t = timer_infos; t < timer_infos + n; t++) {
1064 if (t->next_elapse > 0) {
1065 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1067 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
1068 nextlen = MAX(nextlen, strlen(tstamp) + 1);
1070 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
1071 leftlen = MAX(leftlen, strlen(trel));
1074 if (t->last_trigger > 0) {
1075 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1077 format_timestamp(tstamp, sizeof(tstamp), t->last_trigger);
1078 lastlen = MAX(lastlen, strlen(tstamp) + 1);
1080 format_timestamp_relative(trel, sizeof(trel), t->last_trigger);
1081 passedlen = MAX(passedlen, strlen(trel));
1084 unitlen = MAX(unitlen, strlen(t->id) + (t->machine ? strlen(t->machine)+1 : 0));
1086 STRV_FOREACH(a, t->triggered)
1087 ul += strlen(*a) + 2*(a != t->triggered);
1089 activatelen = MAX(activatelen, ul);
1094 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1098 passedlen, "PASSED",
1102 for (t = timer_infos; t < timer_infos + n; t++) {
1103 _cleanup_free_ char *j = NULL;
1105 char tstamp1[FORMAT_TIMESTAMP_MAX] = "n/a", trel1[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1106 char tstamp2[FORMAT_TIMESTAMP_MAX] = "n/a", trel2[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1109 format_timestamp(tstamp1, sizeof(tstamp1), t->next_elapse);
1110 format_timestamp_relative(trel1, sizeof(trel1), t->next_elapse);
1112 format_timestamp(tstamp2, sizeof(tstamp2), t->last_trigger);
1113 format_timestamp_relative(trel2, sizeof(trel2), t->last_trigger);
1116 j = strjoin(t->machine, ":", t->id, NULL);
1123 printf("%-*s %-*s %-*s %-*s %-*s",
1124 nextlen, tstamp1, leftlen, trel1, lastlen, tstamp2, passedlen, trel2, unitlen, unit);
1126 STRV_FOREACH(a, t->triggered)
1128 a == t->triggered ? "" : ",", *a);
1132 on = ansi_highlight();
1133 off = ansi_highlight_off();
1137 on = ansi_highlight_red();
1138 off = ansi_highlight_off();
1141 if (!arg_no_legend) {
1142 printf("%s%u timers listed.%s\n", on, n, off);
1144 printf("Pass --all to see loaded but inactive timers, too.\n");
1150 static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
1156 if (next->monotonic != USEC_INFINITY && next->monotonic > 0) {
1159 if (next->monotonic > nw->monotonic)
1160 converted = nw->realtime + (next->monotonic - nw->monotonic);
1162 converted = nw->realtime - (nw->monotonic - next->monotonic);
1164 if (next->realtime != USEC_INFINITY && next->realtime > 0)
1165 next_elapse = MIN(converted, next->realtime);
1167 next_elapse = converted;
1170 next_elapse = next->realtime;
1175 static int list_timers(sd_bus *bus, char **args) {
1176 _cleanup_(message_set_freep) Set *replies = NULL;
1177 _cleanup_strv_free_ char **machines = NULL;
1178 _cleanup_free_ struct timer_info *timer_infos = NULL;
1179 _cleanup_free_ UnitInfo *unit_infos = NULL;
1180 struct timer_info *t;
1187 pager_open_if_enabled();
1189 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
1193 dual_timestamp_get(&nw);
1195 for (u = unit_infos; u < unit_infos + n; u++) {
1196 _cleanup_strv_free_ char **triggered = NULL;
1197 dual_timestamp next = {};
1200 if (!endswith(u->id, ".timer"))
1203 r = get_triggered_units(bus, u->unit_path, &triggered);
1207 r = get_next_elapse(bus, u->unit_path, &next);
1211 get_last_trigger(bus, u->unit_path, &last);
1213 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
1218 m = calc_next_elapse(&nw, &next);
1220 timer_infos[c++] = (struct timer_info) {
1221 .machine = u->machine,
1224 .last_trigger = last,
1225 .triggered = triggered,
1228 triggered = NULL; /* avoid cleanup */
1231 qsort_safe(timer_infos, c, sizeof(struct timer_info),
1232 (__compar_fn_t) timer_info_compare);
1234 output_timers_list(timer_infos, c);
1237 for (t = timer_infos; t < timer_infos + c; t++)
1238 strv_free(t->triggered);
1243 static int compare_unit_file_list(const void *a, const void *b) {
1244 const char *d1, *d2;
1245 const UnitFileList *u = a, *v = b;
1247 d1 = strrchr(u->path, '.');
1248 d2 = strrchr(v->path, '.');
1253 r = strcasecmp(d1, d2);
1258 return strcasecmp(basename(u->path), basename(v->path));
1261 static bool output_show_unit_file(const UnitFileList *u, char **patterns) {
1262 if (!strv_isempty(patterns)) {
1265 STRV_FOREACH(pattern, patterns)
1266 if (fnmatch(*pattern, basename(u->path), FNM_NOESCAPE) == 0)
1272 if (!strv_isempty(arg_types)) {
1275 dot = strrchr(u->path, '.');
1279 if (!strv_find(arg_types, dot+1))
1283 if (!strv_isempty(arg_states)) {
1284 if (!strv_find(arg_states, unit_file_state_to_string(u->state)))
1291 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
1292 unsigned max_id_len, id_cols, state_cols;
1293 const UnitFileList *u;
1295 max_id_len = strlen("UNIT FILE");
1296 state_cols = strlen("STATE");
1298 for (u = units; u < units + c; u++) {
1299 max_id_len = MAX(max_id_len, strlen(basename(u->path)));
1300 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1304 unsigned basic_cols;
1306 id_cols = MIN(max_id_len, 25u);
1307 basic_cols = 1 + id_cols + state_cols;
1308 if (basic_cols < (unsigned) columns())
1309 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1311 id_cols = max_id_len;
1314 printf("%-*s %-*s\n",
1315 id_cols, "UNIT FILE",
1316 state_cols, "STATE");
1318 for (u = units; u < units + c; u++) {
1319 _cleanup_free_ char *e = NULL;
1320 const char *on, *off;
1323 if (u->state == UNIT_FILE_MASKED ||
1324 u->state == UNIT_FILE_MASKED_RUNTIME ||
1325 u->state == UNIT_FILE_DISABLED ||
1326 u->state == UNIT_FILE_INVALID) {
1327 on = ansi_highlight_red();
1328 off = ansi_highlight_off();
1329 } else if (u->state == UNIT_FILE_ENABLED) {
1330 on = ansi_highlight_green();
1331 off = ansi_highlight_off();
1335 id = basename(u->path);
1337 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1339 printf("%-*s %s%-*s%s\n",
1340 id_cols, e ? e : id,
1341 on, state_cols, unit_file_state_to_string(u->state), off);
1345 printf("\n%u unit files listed.\n", c);
1348 static int list_unit_files(sd_bus *bus, char **args) {
1349 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1350 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1351 _cleanup_free_ UnitFileList *units = NULL;
1359 pager_open_if_enabled();
1367 h = hashmap_new(&string_hash_ops);
1371 r = unit_file_get_list(arg_scope, arg_root, h);
1373 unit_file_list_free(h);
1374 log_error_errno(r, "Failed to get unit file list: %m");
1378 n_units = hashmap_size(h);
1380 units = new(UnitFileList, n_units);
1381 if (!units && n_units > 0) {
1382 unit_file_list_free(h);
1386 HASHMAP_FOREACH(u, h, i) {
1387 if (!output_show_unit_file(u, strv_skip_first(args)))
1394 assert(c <= n_units);
1397 r = sd_bus_call_method(
1399 "org.freedesktop.systemd1",
1400 "/org/freedesktop/systemd1",
1401 "org.freedesktop.systemd1.Manager",
1407 log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1411 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1413 return bus_log_parse_error(r);
1415 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1417 if (!GREEDY_REALLOC(units, size, c + 1))
1420 units[c] = (struct UnitFileList) {
1422 unit_file_state_from_string(state)
1425 if (output_show_unit_file(&units[c], strv_skip_first(args)))
1430 return bus_log_parse_error(r);
1432 r = sd_bus_message_exit_container(reply);
1434 return bus_log_parse_error(r);
1437 qsort_safe(units, c, sizeof(UnitFileList), compare_unit_file_list);
1438 output_unit_file_list(units, c);
1441 for (unit = units; unit < units + c; unit++)
1448 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1449 _cleanup_free_ char *n = NULL;
1450 size_t max_len = MAX(columns(),20u);
1456 for (i = level - 1; i >= 0; i--) {
1458 if (len > max_len - 3 && !arg_full) {
1459 printf("%s...\n",max_len % 2 ? "" : " ");
1462 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERTICAL : DRAW_TREE_SPACE));
1466 if (len > max_len - 3 && !arg_full) {
1467 printf("%s...\n",max_len % 2 ? "" : " ");
1471 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
1475 printf("%s\n", name);
1479 n = ellipsize(name, max_len-len, 100);
1487 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1489 static const char *dependencies[_DEPENDENCY_MAX] = {
1490 [DEPENDENCY_FORWARD] = "Requires\0"
1491 "RequiresOverridable\0"
1493 "RequisiteOverridable\0"
1496 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1497 "RequiredByOverridable\0"
1501 [DEPENDENCY_AFTER] = "After\0",
1502 [DEPENDENCY_BEFORE] = "Before\0",
1505 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1506 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1507 _cleanup_strv_free_ char **ret = NULL;
1508 _cleanup_free_ char *path = NULL;
1514 assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
1516 path = unit_dbus_path_from_name(name);
1520 r = sd_bus_call_method(
1522 "org.freedesktop.systemd1",
1524 "org.freedesktop.DBus.Properties",
1528 "s", "org.freedesktop.systemd1.Unit");
1530 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1534 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1536 return bus_log_parse_error(r);
1538 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1541 r = sd_bus_message_read(reply, "s", &prop);
1543 return bus_log_parse_error(r);
1545 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1546 r = sd_bus_message_skip(reply, "v");
1548 return bus_log_parse_error(r);
1551 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1553 return bus_log_parse_error(r);
1555 r = bus_message_read_strv_extend(reply, &ret);
1557 return bus_log_parse_error(r);
1559 r = sd_bus_message_exit_container(reply);
1561 return bus_log_parse_error(r);
1564 r = sd_bus_message_exit_container(reply);
1566 return bus_log_parse_error(r);
1570 return bus_log_parse_error(r);
1572 r = sd_bus_message_exit_container(reply);
1574 return bus_log_parse_error(r);
1582 static int list_dependencies_compare(const void *_a, const void *_b) {
1583 const char **a = (const char**) _a, **b = (const char**) _b;
1585 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1587 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1590 return strcasecmp(*a, *b);
1593 static int list_dependencies_one(
1598 unsigned int branches) {
1600 _cleanup_strv_free_ char **deps = NULL;
1608 r = strv_extend(units, name);
1612 r = list_dependencies_get_dependencies(bus, name, &deps);
1616 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1618 STRV_FOREACH(c, deps) {
1621 if (strv_contains(*units, *c)) {
1623 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);
1632 printf("%s%s%s ", ansi_highlight_green(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1634 printf("%s%s%s ", ansi_highlight_red(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1636 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1640 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1641 r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1648 strv_remove(*units, name);
1653 static int list_dependencies(sd_bus *bus, char **args) {
1654 _cleanup_strv_free_ char **units = NULL;
1655 _cleanup_free_ char *unit = NULL;
1661 unit = unit_name_mangle(args[1], MANGLE_NOGLOB);
1666 u = SPECIAL_DEFAULT_TARGET;
1668 pager_open_if_enabled();
1672 return list_dependencies_one(bus, u, 0, &units, 0);
1675 struct machine_info {
1679 char *control_group;
1680 uint32_t n_failed_units;
1685 static const struct bus_properties_map machine_info_property_map[] = {
1686 { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
1687 { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
1688 { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
1689 { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
1690 { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
1694 static void free_machines_list(struct machine_info *machine_infos, int n) {
1700 for (i = 0; i < n; i++) {
1701 free(machine_infos[i].name);
1702 free(machine_infos[i].state);
1703 free(machine_infos[i].control_group);
1706 free(machine_infos);
1709 static int compare_machine_info(const void *a, const void *b) {
1710 const struct machine_info *u = a, *v = b;
1712 if (u->is_host != v->is_host)
1713 return u->is_host > v->is_host ? -1 : 1;
1715 return strcasecmp(u->name, v->name);
1718 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1719 _cleanup_bus_close_unref_ sd_bus *container = NULL;
1725 r = sd_bus_open_system_machine(&container, mi->name);
1732 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi);
1739 static bool output_show_machine(const char *name, char **patterns) {
1744 if (strv_isempty(patterns))
1747 STRV_FOREACH(i, patterns)
1748 if (fnmatch(*i, name, FNM_NOESCAPE) == 0)
1754 static int get_machine_list(
1756 struct machine_info **_machine_infos,
1759 struct machine_info *machine_infos = NULL;
1760 _cleanup_strv_free_ char **m = NULL;
1761 _cleanup_free_ char *hn = NULL;
1766 hn = gethostname_malloc();
1770 if (output_show_machine(hn, patterns)) {
1771 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1774 machine_infos[c].is_host = true;
1775 machine_infos[c].name = hn;
1778 get_machine_properties(bus, &machine_infos[c]);
1782 sd_get_machine_names(&m);
1783 STRV_FOREACH(i, m) {
1784 _cleanup_free_ char *class = NULL;
1786 if (!output_show_machine(*i, patterns))
1789 sd_machine_get_class(*i, &class);
1790 if (!streq_ptr(class, "container"))
1793 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1794 free_machines_list(machine_infos, c);
1798 machine_infos[c].is_host = false;
1799 machine_infos[c].name = strdup(*i);
1800 if (!machine_infos[c].name) {
1801 free_machines_list(machine_infos, c);
1805 get_machine_properties(NULL, &machine_infos[c]);
1809 *_machine_infos = machine_infos;
1813 static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1814 struct machine_info *m;
1817 namelen = sizeof("NAME") - 1,
1818 statelen = sizeof("STATE") - 1,
1819 failedlen = sizeof("FAILED") - 1,
1820 jobslen = sizeof("JOBS") - 1;
1822 assert(machine_infos || n == 0);
1824 for (m = machine_infos; m < machine_infos + n; m++) {
1825 namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
1826 statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
1827 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
1828 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
1830 if (!arg_no_legend && !streq_ptr(m->state, "running"))
1834 if (!arg_no_legend) {
1838 printf("%-*s %-*s %-*s %-*s\n",
1841 failedlen, "FAILED",
1845 for (m = machine_infos; m < machine_infos + n; m++) {
1846 const char *on_state = "", *off_state = "";
1847 const char *on_failed = "", *off_failed = "";
1848 bool circle = false;
1850 if (streq_ptr(m->state, "degraded")) {
1851 on_state = ansi_highlight_red();
1852 off_state = ansi_highlight_off();
1854 } else if (!streq_ptr(m->state, "running")) {
1855 on_state = ansi_highlight_yellow();
1856 off_state = ansi_highlight_off();
1860 if (m->n_failed_units > 0) {
1861 on_failed = ansi_highlight_red();
1862 off_failed = ansi_highlight_off();
1864 on_failed = off_failed = "";
1867 printf("%s%s%s ", on_state, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_state);
1870 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1871 (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
1872 on_state, statelen, strna(m->state), off_state,
1873 on_failed, failedlen, m->n_failed_units, off_failed,
1874 jobslen, m->n_jobs);
1876 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1877 namelen, strna(m->name),
1878 on_state, statelen, strna(m->state), off_state,
1879 on_failed, failedlen, m->n_failed_units, off_failed,
1880 jobslen, m->n_jobs);
1884 printf("\n%u machines listed.\n", n);
1887 static int list_machines(sd_bus *bus, char **args) {
1888 struct machine_info *machine_infos = NULL;
1893 if (geteuid() != 0) {
1894 log_error("Must be root.");
1898 pager_open_if_enabled();
1900 r = get_machine_list(bus, &machine_infos, strv_skip_first(args));
1904 qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
1905 output_machines_list(machine_infos, r);
1906 free_machines_list(machine_infos, r);
1911 static int get_default(sd_bus *bus, char **args) {
1912 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1913 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1914 _cleanup_free_ char *_path = NULL;
1918 if (!bus || avoid_bus()) {
1919 r = unit_file_get_default(arg_scope, arg_root, &_path);
1921 return log_error_errno(r, "Failed to get default target: %m");
1925 r = sd_bus_call_method(
1927 "org.freedesktop.systemd1",
1928 "/org/freedesktop/systemd1",
1929 "org.freedesktop.systemd1.Manager",
1935 log_error("Failed to get default target: %s", bus_error_message(&error, -r));
1939 r = sd_bus_message_read(reply, "s", &path);
1941 return bus_log_parse_error(r);
1945 printf("%s\n", path);
1950 static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) {
1953 assert(changes || n_changes == 0);
1955 for (i = 0; i < n_changes; i++) {
1956 if (changes[i].type == UNIT_FILE_SYMLINK)
1957 log_info("Created symlink from %s to %s.", changes[i].path, changes[i].source);
1959 log_info("Removed symlink %s.", changes[i].path);
1963 static int set_default(sd_bus *bus, char **args) {
1964 _cleanup_free_ char *unit = NULL;
1965 UnitFileChange *changes = NULL;
1966 unsigned n_changes = 0;
1969 unit = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
1973 if (!bus || avoid_bus()) {
1974 r = unit_file_set_default(arg_scope, arg_root, unit, true, &changes, &n_changes);
1976 return log_error_errno(r, "Failed to set default target: %m");
1979 dump_unit_file_changes(changes, n_changes);
1983 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1984 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1986 r = sd_bus_message_new_method_call(
1989 "org.freedesktop.systemd1",
1990 "/org/freedesktop/systemd1",
1991 "org.freedesktop.systemd1.Manager",
1992 "SetDefaultTarget");
1994 return bus_log_create_error(r);
1996 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
1998 return bus_log_create_error(r);
2000 r = sd_bus_message_append(m, "sb", unit, 1);
2002 return bus_log_create_error(r);
2004 r = sd_bus_call(bus, m, 0, &error, &reply);
2006 log_error("Failed to set default target: %s", bus_error_message(&error, -r));
2010 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
2014 /* Try to reload if enabled */
2016 r = daemon_reload(bus, args);
2021 unit_file_changes_free(changes, n_changes);
2028 const char *name, *type, *state;
2031 static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
2032 unsigned id_len, unit_len, type_len, state_len;
2033 const struct job_info *j;
2034 const char *on, *off;
2035 bool shorten = false;
2037 assert(n == 0 || jobs);
2040 on = ansi_highlight_green();
2041 off = ansi_highlight_off();
2043 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
2047 pager_open_if_enabled();
2049 id_len = strlen("JOB");
2050 unit_len = strlen("UNIT");
2051 type_len = strlen("TYPE");
2052 state_len = strlen("STATE");
2054 for (j = jobs; j < jobs + n; j++) {
2055 uint32_t id = j->id;
2056 assert(j->name && j->type && j->state);
2058 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
2059 unit_len = MAX(unit_len, strlen(j->name));
2060 type_len = MAX(type_len, strlen(j->type));
2061 state_len = MAX(state_len, strlen(j->state));
2064 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
2065 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
2070 printf("%*s %-*s %-*s %-*s\n",
2074 state_len, "STATE");
2076 for (j = jobs; j < jobs + n; j++) {
2077 _cleanup_free_ char *e = NULL;
2079 if (streq(j->state, "running")) {
2080 on = ansi_highlight();
2081 off = ansi_highlight_off();
2085 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
2086 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2088 on, unit_len, e ? e : j->name, off,
2090 on, state_len, j->state, off);
2093 if (!arg_no_legend) {
2094 on = ansi_highlight();
2095 off = ansi_highlight_off();
2097 printf("\n%s%u jobs listed%s.\n", on, n, off);
2101 static bool output_show_job(struct job_info *job, char **patterns) {
2106 if (strv_isempty(patterns))
2109 STRV_FOREACH(pattern, patterns)
2110 if (fnmatch(*pattern, job->name, FNM_NOESCAPE) == 0)
2115 static int list_jobs(sd_bus *bus, char **args) {
2116 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2117 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2118 const char *name, *type, *state, *job_path, *unit_path;
2119 _cleanup_free_ struct job_info *jobs = NULL;
2124 bool skipped = false;
2126 r = sd_bus_call_method(
2128 "org.freedesktop.systemd1",
2129 "/org/freedesktop/systemd1",
2130 "org.freedesktop.systemd1.Manager",
2136 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
2140 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2142 return bus_log_parse_error(r);
2144 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
2145 struct job_info job = { id, name, type, state };
2147 if (!output_show_job(&job, strv_skip_first(args))) {
2152 if (!GREEDY_REALLOC(jobs, size, c + 1))
2158 return bus_log_parse_error(r);
2160 r = sd_bus_message_exit_container(reply);
2162 return bus_log_parse_error(r);
2164 output_jobs_list(jobs, c, skipped);
2168 static int cancel_job(sd_bus *bus, char **args) {
2169 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2175 if (strv_length(args) <= 1)
2176 return daemon_reload(bus, args);
2178 STRV_FOREACH(name, args+1) {
2179 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2183 q = safe_atou32(*name, &id);
2185 return log_error_errno(q, "Failed to parse job id \"%s\": %m", *name);
2187 q = sd_bus_message_new_method_call(
2190 "org.freedesktop.systemd1",
2191 "/org/freedesktop/systemd1",
2192 "org.freedesktop.systemd1.Manager",
2195 return bus_log_create_error(q);
2197 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2199 return bus_log_create_error(1);
2201 q = sd_bus_message_append(m, "u", id);
2203 return bus_log_create_error(q);
2205 q = sd_bus_call(bus, m, 0, &error, NULL);
2207 log_error("Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, q));
2216 static int need_daemon_reload(sd_bus *bus, const char *unit) {
2217 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2221 /* We ignore all errors here, since this is used to show a
2224 /* We don't use unit_dbus_path_from_name() directly since we
2225 * don't want to load the unit if it isn't loaded. */
2227 r = sd_bus_call_method(
2229 "org.freedesktop.systemd1",
2230 "/org/freedesktop/systemd1",
2231 "org.freedesktop.systemd1.Manager",
2239 r = sd_bus_message_read(reply, "o", &path);
2243 r = sd_bus_get_property_trivial(
2245 "org.freedesktop.systemd1",
2247 "org.freedesktop.systemd1.Unit",
2257 static void warn_unit_file_changed(const char *name) {
2258 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2259 ansi_highlight_red(),
2260 ansi_highlight_off(),
2262 arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2265 static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **unit_path) {
2272 STRV_FOREACH(p, lp->unit_path) {
2273 _cleanup_free_ char *path;
2275 path = path_join(arg_root, *p, unit_name);
2279 if (access(path, F_OK) == 0) {
2289 static int unit_find_paths(sd_bus *bus,
2290 const char *unit_name,
2291 bool avoid_bus_cache,
2293 char **fragment_path,
2294 char ***dropin_paths) {
2298 * Finds where the unit is defined on disk. Returns 0 if the unit
2299 * is not found. Returns 1 if it is found, and sets
2300 * - the path to the unit in *path, if it exists on disk,
2301 * - and a strv of existing drop-ins in *dropins,
2302 * if the arg is not NULL and any dropins were found.
2306 assert(fragment_path);
2309 if (!avoid_bus_cache && !unit_name_is_template(unit_name)) {
2310 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2311 _cleanup_free_ char *unit = NULL;
2312 _cleanup_free_ char *path = NULL;
2313 _cleanup_strv_free_ char **dropins = NULL;
2315 unit = unit_dbus_path_from_name(unit_name);
2319 if (need_daemon_reload(bus, unit_name) > 0)
2320 warn_unit_file_changed(unit_name);
2322 r = sd_bus_get_property_string(
2324 "org.freedesktop.systemd1",
2326 "org.freedesktop.systemd1.Unit",
2331 return log_error_errno(r, "Failed to get FragmentPath: %s", bus_error_message(&error, r));
2333 r = sd_bus_get_property_strv(
2335 "org.freedesktop.systemd1",
2337 "org.freedesktop.systemd1.Unit",
2342 return log_error_errno(r, "Failed to get DropInPaths: %s", bus_error_message(&error, r));
2345 if (!isempty(path)) {
2346 *fragment_path = path;
2351 if (dropin_paths && !strv_isempty(dropins)) {
2352 *dropin_paths = dropins;
2357 _cleanup_set_free_ Set *names;
2359 names = set_new(NULL);
2363 r = set_put(names, unit_name);
2367 r = unit_file_find_path(lp, unit_name, fragment_path);
2372 _cleanup_free_ char *template;
2374 template = unit_name_template(unit_name);
2378 if (!streq(template, unit_name)) {
2379 r = unit_file_find_path(lp, template, fragment_path);
2386 r = unit_file_find_dropin_paths(lp->unit_path, NULL, names, dropin_paths);
2392 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2393 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2394 _cleanup_free_ char *n = NULL, *state = NULL;
2400 n = unit_name_mangle(name, MANGLE_NOGLOB);
2404 /* We don't use unit_dbus_path_from_name() directly since we
2405 * don't want to load the unit if it isn't loaded. */
2407 r = sd_bus_call_method(
2409 "org.freedesktop.systemd1",
2410 "/org/freedesktop/systemd1",
2411 "org.freedesktop.systemd1.Manager",
2422 r = sd_bus_message_read(reply, "o", &path);
2424 return bus_log_parse_error(r);
2426 r = sd_bus_get_property_string(
2428 "org.freedesktop.systemd1",
2430 "org.freedesktop.systemd1.Unit",
2443 return nulstr_contains(good_states, state);
2446 static int check_triggering_units(
2450 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2451 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2452 _cleanup_strv_free_ char **triggered_by = NULL;
2453 bool print_warning_label = true;
2457 n = unit_name_mangle(name, MANGLE_NOGLOB);
2461 path = unit_dbus_path_from_name(n);
2465 r = sd_bus_get_property_string(
2467 "org.freedesktop.systemd1",
2469 "org.freedesktop.systemd1.Unit",
2474 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2478 if (streq(state, "masked"))
2481 r = sd_bus_get_property_strv(
2483 "org.freedesktop.systemd1",
2485 "org.freedesktop.systemd1.Unit",
2490 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2494 STRV_FOREACH(i, triggered_by) {
2495 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2497 return log_error_errno(r, "Failed to check unit: %m");
2502 if (print_warning_label) {
2503 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2504 print_warning_label = false;
2507 log_warning(" %s", *i);
2513 static const struct {
2516 } unit_actions[] = {
2517 { "start", "StartUnit" },
2518 { "stop", "StopUnit" },
2519 { "condstop", "StopUnit" },
2520 { "reload", "ReloadUnit" },
2521 { "restart", "RestartUnit" },
2522 { "try-restart", "TryRestartUnit" },
2523 { "condrestart", "TryRestartUnit" },
2524 { "reload-or-restart", "ReloadOrRestartUnit" },
2525 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2526 { "condreload", "ReloadOrTryRestartUnit" },
2527 { "force-reload", "ReloadOrTryRestartUnit" }
2530 static const char *verb_to_method(const char *verb) {
2533 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2534 if (streq_ptr(unit_actions[i].verb, verb))
2535 return unit_actions[i].method;
2540 static const char *method_to_verb(const char *method) {
2543 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2544 if (streq_ptr(unit_actions[i].method, method))
2545 return unit_actions[i].verb;
2550 static int start_unit_one(
2555 sd_bus_error *error,
2556 BusWaitForJobs *w) {
2558 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2567 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2569 r = sd_bus_message_new_method_call(
2572 "org.freedesktop.systemd1",
2573 "/org/freedesktop/systemd1",
2574 "org.freedesktop.systemd1.Manager",
2577 return bus_log_create_error(r);
2579 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2581 return bus_log_create_error(r);
2583 r = sd_bus_message_append(m, "ss", name, mode);
2585 return bus_log_create_error(r);
2587 r = sd_bus_call(bus, m, 0, error, &reply);
2591 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2592 /* There's always a fallback possible for
2593 * legacy actions. */
2594 return -EADDRNOTAVAIL;
2596 verb = method_to_verb(method);
2598 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2602 r = sd_bus_message_read(reply, "o", &path);
2604 return bus_log_parse_error(r);
2606 if (need_daemon_reload(bus, name) > 0)
2607 warn_unit_file_changed(name);
2610 log_debug("Adding %s to the set", path);
2611 r = bus_wait_for_jobs_add(w, path);
2619 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2621 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2625 STRV_FOREACH(name, names) {
2629 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2631 t = unit_name_mangle(*name, MANGLE_GLOB);
2635 if (string_is_glob(t))
2636 r = strv_consume(&globs, t);
2638 r = strv_consume(&mangled, t);
2643 /* Query the manager only if any of the names are a glob, since
2644 * this is fairly expensive */
2645 if (!strv_isempty(globs)) {
2646 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2647 _cleanup_free_ UnitInfo *unit_infos = NULL;
2650 return log_error_errno(ENOTSUP, "Unit name globbing without bus is not implemented.");
2652 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2656 for (i = 0; i < r; i++)
2657 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2662 mangled = NULL; /* do not free */
2667 static const struct {
2671 } action_table[_ACTION_MAX] = {
2672 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2673 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2674 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2675 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2676 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
2677 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
2678 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
2679 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
2680 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2681 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2682 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2683 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2684 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2685 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2686 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2689 static enum action verb_to_action(const char *verb) {
2692 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2693 if (streq_ptr(action_table[i].verb, verb))
2696 return _ACTION_INVALID;
2699 static int start_unit(sd_bus *bus, char **args) {
2700 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
2701 const char *method, *mode, *one_name, *suffix = NULL;
2702 _cleanup_strv_free_ char **names = NULL;
2708 ask_password_agent_open_if_enabled();
2710 if (arg_action == ACTION_SYSTEMCTL) {
2712 method = verb_to_method(args[0]);
2713 action = verb_to_action(args[0]);
2715 if (streq(args[0], "isolate")) {
2719 mode = action_table[action].mode ?: arg_job_mode;
2721 one_name = action_table[action].target;
2723 assert(arg_action < ELEMENTSOF(action_table));
2724 assert(action_table[arg_action].target);
2726 method = "StartUnit";
2728 mode = action_table[arg_action].mode;
2729 one_name = action_table[arg_action].target;
2733 names = strv_new(one_name, NULL);
2735 r = expand_names(bus, args + 1, suffix, &names);
2737 log_error_errno(r, "Failed to expand names: %m");
2740 if (!arg_no_block) {
2741 r = bus_wait_for_jobs_new(bus, &w);
2743 return log_error_errno(r, "Could not watch jobs: %m");
2746 STRV_FOREACH(name, names) {
2747 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2750 q = start_unit_one(bus, method, *name, mode, &error, w);
2751 if (r >= 0 && q < 0)
2752 r = translate_bus_error_to_exit_status(q, &error);
2755 if (!arg_no_block) {
2758 q = bus_wait_for_jobs(w, arg_quiet);
2762 /* When stopping units, warn if they can still be triggered by
2763 * another active unit (socket, path, timer) */
2764 if (!arg_quiet && streq(method, "StopUnit"))
2765 STRV_FOREACH(name, names)
2766 check_triggering_units(bus, *name);
2772 /* Ask systemd-logind, which might grant access to unprivileged users
2773 * through PolicyKit */
2774 static int reboot_with_logind(sd_bus *bus, enum action a) {
2776 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2783 polkit_agent_open_if_enabled();
2791 case ACTION_POWEROFF:
2792 method = "PowerOff";
2795 case ACTION_SUSPEND:
2799 case ACTION_HIBERNATE:
2800 method = "Hibernate";
2803 case ACTION_HYBRID_SLEEP:
2804 method = "HybridSleep";
2811 r = sd_bus_call_method(
2813 "org.freedesktop.login1",
2814 "/org/freedesktop/login1",
2815 "org.freedesktop.login1.Manager",
2819 "b", arg_ask_password);
2821 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2829 static int check_inhibitors(sd_bus *bus, enum action a) {
2831 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2832 _cleanup_strv_free_ char **sessions = NULL;
2833 const char *what, *who, *why, *mode;
2842 if (arg_ignore_inhibitors || arg_force > 0)
2854 r = sd_bus_call_method(
2856 "org.freedesktop.login1",
2857 "/org/freedesktop/login1",
2858 "org.freedesktop.login1.Manager",
2864 /* If logind is not around, then there are no inhibitors... */
2867 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2869 return bus_log_parse_error(r);
2871 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2872 _cleanup_free_ char *comm = NULL, *user = NULL;
2873 _cleanup_strv_free_ char **sv = NULL;
2875 if (!streq(mode, "block"))
2878 sv = strv_split(what, ":");
2882 if (!strv_contains(sv,
2884 a == ACTION_POWEROFF ||
2885 a == ACTION_REBOOT ||
2886 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2889 get_process_comm(pid, &comm);
2890 user = uid_to_name(uid);
2892 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
2893 who, pid, strna(comm), strna(user), why);
2898 return bus_log_parse_error(r);
2900 r = sd_bus_message_exit_container(reply);
2902 return bus_log_parse_error(r);
2904 /* Check for current sessions */
2905 sd_get_sessions(&sessions);
2906 STRV_FOREACH(s, sessions) {
2907 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2909 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2912 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2915 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2918 sd_session_get_tty(*s, &tty);
2919 sd_session_get_seat(*s, &seat);
2920 sd_session_get_service(*s, &service);
2921 user = uid_to_name(uid);
2923 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2930 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2931 action_table[a].verb);
2939 static int start_special(sd_bus *bus, char **args) {
2945 a = verb_to_action(args[0]);
2947 r = check_inhibitors(bus, a);
2951 if (arg_force >= 2 && geteuid() != 0) {
2952 log_error("Must be root.");
2956 if (arg_force >= 2 &&
2957 (a == ACTION_HALT ||
2958 a == ACTION_POWEROFF ||
2959 a == ACTION_REBOOT))
2962 if (arg_force >= 1 &&
2963 (a == ACTION_HALT ||
2964 a == ACTION_POWEROFF ||
2965 a == ACTION_REBOOT ||
2966 a == ACTION_KEXEC ||
2968 return daemon_reload(bus, args);
2970 /* first try logind, to allow authentication with polkit */
2971 if (geteuid() != 0 &&
2972 (a == ACTION_POWEROFF ||
2973 a == ACTION_REBOOT ||
2974 a == ACTION_SUSPEND ||
2975 a == ACTION_HIBERNATE ||
2976 a == ACTION_HYBRID_SLEEP)) {
2977 r = reboot_with_logind(bus, a);
2978 if (r >= 0 || IN_SET(r, -ENOTSUP, -EINPROGRESS))
2982 r = start_unit(bus, args);
2983 if (r == EXIT_SUCCESS)
2989 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
2990 _cleanup_strv_free_ char **names = NULL;
2997 r = expand_names(bus, args, NULL, &names);
2999 return log_error_errno(r, "Failed to expand names: %m");
3001 STRV_FOREACH(name, names) {
3004 state = check_one_unit(bus, *name, good_states, arg_quiet);
3014 static int check_unit_active(sd_bus *bus, char **args) {
3015 /* According to LSB: 3, "program is not running" */
3016 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
3019 static int check_unit_failed(sd_bus *bus, char **args) {
3020 return check_unit_generic(bus, 1, "failed\0", args + 1);
3023 static int kill_unit(sd_bus *bus, char **args) {
3024 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3025 _cleanup_strv_free_ char **names = NULL;
3033 arg_kill_who = "all";
3035 r = expand_names(bus, args + 1, NULL, &names);
3037 log_error_errno(r, "Failed to expand names: %m");
3039 STRV_FOREACH(name, names) {
3040 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3042 q = sd_bus_message_new_method_call(
3045 "org.freedesktop.systemd1",
3046 "/org/freedesktop/systemd1",
3047 "org.freedesktop.systemd1.Manager",
3050 return bus_log_create_error(q);
3052 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
3054 return bus_log_create_error(q);
3056 q = sd_bus_message_append(m, "ssi", *names, arg_kill_who, arg_signal);
3058 return bus_log_create_error(q);
3060 q = sd_bus_call(bus, m, 0, &error, NULL);
3062 log_error("Failed to kill unit %s: %s", *names, bus_error_message(&error, q));
3071 typedef struct ExecStatusInfo {
3079 usec_t start_timestamp;
3080 usec_t exit_timestamp;
3085 LIST_FIELDS(struct ExecStatusInfo, exec);
3088 static void exec_status_info_free(ExecStatusInfo *i) {
3097 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3098 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3101 int32_t code, status;
3107 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3109 return bus_log_parse_error(r);
3113 r = sd_bus_message_read(m, "s", &path);
3115 return bus_log_parse_error(r);
3117 i->path = strdup(path);
3121 r = sd_bus_message_read_strv(m, &i->argv);
3123 return bus_log_parse_error(r);
3125 r = sd_bus_message_read(m,
3128 &start_timestamp, &start_timestamp_monotonic,
3129 &exit_timestamp, &exit_timestamp_monotonic,
3133 return bus_log_parse_error(r);
3136 i->start_timestamp = (usec_t) start_timestamp;
3137 i->exit_timestamp = (usec_t) exit_timestamp;
3138 i->pid = (pid_t) pid;
3142 r = sd_bus_message_exit_container(m);
3144 return bus_log_parse_error(r);
3149 typedef struct UnitStatusInfo {
3151 const char *load_state;
3152 const char *active_state;
3153 const char *sub_state;
3154 const char *unit_file_state;
3155 const char *unit_file_preset;
3157 const char *description;
3158 const char *following;
3160 char **documentation;
3162 const char *fragment_path;
3163 const char *source_path;
3164 const char *control_group;
3166 char **dropin_paths;
3168 const char *load_error;
3171 usec_t inactive_exit_timestamp;
3172 usec_t inactive_exit_timestamp_monotonic;
3173 usec_t active_enter_timestamp;
3174 usec_t active_exit_timestamp;
3175 usec_t inactive_enter_timestamp;
3177 bool need_daemon_reload;
3182 const char *status_text;
3183 const char *pid_file;
3187 usec_t start_timestamp;
3188 usec_t exit_timestamp;
3190 int exit_code, exit_status;
3192 usec_t condition_timestamp;
3193 bool condition_result;
3194 bool failed_condition_trigger;
3195 bool failed_condition_negate;
3196 const char *failed_condition;
3197 const char *failed_condition_parameter;
3199 usec_t assert_timestamp;
3201 bool failed_assert_trigger;
3202 bool failed_assert_negate;
3203 const char *failed_assert;
3204 const char *failed_assert_parameter;
3207 unsigned n_accepted;
3208 unsigned n_connections;
3211 /* Pairs of type, path */
3215 const char *sysfs_path;
3217 /* Mount, Automount */
3223 LIST_HEAD(ExecStatusInfo, exec);
3226 static void print_status_info(
3231 const char *active_on, *active_off, *on, *off, *ss;
3233 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3234 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3240 /* This shows pretty information about a unit. See
3241 * print_property() for a low-level property printer */
3243 if (streq_ptr(i->active_state, "failed")) {
3244 active_on = ansi_highlight_red();
3245 active_off = ansi_highlight_off();
3246 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3247 active_on = ansi_highlight_green();
3248 active_off = ansi_highlight_off();
3250 active_on = active_off = "";
3252 printf("%s%s%s %s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3254 if (i->description && !streq_ptr(i->id, i->description))
3255 printf(" - %s", i->description);
3260 printf(" Follow: unit currently follows state of %s\n", i->following);
3262 if (streq_ptr(i->load_state, "error")) {
3263 on = ansi_highlight_red();
3264 off = ansi_highlight_off();
3268 path = i->source_path ? i->source_path : i->fragment_path;
3271 printf(" Loaded: %s%s%s (Reason: %s)\n",
3272 on, strna(i->load_state), off, i->load_error);
3273 else if (path && !isempty(i->unit_file_state) && !isempty(i->unit_file_preset))
3274 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3275 on, strna(i->load_state), off, path, i->unit_file_state, i->unit_file_preset);
3276 else if (path && !isempty(i->unit_file_state))
3277 printf(" Loaded: %s%s%s (%s; %s)\n",
3278 on, strna(i->load_state), off, path, i->unit_file_state);
3280 printf(" Loaded: %s%s%s (%s)\n",
3281 on, strna(i->load_state), off, path);
3283 printf(" Loaded: %s%s%s\n",
3284 on, strna(i->load_state), off);
3286 if (!strv_isempty(i->dropin_paths)) {
3287 _cleanup_free_ char *dir = NULL;
3291 STRV_FOREACH(dropin, i->dropin_paths) {
3292 if (! dir || last) {
3293 printf(dir ? " " : " Drop-In: ");
3298 if (path_get_parent(*dropin, &dir) < 0) {
3303 printf("%s\n %s", dir,
3304 draw_special_char(DRAW_TREE_RIGHT));
3307 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3309 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3313 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3315 printf(" Active: %s%s (%s)%s",
3316 active_on, strna(i->active_state), ss, active_off);
3318 printf(" Active: %s%s%s",
3319 active_on, strna(i->active_state), active_off);
3321 if (!isempty(i->result) && !streq(i->result, "success"))
3322 printf(" (Result: %s)", i->result);
3324 timestamp = (streq_ptr(i->active_state, "active") ||
3325 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
3326 (streq_ptr(i->active_state, "inactive") ||
3327 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
3328 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
3329 i->active_exit_timestamp;
3331 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3332 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3335 printf(" since %s; %s\n", s2, s1);
3337 printf(" since %s\n", s2);
3341 if (!i->condition_result && i->condition_timestamp > 0) {
3342 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3343 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3345 printf("Condition: start %scondition failed%s at %s%s%s\n",
3346 ansi_highlight_yellow(), ansi_highlight_off(),
3347 s2, s1 ? "; " : "", s1 ? s1 : "");
3348 if (i->failed_condition_trigger)
3349 printf(" none of the trigger conditions were met\n");
3350 else if (i->failed_condition)
3351 printf(" %s=%s%s was not met\n",
3352 i->failed_condition,
3353 i->failed_condition_negate ? "!" : "",
3354 i->failed_condition_parameter);
3357 if (!i->assert_result && i->assert_timestamp > 0) {
3358 s1 = format_timestamp_relative(since1, sizeof(since1), i->assert_timestamp);
3359 s2 = format_timestamp(since2, sizeof(since2), i->assert_timestamp);
3361 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3362 ansi_highlight_red(), ansi_highlight_off(),
3363 s2, s1 ? "; " : "", s1 ? s1 : "");
3364 if (i->failed_assert_trigger)
3365 printf(" none of the trigger assertions were met\n");
3366 else if (i->failed_assert)
3367 printf(" %s=%s%s was not met\n",
3369 i->failed_assert_negate ? "!" : "",
3370 i->failed_assert_parameter);
3374 printf(" Device: %s\n", i->sysfs_path);
3376 printf(" Where: %s\n", i->where);
3378 printf(" What: %s\n", i->what);
3380 STRV_FOREACH(t, i->documentation)
3381 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3383 STRV_FOREACH_PAIR(t, t2, i->listen)
3384 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3387 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3389 LIST_FOREACH(exec, p, i->exec) {
3390 _cleanup_free_ char *argv = NULL;
3393 /* Only show exited processes here */
3397 argv = strv_join(p->argv, " ");
3398 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
3400 good = is_clean_exit_lsb(p->code, p->status, NULL);
3402 on = ansi_highlight_red();
3403 off = ansi_highlight_off();
3407 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3409 if (p->code == CLD_EXITED) {
3412 printf("status=%i", p->status);
3414 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3419 printf("signal=%s", signal_to_string(p->status));
3421 printf(")%s\n", off);
3423 if (i->main_pid == p->pid &&
3424 i->start_timestamp == p->start_timestamp &&
3425 i->exit_timestamp == p->start_timestamp)
3426 /* Let's not show this twice */
3429 if (p->pid == i->control_pid)
3433 if (i->main_pid > 0 || i->control_pid > 0) {
3434 if (i->main_pid > 0) {
3435 printf(" Main PID: "PID_FMT, i->main_pid);
3438 _cleanup_free_ char *comm = NULL;
3439 get_process_comm(i->main_pid, &comm);
3441 printf(" (%s)", comm);
3442 } else if (i->exit_code > 0) {
3443 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3445 if (i->exit_code == CLD_EXITED) {
3448 printf("status=%i", i->exit_status);
3450 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3455 printf("signal=%s", signal_to_string(i->exit_status));
3459 if (i->control_pid > 0)
3463 if (i->control_pid > 0) {
3464 _cleanup_free_ char *c = NULL;
3466 printf(" %8s: "PID_FMT, i->main_pid ? "" : " Control", i->control_pid);
3468 get_process_comm(i->control_pid, &c);
3477 printf(" Status: \"%s\"\n", i->status_text);
3478 if (i->status_errno > 0)
3479 printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
3481 if (i->control_group &&
3482 (i->main_pid > 0 || i->control_pid > 0 ||
3483 ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_MACHINE) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3486 printf(" CGroup: %s\n", i->control_group);
3488 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_MACHINE) {
3491 static const char prefix[] = " ";
3494 if (c > sizeof(prefix) - 1)
3495 c -= sizeof(prefix) - 1;
3499 if (i->main_pid > 0)
3500 extra[k++] = i->main_pid;
3502 if (i->control_pid > 0)
3503 extra[k++] = i->control_pid;
3505 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, get_output_flags());
3509 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3510 show_journal_by_unit(
3515 i->inactive_exit_timestamp_monotonic,
3518 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
3519 SD_JOURNAL_LOCAL_ONLY,
3520 arg_scope == UNIT_FILE_SYSTEM,
3524 if (i->need_daemon_reload)
3525 warn_unit_file_changed(i->id);
3528 static void show_unit_help(UnitStatusInfo *i) {
3533 if (!i->documentation) {
3534 log_info("Documentation for %s not known.", i->id);
3538 STRV_FOREACH(p, i->documentation)
3539 if (startswith(*p, "man:"))
3540 show_man_page(*p + 4, false);
3542 log_info("Can't show: %s", *p);
3545 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3552 switch (contents[0]) {
3554 case SD_BUS_TYPE_STRING: {
3557 r = sd_bus_message_read(m, "s", &s);
3559 return bus_log_parse_error(r);
3562 if (streq(name, "Id"))
3564 else if (streq(name, "LoadState"))
3566 else if (streq(name, "ActiveState"))
3567 i->active_state = s;
3568 else if (streq(name, "SubState"))
3570 else if (streq(name, "Description"))
3572 else if (streq(name, "FragmentPath"))
3573 i->fragment_path = s;
3574 else if (streq(name, "SourcePath"))
3577 else if (streq(name, "DefaultControlGroup")) {
3579 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3581 i->control_group = e;
3584 else if (streq(name, "ControlGroup"))
3585 i->control_group = s;
3586 else if (streq(name, "StatusText"))
3588 else if (streq(name, "PIDFile"))
3590 else if (streq(name, "SysFSPath"))
3592 else if (streq(name, "Where"))
3594 else if (streq(name, "What"))
3596 else if (streq(name, "Following"))
3598 else if (streq(name, "UnitFileState"))
3599 i->unit_file_state = s;
3600 else if (streq(name, "UnitFilePreset"))
3601 i->unit_file_preset = s;
3602 else if (streq(name, "Result"))
3609 case SD_BUS_TYPE_BOOLEAN: {
3612 r = sd_bus_message_read(m, "b", &b);
3614 return bus_log_parse_error(r);
3616 if (streq(name, "Accept"))
3618 else if (streq(name, "NeedDaemonReload"))
3619 i->need_daemon_reload = b;
3620 else if (streq(name, "ConditionResult"))
3621 i->condition_result = b;
3622 else if (streq(name, "AssertResult"))
3623 i->assert_result = b;
3628 case SD_BUS_TYPE_UINT32: {
3631 r = sd_bus_message_read(m, "u", &u);
3633 return bus_log_parse_error(r);
3635 if (streq(name, "MainPID")) {
3637 i->main_pid = (pid_t) u;
3640 } else if (streq(name, "ControlPID"))
3641 i->control_pid = (pid_t) u;
3642 else if (streq(name, "ExecMainPID")) {
3644 i->main_pid = (pid_t) u;
3645 } else if (streq(name, "NAccepted"))
3647 else if (streq(name, "NConnections"))
3648 i->n_connections = u;
3653 case SD_BUS_TYPE_INT32: {
3656 r = sd_bus_message_read(m, "i", &j);
3658 return bus_log_parse_error(r);
3660 if (streq(name, "ExecMainCode"))
3661 i->exit_code = (int) j;
3662 else if (streq(name, "ExecMainStatus"))
3663 i->exit_status = (int) j;
3664 else if (streq(name, "StatusErrno"))
3665 i->status_errno = (int) j;
3670 case SD_BUS_TYPE_UINT64: {
3673 r = sd_bus_message_read(m, "t", &u);
3675 return bus_log_parse_error(r);
3677 if (streq(name, "ExecMainStartTimestamp"))
3678 i->start_timestamp = (usec_t) u;
3679 else if (streq(name, "ExecMainExitTimestamp"))
3680 i->exit_timestamp = (usec_t) u;
3681 else if (streq(name, "ActiveEnterTimestamp"))
3682 i->active_enter_timestamp = (usec_t) u;
3683 else if (streq(name, "InactiveEnterTimestamp"))
3684 i->inactive_enter_timestamp = (usec_t) u;
3685 else if (streq(name, "InactiveExitTimestamp"))
3686 i->inactive_exit_timestamp = (usec_t) u;
3687 else if (streq(name, "InactiveExitTimestampMonotonic"))
3688 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3689 else if (streq(name, "ActiveExitTimestamp"))
3690 i->active_exit_timestamp = (usec_t) u;
3691 else if (streq(name, "ConditionTimestamp"))
3692 i->condition_timestamp = (usec_t) u;
3693 else if (streq(name, "AssertTimestamp"))
3694 i->assert_timestamp = (usec_t) u;
3699 case SD_BUS_TYPE_ARRAY:
3701 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3702 _cleanup_free_ ExecStatusInfo *info = NULL;
3704 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3706 return bus_log_parse_error(r);
3708 info = new0(ExecStatusInfo, 1);
3712 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3714 info->name = strdup(name);
3718 LIST_PREPEND(exec, i->exec, info);
3720 info = new0(ExecStatusInfo, 1);
3726 return bus_log_parse_error(r);
3728 r = sd_bus_message_exit_container(m);
3730 return bus_log_parse_error(r);
3734 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3735 const char *type, *path;
3737 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3739 return bus_log_parse_error(r);
3741 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3743 r = strv_extend(&i->listen, type);
3747 r = strv_extend(&i->listen, path);
3752 return bus_log_parse_error(r);
3754 r = sd_bus_message_exit_container(m);
3756 return bus_log_parse_error(r);
3760 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3762 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3764 return bus_log_parse_error(r);
3766 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3768 r = sd_bus_message_read_strv(m, &i->documentation);
3770 return bus_log_parse_error(r);
3772 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3773 const char *cond, *param;
3774 int trigger, negate;
3777 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3779 return bus_log_parse_error(r);
3781 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3782 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3783 if (state < 0 && (!trigger || !i->failed_condition)) {
3784 i->failed_condition = cond;
3785 i->failed_condition_trigger = trigger;
3786 i->failed_condition_negate = negate;
3787 i->failed_condition_parameter = param;
3791 return bus_log_parse_error(r);
3793 r = sd_bus_message_exit_container(m);
3795 return bus_log_parse_error(r);
3797 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Asserts")) {
3798 const char *cond, *param;
3799 int trigger, negate;
3802 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3804 return bus_log_parse_error(r);
3806 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3807 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3808 if (state < 0 && (!trigger || !i->failed_assert)) {
3809 i->failed_assert = cond;
3810 i->failed_assert_trigger = trigger;
3811 i->failed_assert_negate = negate;
3812 i->failed_assert_parameter = param;
3816 return bus_log_parse_error(r);
3818 r = sd_bus_message_exit_container(m);
3820 return bus_log_parse_error(r);
3827 case SD_BUS_TYPE_STRUCT_BEGIN:
3829 if (streq(name, "LoadError")) {
3830 const char *n, *message;
3832 r = sd_bus_message_read(m, "(ss)", &n, &message);
3834 return bus_log_parse_error(r);
3836 if (!isempty(message))
3837 i->load_error = message;
3850 r = sd_bus_message_skip(m, contents);
3852 return bus_log_parse_error(r);
3857 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3863 /* This is a low-level property printer, see
3864 * print_status_info() for the nicer output */
3866 if (arg_properties && !strv_find(arg_properties, name)) {
3867 /* skip what we didn't read */
3868 r = sd_bus_message_skip(m, contents);
3872 switch (contents[0]) {
3874 case SD_BUS_TYPE_STRUCT_BEGIN:
3876 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3879 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3881 return bus_log_parse_error(r);
3884 printf("%s=%"PRIu32"\n", name, u);
3886 printf("%s=\n", name);
3890 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3893 r = sd_bus_message_read(m, "(so)", &s, NULL);
3895 return bus_log_parse_error(r);
3897 if (arg_all || !isempty(s))
3898 printf("%s=%s\n", name, s);
3902 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3903 const char *a = NULL, *b = NULL;
3905 r = sd_bus_message_read(m, "(ss)", &a, &b);
3907 return bus_log_parse_error(r);
3909 if (arg_all || !isempty(a) || !isempty(b))
3910 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3913 } else if (streq_ptr(name, "SystemCallFilter")) {
3914 _cleanup_strv_free_ char **l = NULL;
3917 r = sd_bus_message_enter_container(m, 'r', "bas");
3919 return bus_log_parse_error(r);
3921 r = sd_bus_message_read(m, "b", &whitelist);
3923 return bus_log_parse_error(r);
3925 r = sd_bus_message_read_strv(m, &l);
3927 return bus_log_parse_error(r);
3929 r = sd_bus_message_exit_container(m);
3931 return bus_log_parse_error(r);
3933 if (arg_all || whitelist || !strv_isempty(l)) {
3937 fputs(name, stdout);
3943 STRV_FOREACH(i, l) {
3951 fputc('\n', stdout);
3959 case SD_BUS_TYPE_ARRAY:
3961 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
3965 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
3967 return bus_log_parse_error(r);
3969 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
3970 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3973 return bus_log_parse_error(r);
3975 r = sd_bus_message_exit_container(m);
3977 return bus_log_parse_error(r);
3981 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
3982 const char *type, *path;
3984 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3986 return bus_log_parse_error(r);
3988 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3989 printf("%s=%s\n", type, path);
3991 return bus_log_parse_error(r);
3993 r = sd_bus_message_exit_container(m);
3995 return bus_log_parse_error(r);
3999 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
4000 const char *type, *path;
4002 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4004 return bus_log_parse_error(r);
4006 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4007 printf("Listen%s=%s\n", type, path);
4009 return bus_log_parse_error(r);
4011 r = sd_bus_message_exit_container(m);
4013 return bus_log_parse_error(r);
4017 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
4019 uint64_t value, next_elapse;
4021 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
4023 return bus_log_parse_error(r);
4025 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
4026 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
4028 printf("%s={ value=%s ; next_elapse=%s }\n",
4030 format_timespan(timespan1, sizeof(timespan1), value, 0),
4031 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
4034 return bus_log_parse_error(r);
4036 r = sd_bus_message_exit_container(m);
4038 return bus_log_parse_error(r);
4042 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
4043 ExecStatusInfo info = {};
4045 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
4047 return bus_log_parse_error(r);
4049 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
4050 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
4051 _cleanup_free_ char *tt;
4053 tt = strv_join(info.argv, " ");
4055 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",
4059 yes_no(info.ignore),
4060 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
4061 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
4063 sigchld_code_to_string(info.code),
4065 info.code == CLD_EXITED ? "" : "/",
4066 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
4069 strv_free(info.argv);
4073 r = sd_bus_message_exit_container(m);
4075 return bus_log_parse_error(r);
4079 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
4080 const char *path, *rwm;
4082 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4084 return bus_log_parse_error(r);
4086 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
4087 printf("%s=%s %s\n", name, strna(path), strna(rwm));
4089 return bus_log_parse_error(r);
4091 r = sd_bus_message_exit_container(m);
4093 return bus_log_parse_error(r);
4097 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
4101 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4103 return bus_log_parse_error(r);
4105 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4106 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
4108 return bus_log_parse_error(r);
4110 r = sd_bus_message_exit_container(m);
4112 return bus_log_parse_error(r);
4116 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
4120 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4122 return bus_log_parse_error(r);
4124 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4125 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
4127 return bus_log_parse_error(r);
4129 r = sd_bus_message_exit_container(m);
4131 return bus_log_parse_error(r);
4139 r = bus_print_property(name, m, arg_all);
4141 return bus_log_parse_error(r);
4144 r = sd_bus_message_skip(m, contents);
4146 return bus_log_parse_error(r);
4149 printf("%s=[unprintable]\n", name);
4155 static int show_one(
4159 bool show_properties,
4163 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4164 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4165 UnitStatusInfo info = {};
4172 log_debug("Showing one %s", path);
4174 r = sd_bus_call_method(
4176 "org.freedesktop.systemd1",
4178 "org.freedesktop.DBus.Properties",
4184 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4188 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4190 return bus_log_parse_error(r);
4197 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4198 const char *name, *contents;
4200 r = sd_bus_message_read(reply, "s", &name);
4202 return bus_log_parse_error(r);
4204 r = sd_bus_message_peek_type(reply, NULL, &contents);
4206 return bus_log_parse_error(r);
4208 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4210 return bus_log_parse_error(r);
4212 if (show_properties)
4213 r = print_property(name, reply, contents);
4215 r = status_property(name, reply, &info, contents);
4219 r = sd_bus_message_exit_container(reply);
4221 return bus_log_parse_error(r);
4223 r = sd_bus_message_exit_container(reply);
4225 return bus_log_parse_error(r);
4228 return bus_log_parse_error(r);
4230 r = sd_bus_message_exit_container(reply);
4232 return bus_log_parse_error(r);
4236 if (!show_properties) {
4237 if (streq(verb, "help"))
4238 show_unit_help(&info);
4240 print_status_info(&info, ellipsized);
4243 strv_free(info.documentation);
4244 strv_free(info.dropin_paths);
4245 strv_free(info.listen);
4247 if (!streq_ptr(info.active_state, "active") &&
4248 !streq_ptr(info.active_state, "reloading") &&
4249 streq(verb, "status")) {
4250 /* According to LSB: "program not running" */
4251 /* 0: program is running or service is OK
4252 * 1: program is dead and /run PID file exists
4253 * 2: program is dead and /run/lock lock file exists
4254 * 3: program is not running
4255 * 4: program or service status is unknown
4257 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4263 while ((p = info.exec)) {
4264 LIST_REMOVE(exec, info.exec, p);
4265 exec_status_info_free(p);
4271 static int get_unit_dbus_path_by_pid(
4276 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4277 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4281 r = sd_bus_call_method(
4283 "org.freedesktop.systemd1",
4284 "/org/freedesktop/systemd1",
4285 "org.freedesktop.systemd1.Manager",
4291 log_error("Failed to get unit for PID "PID_FMT": %s", pid, bus_error_message(&error, r));
4295 r = sd_bus_message_read(reply, "o", &u);
4297 return bus_log_parse_error(r);
4307 static int show_all(
4310 bool show_properties,
4314 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4315 _cleanup_free_ UnitInfo *unit_infos = NULL;
4320 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4324 pager_open_if_enabled();
4328 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4330 for (u = unit_infos; u < unit_infos + c; u++) {
4331 _cleanup_free_ char *p = NULL;
4333 p = unit_dbus_path_from_name(u->id);
4337 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4340 else if (r > 0 && ret == 0)
4347 static int show_system_status(sd_bus *bus) {
4348 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4349 _cleanup_free_ char *hn = NULL;
4350 struct machine_info mi = {};
4351 const char *on, *off;
4354 hn = gethostname_malloc();
4358 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4360 return log_error_errno(r, "Failed to read server status: %m");
4362 if (streq_ptr(mi.state, "degraded")) {
4363 on = ansi_highlight_red();
4364 off = ansi_highlight_off();
4365 } else if (!streq_ptr(mi.state, "running")) {
4366 on = ansi_highlight_yellow();
4367 off = ansi_highlight_off();
4371 printf("%s%s%s %s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4373 printf(" State: %s%s%s\n",
4374 on, strna(mi.state), off);
4376 printf(" Jobs: %u queued\n", mi.n_jobs);
4377 printf(" Failed: %u units\n", mi.n_failed_units);
4379 printf(" Since: %s; %s\n",
4380 format_timestamp(since2, sizeof(since2), mi.timestamp),
4381 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4383 printf(" CGroup: %s\n", mi.control_group ?: "/");
4384 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_MACHINE) {
4385 static const char prefix[] = " ";
4389 if (c > sizeof(prefix) - 1)
4390 c -= sizeof(prefix) - 1;
4394 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, get_output_flags());
4398 free(mi.control_group);
4403 static int show(sd_bus *bus, char **args) {
4404 bool show_properties, show_status, new_line = false;
4405 bool ellipsized = false;
4411 show_properties = streq(args[0], "show");
4412 show_status = streq(args[0], "status");
4414 if (show_properties)
4415 pager_open_if_enabled();
4417 /* If no argument is specified inspect the manager itself */
4419 if (show_properties && strv_length(args) <= 1)
4420 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4422 if (show_status && strv_length(args) <= 1) {
4424 pager_open_if_enabled();
4425 show_system_status(bus);
4429 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4431 _cleanup_free_ char **patterns = NULL;
4434 STRV_FOREACH(name, args + 1) {
4435 _cleanup_free_ char *unit = NULL;
4438 if (safe_atou32(*name, &id) < 0) {
4439 if (strv_push(&patterns, *name) < 0)
4443 } else if (show_properties) {
4444 /* Interpret as job id */
4445 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4449 /* Interpret as PID */
4450 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4457 r = show_one(args[0], bus, unit, show_properties,
4458 &new_line, &ellipsized);
4461 else if (r > 0 && ret == 0)
4465 if (!strv_isempty(patterns)) {
4466 _cleanup_strv_free_ char **names = NULL;
4468 r = expand_names(bus, patterns, NULL, &names);
4470 log_error_errno(r, "Failed to expand names: %m");
4472 STRV_FOREACH(name, names) {
4473 _cleanup_free_ char *unit;
4475 unit = unit_dbus_path_from_name(*name);
4479 r = show_one(args[0], bus, unit, show_properties,
4480 &new_line, &ellipsized);
4483 else if (r > 0 && ret == 0)
4489 if (ellipsized && !arg_quiet)
4490 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4495 static int init_home_and_lookup_paths(char **user_home, char **user_runtime, LookupPaths *lp) {
4499 assert(user_runtime);
4502 if (arg_scope == UNIT_FILE_USER) {
4503 r = user_config_home(user_home);
4505 return log_error_errno(r, "Failed to query XDG_CONFIG_HOME: %m");
4507 return log_error_errno(ENOTDIR, "Cannot find units: $XDG_CONFIG_HOME and $HOME are not set.");
4509 r = user_runtime_dir(user_runtime);
4511 return log_error_errno(r, "Failed to query XDG_CONFIG_HOME: %m");
4513 return log_error_errno(ENOTDIR, "Cannot find units: $XDG_RUNTIME_DIR is not set.");
4516 r = lookup_paths_init_from_scope(lp, arg_scope, arg_root);
4518 return log_error_errno(r, "Failed to lookup unit lookup paths: %m");
4523 static int cat(sd_bus *bus, char **args) {
4524 _cleanup_free_ char *user_home = NULL;
4525 _cleanup_free_ char *user_runtime = NULL;
4526 _cleanup_lookup_paths_free_ LookupPaths lp = {};
4527 _cleanup_strv_free_ char **names = NULL;
4529 bool first = true, avoid_bus_cache;
4534 r = init_home_and_lookup_paths(&user_home, &user_runtime, &lp);
4538 r = expand_names(bus, args + 1, NULL, &names);
4540 log_error_errno(r, "Failed to expand names: %m");
4542 avoid_bus_cache = !bus || avoid_bus();
4544 pager_open_if_enabled();
4546 STRV_FOREACH(name, names) {
4547 _cleanup_free_ char *fragment_path = NULL;
4548 _cleanup_strv_free_ char **dropin_paths = NULL;
4551 r = unit_find_paths(bus, *name, avoid_bus_cache, &lp, &fragment_path, &dropin_paths);
4555 log_warning("Unit %s does not have any files on disk", *name);
4564 if (fragment_path) {
4565 printf("%s# %s%s\n",
4566 ansi_highlight_blue(),
4568 ansi_highlight_off());
4571 r = copy_file_fd(fragment_path, STDOUT_FILENO, false);
4573 log_warning_errno(r, "Failed to cat %s: %m", fragment_path);
4578 STRV_FOREACH(path, dropin_paths) {
4579 printf("%s%s# %s%s\n",
4580 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4581 ansi_highlight_blue(),
4583 ansi_highlight_off());
4586 r = copy_file_fd(*path, STDOUT_FILENO, false);
4588 log_warning_errno(r, "Failed to cat %s: %m", *path);
4594 return r < 0 ? r : 0;
4597 static int set_property(sd_bus *bus, char **args) {
4598 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4599 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4600 _cleanup_free_ char *n = NULL;
4604 r = sd_bus_message_new_method_call(
4607 "org.freedesktop.systemd1",
4608 "/org/freedesktop/systemd1",
4609 "org.freedesktop.systemd1.Manager",
4610 "SetUnitProperties");
4612 return bus_log_create_error(r);
4614 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4616 return bus_log_create_error(r);
4618 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4622 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4624 return bus_log_create_error(r);
4626 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4628 return bus_log_create_error(r);
4630 STRV_FOREACH(i, args + 2) {
4631 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4633 return bus_log_create_error(r);
4635 r = bus_append_unit_property_assignment(m, *i);
4639 r = sd_bus_message_close_container(m);
4641 return bus_log_create_error(r);
4644 r = sd_bus_message_close_container(m);
4646 return bus_log_create_error(r);
4648 r = sd_bus_call(bus, m, 0, &error, NULL);
4650 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4657 static int snapshot(sd_bus *bus, char **args) {
4658 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4659 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
4660 _cleanup_free_ char *n = NULL, *id = NULL;
4664 if (strv_length(args) > 1)
4665 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4671 r = sd_bus_message_new_method_call(
4674 "org.freedesktop.systemd1",
4675 "/org/freedesktop/systemd1",
4676 "org.freedesktop.systemd1.Manager",
4679 return bus_log_create_error(r);
4681 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4683 return bus_log_create_error(r);
4685 r = sd_bus_message_append(m, "sb", n, false);
4687 return bus_log_create_error(r);
4689 r = sd_bus_call(bus, m, 0, &error, &reply);
4691 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4695 r = sd_bus_message_read(reply, "o", &path);
4697 return bus_log_parse_error(r);
4699 r = sd_bus_get_property_string(
4701 "org.freedesktop.systemd1",
4703 "org.freedesktop.systemd1.Unit",
4708 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4718 static int delete_snapshot(sd_bus *bus, char **args) {
4719 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4720 _cleanup_strv_free_ char **names = NULL;
4726 r = expand_names(bus, args + 1, ".snapshot", &names);
4728 log_error_errno(r, "Failed to expand names: %m");
4730 STRV_FOREACH(name, names) {
4731 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4734 q = sd_bus_message_new_method_call(
4737 "org.freedesktop.systemd1",
4738 "/org/freedesktop/systemd1",
4739 "org.freedesktop.systemd1.Manager",
4742 return bus_log_create_error(q);
4744 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4746 return bus_log_create_error(q);
4748 q = sd_bus_message_append(m, "s", *name);
4750 return bus_log_create_error(q);
4752 q = sd_bus_call(bus, m, 0, &error, NULL);
4754 log_error("Failed to remove snapshot %s: %s", *name, bus_error_message(&error, q));
4763 static int daemon_reload(sd_bus *bus, char **args) {
4764 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4765 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4769 if (arg_action == ACTION_RELOAD)
4771 else if (arg_action == ACTION_REEXEC)
4772 method = "Reexecute";
4774 assert(arg_action == ACTION_SYSTEMCTL);
4777 streq(args[0], "clear-jobs") ||
4778 streq(args[0], "cancel") ? "ClearJobs" :
4779 streq(args[0], "daemon-reexec") ? "Reexecute" :
4780 streq(args[0], "reset-failed") ? "ResetFailed" :
4781 streq(args[0], "halt") ? "Halt" :
4782 streq(args[0], "poweroff") ? "PowerOff" :
4783 streq(args[0], "reboot") ? "Reboot" :
4784 streq(args[0], "kexec") ? "KExec" :
4785 streq(args[0], "exit") ? "Exit" :
4786 /* "daemon-reload" */ "Reload";
4789 r = sd_bus_message_new_method_call(
4792 "org.freedesktop.systemd1",
4793 "/org/freedesktop/systemd1",
4794 "org.freedesktop.systemd1.Manager",
4797 return bus_log_create_error(r);
4799 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4801 return bus_log_create_error(r);
4803 r = sd_bus_call(bus, m, 0, &error, NULL);
4804 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4805 /* There's always a fallback possible for
4806 * legacy actions. */
4808 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4809 /* On reexecution, we expect a disconnect, not a
4813 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4815 return r < 0 ? r : 0;
4818 static int reset_failed(sd_bus *bus, char **args) {
4819 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4820 _cleanup_strv_free_ char **names = NULL;
4824 if (strv_length(args) <= 1)
4825 return daemon_reload(bus, args);
4827 r = expand_names(bus, args + 1, NULL, &names);
4829 log_error_errno(r, "Failed to expand names: %m");
4831 STRV_FOREACH(name, names) {
4832 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4834 q = sd_bus_message_new_method_call(
4837 "org.freedesktop.systemd1",
4838 "/org/freedesktop/systemd1",
4839 "org.freedesktop.systemd1.Manager",
4842 return bus_log_create_error(q);
4844 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4846 return bus_log_create_error(q);
4848 q = sd_bus_message_append(m, "s", *name);
4850 return bus_log_create_error(q);
4852 q = sd_bus_call(bus, m, 0, &error, NULL);
4854 log_error("Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q));
4863 static int show_environment(sd_bus *bus, char **args) {
4864 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4865 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4869 pager_open_if_enabled();
4871 r = sd_bus_get_property(
4873 "org.freedesktop.systemd1",
4874 "/org/freedesktop/systemd1",
4875 "org.freedesktop.systemd1.Manager",
4881 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4885 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4887 return bus_log_parse_error(r);
4889 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4892 return bus_log_parse_error(r);
4894 r = sd_bus_message_exit_container(reply);
4896 return bus_log_parse_error(r);
4901 static int switch_root(sd_bus *bus, char **args) {
4902 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4903 _cleanup_free_ char *cmdline_init = NULL;
4904 const char *root, *init;
4908 l = strv_length(args);
4909 if (l < 2 || l > 3) {
4910 log_error("Wrong number of arguments.");
4919 r = parse_env_file("/proc/cmdline", WHITESPACE,
4920 "init", &cmdline_init,
4923 log_debug_errno(r, "Failed to parse /proc/cmdline: %m");
4925 init = cmdline_init;
4932 const char *root_systemd_path = NULL, *root_init_path = NULL;
4934 root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
4935 root_init_path = strappenda(root, "/", init);
4937 /* If the passed init is actually the same as the
4938 * systemd binary, then let's suppress it. */
4939 if (files_same(root_init_path, root_systemd_path) > 0)
4943 log_debug("Switching root - root: %s; init: %s", root, strna(init));
4945 r = sd_bus_call_method(
4947 "org.freedesktop.systemd1",
4948 "/org/freedesktop/systemd1",
4949 "org.freedesktop.systemd1.Manager",
4955 log_error("Failed to switch root: %s", bus_error_message(&error, r));
4962 static int set_environment(sd_bus *bus, char **args) {
4963 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4964 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4971 method = streq(args[0], "set-environment")
4973 : "UnsetEnvironment";
4975 r = sd_bus_message_new_method_call(
4978 "org.freedesktop.systemd1",
4979 "/org/freedesktop/systemd1",
4980 "org.freedesktop.systemd1.Manager",
4983 return bus_log_create_error(r);
4985 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4987 return bus_log_create_error(r);
4989 r = sd_bus_message_append_strv(m, args + 1);
4991 return bus_log_create_error(r);
4993 r = sd_bus_call(bus, m, 0, &error, NULL);
4995 log_error("Failed to set environment: %s", bus_error_message(&error, r));
5002 static int import_environment(sd_bus *bus, char **args) {
5003 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5004 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
5010 r = sd_bus_message_new_method_call(
5013 "org.freedesktop.systemd1",
5014 "/org/freedesktop/systemd1",
5015 "org.freedesktop.systemd1.Manager",
5018 return bus_log_create_error(r);
5020 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5022 return bus_log_create_error(r);
5024 if (strv_isempty(args + 1))
5025 r = sd_bus_message_append_strv(m, environ);
5029 r = sd_bus_message_open_container(m, 'a', "s");
5031 return bus_log_create_error(r);
5033 STRV_FOREACH(a, args + 1) {
5035 if (!env_name_is_valid(*a)) {
5036 log_error("Not a valid environment variable name: %s", *a);
5040 STRV_FOREACH(b, environ) {
5043 eq = startswith(*b, *a);
5044 if (eq && *eq == '=') {
5046 r = sd_bus_message_append(m, "s", *b);
5048 return bus_log_create_error(r);
5055 r = sd_bus_message_close_container(m);
5058 return bus_log_create_error(r);
5060 r = sd_bus_call(bus, m, 0, &error, NULL);
5062 log_error("Failed to import environment: %s", bus_error_message(&error, r));
5069 static int enable_sysv_units(const char *verb, char **args) {
5072 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
5074 _cleanup_lookup_paths_free_ LookupPaths paths = {};
5076 if (arg_scope != UNIT_FILE_SYSTEM)
5079 if (!streq(verb, "enable") &&
5080 !streq(verb, "disable") &&
5081 !streq(verb, "is-enabled"))
5084 /* Processes all SysV units, and reshuffles the array so that
5085 * afterwards only the native units remain */
5087 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, arg_root, NULL, NULL, NULL);
5094 _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL;
5095 bool found_native = false, found_sysv;
5097 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
5105 if (!endswith(name, ".service"))
5108 if (path_is_absolute(name))
5111 STRV_FOREACH(k, paths.unit_path) {
5112 _cleanup_free_ char *path = NULL;
5114 path = path_join(arg_root, *k, name);
5118 found_native = access(path, F_OK) >= 0;
5126 p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name);
5130 p[strlen(p) - strlen(".service")] = 0;
5131 found_sysv = access(p, F_OK) >= 0;
5135 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
5137 if (!isempty(arg_root))
5138 argv[c++] = q = strappend("--root=", arg_root);
5140 argv[c++] = basename(p);
5142 streq(verb, "enable") ? "on" :
5143 streq(verb, "disable") ? "off" : "--level=5";
5146 l = strv_join((char**)argv, " ");
5150 log_info("Executing %s", l);
5154 return log_error_errno(errno, "Failed to fork: %m");
5155 else if (pid == 0) {
5158 execv(argv[0], (char**) argv);
5159 _exit(EXIT_FAILURE);
5162 j = wait_for_terminate(pid, &status);
5164 log_error_errno(r, "Failed to wait for child: %m");
5168 if (status.si_code == CLD_EXITED) {
5169 if (streq(verb, "is-enabled")) {
5170 if (status.si_status == 0) {
5179 } else if (status.si_status != 0)
5184 /* Remove this entry, so that we don't try enabling it as native unit */
5187 assert(args[f] == name);
5188 strv_remove(args, name);
5195 static int mangle_names(char **original_names, char ***mangled_names) {
5196 char **i, **l, **name;
5198 l = new(char*, strv_length(original_names) + 1);
5203 STRV_FOREACH(name, original_names) {
5205 /* When enabling units qualified path names are OK,
5206 * too, hence allow them explicitly. */
5211 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5227 static int enable_unit(sd_bus *bus, char **args) {
5228 _cleanup_strv_free_ char **names = NULL;
5229 const char *verb = args[0];
5230 UnitFileChange *changes = NULL;
5231 unsigned n_changes = 0;
5232 int carries_install_info = -1;
5238 r = mangle_names(args+1, &names);
5242 r = enable_sysv_units(verb, names);
5246 /* If the operation was fully executed by the SysV compat,
5247 * let's finish early */
5248 if (strv_isempty(names))
5251 if (!bus || avoid_bus()) {
5252 if (streq(verb, "enable")) {
5253 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5254 carries_install_info = r;
5255 } else if (streq(verb, "disable"))
5256 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5257 else if (streq(verb, "reenable")) {
5258 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5259 carries_install_info = r;
5260 } else if (streq(verb, "link"))
5261 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5262 else if (streq(verb, "preset")) {
5263 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_preset_mode, arg_force, &changes, &n_changes);
5264 carries_install_info = r;
5265 } else if (streq(verb, "mask"))
5266 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5267 else if (streq(verb, "unmask"))
5268 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5270 assert_not_reached("Unknown verb");
5273 log_error_errno(r, "Operation failed: %m");
5278 dump_unit_file_changes(changes, n_changes);
5282 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5283 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5284 int expect_carries_install_info = false;
5285 bool send_force = true, send_preset_mode = false;
5288 if (streq(verb, "enable")) {
5289 method = "EnableUnitFiles";
5290 expect_carries_install_info = true;
5291 } else if (streq(verb, "disable")) {
5292 method = "DisableUnitFiles";
5294 } else if (streq(verb, "reenable")) {
5295 method = "ReenableUnitFiles";
5296 expect_carries_install_info = true;
5297 } else if (streq(verb, "link"))
5298 method = "LinkUnitFiles";
5299 else if (streq(verb, "preset")) {
5301 if (arg_preset_mode != UNIT_FILE_PRESET_FULL) {
5302 method = "PresetUnitFilesWithMode";
5303 send_preset_mode = true;
5305 method = "PresetUnitFiles";
5307 expect_carries_install_info = true;
5308 } else if (streq(verb, "mask"))
5309 method = "MaskUnitFiles";
5310 else if (streq(verb, "unmask")) {
5311 method = "UnmaskUnitFiles";
5314 assert_not_reached("Unknown verb");
5316 r = sd_bus_message_new_method_call(
5319 "org.freedesktop.systemd1",
5320 "/org/freedesktop/systemd1",
5321 "org.freedesktop.systemd1.Manager",
5324 return bus_log_create_error(r);
5326 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5328 return bus_log_create_error(r);
5330 r = sd_bus_message_append_strv(m, names);
5332 return bus_log_create_error(r);
5334 if (send_preset_mode) {
5335 r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode));
5337 return bus_log_create_error(r);
5340 r = sd_bus_message_append(m, "b", arg_runtime);
5342 return bus_log_create_error(r);
5345 r = sd_bus_message_append(m, "b", arg_force);
5347 return bus_log_create_error(r);
5350 r = sd_bus_call(bus, m, 0, &error, &reply);
5352 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5356 if (expect_carries_install_info) {
5357 r = sd_bus_message_read(reply, "b", &carries_install_info);
5359 return bus_log_parse_error(r);
5362 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
5366 /* Try to reload if enabled */
5368 r = daemon_reload(bus, args);
5373 if (carries_install_info == 0)
5374 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5375 "using systemctl.\n"
5376 "Possible reasons for having this kind of units are:\n"
5377 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5378 " .wants/ or .requires/ directory.\n"
5379 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5380 " a requirement dependency on it.\n"
5381 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5382 " D-Bus, udev, scripted systemctl call, ...).\n");
5385 unit_file_changes_free(changes, n_changes);
5390 static int add_dependency(sd_bus *bus, char **args) {
5391 _cleanup_strv_free_ char **names = NULL;
5392 _cleanup_free_ char *target = NULL;
5393 const char *verb = args[0];
5400 target = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
5404 r = mangle_names(args+2, &names);
5408 if (streq(verb, "add-wants"))
5410 else if (streq(verb, "add-requires"))
5411 dep = UNIT_REQUIRES;
5413 assert_not_reached("Unknown verb");
5415 if (!bus || avoid_bus()) {
5416 UnitFileChange *changes = NULL;
5417 unsigned n_changes = 0;
5419 r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes);
5422 return log_error_errno(r, "Can't add dependency: %m");
5425 dump_unit_file_changes(changes, n_changes);
5427 unit_file_changes_free(changes, n_changes);
5430 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5431 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5433 r = sd_bus_message_new_method_call(
5436 "org.freedesktop.systemd1",
5437 "/org/freedesktop/systemd1",
5438 "org.freedesktop.systemd1.Manager",
5439 "AddDependencyUnitFiles");
5441 return bus_log_create_error(r);
5443 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5445 return bus_log_create_error(r);
5447 r = sd_bus_message_append_strv(m, names);
5449 return bus_log_create_error(r);
5451 r = sd_bus_message_append(m, "ssbb", target, unit_dependency_to_string(dep), arg_runtime, arg_force);
5453 return bus_log_create_error(r);
5455 r = sd_bus_call(bus, m, 0, &error, &reply);
5457 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5461 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
5466 r = daemon_reload(bus, args);
5474 static int preset_all(sd_bus *bus, char **args) {
5475 UnitFileChange *changes = NULL;
5476 unsigned n_changes = 0;
5479 if (!bus || avoid_bus()) {
5481 r = unit_file_preset_all(arg_scope, arg_runtime, arg_root, arg_preset_mode, arg_force, &changes, &n_changes);
5483 log_error_errno(r, "Operation failed: %m");
5488 dump_unit_file_changes(changes, n_changes);
5493 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
5494 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5496 r = sd_bus_message_new_method_call(
5499 "org.freedesktop.systemd1",
5500 "/org/freedesktop/systemd1",
5501 "org.freedesktop.systemd1.Manager",
5502 "PresetAllUnitFiles");
5504 return bus_log_create_error(r);
5506 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5508 return bus_log_create_error(r);
5510 r = sd_bus_message_append(
5513 unit_file_preset_mode_to_string(arg_preset_mode),
5517 return bus_log_create_error(r);
5519 r = sd_bus_call(bus, m, 0, &error, &reply);
5521 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5525 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
5530 r = daemon_reload(bus, args);
5536 unit_file_changes_free(changes, n_changes);
5541 static int unit_is_enabled(sd_bus *bus, char **args) {
5543 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5544 _cleanup_strv_free_ char **names = NULL;
5549 r = mangle_names(args+1, &names);
5553 r = enable_sysv_units(args[0], names);
5559 if (!bus || avoid_bus()) {
5561 STRV_FOREACH(name, names) {
5562 UnitFileState state;
5564 state = unit_file_get_state(arg_scope, arg_root, *name);
5566 return log_error_errno(state, "Failed to get unit file state for %s: %m", *name);
5568 if (state == UNIT_FILE_ENABLED ||
5569 state == UNIT_FILE_ENABLED_RUNTIME ||
5570 state == UNIT_FILE_STATIC ||
5571 state == UNIT_FILE_INDIRECT)
5575 puts(unit_file_state_to_string(state));
5579 STRV_FOREACH(name, names) {
5580 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5583 r = sd_bus_call_method(
5585 "org.freedesktop.systemd1",
5586 "/org/freedesktop/systemd1",
5587 "org.freedesktop.systemd1.Manager",
5593 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5597 r = sd_bus_message_read(reply, "s", &s);
5599 return bus_log_parse_error(r);
5601 if (STR_IN_SET(s, "enabled", "enabled-runtime", "static", "indirect"))
5612 static int is_system_running(sd_bus *bus, char **args) {
5613 _cleanup_free_ char *state = NULL;
5616 r = sd_bus_get_property_string(
5618 "org.freedesktop.systemd1",
5619 "/org/freedesktop/systemd1",
5620 "org.freedesktop.systemd1.Manager",
5633 return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE;
5636 static int create_edit_temp_file(const char *new_path, const char *original_path, char **ret_tmp_fn) {
5641 assert(original_path);
5644 r = tempfn_random(new_path, &t);
5646 return log_error_errno(r, "Failed to determine temporary filename for %s: %m", new_path);
5648 r = mkdir_parents(new_path, 0755);
5650 log_error_errno(r, "Failed to create directories for %s: %m", new_path);
5655 r = copy_file(original_path, t, 0, 0644);
5659 log_error_errno(r, "Failed to create temporary file %s: %m", t);
5664 log_error_errno(r, "Failed to copy %s to %s: %m", original_path, t);
5674 static int get_file_to_edit(const char *name, const char *user_home, const char *user_runtime, char **ret_path) {
5675 _cleanup_free_ char *path = NULL, *path2 = NULL, *run = NULL;
5677 switch (arg_scope) {
5678 case UNIT_FILE_SYSTEM:
5679 path = path_join(arg_root, SYSTEM_CONFIG_UNIT_PATH, name);
5681 run = path_join(arg_root, "/run/systemd/system/", name);
5683 case UNIT_FILE_GLOBAL:
5684 path = path_join(arg_root, USER_CONFIG_UNIT_PATH, name);
5686 run = path_join(arg_root, "/run/systemd/user/", name);
5688 case UNIT_FILE_USER:
5690 assert(user_runtime);
5692 path = path_join(arg_root, user_home, name);
5694 path2 = path_join(arg_root, USER_CONFIG_UNIT_PATH, name);
5697 run = path_join(arg_root, user_runtime, name);
5701 assert_not_reached("Invalid scope");
5703 if (!path || (arg_runtime && !run))
5707 if (access(path, F_OK) >= 0)
5708 return log_error_errno(EEXIST, "Refusing to create \"%s\" because it would be overriden by \"%s\" anyway.",
5710 if (path2 && access(path2, F_OK) >= 0)
5711 return log_error_errno(EEXIST, "Refusing to create \"%s\" because it would be overriden by \"%s\" anyway.",
5724 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) {
5725 char *tmp_new_path, *ending;
5730 assert(ret_new_path);
5731 assert(ret_tmp_path);
5733 ending = strappenda(unit_name, ".d/override.conf");
5734 r = get_file_to_edit(ending, user_home, user_runtime, &tmp_new_path);
5738 r = create_edit_temp_file(tmp_new_path, tmp_new_path, &tmp_tmp_path);
5744 *ret_new_path = tmp_new_path;
5745 *ret_tmp_path = tmp_tmp_path;
5750 static int unit_file_create_copy(const char *unit_name,
5751 const char *fragment_path,
5752 const char *user_home,
5753 const char *user_runtime,
5754 char **ret_new_path,
5755 char **ret_tmp_path) {
5760 assert(fragment_path);
5762 assert(ret_new_path);
5763 assert(ret_tmp_path);
5765 r = get_file_to_edit(unit_name, user_home, user_runtime, &tmp_new_path);
5769 if (!path_equal(fragment_path, tmp_new_path) && access(tmp_new_path, F_OK) == 0) {
5772 r = ask_char(&response, "yn", "%s already exists, are you sure to overwrite it with %s? [(y)es, (n)o] ", tmp_new_path, fragment_path);
5777 if (response != 'y') {
5778 log_warning("%s ignored", unit_name);
5784 r = create_edit_temp_file(tmp_new_path, fragment_path, &tmp_tmp_path);
5786 log_error_errno(r, "Failed to create temporary file for %s: %m", tmp_new_path);
5791 *ret_new_path = tmp_new_path;
5792 *ret_tmp_path = tmp_tmp_path;
5797 static int run_editor(char **paths) {
5805 log_error_errno(errno, "Failed to fork: %m");
5811 char **backup_editors = STRV_MAKE("nano", "vim", "vi");
5813 char **tmp_path, **original_path, **p;
5817 argc = strv_length(paths)/2 + 1;
5818 args = newa(const char*, argc + 1);
5821 STRV_FOREACH_PAIR(original_path, tmp_path, paths) {
5822 args[i] = *tmp_path;
5827 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
5828 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
5829 * we try to execute well known editors
5831 editor = getenv("SYSTEMD_EDITOR");
5833 editor = getenv("EDITOR");
5835 editor = getenv("VISUAL");
5837 if (!isempty(editor)) {
5839 execvp(editor, (char* const*) args);
5842 STRV_FOREACH(p, backup_editors) {
5844 execvp(*p, (char* const*) args);
5845 /* We do not fail if the editor doesn't exist
5846 * because we want to try each one of them before
5849 if (errno != ENOENT) {
5850 log_error("Failed to execute %s: %m", editor);
5851 _exit(EXIT_FAILURE);
5855 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR or $EDITOR or $VISUAL.");
5856 _exit(EXIT_FAILURE);
5859 r = wait_for_terminate_and_warn("editor", pid, true);
5861 return log_error_errno(r, "Failed to wait for child: %m");
5866 static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
5867 _cleanup_free_ char *user_home = NULL;
5868 _cleanup_free_ char *user_runtime = NULL;
5869 _cleanup_lookup_paths_free_ LookupPaths lp = {};
5870 bool avoid_bus_cache;
5877 r = init_home_and_lookup_paths(&user_home, &user_runtime, &lp);
5881 avoid_bus_cache = !bus || avoid_bus();
5883 STRV_FOREACH(name, names) {
5884 _cleanup_free_ char *path = NULL;
5885 char *new_path, *tmp_path;
5887 r = unit_find_paths(bus, *name, avoid_bus_cache, &lp, &path, NULL);
5890 else if (r == 0 || !path)
5891 // FIXME: support units with path==NULL (no FragmentPath)
5892 return log_error_errno(ENOENT, "Unit %s not found, cannot edit.", *name);
5895 r = unit_file_create_copy(*name, path, user_home, user_runtime, &new_path, &tmp_path);
5897 r = unit_file_create_dropin(*name, user_home, user_runtime, &new_path, &tmp_path);
5901 r = strv_push_pair(paths, new_path, tmp_path);
5909 static int edit(sd_bus *bus, char **args) {
5910 _cleanup_strv_free_ char **names = NULL;
5911 _cleanup_strv_free_ char **paths = NULL;
5912 char **original, **tmp;
5918 log_error("Cannot edit units if we are not on a tty");
5922 if (arg_transport != BUS_TRANSPORT_LOCAL) {
5923 log_error("Cannot remotely edit units");
5927 r = expand_names(bus, args + 1, NULL, &names);
5929 return log_error_errno(r, "Failed to expand names: %m");
5932 log_error("No unit name found by expanding names");
5936 r = find_paths_to_edit(bus, names, &paths);
5940 if (strv_isempty(paths)) {
5941 log_error("Cannot find any units to edit");
5945 r = run_editor(paths);
5949 STRV_FOREACH_PAIR(original, tmp, paths) {
5950 /* If the temporary file is empty we ignore it.
5951 * It's useful if the user wants to cancel its modification
5953 if (null_or_empty_path(*tmp)) {
5954 log_warning("Edition of %s canceled: temporary file empty", *original);
5957 r = rename(*tmp, *original);
5959 r = log_error_errno(errno, "Failed to rename %s to %s: %m", *tmp, *original);
5964 if (!arg_no_reload && bus && !avoid_bus())
5965 r = daemon_reload(bus, args);
5968 STRV_FOREACH_PAIR(original, tmp, paths)
5969 unlink_noerrno(*tmp);
5974 static void systemctl_help(void) {
5976 pager_open_if_enabled();
5978 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
5979 "Query or send control commands to the systemd manager.\n\n"
5980 " -h --help Show this help\n"
5981 " --version Show package version\n"
5982 " --system Connect to system manager\n"
5983 " --user Connect to user service manager\n"
5984 " -H --host=[USER@]HOST\n"
5985 " Operate on remote host\n"
5986 " -M --machine=CONTAINER\n"
5987 " Operate on local container\n"
5988 " -t --type=TYPE List only units of a particular type\n"
5989 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
5990 " -p --property=NAME Show only properties by this name\n"
5991 " -a --all Show all loaded units/properties, including dead/empty\n"
5992 " ones. To list all units installed on the system, use\n"
5993 " the 'list-unit-files' command instead.\n"
5994 " -l --full Don't ellipsize unit names on output\n"
5995 " -r --recursive Show unit list of host and local containers\n"
5996 " --reverse Show reverse dependencies with 'list-dependencies'\n"
5997 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
5998 " queueing a new job\n"
5999 " --show-types When showing sockets, explicitly show their type\n"
6000 " -i --ignore-inhibitors\n"
6001 " When shutting down or sleeping, ignore inhibitors\n"
6002 " --kill-who=WHO Who to send signal to\n"
6003 " -s --signal=SIGNAL Which signal to send\n"
6004 " -q --quiet Suppress output\n"
6005 " --no-block Do not wait until operation finished\n"
6006 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6007 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
6009 " --no-legend Do not print a legend (column headers and hints)\n"
6010 " --no-pager Do not pipe output into a pager\n"
6011 " --no-ask-password\n"
6012 " Do not ask for system passwords\n"
6013 " --global Enable/disable unit files globally\n"
6014 " --runtime Enable unit files only temporarily until next reboot\n"
6015 " -f --force When enabling unit files, override existing symlinks\n"
6016 " When shutting down, execute action immediately\n"
6017 " --preset-mode= Specifies whether fully apply presets, or only enable,\n"
6018 " or only disable\n"
6019 " --root=PATH Enable unit files in the specified root directory\n"
6020 " -n --lines=INTEGER Number of journal entries to show\n"
6021 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
6022 " verbose, export, json, json-pretty, json-sse, cat)\n"
6023 " --plain Print unit dependencies as a list instead of a tree\n\n"
6025 " list-units [PATTERN...] List loaded units\n"
6026 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
6027 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
6028 " start NAME... Start (activate) one or more units\n"
6029 " stop NAME... Stop (deactivate) one or more units\n"
6030 " reload NAME... Reload one or more units\n"
6031 " restart NAME... Start or restart one or more units\n"
6032 " try-restart NAME... Restart one or more units if active\n"
6033 " reload-or-restart NAME... Reload one or more units if possible,\n"
6034 " otherwise start or restart\n"
6035 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
6036 " otherwise restart if active\n"
6037 " isolate NAME Start one unit and stop all others\n"
6038 " kill NAME... Send signal to processes of a unit\n"
6039 " is-active PATTERN... Check whether units are active\n"
6040 " is-failed PATTERN... Check whether units are failed\n"
6041 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
6042 " show [PATTERN...|JOB...] Show properties of one or more\n"
6043 " units/jobs or the manager\n"
6044 " cat PATTERN... Show files and drop-ins of one or more units\n"
6045 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
6046 " help PATTERN...|PID... Show manual for one or more units\n"
6047 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
6049 " list-dependencies [NAME] Recursively show units which are required\n"
6050 " or wanted by this unit or by which this\n"
6051 " unit is required or wanted\n\n"
6052 "Unit File Commands:\n"
6053 " list-unit-files [PATTERN...] List installed unit files\n"
6054 " enable NAME... Enable one or more unit files\n"
6055 " disable NAME... Disable one or more unit files\n"
6056 " reenable NAME... Reenable one or more unit files\n"
6057 " preset NAME... Enable/disable one or more unit files\n"
6058 " based on preset configuration\n"
6059 " preset-all Enable/disable all unit files based on\n"
6060 " preset configuration\n"
6061 " is-enabled NAME... Check whether unit files are enabled\n\n"
6062 " mask NAME... Mask one or more units\n"
6063 " unmask NAME... Unmask one or more units\n"
6064 " link PATH... Link one or more units files into\n"
6065 " the search path\n"
6066 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6067 " on specified one or more units\n"
6068 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6069 " on specified one or more units\n"
6070 " get-default Get the name of the default target\n"
6071 " set-default NAME Set the default target\n"
6072 " edit NAME... Edit one or more unit files\n"
6074 "Machine Commands:\n"
6075 " list-machines [PATTERN...] List local containers and host\n\n"
6077 " list-jobs [PATTERN...] List jobs\n"
6078 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
6079 "Snapshot Commands:\n"
6080 " snapshot [NAME] Create a snapshot\n"
6081 " delete NAME... Remove one or more snapshots\n\n"
6082 "Environment Commands:\n"
6083 " show-environment Dump environment\n"
6084 " set-environment NAME=VALUE... Set one or more environment variables\n"
6085 " unset-environment NAME... Unset one or more environment variables\n"
6086 " import-environment NAME... Import all, one or more environment variables\n\n"
6087 "Manager Lifecycle Commands:\n"
6088 " daemon-reload Reload systemd manager configuration\n"
6089 " daemon-reexec Reexecute systemd manager\n\n"
6090 "System Commands:\n"
6091 " is-system-running Check whether system is fully running\n"
6092 " default Enter system default mode\n"
6093 " rescue Enter system rescue mode\n"
6094 " emergency Enter system emergency mode\n"
6095 " halt Shut down and halt the system\n"
6096 " poweroff Shut down and power-off the system\n"
6097 " reboot [ARG] Shut down and reboot the system\n"
6098 " kexec Shut down and reboot the system with kexec\n"
6099 " exit Request user instance exit\n"
6100 " switch-root ROOT [INIT] Change to a different root file system\n"
6101 " suspend Suspend the system\n"
6102 " hibernate Hibernate the system\n"
6103 " hybrid-sleep Hibernate and suspend the system\n",
6104 program_invocation_short_name);
6107 static void halt_help(void) {
6108 printf("%s [OPTIONS...]%s\n\n"
6109 "%s the system.\n\n"
6110 " --help Show this help\n"
6111 " --halt Halt the machine\n"
6112 " -p --poweroff Switch off the machine\n"
6113 " --reboot Reboot the machine\n"
6114 " -f --force Force immediate halt/power-off/reboot\n"
6115 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
6116 " -d --no-wtmp Don't write wtmp record\n"
6117 " --no-wall Don't send wall message before halt/power-off/reboot\n",
6118 program_invocation_short_name,
6119 arg_action == ACTION_REBOOT ? " [ARG]" : "",
6120 arg_action == ACTION_REBOOT ? "Reboot" :
6121 arg_action == ACTION_POWEROFF ? "Power off" :
6125 static void shutdown_help(void) {
6126 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
6127 "Shut down the system.\n\n"
6128 " --help Show this help\n"
6129 " -H --halt Halt the machine\n"
6130 " -P --poweroff Power-off the machine\n"
6131 " -r --reboot Reboot the machine\n"
6132 " -h Equivalent to --poweroff, overridden by --halt\n"
6133 " -k Don't halt/power-off/reboot, just send warnings\n"
6134 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6135 " -c Cancel a pending shutdown\n",
6136 program_invocation_short_name);
6139 static void telinit_help(void) {
6140 printf("%s [OPTIONS...] {COMMAND}\n\n"
6141 "Send control commands to the init daemon.\n\n"
6142 " --help Show this help\n"
6143 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
6145 " 0 Power-off the machine\n"
6146 " 6 Reboot the machine\n"
6147 " 2, 3, 4, 5 Start runlevelX.target unit\n"
6148 " 1, s, S Enter rescue mode\n"
6149 " q, Q Reload init daemon configuration\n"
6150 " u, U Reexecute init daemon\n",
6151 program_invocation_short_name);
6154 static void runlevel_help(void) {
6155 printf("%s [OPTIONS...]\n\n"
6156 "Prints the previous and current runlevel of the init system.\n\n"
6157 " --help Show this help\n",
6158 program_invocation_short_name);
6161 static void help_types(void) {
6166 puts("Available unit types:");
6167 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
6168 t = unit_type_to_string(i);
6174 static int systemctl_parse_argv(int argc, char *argv[]) {
6183 ARG_IGNORE_DEPENDENCIES,
6195 ARG_NO_ASK_PASSWORD,
6205 static const struct option options[] = {
6206 { "help", no_argument, NULL, 'h' },
6207 { "version", no_argument, NULL, ARG_VERSION },
6208 { "type", required_argument, NULL, 't' },
6209 { "property", required_argument, NULL, 'p' },
6210 { "all", no_argument, NULL, 'a' },
6211 { "reverse", no_argument, NULL, ARG_REVERSE },
6212 { "after", no_argument, NULL, ARG_AFTER },
6213 { "before", no_argument, NULL, ARG_BEFORE },
6214 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
6215 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
6216 { "full", no_argument, NULL, 'l' },
6217 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
6218 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
6219 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
6220 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
6221 { "ignore-inhibitors", no_argument, NULL, 'i' },
6222 { "user", no_argument, NULL, ARG_USER },
6223 { "system", no_argument, NULL, ARG_SYSTEM },
6224 { "global", no_argument, NULL, ARG_GLOBAL },
6225 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
6226 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
6227 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
6228 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6229 { "quiet", no_argument, NULL, 'q' },
6230 { "root", required_argument, NULL, ARG_ROOT },
6231 { "force", no_argument, NULL, ARG_FORCE },
6232 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
6233 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
6234 { "signal", required_argument, NULL, 's' },
6235 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
6236 { "host", required_argument, NULL, 'H' },
6237 { "machine", required_argument, NULL, 'M' },
6238 { "runtime", no_argument, NULL, ARG_RUNTIME },
6239 { "lines", required_argument, NULL, 'n' },
6240 { "output", required_argument, NULL, 'o' },
6241 { "plain", no_argument, NULL, ARG_PLAIN },
6242 { "state", required_argument, NULL, ARG_STATE },
6243 { "recursive", no_argument, NULL, 'r' },
6244 { "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
6253 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
6262 puts(PACKAGE_STRING);
6263 puts(SYSTEMD_FEATURES);
6267 const char *word, *state;
6270 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6271 _cleanup_free_ char *type;
6273 type = strndup(word, size);
6277 if (streq(type, "help")) {
6282 if (unit_type_from_string(type) >= 0) {
6283 if (strv_push(&arg_types, type))
6289 /* It's much nicer to use --state= for
6290 * load states, but let's support this
6291 * in --types= too for compatibility
6292 * with old versions */
6293 if (unit_load_state_from_string(optarg) >= 0) {
6294 if (strv_push(&arg_states, type) < 0)
6300 log_error("Unknown unit type or load state '%s'.", type);
6301 log_info("Use -t help to see a list of allowed values.");
6309 /* Make sure that if the empty property list
6310 was specified, we won't show any properties. */
6311 if (isempty(optarg) && !arg_properties) {
6312 arg_properties = new0(char*, 1);
6313 if (!arg_properties)
6316 const char *word, *state;
6319 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6322 prop = strndup(word, size);
6326 if (strv_consume(&arg_properties, prop) < 0)
6331 /* If the user asked for a particular
6332 * property, show it to him, even if it is
6344 arg_dependency = DEPENDENCY_REVERSE;
6348 arg_dependency = DEPENDENCY_AFTER;
6352 arg_dependency = DEPENDENCY_BEFORE;
6355 case ARG_SHOW_TYPES:
6356 arg_show_types = true;
6360 arg_job_mode = optarg;
6364 arg_job_mode = "fail";
6367 case ARG_IRREVERSIBLE:
6368 arg_job_mode = "replace-irreversibly";
6371 case ARG_IGNORE_DEPENDENCIES:
6372 arg_job_mode = "ignore-dependencies";
6376 arg_scope = UNIT_FILE_USER;
6380 arg_scope = UNIT_FILE_SYSTEM;
6384 arg_scope = UNIT_FILE_GLOBAL;
6388 arg_no_block = true;
6392 arg_no_legend = true;
6396 arg_no_pager = true;
6412 if (strv_extend(&arg_states, "failed") < 0)
6430 arg_no_reload = true;
6434 arg_kill_who = optarg;
6438 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
6439 log_error("Failed to parse signal string %s.", optarg);
6444 case ARG_NO_ASK_PASSWORD:
6445 arg_ask_password = false;
6449 arg_transport = BUS_TRANSPORT_REMOTE;
6454 arg_transport = BUS_TRANSPORT_MACHINE;
6463 if (safe_atou(optarg, &arg_lines) < 0) {
6464 log_error("Failed to parse lines '%s'", optarg);
6470 arg_output = output_mode_from_string(optarg);
6471 if (arg_output < 0) {
6472 log_error("Unknown output '%s'.", optarg);
6478 arg_ignore_inhibitors = true;
6486 const char *word, *state;
6489 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6492 s = strndup(word, size);
6496 if (strv_consume(&arg_states, s) < 0)
6503 if (geteuid() != 0) {
6504 log_error("--recursive requires root privileges.");
6508 arg_recursive = true;
6511 case ARG_PRESET_MODE:
6513 arg_preset_mode = unit_file_preset_mode_from_string(optarg);
6514 if (arg_preset_mode < 0) {
6515 log_error("Failed to parse preset mode: %s.", optarg);
6525 assert_not_reached("Unhandled option");
6528 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
6529 log_error("Cannot access user instance remotely.");
6536 static int halt_parse_argv(int argc, char *argv[]) {
6545 static const struct option options[] = {
6546 { "help", no_argument, NULL, ARG_HELP },
6547 { "halt", no_argument, NULL, ARG_HALT },
6548 { "poweroff", no_argument, NULL, 'p' },
6549 { "reboot", no_argument, NULL, ARG_REBOOT },
6550 { "force", no_argument, NULL, 'f' },
6551 { "wtmp-only", no_argument, NULL, 'w' },
6552 { "no-wtmp", no_argument, NULL, 'd' },
6553 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6562 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
6563 if (runlevel == '0' || runlevel == '6')
6566 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
6574 arg_action = ACTION_HALT;
6578 if (arg_action != ACTION_REBOOT)
6579 arg_action = ACTION_POWEROFF;
6583 arg_action = ACTION_REBOOT;
6605 /* Compatibility nops */
6612 assert_not_reached("Unhandled option");
6615 if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
6616 r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL);
6619 } else if (optind < argc) {
6620 log_error("Too many arguments.");
6627 static int parse_time_spec(const char *t, usec_t *_u) {
6631 if (streq(t, "now"))
6633 else if (!strchr(t, ':')) {
6636 if (safe_atou64(t, &u) < 0)
6639 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
6648 hour = strtol(t, &e, 10);
6649 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
6652 minute = strtol(e+1, &e, 10);
6653 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
6656 n = now(CLOCK_REALTIME);
6657 s = (time_t) (n / USEC_PER_SEC);
6659 assert_se(localtime_r(&s, &tm));
6661 tm.tm_hour = (int) hour;
6662 tm.tm_min = (int) minute;
6665 assert_se(s = mktime(&tm));
6667 *_u = (usec_t) s * USEC_PER_SEC;
6670 *_u += USEC_PER_DAY;
6676 static int shutdown_parse_argv(int argc, char *argv[]) {
6683 static const struct option options[] = {
6684 { "help", no_argument, NULL, ARG_HELP },
6685 { "halt", no_argument, NULL, 'H' },
6686 { "poweroff", no_argument, NULL, 'P' },
6687 { "reboot", no_argument, NULL, 'r' },
6688 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
6689 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6698 while ((c = getopt_long(argc, argv, "HPrhkKt:afFc", options, NULL)) >= 0)
6706 arg_action = ACTION_HALT;
6710 arg_action = ACTION_POWEROFF;
6715 arg_action = ACTION_KEXEC;
6717 arg_action = ACTION_REBOOT;
6721 arg_action = ACTION_KEXEC;
6725 if (arg_action != ACTION_HALT)
6726 arg_action = ACTION_POWEROFF;
6741 /* Compatibility nops */
6745 arg_action = ACTION_CANCEL_SHUTDOWN;
6752 assert_not_reached("Unhandled option");
6755 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
6756 r = parse_time_spec(argv[optind], &arg_when);
6758 log_error("Failed to parse time specification: %s", argv[optind]);
6762 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
6764 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
6765 /* No time argument for shutdown cancel */
6766 arg_wall = argv + optind;
6767 else if (argc > optind + 1)
6768 /* We skip the time argument */
6769 arg_wall = argv + optind + 1;
6776 static int telinit_parse_argv(int argc, char *argv[]) {
6783 static const struct option options[] = {
6784 { "help", no_argument, NULL, ARG_HELP },
6785 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6789 static const struct {
6793 { '0', ACTION_POWEROFF },
6794 { '6', ACTION_REBOOT },
6795 { '1', ACTION_RESCUE },
6796 { '2', ACTION_RUNLEVEL2 },
6797 { '3', ACTION_RUNLEVEL3 },
6798 { '4', ACTION_RUNLEVEL4 },
6799 { '5', ACTION_RUNLEVEL5 },
6800 { 's', ACTION_RESCUE },
6801 { 'S', ACTION_RESCUE },
6802 { 'q', ACTION_RELOAD },
6803 { 'Q', ACTION_RELOAD },
6804 { 'u', ACTION_REEXEC },
6805 { 'U', ACTION_REEXEC }
6814 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6829 assert_not_reached("Unhandled option");
6832 if (optind >= argc) {
6833 log_error("%s: required argument missing.",
6834 program_invocation_short_name);
6838 if (optind + 1 < argc) {
6839 log_error("Too many arguments.");
6843 if (strlen(argv[optind]) != 1) {
6844 log_error("Expected single character argument.");
6848 for (i = 0; i < ELEMENTSOF(table); i++)
6849 if (table[i].from == argv[optind][0])
6852 if (i >= ELEMENTSOF(table)) {
6853 log_error("Unknown command '%s'.", argv[optind]);
6857 arg_action = table[i].to;
6864 static int runlevel_parse_argv(int argc, char *argv[]) {
6870 static const struct option options[] = {
6871 { "help", no_argument, NULL, ARG_HELP },
6880 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6891 assert_not_reached("Unhandled option");
6894 if (optind < argc) {
6895 log_error("Too many arguments.");
6902 static int parse_argv(int argc, char *argv[]) {
6906 if (program_invocation_short_name) {
6908 if (strstr(program_invocation_short_name, "halt")) {
6909 arg_action = ACTION_HALT;
6910 return halt_parse_argv(argc, argv);
6911 } else if (strstr(program_invocation_short_name, "poweroff")) {
6912 arg_action = ACTION_POWEROFF;
6913 return halt_parse_argv(argc, argv);
6914 } else if (strstr(program_invocation_short_name, "reboot")) {
6916 arg_action = ACTION_KEXEC;
6918 arg_action = ACTION_REBOOT;
6919 return halt_parse_argv(argc, argv);
6920 } else if (strstr(program_invocation_short_name, "shutdown")) {
6921 arg_action = ACTION_POWEROFF;
6922 return shutdown_parse_argv(argc, argv);
6923 } else if (strstr(program_invocation_short_name, "init")) {
6925 if (sd_booted() > 0) {
6926 arg_action = _ACTION_INVALID;
6927 return telinit_parse_argv(argc, argv);
6929 /* Hmm, so some other init system is
6930 * running, we need to forward this
6931 * request to it. For now we simply
6932 * guess that it is Upstart. */
6934 execv(TELINIT, argv);
6936 log_error("Couldn't find an alternative telinit implementation to spawn.");
6940 } else if (strstr(program_invocation_short_name, "runlevel")) {
6941 arg_action = ACTION_RUNLEVEL;
6942 return runlevel_parse_argv(argc, argv);
6946 arg_action = ACTION_SYSTEMCTL;
6947 return systemctl_parse_argv(argc, argv);
6950 _pure_ static int action_to_runlevel(void) {
6952 static const char table[_ACTION_MAX] = {
6953 [ACTION_HALT] = '0',
6954 [ACTION_POWEROFF] = '0',
6955 [ACTION_REBOOT] = '6',
6956 [ACTION_RUNLEVEL2] = '2',
6957 [ACTION_RUNLEVEL3] = '3',
6958 [ACTION_RUNLEVEL4] = '4',
6959 [ACTION_RUNLEVEL5] = '5',
6960 [ACTION_RESCUE] = '1'
6963 assert(arg_action < _ACTION_MAX);
6965 return table[arg_action];
6968 static int talk_initctl(void) {
6970 struct init_request request = {
6971 .magic = INIT_MAGIC,
6973 .cmd = INIT_CMD_RUNLVL
6976 _cleanup_close_ int fd = -1;
6980 rl = action_to_runlevel();
6984 request.runlevel = rl;
6986 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
6988 if (errno == ENOENT)
6991 log_error_errno(errno, "Failed to open "INIT_FIFO": %m");
6995 r = loop_write(fd, &request, sizeof(request), false);
6997 return log_error_errno(r, "Failed to write to "INIT_FIFO": %m");
7002 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
7004 static const struct {
7012 int (* const dispatch)(sd_bus *bus, char **args);
7018 { "list-units", MORE, 0, list_units },
7019 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
7020 { "list-sockets", MORE, 1, list_sockets },
7021 { "list-timers", MORE, 1, list_timers },
7022 { "list-jobs", MORE, 1, list_jobs },
7023 { "list-machines", MORE, 1, list_machines },
7024 { "clear-jobs", EQUAL, 1, daemon_reload },
7025 { "cancel", MORE, 2, cancel_job },
7026 { "start", MORE, 2, start_unit },
7027 { "stop", MORE, 2, start_unit },
7028 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
7029 { "reload", MORE, 2, start_unit },
7030 { "restart", MORE, 2, start_unit },
7031 { "try-restart", MORE, 2, start_unit },
7032 { "reload-or-restart", MORE, 2, start_unit },
7033 { "reload-or-try-restart", MORE, 2, start_unit },
7034 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
7035 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
7036 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
7037 { "isolate", EQUAL, 2, start_unit },
7038 { "kill", MORE, 2, kill_unit },
7039 { "is-active", MORE, 2, check_unit_active },
7040 { "check", MORE, 2, check_unit_active },
7041 { "is-failed", MORE, 2, check_unit_failed },
7042 { "show", MORE, 1, show },
7043 { "cat", MORE, 2, cat, NOBUS },
7044 { "status", MORE, 1, show },
7045 { "help", MORE, 2, show },
7046 { "snapshot", LESS, 2, snapshot },
7047 { "delete", MORE, 2, delete_snapshot },
7048 { "daemon-reload", EQUAL, 1, daemon_reload },
7049 { "daemon-reexec", EQUAL, 1, daemon_reload },
7050 { "show-environment", EQUAL, 1, show_environment },
7051 { "set-environment", MORE, 2, set_environment },
7052 { "unset-environment", MORE, 2, set_environment },
7053 { "import-environment", MORE, 1, import_environment},
7054 { "halt", EQUAL, 1, start_special, FORCE },
7055 { "poweroff", EQUAL, 1, start_special, FORCE },
7056 { "reboot", EQUAL, 1, start_special, FORCE },
7057 { "kexec", EQUAL, 1, start_special },
7058 { "suspend", EQUAL, 1, start_special },
7059 { "hibernate", EQUAL, 1, start_special },
7060 { "hybrid-sleep", EQUAL, 1, start_special },
7061 { "default", EQUAL, 1, start_special },
7062 { "rescue", EQUAL, 1, start_special },
7063 { "emergency", EQUAL, 1, start_special },
7064 { "exit", EQUAL, 1, start_special },
7065 { "reset-failed", MORE, 1, reset_failed },
7066 { "enable", MORE, 2, enable_unit, NOBUS },
7067 { "disable", MORE, 2, enable_unit, NOBUS },
7068 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
7069 { "reenable", MORE, 2, enable_unit, NOBUS },
7070 { "preset", MORE, 2, enable_unit, NOBUS },
7071 { "preset-all", EQUAL, 1, preset_all, NOBUS },
7072 { "mask", MORE, 2, enable_unit, NOBUS },
7073 { "unmask", MORE, 2, enable_unit, NOBUS },
7074 { "link", MORE, 2, enable_unit, NOBUS },
7075 { "switch-root", MORE, 2, switch_root },
7076 { "list-dependencies", LESS, 2, list_dependencies },
7077 { "set-default", EQUAL, 2, set_default, NOBUS },
7078 { "get-default", EQUAL, 1, get_default, NOBUS },
7079 { "set-property", MORE, 3, set_property },
7080 { "is-system-running", EQUAL, 1, is_system_running },
7081 { "add-wants", MORE, 3, add_dependency, NOBUS },
7082 { "add-requires", MORE, 3, add_dependency, NOBUS },
7083 { "edit", MORE, 2, edit, NOBUS },
7092 left = argc - optind;
7094 /* Special rule: no arguments (left == 0) means "list-units" */
7096 if (streq(argv[optind], "help") && !argv[optind+1]) {
7097 log_error("This command expects one or more "
7098 "unit names. Did you mean --help?");
7102 for (; verb->verb; verb++)
7103 if (streq(argv[optind], verb->verb))
7106 log_error("Unknown operation '%s'.", argv[optind]);
7111 switch (verb->argc_cmp) {
7114 if (left != verb->argc) {
7115 log_error("Invalid number of arguments.");
7122 if (left < verb->argc) {
7123 log_error("Too few arguments.");
7130 if (left > verb->argc) {
7131 log_error("Too many arguments.");
7138 assert_not_reached("Unknown comparison operator.");
7141 /* Require a bus connection for all operations but
7143 if (verb->bus == NOBUS) {
7144 if (!bus && !avoid_bus()) {
7145 log_error_errno(bus_error, "Failed to get D-Bus connection: %m");
7150 if (running_in_chroot() > 0) {
7151 log_info("Running in chroot, ignoring request.");
7155 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
7156 log_error_errno(bus_error, "Failed to get D-Bus connection: %m");
7161 return verb->dispatch(bus, argv + optind);
7164 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
7166 struct sd_shutdown_command c = {
7173 union sockaddr_union sockaddr = {
7174 .un.sun_family = AF_UNIX,
7175 .un.sun_path = "/run/systemd/shutdownd",
7178 struct iovec iovec[2] = {{
7179 .iov_base = (char*) &c,
7180 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
7183 struct msghdr msghdr = {
7184 .msg_name = &sockaddr,
7185 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
7186 + strlen("/run/systemd/shutdownd"),
7191 _cleanup_close_ int fd;
7193 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
7197 if (!isempty(message)) {
7198 iovec[1].iov_base = (char*) message;
7199 iovec[1].iov_len = strlen(message);
7200 msghdr.msg_iovlen++;
7203 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
7209 static int reload_with_fallback(sd_bus *bus) {
7212 /* First, try systemd via D-Bus. */
7213 if (daemon_reload(bus, NULL) >= 0)
7217 /* Nothing else worked, so let's try signals */
7218 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
7220 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0)
7221 return log_error_errno(errno, "kill() failed: %m");
7226 static int start_with_fallback(sd_bus *bus) {
7229 /* First, try systemd via D-Bus. */
7230 if (start_unit(bus, NULL) >= 0)
7234 /* Nothing else worked, so let's try
7236 if (talk_initctl() > 0)
7239 log_error("Failed to talk to init daemon.");
7243 warn_wall(arg_action);
7247 static int halt_now(enum action a) {
7249 /* The kernel will automaticall flush ATA disks and suchlike
7250 * on reboot(), but the file systems need to be synce'd
7251 * explicitly in advance. */
7254 /* Make sure C-A-D is handled by the kernel from this point
7256 reboot(RB_ENABLE_CAD);
7261 log_info("Halting.");
7262 reboot(RB_HALT_SYSTEM);
7265 case ACTION_POWEROFF:
7266 log_info("Powering off.");
7267 reboot(RB_POWER_OFF);
7270 case ACTION_REBOOT: {
7271 _cleanup_free_ char *param = NULL;
7273 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
7274 log_info("Rebooting with argument '%s'.", param);
7275 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
7276 LINUX_REBOOT_CMD_RESTART2, param);
7279 log_info("Rebooting.");
7280 reboot(RB_AUTOBOOT);
7285 assert_not_reached("Unknown action.");
7289 static int halt_main(sd_bus *bus) {
7292 r = check_inhibitors(bus, arg_action);
7296 if (geteuid() != 0) {
7297 /* Try logind if we are a normal user and no special
7298 * mode applies. Maybe PolicyKit allows us to shutdown
7301 if (arg_when <= 0 &&
7304 (arg_action == ACTION_POWEROFF ||
7305 arg_action == ACTION_REBOOT)) {
7306 r = reboot_with_logind(bus, arg_action);
7311 log_error("Must be root.");
7316 _cleanup_free_ char *m;
7318 m = strv_join(arg_wall, " ");
7322 r = send_shutdownd(arg_when,
7323 arg_action == ACTION_HALT ? 'H' :
7324 arg_action == ACTION_POWEROFF ? 'P' :
7325 arg_action == ACTION_KEXEC ? 'K' :
7332 log_warning_errno(r, "Failed to talk to shutdownd, proceeding with immediate shutdown: %m");
7334 char date[FORMAT_TIMESTAMP_MAX];
7336 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
7337 format_timestamp(date, sizeof(date), arg_when));
7342 if (!arg_dry && !arg_force)
7343 return start_with_fallback(bus);
7346 if (sd_booted() > 0)
7347 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7349 r = utmp_put_shutdown();
7351 log_warning_errno(r, "Failed to write utmp record: %m");
7358 r = halt_now(arg_action);
7359 log_error_errno(r, "Failed to reboot: %m");
7364 static int runlevel_main(void) {
7365 int r, runlevel, previous;
7367 r = utmp_get_runlevel(&runlevel, &previous);
7374 previous <= 0 ? 'N' : previous,
7375 runlevel <= 0 ? 'N' : runlevel);
7380 int main(int argc, char*argv[]) {
7381 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
7384 setlocale(LC_ALL, "");
7385 log_parse_environment();
7388 /* Explicitly not on_tty() to avoid setting cached value.
7389 * This becomes relevant for piping output which might be
7391 original_stdout_is_tty = isatty(STDOUT_FILENO);
7393 r = parse_argv(argc, argv);
7397 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
7398 * let's shortcut this */
7399 if (arg_action == ACTION_RUNLEVEL) {
7400 r = runlevel_main();
7404 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
7405 log_info("Running in chroot, ignoring request.");
7410 /* Increase max number of open files to 16K if we can, we
7411 * might needs this when browsing journal files, which might
7412 * be split up into many files. */
7413 setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(16384));
7416 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
7418 /* systemctl_main() will print an error message for the bus
7419 * connection, but only if it needs to */
7421 switch (arg_action) {
7423 case ACTION_SYSTEMCTL:
7424 r = systemctl_main(bus, argc, argv, r);
7428 case ACTION_POWEROFF:
7434 case ACTION_RUNLEVEL2:
7435 case ACTION_RUNLEVEL3:
7436 case ACTION_RUNLEVEL4:
7437 case ACTION_RUNLEVEL5:
7439 case ACTION_EMERGENCY:
7440 case ACTION_DEFAULT:
7441 r = start_with_fallback(bus);
7446 r = reload_with_fallback(bus);
7449 case ACTION_CANCEL_SHUTDOWN: {
7450 _cleanup_free_ char *m = NULL;
7453 m = strv_join(arg_wall, " ");
7460 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
7462 log_warning_errno(r, "Failed to talk to shutdownd, shutdown hasn't been cancelled: %m");
7466 case ACTION_RUNLEVEL:
7467 case _ACTION_INVALID:
7469 assert_not_reached("Unknown action");
7474 ask_password_agent_close();
7475 polkit_agent_close();
7477 strv_free(arg_types);
7478 strv_free(arg_states);
7479 strv_free(arg_properties);
7481 return r < 0 ? EXIT_FAILURE : r;