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>
33 #include <sys/socket.h>
36 #include "sd-daemon.h"
37 #include "sd-shutdown.h"
44 #include "utmp-wtmp.h"
47 #include "path-util.h"
49 #include "cgroup-show.h"
50 #include "cgroup-util.h"
52 #include "path-lookup.h"
53 #include "exit-status.h"
55 #include "unit-name.h"
57 #include "spawn-ask-password-agent.h"
58 #include "spawn-polkit-agent.h"
60 #include "logs-show.h"
61 #include "socket-util.h"
66 #include "bus-message.h"
67 #include "bus-error.h"
68 #include "bus-common-errors.h"
72 static char **arg_types = NULL;
73 static char **arg_states = NULL;
74 static char **arg_properties = NULL;
75 static bool arg_all = false;
76 static enum dependency {
82 } arg_dependency = DEPENDENCY_FORWARD;
83 static const char *arg_job_mode = "replace";
84 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
85 static bool arg_no_block = false;
86 static bool arg_no_legend = false;
87 static bool arg_no_pager = false;
88 static bool arg_no_wtmp = false;
89 static bool arg_no_wall = false;
90 static bool arg_no_reload = false;
91 static bool arg_show_types = false;
92 static bool arg_ignore_inhibitors = false;
93 static bool arg_dry = false;
94 static bool arg_quiet = false;
95 static bool arg_full = false;
96 static bool arg_recursive = false;
97 static int arg_force = 0;
98 static bool arg_ask_password = true;
99 static bool arg_runtime = false;
100 static UnitFilePresetMode arg_preset_mode = UNIT_FILE_PRESET_FULL;
101 static char **arg_wall = NULL;
102 static const char *arg_kill_who = NULL;
103 static int arg_signal = SIGTERM;
104 static const char *arg_root = NULL;
105 static usec_t arg_when = 0;
127 ACTION_CANCEL_SHUTDOWN,
129 } arg_action = ACTION_SYSTEMCTL;
130 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
131 static char *arg_host = NULL;
132 static unsigned arg_lines = 10;
133 static OutputMode arg_output = OUTPUT_SHORT;
134 static bool arg_plain = false;
136 static bool original_stdout_is_tty;
138 static int daemon_reload(sd_bus *bus, char **args);
139 static int halt_now(enum action a);
140 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet);
142 static char** strv_skip_first(char **strv) {
143 if (strv_length(strv) > 0)
148 static void pager_open_if_enabled(void) {
156 static void ask_password_agent_open_if_enabled(void) {
158 /* Open the password agent as a child process if necessary */
160 if (!arg_ask_password)
163 if (arg_scope != UNIT_FILE_SYSTEM)
166 if (arg_transport != BUS_TRANSPORT_LOCAL)
169 ask_password_agent_open();
172 static void polkit_agent_open_if_enabled(void) {
174 /* Open the polkit agent as a child process if necessary */
176 if (!arg_ask_password)
179 if (arg_scope != UNIT_FILE_SYSTEM)
182 if (arg_transport != BUS_TRANSPORT_LOCAL)
188 static OutputFlags get_output_flags(void) {
190 arg_all * OUTPUT_SHOW_ALL |
191 arg_full * OUTPUT_FULL_WIDTH |
192 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
193 on_tty() * OUTPUT_COLOR |
194 !arg_quiet * OUTPUT_WARN_CUTOFF;
197 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
200 if (!sd_bus_error_is_set(error))
203 if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) ||
204 sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
205 sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
206 sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
207 return EXIT_NOPERMISSION;
209 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
210 return EXIT_NOTINSTALLED;
212 if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
213 sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED))
214 return EXIT_NOTIMPLEMENTED;
216 if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
217 return EXIT_NOTCONFIGURED;
225 static void warn_wall(enum action a) {
226 static const char *table[_ACTION_MAX] = {
227 [ACTION_HALT] = "The system is going down for system halt NOW!",
228 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
229 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
230 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
231 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
232 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
233 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
240 _cleanup_free_ char *p;
242 p = strv_join(arg_wall, " ");
249 utmp_wall(p, NULL, NULL);
257 utmp_wall(table[a], NULL, NULL);
260 static bool avoid_bus(void) {
262 if (running_in_chroot() > 0)
265 if (sd_booted() <= 0)
268 if (!isempty(arg_root))
271 if (arg_scope == UNIT_FILE_GLOBAL)
277 static int compare_unit_info(const void *a, const void *b) {
278 const UnitInfo *u = a, *v = b;
282 /* First, order by machine */
283 if (!u->machine && v->machine)
285 if (u->machine && !v->machine)
287 if (u->machine && v->machine) {
288 r = strcasecmp(u->machine, v->machine);
293 /* Second, order by unit type */
294 d1 = strrchr(u->id, '.');
295 d2 = strrchr(v->id, '.');
297 r = strcasecmp(d1, d2);
302 /* Third, order by name */
303 return strcasecmp(u->id, v->id);
306 static bool output_show_unit(const UnitInfo *u, char **patterns) {
307 if (!strv_fnmatch_or_empty(patterns, u->id, FNM_NOESCAPE))
313 dot = strrchr(u->id, '.');
317 if (!strv_find(arg_types, dot+1))
327 if (streq(u->active_state, "inactive") || u->following[0])
333 static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
334 unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
336 unsigned n_shown = 0;
339 max_id_len = strlen("UNIT");
340 load_len = strlen("LOAD");
341 active_len = strlen("ACTIVE");
342 sub_len = strlen("SUB");
343 job_len = strlen("JOB");
346 for (u = unit_infos; u < unit_infos + c; u++) {
347 max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0));
348 load_len = MAX(load_len, strlen(u->load_state));
349 active_len = MAX(active_len, strlen(u->active_state));
350 sub_len = MAX(sub_len, strlen(u->sub_state));
352 if (u->job_id != 0) {
353 job_len = MAX(job_len, strlen(u->job_type));
357 if (!arg_no_legend &&
358 (streq(u->active_state, "failed") ||
359 STR_IN_SET(u->load_state, "error", "not-found", "masked")))
363 if (!arg_full && original_stdout_is_tty) {
366 id_len = MIN(max_id_len, 25u);
367 basic_len = circle_len + 5 + id_len + 5 + active_len + sub_len;
370 basic_len += job_len + 1;
372 if (basic_len < (unsigned) columns()) {
373 unsigned extra_len, incr;
374 extra_len = columns() - basic_len;
376 /* Either UNIT already got 25, or is fully satisfied.
377 * Grant up to 25 to DESC now. */
378 incr = MIN(extra_len, 25u);
382 /* split the remaining space between UNIT and DESC,
383 * but do not give UNIT more than it needs. */
385 incr = MIN(extra_len / 2, max_id_len - id_len);
387 desc_len += extra_len - incr;
393 for (u = unit_infos; u < unit_infos + c; u++) {
394 _cleanup_free_ char *e = NULL, *j = NULL;
395 const char *on_loaded = "", *off_loaded = "";
396 const char *on_active = "", *off_active = "";
397 const char *on_circle = "", *off_circle = "";
401 if (!n_shown && !arg_no_legend) {
406 printf("%-*s %-*s %-*s %-*s ",
409 active_len, "ACTIVE",
413 printf("%-*s ", job_len, "JOB");
415 if (!arg_full && arg_no_pager)
416 printf("%.*s\n", desc_len, "DESCRIPTION");
418 printf("%s\n", "DESCRIPTION");
423 if (STR_IN_SET(u->load_state, "error", "not-found", "masked") && !arg_plain) {
424 on_loaded = ansi_highlight_red();
425 on_circle = ansi_highlight_yellow();
426 off_loaded = off_circle = ansi_highlight_off();
428 } else if (streq(u->active_state, "failed") && !arg_plain) {
429 on_circle = on_active = ansi_highlight_red();
430 off_circle = off_active = ansi_highlight_off();
435 j = strjoin(u->machine, ":", u->id, NULL);
444 e = ellipsize(id, id_len, 33);
452 printf("%s%s%s ", on_circle, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_circle);
454 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
455 on_active, id_len, id, off_active,
456 on_loaded, load_len, u->load_state, off_loaded,
457 on_active, active_len, u->active_state,
458 sub_len, u->sub_state, off_active,
459 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
462 printf("%.*s\n", desc_len, u->description);
464 printf("%s\n", u->description);
467 if (!arg_no_legend) {
468 const char *on, *off;
472 "LOAD = Reflects whether the unit definition was properly loaded.\n"
473 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
474 "SUB = The low-level unit activation state, values depend on unit type.");
475 puts(job_count ? "JOB = Pending job for the unit.\n" : "");
476 on = ansi_highlight();
477 off = ansi_highlight_off();
479 on = ansi_highlight_red();
480 off = ansi_highlight_off();
484 printf("%s%u loaded units listed.%s\n"
485 "To show all installed unit files use 'systemctl list-unit-files'.\n",
488 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
489 "To show all installed unit files use 'systemctl list-unit-files'.\n",
496 static int get_unit_list(
500 UnitInfo **unit_infos,
502 sd_bus_message **_reply) {
504 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
505 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
506 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
515 r = sd_bus_message_new_method_call(
518 "org.freedesktop.systemd1",
519 "/org/freedesktop/systemd1",
520 "org.freedesktop.systemd1.Manager",
521 "ListUnitsFiltered");
524 return bus_log_create_error(r);
526 r = sd_bus_message_append_strv(m, arg_states);
528 return bus_log_create_error(r);
530 r = sd_bus_call(bus, m, 0, &error, &reply);
532 log_error("Failed to list units: %s", bus_error_message(&error, r));
536 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
538 return bus_log_parse_error(r);
540 while ((r = bus_parse_unit_info(reply, &u)) > 0) {
543 if (!output_show_unit(&u, patterns))
546 if (!GREEDY_REALLOC(*unit_infos, size, c+1))
549 (*unit_infos)[c++] = u;
552 return bus_log_parse_error(r);
554 r = sd_bus_message_exit_container(reply);
556 return bus_log_parse_error(r);
564 static void message_set_freep(Set **set) {
567 while ((m = set_steal_first(*set)))
568 sd_bus_message_unref(m);
573 static int get_unit_list_recursive(
576 UnitInfo **_unit_infos,
580 _cleanup_free_ UnitInfo *unit_infos = NULL;
581 _cleanup_(message_set_freep) Set *replies;
582 sd_bus_message *reply;
590 replies = set_new(NULL);
594 c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
598 r = set_put(replies, reply);
600 sd_bus_message_unref(reply);
605 _cleanup_strv_free_ char **machines = NULL;
608 r = sd_get_machine_names(&machines);
612 STRV_FOREACH(i, machines) {
613 _cleanup_bus_close_unref_ sd_bus *container = NULL;
616 r = sd_bus_open_system_machine(&container, *i);
618 log_error_errno(r, "Failed to connect to container %s: %m", *i);
622 k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
628 r = set_put(replies, reply);
630 sd_bus_message_unref(reply);
635 *_machines = machines;
640 *_unit_infos = unit_infos;
649 static int list_units(sd_bus *bus, char **args) {
650 _cleanup_free_ UnitInfo *unit_infos = NULL;
651 _cleanup_(message_set_freep) Set *replies = NULL;
652 _cleanup_strv_free_ char **machines = NULL;
655 pager_open_if_enabled();
657 r = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
661 qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
662 return output_units_list(unit_infos, r);
665 static int get_triggered_units(
670 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
673 r = sd_bus_get_property_strv(
675 "org.freedesktop.systemd1",
677 "org.freedesktop.systemd1.Unit",
683 log_error("Failed to determine triggers: %s", bus_error_message(&error, r));
688 static int get_listening(
690 const char* unit_path,
693 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
694 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
695 const char *type, *path;
698 r = sd_bus_get_property(
700 "org.freedesktop.systemd1",
702 "org.freedesktop.systemd1.Socket",
708 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r));
712 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
714 return bus_log_parse_error(r);
716 while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
718 r = strv_extend(listening, type);
722 r = strv_extend(listening, path);
729 return bus_log_parse_error(r);
731 r = sd_bus_message_exit_container(reply);
733 return bus_log_parse_error(r);
745 /* Note: triggered is a list here, although it almost certainly
746 * will always be one unit. Nevertheless, dbus API allows for multiple
747 * values, so let's follow that. */
750 /* The strv above is shared. free is set only in the first one. */
754 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
760 if (!a->machine && b->machine)
762 if (a->machine && !b->machine)
764 if (a->machine && b->machine) {
765 o = strcasecmp(a->machine, b->machine);
770 o = strcmp(a->path, b->path);
772 o = strcmp(a->type, b->type);
777 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
778 struct socket_info *s;
779 unsigned pathlen = strlen("LISTEN"),
780 typelen = strlen("TYPE") * arg_show_types,
781 socklen = strlen("UNIT"),
782 servlen = strlen("ACTIVATES");
783 const char *on, *off;
785 for (s = socket_infos; s < socket_infos + cs; s++) {
789 socklen = MAX(socklen, strlen(s->id));
791 typelen = MAX(typelen, strlen(s->type));
792 pathlen = MAX(pathlen, strlen(s->path) + (s->machine ? strlen(s->machine)+1 : 0));
794 STRV_FOREACH(a, s->triggered)
795 tmp += strlen(*a) + 2*(a != s->triggered);
796 servlen = MAX(servlen, tmp);
801 printf("%-*s %-*.*s%-*s %s\n",
803 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
807 for (s = socket_infos; s < socket_infos + cs; s++) {
808 _cleanup_free_ char *j = NULL;
813 j = strjoin(s->machine, ":", s->path, NULL);
821 printf("%-*s %-*s %-*s",
822 pathlen, path, typelen, s->type, socklen, s->id);
825 pathlen, path, socklen, s->id);
826 STRV_FOREACH(a, s->triggered)
828 a == s->triggered ? "" : ",", *a);
832 on = ansi_highlight();
833 off = ansi_highlight_off();
837 on = ansi_highlight_red();
838 off = ansi_highlight_off();
841 if (!arg_no_legend) {
842 printf("%s%u sockets listed.%s\n", on, cs, off);
844 printf("Pass --all to see loaded but inactive sockets, too.\n");
850 static int list_sockets(sd_bus *bus, char **args) {
851 _cleanup_(message_set_freep) Set *replies = NULL;
852 _cleanup_strv_free_ char **machines = NULL;
853 _cleanup_free_ UnitInfo *unit_infos = NULL;
854 _cleanup_free_ struct socket_info *socket_infos = NULL;
856 struct socket_info *s;
861 pager_open_if_enabled();
863 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
867 for (u = unit_infos; u < unit_infos + n; u++) {
868 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
871 if (!endswith(u->id, ".socket"))
874 r = get_triggered_units(bus, u->unit_path, &triggered);
878 c = get_listening(bus, u->unit_path, &listening);
884 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
889 for (i = 0; i < c; i++)
890 socket_infos[cs + i] = (struct socket_info) {
891 .machine = u->machine,
893 .type = listening[i*2],
894 .path = listening[i*2 + 1],
895 .triggered = triggered,
896 .own_triggered = i==0,
899 /* from this point on we will cleanup those socket_infos */
902 listening = triggered = NULL; /* avoid cleanup */
905 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
906 (__compar_fn_t) socket_info_compare);
908 output_sockets_list(socket_infos, cs);
911 assert(cs == 0 || socket_infos);
912 for (s = socket_infos; s < socket_infos + cs; s++) {
915 if (s->own_triggered)
916 strv_free(s->triggered);
922 static int get_next_elapse(
925 dual_timestamp *next) {
927 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
935 r = sd_bus_get_property_trivial(
937 "org.freedesktop.systemd1",
939 "org.freedesktop.systemd1.Timer",
940 "NextElapseUSecMonotonic",
945 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
949 r = sd_bus_get_property_trivial(
951 "org.freedesktop.systemd1",
953 "org.freedesktop.systemd1.Timer",
954 "NextElapseUSecRealtime",
959 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
967 static int get_last_trigger(
972 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
979 r = sd_bus_get_property_trivial(
981 "org.freedesktop.systemd1",
983 "org.freedesktop.systemd1.Timer",
989 log_error("Failed to get last trigger time: %s", bus_error_message(&error, r));
1000 usec_t last_trigger;
1004 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
1010 if (!a->machine && b->machine)
1012 if (a->machine && !b->machine)
1014 if (a->machine && b->machine) {
1015 o = strcasecmp(a->machine, b->machine);
1020 if (a->next_elapse < b->next_elapse)
1022 if (a->next_elapse > b->next_elapse)
1025 return strcmp(a->id, b->id);
1028 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
1029 struct timer_info *t;
1031 nextlen = strlen("NEXT"),
1032 leftlen = strlen("LEFT"),
1033 lastlen = strlen("LAST"),
1034 passedlen = strlen("PASSED"),
1035 unitlen = strlen("UNIT"),
1036 activatelen = strlen("ACTIVATES");
1038 const char *on, *off;
1040 assert(timer_infos || n == 0);
1042 for (t = timer_infos; t < timer_infos + n; t++) {
1046 if (t->next_elapse > 0) {
1047 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1049 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
1050 nextlen = MAX(nextlen, strlen(tstamp) + 1);
1052 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
1053 leftlen = MAX(leftlen, strlen(trel));
1056 if (t->last_trigger > 0) {
1057 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1059 format_timestamp(tstamp, sizeof(tstamp), t->last_trigger);
1060 lastlen = MAX(lastlen, strlen(tstamp) + 1);
1062 format_timestamp_relative(trel, sizeof(trel), t->last_trigger);
1063 passedlen = MAX(passedlen, strlen(trel));
1066 unitlen = MAX(unitlen, strlen(t->id) + (t->machine ? strlen(t->machine)+1 : 0));
1068 STRV_FOREACH(a, t->triggered)
1069 ul += strlen(*a) + 2*(a != t->triggered);
1071 activatelen = MAX(activatelen, ul);
1076 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1080 passedlen, "PASSED",
1084 for (t = timer_infos; t < timer_infos + n; t++) {
1085 _cleanup_free_ char *j = NULL;
1087 char tstamp1[FORMAT_TIMESTAMP_MAX] = "n/a", trel1[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1088 char tstamp2[FORMAT_TIMESTAMP_MAX] = "n/a", trel2[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1091 format_timestamp(tstamp1, sizeof(tstamp1), t->next_elapse);
1092 format_timestamp_relative(trel1, sizeof(trel1), t->next_elapse);
1094 format_timestamp(tstamp2, sizeof(tstamp2), t->last_trigger);
1095 format_timestamp_relative(trel2, sizeof(trel2), t->last_trigger);
1098 j = strjoin(t->machine, ":", t->id, NULL);
1105 printf("%-*s %-*s %-*s %-*s %-*s",
1106 nextlen, tstamp1, leftlen, trel1, lastlen, tstamp2, passedlen, trel2, unitlen, unit);
1108 STRV_FOREACH(a, t->triggered)
1110 a == t->triggered ? "" : ",", *a);
1114 on = ansi_highlight();
1115 off = ansi_highlight_off();
1119 on = ansi_highlight_red();
1120 off = ansi_highlight_off();
1123 if (!arg_no_legend) {
1124 printf("%s%u timers listed.%s\n", on, n, off);
1126 printf("Pass --all to see loaded but inactive timers, too.\n");
1132 static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
1138 if (next->monotonic != USEC_INFINITY && next->monotonic > 0) {
1141 if (next->monotonic > nw->monotonic)
1142 converted = nw->realtime + (next->monotonic - nw->monotonic);
1144 converted = nw->realtime - (nw->monotonic - next->monotonic);
1146 if (next->realtime != USEC_INFINITY && next->realtime > 0)
1147 next_elapse = MIN(converted, next->realtime);
1149 next_elapse = converted;
1152 next_elapse = next->realtime;
1157 static int list_timers(sd_bus *bus, char **args) {
1158 _cleanup_(message_set_freep) Set *replies = NULL;
1159 _cleanup_strv_free_ char **machines = NULL;
1160 _cleanup_free_ struct timer_info *timer_infos = NULL;
1161 _cleanup_free_ UnitInfo *unit_infos = NULL;
1162 struct timer_info *t;
1169 pager_open_if_enabled();
1171 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
1175 dual_timestamp_get(&nw);
1177 for (u = unit_infos; u < unit_infos + n; u++) {
1178 _cleanup_strv_free_ char **triggered = NULL;
1179 dual_timestamp next = {};
1182 if (!endswith(u->id, ".timer"))
1185 r = get_triggered_units(bus, u->unit_path, &triggered);
1189 r = get_next_elapse(bus, u->unit_path, &next);
1193 get_last_trigger(bus, u->unit_path, &last);
1195 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
1200 m = calc_next_elapse(&nw, &next);
1202 timer_infos[c++] = (struct timer_info) {
1203 .machine = u->machine,
1206 .last_trigger = last,
1207 .triggered = triggered,
1210 triggered = NULL; /* avoid cleanup */
1213 qsort_safe(timer_infos, c, sizeof(struct timer_info),
1214 (__compar_fn_t) timer_info_compare);
1216 output_timers_list(timer_infos, c);
1219 for (t = timer_infos; t < timer_infos + c; t++)
1220 strv_free(t->triggered);
1225 static int compare_unit_file_list(const void *a, const void *b) {
1226 const char *d1, *d2;
1227 const UnitFileList *u = a, *v = b;
1229 d1 = strrchr(u->path, '.');
1230 d2 = strrchr(v->path, '.');
1235 r = strcasecmp(d1, d2);
1240 return strcasecmp(basename(u->path), basename(v->path));
1243 static bool output_show_unit_file(const UnitFileList *u, char **patterns) {
1244 if (!strv_fnmatch_or_empty(patterns, basename(u->path), FNM_NOESCAPE))
1247 if (!strv_isempty(arg_types)) {
1250 dot = strrchr(u->path, '.');
1254 if (!strv_find(arg_types, dot+1))
1258 if (!strv_isempty(arg_states) &&
1259 !strv_find(arg_states, unit_file_state_to_string(u->state)))
1265 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
1266 unsigned max_id_len, id_cols, state_cols;
1267 const UnitFileList *u;
1269 max_id_len = strlen("UNIT FILE");
1270 state_cols = strlen("STATE");
1272 for (u = units; u < units + c; u++) {
1273 max_id_len = MAX(max_id_len, strlen(basename(u->path)));
1274 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1278 unsigned basic_cols;
1280 id_cols = MIN(max_id_len, 25u);
1281 basic_cols = 1 + id_cols + state_cols;
1282 if (basic_cols < (unsigned) columns())
1283 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1285 id_cols = max_id_len;
1288 printf("%-*s %-*s\n",
1289 id_cols, "UNIT FILE",
1290 state_cols, "STATE");
1292 for (u = units; u < units + c; u++) {
1293 _cleanup_free_ char *e = NULL;
1294 const char *on, *off;
1297 if (u->state == UNIT_FILE_MASKED ||
1298 u->state == UNIT_FILE_MASKED_RUNTIME ||
1299 u->state == UNIT_FILE_DISABLED ||
1300 u->state == UNIT_FILE_INVALID) {
1301 on = ansi_highlight_red();
1302 off = ansi_highlight_off();
1303 } else if (u->state == UNIT_FILE_ENABLED) {
1304 on = ansi_highlight_green();
1305 off = ansi_highlight_off();
1309 id = basename(u->path);
1311 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1313 printf("%-*s %s%-*s%s\n",
1314 id_cols, e ? e : id,
1315 on, state_cols, unit_file_state_to_string(u->state), off);
1319 printf("\n%u unit files listed.\n", c);
1322 static int list_unit_files(sd_bus *bus, char **args) {
1323 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1324 _cleanup_free_ UnitFileList *units = NULL;
1332 pager_open_if_enabled();
1340 h = hashmap_new(&string_hash_ops);
1344 r = unit_file_get_list(arg_scope, arg_root, h);
1346 unit_file_list_free(h);
1347 log_error_errno(r, "Failed to get unit file list: %m");
1351 n_units = hashmap_size(h);
1353 units = new(UnitFileList, n_units);
1354 if (!units && n_units > 0) {
1355 unit_file_list_free(h);
1359 HASHMAP_FOREACH(u, h, i) {
1360 if (!output_show_unit_file(u, strv_skip_first(args)))
1367 assert(c <= n_units);
1370 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1372 r = sd_bus_call_method(
1374 "org.freedesktop.systemd1",
1375 "/org/freedesktop/systemd1",
1376 "org.freedesktop.systemd1.Manager",
1382 log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1386 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1388 return bus_log_parse_error(r);
1390 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1392 if (!GREEDY_REALLOC(units, size, c + 1))
1395 units[c] = (struct UnitFileList) {
1397 unit_file_state_from_string(state)
1400 if (output_show_unit_file(&units[c], strv_skip_first(args)))
1405 return bus_log_parse_error(r);
1407 r = sd_bus_message_exit_container(reply);
1409 return bus_log_parse_error(r);
1412 qsort_safe(units, c, sizeof(UnitFileList), compare_unit_file_list);
1413 output_unit_file_list(units, c);
1416 for (unit = units; unit < units + c; unit++)
1423 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1424 _cleanup_free_ char *n = NULL;
1425 size_t max_len = MAX(columns(),20u);
1431 for (i = level - 1; i >= 0; i--) {
1433 if (len > max_len - 3 && !arg_full) {
1434 printf("%s...\n",max_len % 2 ? "" : " ");
1437 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERTICAL : DRAW_TREE_SPACE));
1441 if (len > max_len - 3 && !arg_full) {
1442 printf("%s...\n",max_len % 2 ? "" : " ");
1446 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
1450 printf("%s\n", name);
1454 n = ellipsize(name, max_len-len, 100);
1462 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1464 static const char *dependencies[_DEPENDENCY_MAX] = {
1465 [DEPENDENCY_FORWARD] = "Requires\0"
1466 "RequiresOverridable\0"
1468 "RequisiteOverridable\0"
1471 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1472 "RequiredByOverridable\0"
1476 [DEPENDENCY_AFTER] = "After\0",
1477 [DEPENDENCY_BEFORE] = "Before\0",
1480 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1481 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1482 _cleanup_strv_free_ char **ret = NULL;
1483 _cleanup_free_ char *path = NULL;
1489 assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
1491 path = unit_dbus_path_from_name(name);
1495 r = sd_bus_call_method(
1497 "org.freedesktop.systemd1",
1499 "org.freedesktop.DBus.Properties",
1503 "s", "org.freedesktop.systemd1.Unit");
1505 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1509 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1511 return bus_log_parse_error(r);
1513 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1516 r = sd_bus_message_read(reply, "s", &prop);
1518 return bus_log_parse_error(r);
1520 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1521 r = sd_bus_message_skip(reply, "v");
1523 return bus_log_parse_error(r);
1526 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1528 return bus_log_parse_error(r);
1530 r = bus_message_read_strv_extend(reply, &ret);
1532 return bus_log_parse_error(r);
1534 r = sd_bus_message_exit_container(reply);
1536 return bus_log_parse_error(r);
1539 r = sd_bus_message_exit_container(reply);
1541 return bus_log_parse_error(r);
1545 return bus_log_parse_error(r);
1547 r = sd_bus_message_exit_container(reply);
1549 return bus_log_parse_error(r);
1557 static int list_dependencies_compare(const void *_a, const void *_b) {
1558 const char **a = (const char**) _a, **b = (const char**) _b;
1560 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1562 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1565 return strcasecmp(*a, *b);
1568 static int list_dependencies_one(
1573 unsigned int branches) {
1575 _cleanup_strv_free_ char **deps = NULL;
1583 r = strv_extend(units, name);
1587 r = list_dependencies_get_dependencies(bus, name, &deps);
1591 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1593 STRV_FOREACH(c, deps) {
1594 if (strv_contains(*units, *c)) {
1596 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1609 state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true);
1610 on = state > 0 ? ansi_highlight_green() : ansi_highlight_red();
1611 printf("%s%s%s ", on, draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1614 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1618 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1619 r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1626 strv_remove(*units, name);
1631 static int list_dependencies(sd_bus *bus, char **args) {
1632 _cleanup_strv_free_ char **units = NULL;
1633 _cleanup_free_ char *unit = NULL;
1639 unit = unit_name_mangle(args[1], MANGLE_NOGLOB);
1644 u = SPECIAL_DEFAULT_TARGET;
1646 pager_open_if_enabled();
1650 return list_dependencies_one(bus, u, 0, &units, 0);
1653 struct machine_info {
1657 char *control_group;
1658 uint32_t n_failed_units;
1663 static const struct bus_properties_map machine_info_property_map[] = {
1664 { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
1665 { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
1666 { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
1667 { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
1668 { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
1672 static void free_machines_list(struct machine_info *machine_infos, int n) {
1678 for (i = 0; i < n; i++) {
1679 free(machine_infos[i].name);
1680 free(machine_infos[i].state);
1681 free(machine_infos[i].control_group);
1684 free(machine_infos);
1687 static int compare_machine_info(const void *a, const void *b) {
1688 const struct machine_info *u = a, *v = b;
1690 if (u->is_host != v->is_host)
1691 return u->is_host > v->is_host ? -1 : 1;
1693 return strcasecmp(u->name, v->name);
1696 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1697 _cleanup_bus_close_unref_ sd_bus *container = NULL;
1703 r = sd_bus_open_system_machine(&container, mi->name);
1710 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi);
1717 static bool output_show_machine(const char *name, char **patterns) {
1718 return strv_fnmatch_or_empty(patterns, name, FNM_NOESCAPE);
1721 static int get_machine_list(
1723 struct machine_info **_machine_infos,
1726 struct machine_info *machine_infos = NULL;
1727 _cleanup_strv_free_ char **m = NULL;
1728 _cleanup_free_ char *hn = NULL;
1733 hn = gethostname_malloc();
1737 if (output_show_machine(hn, patterns)) {
1738 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1741 machine_infos[c].is_host = true;
1742 machine_infos[c].name = hn;
1745 get_machine_properties(bus, &machine_infos[c]);
1749 sd_get_machine_names(&m);
1750 STRV_FOREACH(i, m) {
1751 _cleanup_free_ char *class = NULL;
1753 if (!output_show_machine(*i, patterns))
1756 sd_machine_get_class(*i, &class);
1757 if (!streq_ptr(class, "container"))
1760 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1761 free_machines_list(machine_infos, c);
1765 machine_infos[c].is_host = false;
1766 machine_infos[c].name = strdup(*i);
1767 if (!machine_infos[c].name) {
1768 free_machines_list(machine_infos, c);
1772 get_machine_properties(NULL, &machine_infos[c]);
1776 *_machine_infos = machine_infos;
1780 static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1781 struct machine_info *m;
1784 namelen = sizeof("NAME") - 1,
1785 statelen = sizeof("STATE") - 1,
1786 failedlen = sizeof("FAILED") - 1,
1787 jobslen = sizeof("JOBS") - 1;
1789 assert(machine_infos || n == 0);
1791 for (m = machine_infos; m < machine_infos + n; m++) {
1792 namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
1793 statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
1794 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
1795 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
1797 if (!arg_plain && !streq_ptr(m->state, "running"))
1801 if (!arg_no_legend) {
1805 printf("%-*s %-*s %-*s %-*s\n",
1808 failedlen, "FAILED",
1812 for (m = machine_infos; m < machine_infos + n; m++) {
1813 const char *on_state = "", *off_state = "";
1814 const char *on_failed = "", *off_failed = "";
1815 bool circle = false;
1817 if (streq_ptr(m->state, "degraded")) {
1818 on_state = ansi_highlight_red();
1819 off_state = ansi_highlight_off();
1821 } else if (!streq_ptr(m->state, "running")) {
1822 on_state = ansi_highlight_yellow();
1823 off_state = ansi_highlight_off();
1827 if (m->n_failed_units > 0) {
1828 on_failed = ansi_highlight_red();
1829 off_failed = ansi_highlight_off();
1831 on_failed = off_failed = "";
1834 printf("%s%s%s ", on_state, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_state);
1837 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1838 (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
1839 on_state, statelen, strna(m->state), off_state,
1840 on_failed, failedlen, m->n_failed_units, off_failed,
1841 jobslen, m->n_jobs);
1843 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1844 namelen, strna(m->name),
1845 on_state, statelen, strna(m->state), off_state,
1846 on_failed, failedlen, m->n_failed_units, off_failed,
1847 jobslen, m->n_jobs);
1851 printf("\n%u machines listed.\n", n);
1854 static int list_machines(sd_bus *bus, char **args) {
1855 struct machine_info *machine_infos = NULL;
1860 if (geteuid() != 0) {
1861 log_error("Must be root.");
1865 pager_open_if_enabled();
1867 r = get_machine_list(bus, &machine_infos, strv_skip_first(args));
1871 qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
1872 output_machines_list(machine_infos, r);
1873 free_machines_list(machine_infos, r);
1878 static int get_default(sd_bus *bus, char **args) {
1879 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1880 _cleanup_free_ char *_path = NULL;
1884 if (!bus || avoid_bus()) {
1885 r = unit_file_get_default(arg_scope, arg_root, &_path);
1887 return log_error_errno(r, "Failed to get default target: %m");
1891 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1893 r = sd_bus_call_method(
1895 "org.freedesktop.systemd1",
1896 "/org/freedesktop/systemd1",
1897 "org.freedesktop.systemd1.Manager",
1903 log_error("Failed to get default target: %s", bus_error_message(&error, -r));
1907 r = sd_bus_message_read(reply, "s", &path);
1909 return bus_log_parse_error(r);
1913 printf("%s\n", path);
1918 static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) {
1921 assert(changes || n_changes == 0);
1923 for (i = 0; i < n_changes; i++) {
1924 if (changes[i].type == UNIT_FILE_SYMLINK)
1925 log_info("Created symlink from %s to %s.", changes[i].path, changes[i].source);
1927 log_info("Removed symlink %s.", changes[i].path);
1931 static int set_default(sd_bus *bus, char **args) {
1932 _cleanup_free_ char *unit = NULL;
1933 UnitFileChange *changes = NULL;
1934 unsigned n_changes = 0;
1937 unit = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
1941 if (!bus || avoid_bus()) {
1942 r = unit_file_set_default(arg_scope, arg_root, unit, true, &changes, &n_changes);
1944 return log_error_errno(r, "Failed to set default target: %m");
1947 dump_unit_file_changes(changes, n_changes);
1951 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1952 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1954 polkit_agent_open_if_enabled();
1956 r = sd_bus_call_method(
1958 "org.freedesktop.systemd1",
1959 "/org/freedesktop/systemd1",
1960 "org.freedesktop.systemd1.Manager",
1966 log_error("Failed to set default target: %s", bus_error_message(&error, -r));
1970 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
1974 /* Try to reload if enabled */
1976 r = daemon_reload(bus, args);
1981 unit_file_changes_free(changes, n_changes);
1988 const char *name, *type, *state;
1991 static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
1992 unsigned id_len, unit_len, type_len, state_len;
1993 const struct job_info *j;
1994 const char *on, *off;
1995 bool shorten = false;
1997 assert(n == 0 || jobs);
2000 if (!arg_no_legend) {
2001 on = ansi_highlight_green();
2002 off = ansi_highlight_off();
2004 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
2009 pager_open_if_enabled();
2011 id_len = strlen("JOB");
2012 unit_len = strlen("UNIT");
2013 type_len = strlen("TYPE");
2014 state_len = strlen("STATE");
2016 for (j = jobs; j < jobs + n; j++) {
2017 uint32_t id = j->id;
2018 assert(j->name && j->type && j->state);
2020 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
2021 unit_len = MAX(unit_len, strlen(j->name));
2022 type_len = MAX(type_len, strlen(j->type));
2023 state_len = MAX(state_len, strlen(j->state));
2026 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
2027 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
2032 printf("%*s %-*s %-*s %-*s\n",
2036 state_len, "STATE");
2038 for (j = jobs; j < jobs + n; j++) {
2039 _cleanup_free_ char *e = NULL;
2041 if (streq(j->state, "running")) {
2042 on = ansi_highlight();
2043 off = ansi_highlight_off();
2047 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
2048 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2050 on, unit_len, e ? e : j->name, off,
2052 on, state_len, j->state, off);
2055 if (!arg_no_legend) {
2056 on = ansi_highlight();
2057 off = ansi_highlight_off();
2059 printf("\n%s%u jobs listed%s.\n", on, n, off);
2063 static bool output_show_job(struct job_info *job, char **patterns) {
2064 return strv_fnmatch_or_empty(patterns, job->name, FNM_NOESCAPE);
2067 static int list_jobs(sd_bus *bus, char **args) {
2068 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2069 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2070 const char *name, *type, *state, *job_path, *unit_path;
2071 _cleanup_free_ struct job_info *jobs = NULL;
2076 bool skipped = false;
2078 r = sd_bus_call_method(
2080 "org.freedesktop.systemd1",
2081 "/org/freedesktop/systemd1",
2082 "org.freedesktop.systemd1.Manager",
2088 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
2092 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2094 return bus_log_parse_error(r);
2096 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
2097 struct job_info job = { id, name, type, state };
2099 if (!output_show_job(&job, strv_skip_first(args))) {
2104 if (!GREEDY_REALLOC(jobs, size, c + 1))
2110 return bus_log_parse_error(r);
2112 r = sd_bus_message_exit_container(reply);
2114 return bus_log_parse_error(r);
2116 output_jobs_list(jobs, c, skipped);
2120 static int cancel_job(sd_bus *bus, char **args) {
2126 if (strv_length(args) <= 1)
2127 return daemon_reload(bus, args);
2129 polkit_agent_open_if_enabled();
2131 STRV_FOREACH(name, args+1) {
2132 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2136 q = safe_atou32(*name, &id);
2138 return log_error_errno(q, "Failed to parse job id \"%s\": %m", *name);
2140 q = sd_bus_call_method(
2142 "org.freedesktop.systemd1",
2143 "/org/freedesktop/systemd1",
2144 "org.freedesktop.systemd1.Manager",
2150 log_error("Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, q));
2159 static int need_daemon_reload(sd_bus *bus, const char *unit) {
2160 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2164 /* We ignore all errors here, since this is used to show a
2167 /* We don't use unit_dbus_path_from_name() directly since we
2168 * don't want to load the unit if it isn't loaded. */
2170 r = sd_bus_call_method(
2172 "org.freedesktop.systemd1",
2173 "/org/freedesktop/systemd1",
2174 "org.freedesktop.systemd1.Manager",
2182 r = sd_bus_message_read(reply, "o", &path);
2186 r = sd_bus_get_property_trivial(
2188 "org.freedesktop.systemd1",
2190 "org.freedesktop.systemd1.Unit",
2200 static void warn_unit_file_changed(const char *name) {
2201 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2202 ansi_highlight_red(),
2203 ansi_highlight_off(),
2205 arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2208 static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **unit_path) {
2215 STRV_FOREACH(p, lp->unit_path) {
2216 _cleanup_free_ char *path;
2218 path = path_join(arg_root, *p, unit_name);
2222 if (access(path, F_OK) == 0) {
2232 static int unit_find_paths(
2234 const char *unit_name,
2235 bool avoid_bus_cache,
2237 char **fragment_path,
2238 char ***dropin_paths) {
2240 _cleanup_free_ char *path = NULL;
2241 _cleanup_strv_free_ char **dropins = NULL;
2245 * Finds where the unit is defined on disk. Returns 0 if the unit
2246 * is not found. Returns 1 if it is found, and sets
2247 * - the path to the unit in *path, if it exists on disk,
2248 * - and a strv of existing drop-ins in *dropins,
2249 * if the arg is not NULL and any dropins were found.
2253 assert(fragment_path);
2256 if (!avoid_bus_cache && !unit_name_is_template(unit_name)) {
2257 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2258 _cleanup_bus_message_unref_ sd_bus_message *unit_load_error = NULL;
2259 _cleanup_free_ char *unit = NULL;
2260 char *unit_load_error_name, *unit_load_error_message;
2262 unit = unit_dbus_path_from_name(unit_name);
2266 if (need_daemon_reload(bus, unit_name) > 0)
2267 warn_unit_file_changed(unit_name);
2269 r = sd_bus_get_property(
2271 "org.freedesktop.systemd1",
2273 "org.freedesktop.systemd1.Unit",
2279 return log_error_errno(r, "Failed to get LoadError: %s", bus_error_message(&error, r));
2281 r = sd_bus_message_read(
2284 &unit_load_error_name,
2285 &unit_load_error_message);
2287 return bus_log_parse_error(r);
2289 if (!isempty(unit_load_error_name)) {
2290 log_error("Unit %s is not loaded: %s", unit_name, unit_load_error_message);
2294 r = sd_bus_get_property_string(
2296 "org.freedesktop.systemd1",
2298 "org.freedesktop.systemd1.Unit",
2303 return log_error_errno(r, "Failed to get FragmentPath: %s", bus_error_message(&error, r));
2306 r = sd_bus_get_property_strv(
2308 "org.freedesktop.systemd1",
2310 "org.freedesktop.systemd1.Unit",
2315 return log_error_errno(r, "Failed to get DropInPaths: %s", bus_error_message(&error, r));
2318 _cleanup_set_free_ Set *names;
2320 names = set_new(NULL);
2324 r = set_put(names, unit_name);
2328 r = unit_file_find_path(lp, unit_name, &path);
2333 _cleanup_free_ char *template;
2335 template = unit_name_template(unit_name);
2339 if (!streq(template, unit_name)) {
2340 r = unit_file_find_path(lp, template, &path);
2347 r = unit_file_find_dropin_paths(lp->unit_path, NULL, names, &dropins);
2355 if (!isempty(path)) {
2356 *fragment_path = path;
2361 if (dropin_paths && !strv_isempty(dropins)) {
2362 *dropin_paths = dropins;
2368 log_error("No files found for %s.", unit_name);
2373 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2374 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2375 _cleanup_free_ char *n = NULL, *state = NULL;
2381 n = unit_name_mangle(name, MANGLE_NOGLOB);
2385 /* We don't use unit_dbus_path_from_name() directly since we
2386 * don't want to load the unit if it isn't loaded. */
2388 r = sd_bus_call_method(
2390 "org.freedesktop.systemd1",
2391 "/org/freedesktop/systemd1",
2392 "org.freedesktop.systemd1.Manager",
2403 r = sd_bus_message_read(reply, "o", &path);
2405 return bus_log_parse_error(r);
2407 r = sd_bus_get_property_string(
2409 "org.freedesktop.systemd1",
2411 "org.freedesktop.systemd1.Unit",
2424 return nulstr_contains(good_states, state);
2427 static int check_triggering_units(
2431 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2432 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2433 _cleanup_strv_free_ char **triggered_by = NULL;
2434 bool print_warning_label = true;
2438 n = unit_name_mangle(name, MANGLE_NOGLOB);
2442 path = unit_dbus_path_from_name(n);
2446 r = sd_bus_get_property_string(
2448 "org.freedesktop.systemd1",
2450 "org.freedesktop.systemd1.Unit",
2455 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2459 if (streq(state, "masked"))
2462 r = sd_bus_get_property_strv(
2464 "org.freedesktop.systemd1",
2466 "org.freedesktop.systemd1.Unit",
2471 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2475 STRV_FOREACH(i, triggered_by) {
2476 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2478 return log_error_errno(r, "Failed to check unit: %m");
2483 if (print_warning_label) {
2484 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2485 print_warning_label = false;
2488 log_warning(" %s", *i);
2494 static const struct {
2497 } unit_actions[] = {
2498 { "start", "StartUnit" },
2499 { "stop", "StopUnit" },
2500 { "condstop", "StopUnit" },
2501 { "reload", "ReloadUnit" },
2502 { "restart", "RestartUnit" },
2503 { "try-restart", "TryRestartUnit" },
2504 { "condrestart", "TryRestartUnit" },
2505 { "reload-or-restart", "ReloadOrRestartUnit" },
2506 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2507 { "condreload", "ReloadOrTryRestartUnit" },
2508 { "force-reload", "ReloadOrTryRestartUnit" }
2511 static const char *verb_to_method(const char *verb) {
2514 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2515 if (streq_ptr(unit_actions[i].verb, verb))
2516 return unit_actions[i].method;
2521 static const char *method_to_verb(const char *method) {
2524 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2525 if (streq_ptr(unit_actions[i].method, method))
2526 return unit_actions[i].verb;
2531 static int start_unit_one(
2536 sd_bus_error *error,
2537 BusWaitForJobs *w) {
2539 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2548 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2550 r = sd_bus_call_method(
2552 "org.freedesktop.systemd1",
2553 "/org/freedesktop/systemd1",
2554 "org.freedesktop.systemd1.Manager",
2562 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2563 /* There's always a fallback possible for
2564 * legacy actions. */
2565 return -EADDRNOTAVAIL;
2567 verb = method_to_verb(method);
2569 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2573 r = sd_bus_message_read(reply, "o", &path);
2575 return bus_log_parse_error(r);
2577 if (need_daemon_reload(bus, name) > 0)
2578 warn_unit_file_changed(name);
2581 log_debug("Adding %s to the set", path);
2582 r = bus_wait_for_jobs_add(w, path);
2590 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2592 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2596 STRV_FOREACH(name, names) {
2600 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2602 t = unit_name_mangle(*name, MANGLE_GLOB);
2606 if (string_is_glob(t))
2607 r = strv_consume(&globs, t);
2609 r = strv_consume(&mangled, t);
2614 /* Query the manager only if any of the names are a glob, since
2615 * this is fairly expensive */
2616 if (!strv_isempty(globs)) {
2617 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2618 _cleanup_free_ UnitInfo *unit_infos = NULL;
2621 return log_error_errno(ENOTSUP, "Unit name globbing without bus is not implemented.");
2623 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2627 for (i = 0; i < r; i++)
2628 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2633 mangled = NULL; /* do not free */
2638 static const struct {
2642 } action_table[_ACTION_MAX] = {
2643 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2644 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2645 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2646 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2647 [ACTION_RUNLEVEL2] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
2648 [ACTION_RUNLEVEL3] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
2649 [ACTION_RUNLEVEL4] = { SPECIAL_MULTI_USER_TARGET, NULL, "isolate" },
2650 [ACTION_RUNLEVEL5] = { SPECIAL_GRAPHICAL_TARGET, NULL, "isolate" },
2651 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2652 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2653 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2654 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2655 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2656 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2657 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2660 static enum action verb_to_action(const char *verb) {
2663 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2664 if (streq_ptr(action_table[i].verb, verb))
2667 return _ACTION_INVALID;
2670 static int start_unit(sd_bus *bus, char **args) {
2671 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
2672 const char *method, *mode, *one_name, *suffix = NULL;
2673 _cleanup_strv_free_ char **names = NULL;
2679 ask_password_agent_open_if_enabled();
2680 polkit_agent_open_if_enabled();
2682 if (arg_action == ACTION_SYSTEMCTL) {
2684 method = verb_to_method(args[0]);
2685 action = verb_to_action(args[0]);
2687 if (streq(args[0], "isolate")) {
2691 mode = action_table[action].mode ?: arg_job_mode;
2693 one_name = action_table[action].target;
2695 assert(arg_action < ELEMENTSOF(action_table));
2696 assert(action_table[arg_action].target);
2698 method = "StartUnit";
2700 mode = action_table[arg_action].mode;
2701 one_name = action_table[arg_action].target;
2705 names = strv_new(one_name, NULL);
2707 r = expand_names(bus, args + 1, suffix, &names);
2709 log_error_errno(r, "Failed to expand names: %m");
2712 if (!arg_no_block) {
2713 r = bus_wait_for_jobs_new(bus, &w);
2715 return log_error_errno(r, "Could not watch jobs: %m");
2718 STRV_FOREACH(name, names) {
2719 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2722 q = start_unit_one(bus, method, *name, mode, &error, w);
2723 if (r >= 0 && q < 0)
2724 r = translate_bus_error_to_exit_status(q, &error);
2727 if (!arg_no_block) {
2730 q = bus_wait_for_jobs(w, arg_quiet);
2734 /* When stopping units, warn if they can still be triggered by
2735 * another active unit (socket, path, timer) */
2736 if (!arg_quiet && streq(method, "StopUnit"))
2737 STRV_FOREACH(name, names)
2738 check_triggering_units(bus, *name);
2744 /* Ask systemd-logind, which might grant access to unprivileged users
2745 * through PolicyKit */
2746 static int reboot_with_logind(sd_bus *bus, enum action a) {
2748 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2755 polkit_agent_open_if_enabled();
2763 case ACTION_POWEROFF:
2764 method = "PowerOff";
2767 case ACTION_SUSPEND:
2771 case ACTION_HIBERNATE:
2772 method = "Hibernate";
2775 case ACTION_HYBRID_SLEEP:
2776 method = "HybridSleep";
2783 r = sd_bus_call_method(
2785 "org.freedesktop.login1",
2786 "/org/freedesktop/login1",
2787 "org.freedesktop.login1.Manager",
2791 "b", arg_ask_password);
2793 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2801 static int check_inhibitors(sd_bus *bus, enum action a) {
2803 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2804 _cleanup_strv_free_ char **sessions = NULL;
2805 const char *what, *who, *why, *mode;
2814 if (arg_ignore_inhibitors || arg_force > 0)
2826 r = sd_bus_call_method(
2828 "org.freedesktop.login1",
2829 "/org/freedesktop/login1",
2830 "org.freedesktop.login1.Manager",
2836 /* If logind is not around, then there are no inhibitors... */
2839 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2841 return bus_log_parse_error(r);
2843 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2844 _cleanup_free_ char *comm = NULL, *user = NULL;
2845 _cleanup_strv_free_ char **sv = NULL;
2847 if (!streq(mode, "block"))
2850 sv = strv_split(what, ":");
2854 if ((pid_t) pid < 0)
2855 return log_error_errno(ERANGE, "Bad PID %"PRIu32": %m", pid);
2857 if (!strv_contains(sv,
2859 a == ACTION_POWEROFF ||
2860 a == ACTION_REBOOT ||
2861 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2864 get_process_comm(pid, &comm);
2865 user = uid_to_name(uid);
2867 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
2868 who, (pid_t) pid, strna(comm), strna(user), why);
2873 return bus_log_parse_error(r);
2875 r = sd_bus_message_exit_container(reply);
2877 return bus_log_parse_error(r);
2879 /* Check for current sessions */
2880 sd_get_sessions(&sessions);
2881 STRV_FOREACH(s, sessions) {
2882 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2884 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2887 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2890 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2893 sd_session_get_tty(*s, &tty);
2894 sd_session_get_seat(*s, &seat);
2895 sd_session_get_service(*s, &service);
2896 user = uid_to_name(uid);
2898 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2905 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2906 action_table[a].verb);
2914 static int start_special(sd_bus *bus, char **args) {
2920 a = verb_to_action(args[0]);
2922 r = check_inhibitors(bus, a);
2926 if (arg_force >= 2 && geteuid() != 0) {
2927 log_error("Must be root.");
2931 if (a == ACTION_REBOOT && args[1]) {
2932 r = update_reboot_param_file(args[1]);
2937 if (arg_force >= 2 &&
2938 (a == ACTION_HALT ||
2939 a == ACTION_POWEROFF ||
2940 a == ACTION_REBOOT))
2943 if (arg_force >= 1 &&
2944 (a == ACTION_HALT ||
2945 a == ACTION_POWEROFF ||
2946 a == ACTION_REBOOT ||
2947 a == ACTION_KEXEC ||
2949 return daemon_reload(bus, args);
2951 /* first try logind, to allow authentication with polkit */
2952 if (geteuid() != 0 &&
2953 (a == ACTION_POWEROFF ||
2954 a == ACTION_REBOOT ||
2955 a == ACTION_SUSPEND ||
2956 a == ACTION_HIBERNATE ||
2957 a == ACTION_HYBRID_SLEEP)) {
2958 r = reboot_with_logind(bus, a);
2959 if (r >= 0 || IN_SET(r, -ENOTSUP, -EINPROGRESS))
2963 r = start_unit(bus, args);
2964 if (r == EXIT_SUCCESS)
2970 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
2971 _cleanup_strv_free_ char **names = NULL;
2978 r = expand_names(bus, args, NULL, &names);
2980 return log_error_errno(r, "Failed to expand names: %m");
2982 STRV_FOREACH(name, names) {
2985 state = check_one_unit(bus, *name, good_states, arg_quiet);
2995 static int check_unit_active(sd_bus *bus, char **args) {
2996 /* According to LSB: 3, "program is not running" */
2997 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
3000 static int check_unit_failed(sd_bus *bus, char **args) {
3001 return check_unit_generic(bus, 1, "failed\0", args + 1);
3004 static int kill_unit(sd_bus *bus, char **args) {
3005 _cleanup_strv_free_ char **names = NULL;
3012 polkit_agent_open_if_enabled();
3015 arg_kill_who = "all";
3017 r = expand_names(bus, args + 1, NULL, &names);
3019 log_error_errno(r, "Failed to expand names: %m");
3021 STRV_FOREACH(name, names) {
3022 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3024 q = sd_bus_call_method(
3026 "org.freedesktop.systemd1",
3027 "/org/freedesktop/systemd1",
3028 "org.freedesktop.systemd1.Manager",
3032 "ssi", *names, arg_kill_who, arg_signal);
3034 log_error("Failed to kill unit %s: %s", *names, bus_error_message(&error, q));
3043 typedef struct ExecStatusInfo {
3051 usec_t start_timestamp;
3052 usec_t exit_timestamp;
3057 LIST_FIELDS(struct ExecStatusInfo, exec);
3060 static void exec_status_info_free(ExecStatusInfo *i) {
3069 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3070 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3073 int32_t code, status;
3079 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3081 return bus_log_parse_error(r);
3085 r = sd_bus_message_read(m, "s", &path);
3087 return bus_log_parse_error(r);
3089 i->path = strdup(path);
3093 r = sd_bus_message_read_strv(m, &i->argv);
3095 return bus_log_parse_error(r);
3097 r = sd_bus_message_read(m,
3100 &start_timestamp, &start_timestamp_monotonic,
3101 &exit_timestamp, &exit_timestamp_monotonic,
3105 return bus_log_parse_error(r);
3108 i->start_timestamp = (usec_t) start_timestamp;
3109 i->exit_timestamp = (usec_t) exit_timestamp;
3110 i->pid = (pid_t) pid;
3114 r = sd_bus_message_exit_container(m);
3116 return bus_log_parse_error(r);
3121 typedef struct UnitStatusInfo {
3123 const char *load_state;
3124 const char *active_state;
3125 const char *sub_state;
3126 const char *unit_file_state;
3127 const char *unit_file_preset;
3129 const char *description;
3130 const char *following;
3132 char **documentation;
3134 const char *fragment_path;
3135 const char *source_path;
3136 const char *control_group;
3138 char **dropin_paths;
3140 const char *load_error;
3143 usec_t inactive_exit_timestamp;
3144 usec_t inactive_exit_timestamp_monotonic;
3145 usec_t active_enter_timestamp;
3146 usec_t active_exit_timestamp;
3147 usec_t inactive_enter_timestamp;
3149 bool need_daemon_reload;
3154 const char *status_text;
3155 const char *pid_file;
3159 usec_t start_timestamp;
3160 usec_t exit_timestamp;
3162 int exit_code, exit_status;
3164 usec_t condition_timestamp;
3165 bool condition_result;
3166 bool failed_condition_trigger;
3167 bool failed_condition_negate;
3168 const char *failed_condition;
3169 const char *failed_condition_parameter;
3171 usec_t assert_timestamp;
3173 bool failed_assert_trigger;
3174 bool failed_assert_negate;
3175 const char *failed_assert;
3176 const char *failed_assert_parameter;
3179 unsigned n_accepted;
3180 unsigned n_connections;
3183 /* Pairs of type, path */
3187 const char *sysfs_path;
3189 /* Mount, Automount */
3196 uint64_t memory_current;
3197 uint64_t memory_limit;
3199 LIST_HEAD(ExecStatusInfo, exec);
3202 static void print_status_info(
3207 const char *active_on, *active_off, *on, *off, *ss;
3209 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3210 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3216 /* This shows pretty information about a unit. See
3217 * print_property() for a low-level property printer */
3219 if (streq_ptr(i->active_state, "failed")) {
3220 active_on = ansi_highlight_red();
3221 active_off = ansi_highlight_off();
3222 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3223 active_on = ansi_highlight_green();
3224 active_off = ansi_highlight_off();
3226 active_on = active_off = "";
3228 printf("%s%s%s %s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3230 if (i->description && !streq_ptr(i->id, i->description))
3231 printf(" - %s", i->description);
3236 printf(" Follow: unit currently follows state of %s\n", i->following);
3238 if (streq_ptr(i->load_state, "error")) {
3239 on = ansi_highlight_red();
3240 off = ansi_highlight_off();
3244 path = i->source_path ? i->source_path : i->fragment_path;
3247 printf(" Loaded: %s%s%s (Reason: %s)\n",
3248 on, strna(i->load_state), off, i->load_error);
3249 else if (path && !isempty(i->unit_file_state) && !isempty(i->unit_file_preset))
3250 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3251 on, strna(i->load_state), off, path, i->unit_file_state, i->unit_file_preset);
3252 else if (path && !isempty(i->unit_file_state))
3253 printf(" Loaded: %s%s%s (%s; %s)\n",
3254 on, strna(i->load_state), off, path, i->unit_file_state);
3256 printf(" Loaded: %s%s%s (%s)\n",
3257 on, strna(i->load_state), off, path);
3259 printf(" Loaded: %s%s%s\n",
3260 on, strna(i->load_state), off);
3262 if (!strv_isempty(i->dropin_paths)) {
3263 _cleanup_free_ char *dir = NULL;
3267 STRV_FOREACH(dropin, i->dropin_paths) {
3268 if (! dir || last) {
3269 printf(dir ? " " : " Drop-In: ");
3274 if (path_get_parent(*dropin, &dir) < 0) {
3279 printf("%s\n %s", dir,
3280 draw_special_char(DRAW_TREE_RIGHT));
3283 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3285 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3289 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3291 printf(" Active: %s%s (%s)%s",
3292 active_on, strna(i->active_state), ss, active_off);
3294 printf(" Active: %s%s%s",
3295 active_on, strna(i->active_state), active_off);
3297 if (!isempty(i->result) && !streq(i->result, "success"))
3298 printf(" (Result: %s)", i->result);
3300 timestamp = (streq_ptr(i->active_state, "active") ||
3301 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
3302 (streq_ptr(i->active_state, "inactive") ||
3303 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
3304 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
3305 i->active_exit_timestamp;
3307 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3308 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3311 printf(" since %s; %s\n", s2, s1);
3313 printf(" since %s\n", s2);
3317 if (!i->condition_result && i->condition_timestamp > 0) {
3318 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3319 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3321 printf("Condition: start %scondition failed%s at %s%s%s\n",
3322 ansi_highlight_yellow(), ansi_highlight_off(),
3323 s2, s1 ? "; " : "", s1 ? s1 : "");
3324 if (i->failed_condition_trigger)
3325 printf(" none of the trigger conditions were met\n");
3326 else if (i->failed_condition)
3327 printf(" %s=%s%s was not met\n",
3328 i->failed_condition,
3329 i->failed_condition_negate ? "!" : "",
3330 i->failed_condition_parameter);
3333 if (!i->assert_result && i->assert_timestamp > 0) {
3334 s1 = format_timestamp_relative(since1, sizeof(since1), i->assert_timestamp);
3335 s2 = format_timestamp(since2, sizeof(since2), i->assert_timestamp);
3337 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3338 ansi_highlight_red(), ansi_highlight_off(),
3339 s2, s1 ? "; " : "", s1 ? s1 : "");
3340 if (i->failed_assert_trigger)
3341 printf(" none of the trigger assertions were met\n");
3342 else if (i->failed_assert)
3343 printf(" %s=%s%s was not met\n",
3345 i->failed_assert_negate ? "!" : "",
3346 i->failed_assert_parameter);
3350 printf(" Device: %s\n", i->sysfs_path);
3352 printf(" Where: %s\n", i->where);
3354 printf(" What: %s\n", i->what);
3356 STRV_FOREACH(t, i->documentation)
3357 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3359 STRV_FOREACH_PAIR(t, t2, i->listen)
3360 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3363 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3365 LIST_FOREACH(exec, p, i->exec) {
3366 _cleanup_free_ char *argv = NULL;
3369 /* Only show exited processes here */
3373 argv = strv_join(p->argv, " ");
3374 printf(" Process: "PID_FMT" %s=%s ", p->pid, p->name, strna(argv));
3376 good = is_clean_exit_lsb(p->code, p->status, NULL);
3378 on = ansi_highlight_red();
3379 off = ansi_highlight_off();
3383 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3385 if (p->code == CLD_EXITED) {
3388 printf("status=%i", p->status);
3390 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3395 printf("signal=%s", signal_to_string(p->status));
3397 printf(")%s\n", off);
3399 if (i->main_pid == p->pid &&
3400 i->start_timestamp == p->start_timestamp &&
3401 i->exit_timestamp == p->start_timestamp)
3402 /* Let's not show this twice */
3405 if (p->pid == i->control_pid)
3409 if (i->main_pid > 0 || i->control_pid > 0) {
3410 if (i->main_pid > 0) {
3411 printf(" Main PID: "PID_FMT, i->main_pid);
3414 _cleanup_free_ char *comm = NULL;
3415 get_process_comm(i->main_pid, &comm);
3417 printf(" (%s)", comm);
3418 } else if (i->exit_code > 0) {
3419 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3421 if (i->exit_code == CLD_EXITED) {
3424 printf("status=%i", i->exit_status);
3426 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3431 printf("signal=%s", signal_to_string(i->exit_status));
3435 if (i->control_pid > 0)
3439 if (i->control_pid > 0) {
3440 _cleanup_free_ char *c = NULL;
3442 printf(" %8s: "PID_FMT, i->main_pid ? "" : " Control", i->control_pid);
3444 get_process_comm(i->control_pid, &c);
3453 printf(" Status: \"%s\"\n", i->status_text);
3454 if (i->status_errno > 0)
3455 printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
3457 if (i->memory_current != (uint64_t) -1) {
3458 char buf[FORMAT_BYTES_MAX];
3460 printf(" Memory: %s", format_bytes(buf, sizeof(buf), i->memory_current));
3462 if (i->memory_limit != (uint64_t) -1)
3463 printf(" (limit: %s)\n", format_bytes(buf, sizeof(buf), i->memory_limit));
3468 if (i->control_group &&
3469 (i->main_pid > 0 || i->control_pid > 0 ||
3470 ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_MACHINE) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3473 printf(" CGroup: %s\n", i->control_group);
3475 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_MACHINE) {
3478 static const char prefix[] = " ";
3481 if (c > sizeof(prefix) - 1)
3482 c -= sizeof(prefix) - 1;
3486 if (i->main_pid > 0)
3487 extra[k++] = i->main_pid;
3489 if (i->control_pid > 0)
3490 extra[k++] = i->control_pid;
3492 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, get_output_flags());
3496 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3497 show_journal_by_unit(
3502 i->inactive_exit_timestamp_monotonic,
3505 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
3506 SD_JOURNAL_LOCAL_ONLY,
3507 arg_scope == UNIT_FILE_SYSTEM,
3511 if (i->need_daemon_reload)
3512 warn_unit_file_changed(i->id);
3515 static void show_unit_help(UnitStatusInfo *i) {
3520 if (!i->documentation) {
3521 log_info("Documentation for %s not known.", i->id);
3525 STRV_FOREACH(p, i->documentation)
3526 if (startswith(*p, "man:"))
3527 show_man_page(*p + 4, false);
3529 log_info("Can't show: %s", *p);
3532 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3539 switch (contents[0]) {
3541 case SD_BUS_TYPE_STRING: {
3544 r = sd_bus_message_read(m, "s", &s);
3546 return bus_log_parse_error(r);
3549 if (streq(name, "Id"))
3551 else if (streq(name, "LoadState"))
3553 else if (streq(name, "ActiveState"))
3554 i->active_state = s;
3555 else if (streq(name, "SubState"))
3557 else if (streq(name, "Description"))
3559 else if (streq(name, "FragmentPath"))
3560 i->fragment_path = s;
3561 else if (streq(name, "SourcePath"))
3564 else if (streq(name, "DefaultControlGroup")) {
3566 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3568 i->control_group = e;
3571 else if (streq(name, "ControlGroup"))
3572 i->control_group = s;
3573 else if (streq(name, "StatusText"))
3575 else if (streq(name, "PIDFile"))
3577 else if (streq(name, "SysFSPath"))
3579 else if (streq(name, "Where"))
3581 else if (streq(name, "What"))
3583 else if (streq(name, "Following"))
3585 else if (streq(name, "UnitFileState"))
3586 i->unit_file_state = s;
3587 else if (streq(name, "UnitFilePreset"))
3588 i->unit_file_preset = s;
3589 else if (streq(name, "Result"))
3596 case SD_BUS_TYPE_BOOLEAN: {
3599 r = sd_bus_message_read(m, "b", &b);
3601 return bus_log_parse_error(r);
3603 if (streq(name, "Accept"))
3605 else if (streq(name, "NeedDaemonReload"))
3606 i->need_daemon_reload = b;
3607 else if (streq(name, "ConditionResult"))
3608 i->condition_result = b;
3609 else if (streq(name, "AssertResult"))
3610 i->assert_result = b;
3615 case SD_BUS_TYPE_UINT32: {
3618 r = sd_bus_message_read(m, "u", &u);
3620 return bus_log_parse_error(r);
3622 if (streq(name, "MainPID")) {
3624 i->main_pid = (pid_t) u;
3627 } else if (streq(name, "ControlPID"))
3628 i->control_pid = (pid_t) u;
3629 else if (streq(name, "ExecMainPID")) {
3631 i->main_pid = (pid_t) u;
3632 } else if (streq(name, "NAccepted"))
3634 else if (streq(name, "NConnections"))
3635 i->n_connections = u;
3640 case SD_BUS_TYPE_INT32: {
3643 r = sd_bus_message_read(m, "i", &j);
3645 return bus_log_parse_error(r);
3647 if (streq(name, "ExecMainCode"))
3648 i->exit_code = (int) j;
3649 else if (streq(name, "ExecMainStatus"))
3650 i->exit_status = (int) j;
3651 else if (streq(name, "StatusErrno"))
3652 i->status_errno = (int) j;
3657 case SD_BUS_TYPE_UINT64: {
3660 r = sd_bus_message_read(m, "t", &u);
3662 return bus_log_parse_error(r);
3664 if (streq(name, "ExecMainStartTimestamp"))
3665 i->start_timestamp = (usec_t) u;
3666 else if (streq(name, "ExecMainExitTimestamp"))
3667 i->exit_timestamp = (usec_t) u;
3668 else if (streq(name, "ActiveEnterTimestamp"))
3669 i->active_enter_timestamp = (usec_t) u;
3670 else if (streq(name, "InactiveEnterTimestamp"))
3671 i->inactive_enter_timestamp = (usec_t) u;
3672 else if (streq(name, "InactiveExitTimestamp"))
3673 i->inactive_exit_timestamp = (usec_t) u;
3674 else if (streq(name, "InactiveExitTimestampMonotonic"))
3675 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3676 else if (streq(name, "ActiveExitTimestamp"))
3677 i->active_exit_timestamp = (usec_t) u;
3678 else if (streq(name, "ConditionTimestamp"))
3679 i->condition_timestamp = (usec_t) u;
3680 else if (streq(name, "AssertTimestamp"))
3681 i->assert_timestamp = (usec_t) u;
3682 else if (streq(name, "MemoryCurrent"))
3683 i->memory_current = u;
3684 else if (streq(name, "MemoryLimit"))
3685 i->memory_limit = u;
3690 case SD_BUS_TYPE_ARRAY:
3692 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3693 _cleanup_free_ ExecStatusInfo *info = NULL;
3695 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3697 return bus_log_parse_error(r);
3699 info = new0(ExecStatusInfo, 1);
3703 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3705 info->name = strdup(name);
3709 LIST_PREPEND(exec, i->exec, info);
3711 info = new0(ExecStatusInfo, 1);
3717 return bus_log_parse_error(r);
3719 r = sd_bus_message_exit_container(m);
3721 return bus_log_parse_error(r);
3725 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3726 const char *type, *path;
3728 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3730 return bus_log_parse_error(r);
3732 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3734 r = strv_extend(&i->listen, type);
3738 r = strv_extend(&i->listen, path);
3743 return bus_log_parse_error(r);
3745 r = sd_bus_message_exit_container(m);
3747 return bus_log_parse_error(r);
3751 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3753 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3755 return bus_log_parse_error(r);
3757 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3759 r = sd_bus_message_read_strv(m, &i->documentation);
3761 return bus_log_parse_error(r);
3763 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3764 const char *cond, *param;
3765 int trigger, negate;
3768 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3770 return bus_log_parse_error(r);
3772 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3773 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3774 if (state < 0 && (!trigger || !i->failed_condition)) {
3775 i->failed_condition = cond;
3776 i->failed_condition_trigger = trigger;
3777 i->failed_condition_negate = negate;
3778 i->failed_condition_parameter = param;
3782 return bus_log_parse_error(r);
3784 r = sd_bus_message_exit_container(m);
3786 return bus_log_parse_error(r);
3788 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Asserts")) {
3789 const char *cond, *param;
3790 int trigger, negate;
3793 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3795 return bus_log_parse_error(r);
3797 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3798 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3799 if (state < 0 && (!trigger || !i->failed_assert)) {
3800 i->failed_assert = cond;
3801 i->failed_assert_trigger = trigger;
3802 i->failed_assert_negate = negate;
3803 i->failed_assert_parameter = param;
3807 return bus_log_parse_error(r);
3809 r = sd_bus_message_exit_container(m);
3811 return bus_log_parse_error(r);
3818 case SD_BUS_TYPE_STRUCT_BEGIN:
3820 if (streq(name, "LoadError")) {
3821 const char *n, *message;
3823 r = sd_bus_message_read(m, "(ss)", &n, &message);
3825 return bus_log_parse_error(r);
3827 if (!isempty(message))
3828 i->load_error = message;
3841 r = sd_bus_message_skip(m, contents);
3843 return bus_log_parse_error(r);
3848 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3854 /* This is a low-level property printer, see
3855 * print_status_info() for the nicer output */
3857 if (arg_properties && !strv_find(arg_properties, name)) {
3858 /* skip what we didn't read */
3859 r = sd_bus_message_skip(m, contents);
3863 switch (contents[0]) {
3865 case SD_BUS_TYPE_STRUCT_BEGIN:
3867 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3870 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3872 return bus_log_parse_error(r);
3875 printf("%s=%"PRIu32"\n", name, u);
3877 printf("%s=\n", name);
3881 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3884 r = sd_bus_message_read(m, "(so)", &s, NULL);
3886 return bus_log_parse_error(r);
3888 if (arg_all || !isempty(s))
3889 printf("%s=%s\n", name, s);
3893 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3894 const char *a = NULL, *b = NULL;
3896 r = sd_bus_message_read(m, "(ss)", &a, &b);
3898 return bus_log_parse_error(r);
3900 if (arg_all || !isempty(a) || !isempty(b))
3901 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3904 } else if (streq_ptr(name, "SystemCallFilter")) {
3905 _cleanup_strv_free_ char **l = NULL;
3908 r = sd_bus_message_enter_container(m, 'r', "bas");
3910 return bus_log_parse_error(r);
3912 r = sd_bus_message_read(m, "b", &whitelist);
3914 return bus_log_parse_error(r);
3916 r = sd_bus_message_read_strv(m, &l);
3918 return bus_log_parse_error(r);
3920 r = sd_bus_message_exit_container(m);
3922 return bus_log_parse_error(r);
3924 if (arg_all || whitelist || !strv_isempty(l)) {
3928 fputs(name, stdout);
3934 STRV_FOREACH(i, l) {
3942 fputc('\n', stdout);
3950 case SD_BUS_TYPE_ARRAY:
3952 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
3956 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
3958 return bus_log_parse_error(r);
3960 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
3961 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3964 return bus_log_parse_error(r);
3966 r = sd_bus_message_exit_container(m);
3968 return bus_log_parse_error(r);
3972 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
3973 const char *type, *path;
3975 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3977 return bus_log_parse_error(r);
3979 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3980 printf("%s=%s\n", type, path);
3982 return bus_log_parse_error(r);
3984 r = sd_bus_message_exit_container(m);
3986 return bus_log_parse_error(r);
3990 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3991 const char *type, *path;
3993 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3995 return bus_log_parse_error(r);
3997 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3998 printf("Listen%s=%s\n", type, path);
4000 return bus_log_parse_error(r);
4002 r = sd_bus_message_exit_container(m);
4004 return bus_log_parse_error(r);
4008 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
4010 uint64_t value, next_elapse;
4012 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
4014 return bus_log_parse_error(r);
4016 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
4017 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
4019 printf("%s={ value=%s ; next_elapse=%s }\n",
4021 format_timespan(timespan1, sizeof(timespan1), value, 0),
4022 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
4025 return bus_log_parse_error(r);
4027 r = sd_bus_message_exit_container(m);
4029 return bus_log_parse_error(r);
4033 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
4034 ExecStatusInfo info = {};
4036 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
4038 return bus_log_parse_error(r);
4040 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
4041 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
4042 _cleanup_free_ char *tt;
4044 tt = strv_join(info.argv, " ");
4046 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",
4050 yes_no(info.ignore),
4051 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
4052 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
4054 sigchld_code_to_string(info.code),
4056 info.code == CLD_EXITED ? "" : "/",
4057 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
4060 strv_free(info.argv);
4064 r = sd_bus_message_exit_container(m);
4066 return bus_log_parse_error(r);
4070 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
4071 const char *path, *rwm;
4073 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4075 return bus_log_parse_error(r);
4077 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
4078 printf("%s=%s %s\n", name, strna(path), strna(rwm));
4080 return bus_log_parse_error(r);
4082 r = sd_bus_message_exit_container(m);
4084 return bus_log_parse_error(r);
4088 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
4092 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4094 return bus_log_parse_error(r);
4096 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4097 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
4099 return bus_log_parse_error(r);
4101 r = sd_bus_message_exit_container(m);
4103 return bus_log_parse_error(r);
4107 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
4111 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4113 return bus_log_parse_error(r);
4115 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4116 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
4118 return bus_log_parse_error(r);
4120 r = sd_bus_message_exit_container(m);
4122 return bus_log_parse_error(r);
4130 r = bus_print_property(name, m, arg_all);
4132 return bus_log_parse_error(r);
4135 r = sd_bus_message_skip(m, contents);
4137 return bus_log_parse_error(r);
4140 printf("%s=[unprintable]\n", name);
4146 static int show_one(
4150 bool show_properties,
4154 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4155 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4156 UnitStatusInfo info = {
4157 .memory_current = (uint64_t) -1,
4158 .memory_limit = (uint64_t) -1,
4166 log_debug("Showing one %s", path);
4168 r = sd_bus_call_method(
4170 "org.freedesktop.systemd1",
4172 "org.freedesktop.DBus.Properties",
4178 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4182 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4184 return bus_log_parse_error(r);
4191 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4192 const char *name, *contents;
4194 r = sd_bus_message_read(reply, "s", &name);
4196 return bus_log_parse_error(r);
4198 r = sd_bus_message_peek_type(reply, NULL, &contents);
4200 return bus_log_parse_error(r);
4202 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4204 return bus_log_parse_error(r);
4206 if (show_properties)
4207 r = print_property(name, reply, contents);
4209 r = status_property(name, reply, &info, contents);
4213 r = sd_bus_message_exit_container(reply);
4215 return bus_log_parse_error(r);
4217 r = sd_bus_message_exit_container(reply);
4219 return bus_log_parse_error(r);
4222 return bus_log_parse_error(r);
4224 r = sd_bus_message_exit_container(reply);
4226 return bus_log_parse_error(r);
4230 if (!show_properties) {
4231 if (streq(verb, "help"))
4232 show_unit_help(&info);
4234 print_status_info(&info, ellipsized);
4237 strv_free(info.documentation);
4238 strv_free(info.dropin_paths);
4239 strv_free(info.listen);
4241 if (!streq_ptr(info.active_state, "active") &&
4242 !streq_ptr(info.active_state, "reloading") &&
4243 streq(verb, "status")) {
4244 /* According to LSB: "program not running" */
4245 /* 0: program is running or service is OK
4246 * 1: program is dead and /run PID file exists
4247 * 2: program is dead and /run/lock lock file exists
4248 * 3: program is not running
4249 * 4: program or service status is unknown
4251 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4257 while ((p = info.exec)) {
4258 LIST_REMOVE(exec, info.exec, p);
4259 exec_status_info_free(p);
4265 static int get_unit_dbus_path_by_pid(
4270 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4271 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4275 r = sd_bus_call_method(
4277 "org.freedesktop.systemd1",
4278 "/org/freedesktop/systemd1",
4279 "org.freedesktop.systemd1.Manager",
4285 log_error("Failed to get unit for PID %"PRIu32": %s", pid, bus_error_message(&error, r));
4289 r = sd_bus_message_read(reply, "o", &u);
4291 return bus_log_parse_error(r);
4301 static int show_all(
4304 bool show_properties,
4308 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4309 _cleanup_free_ UnitInfo *unit_infos = NULL;
4314 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4318 pager_open_if_enabled();
4322 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4324 for (u = unit_infos; u < unit_infos + c; u++) {
4325 _cleanup_free_ char *p = NULL;
4327 p = unit_dbus_path_from_name(u->id);
4331 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4334 else if (r > 0 && ret == 0)
4341 static int show_system_status(sd_bus *bus) {
4342 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4343 _cleanup_free_ char *hn = NULL;
4344 struct machine_info mi = {};
4345 const char *on, *off;
4348 hn = gethostname_malloc();
4352 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4354 return log_error_errno(r, "Failed to read server status: %m");
4356 if (streq_ptr(mi.state, "degraded")) {
4357 on = ansi_highlight_red();
4358 off = ansi_highlight_off();
4359 } else if (!streq_ptr(mi.state, "running")) {
4360 on = ansi_highlight_yellow();
4361 off = ansi_highlight_off();
4365 printf("%s%s%s %s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4367 printf(" State: %s%s%s\n",
4368 on, strna(mi.state), off);
4370 printf(" Jobs: %u queued\n", mi.n_jobs);
4371 printf(" Failed: %u units\n", mi.n_failed_units);
4373 printf(" Since: %s; %s\n",
4374 format_timestamp(since2, sizeof(since2), mi.timestamp),
4375 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4377 printf(" CGroup: %s\n", mi.control_group ?: "/");
4378 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_MACHINE) {
4379 static const char prefix[] = " ";
4383 if (c > sizeof(prefix) - 1)
4384 c -= sizeof(prefix) - 1;
4388 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, get_output_flags());
4392 free(mi.control_group);
4397 static int show(sd_bus *bus, char **args) {
4398 bool show_properties, show_status, new_line = false;
4399 bool ellipsized = false;
4405 show_properties = streq(args[0], "show");
4406 show_status = streq(args[0], "status");
4408 if (show_properties)
4409 pager_open_if_enabled();
4411 /* If no argument is specified inspect the manager itself */
4413 if (show_properties && strv_length(args) <= 1)
4414 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4416 if (show_status && strv_length(args) <= 1) {
4418 pager_open_if_enabled();
4419 show_system_status(bus);
4423 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4425 _cleanup_free_ char **patterns = NULL;
4428 STRV_FOREACH(name, args + 1) {
4429 _cleanup_free_ char *unit = NULL;
4432 if (safe_atou32(*name, &id) < 0) {
4433 if (strv_push(&patterns, *name) < 0)
4437 } else if (show_properties) {
4438 /* Interpret as job id */
4439 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4443 /* Interpret as PID */
4444 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4451 r = show_one(args[0], bus, unit, show_properties,
4452 &new_line, &ellipsized);
4455 else if (r > 0 && ret == 0)
4459 if (!strv_isempty(patterns)) {
4460 _cleanup_strv_free_ char **names = NULL;
4462 r = expand_names(bus, patterns, NULL, &names);
4464 log_error_errno(r, "Failed to expand names: %m");
4466 STRV_FOREACH(name, names) {
4467 _cleanup_free_ char *unit;
4469 unit = unit_dbus_path_from_name(*name);
4473 r = show_one(args[0], bus, unit, show_properties,
4474 &new_line, &ellipsized);
4477 else if (r > 0 && ret == 0)
4483 if (ellipsized && !arg_quiet)
4484 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4489 static int init_home_and_lookup_paths(char **user_home, char **user_runtime, LookupPaths *lp) {
4493 assert(user_runtime);
4496 if (arg_scope == UNIT_FILE_USER) {
4497 r = user_config_home(user_home);
4499 return log_error_errno(r, "Failed to query XDG_CONFIG_HOME: %m");
4501 return log_error_errno(ENOTDIR, "Cannot find units: $XDG_CONFIG_HOME and $HOME are not set.");
4503 r = user_runtime_dir(user_runtime);
4505 return log_error_errno(r, "Failed to query XDG_CONFIG_HOME: %m");
4507 return log_error_errno(ENOTDIR, "Cannot find units: $XDG_RUNTIME_DIR is not set.");
4510 r = lookup_paths_init_from_scope(lp, arg_scope, arg_root);
4512 return log_error_errno(r, "Failed to query unit lookup paths: %m");
4517 static int cat_file(const char *filename, bool newline) {
4518 _cleanup_close_ int fd;
4520 fd = open(filename, O_RDONLY|O_CLOEXEC|O_NOCTTY);
4524 printf("%s%s# %s%s\n",
4525 newline ? "\n" : "",
4526 ansi_highlight_blue(),
4528 ansi_highlight_off());
4531 return copy_bytes(fd, STDOUT_FILENO, (off_t) -1, false);
4534 static int cat(sd_bus *bus, char **args) {
4535 _cleanup_free_ char *user_home = NULL;
4536 _cleanup_free_ char *user_runtime = NULL;
4537 _cleanup_lookup_paths_free_ LookupPaths lp = {};
4538 _cleanup_strv_free_ char **names = NULL;
4540 bool first = true, avoid_bus_cache;
4545 if (arg_transport != BUS_TRANSPORT_LOCAL) {
4546 log_error("Cannot remotely cat units");
4550 r = init_home_and_lookup_paths(&user_home, &user_runtime, &lp);
4554 r = expand_names(bus, args + 1, NULL, &names);
4556 return log_error_errno(r, "Failed to expand names: %m");
4558 avoid_bus_cache = !bus || avoid_bus();
4560 pager_open_if_enabled();
4562 STRV_FOREACH(name, names) {
4563 _cleanup_free_ char *fragment_path = NULL;
4564 _cleanup_strv_free_ char **dropin_paths = NULL;
4567 r = unit_find_paths(bus, *name, avoid_bus_cache, &lp, &fragment_path, &dropin_paths);
4578 if (fragment_path) {
4579 r = cat_file(fragment_path, false);
4581 return log_warning_errno(r, "Failed to cat %s: %m", fragment_path);
4584 STRV_FOREACH(path, dropin_paths) {
4585 r = cat_file(*path, path == dropin_paths);
4587 return log_warning_errno(r, "Failed to cat %s: %m", *path);
4591 return r < 0 ? r : 0;
4594 static int set_property(sd_bus *bus, char **args) {
4595 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4596 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4597 _cleanup_free_ char *n = NULL;
4601 polkit_agent_open_if_enabled();
4603 r = sd_bus_message_new_method_call(
4606 "org.freedesktop.systemd1",
4607 "/org/freedesktop/systemd1",
4608 "org.freedesktop.systemd1.Manager",
4609 "SetUnitProperties");
4611 return bus_log_create_error(r);
4613 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4617 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4619 return bus_log_create_error(r);
4621 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4623 return bus_log_create_error(r);
4625 STRV_FOREACH(i, args + 2) {
4626 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4628 return bus_log_create_error(r);
4630 r = bus_append_unit_property_assignment(m, *i);
4634 r = sd_bus_message_close_container(m);
4636 return bus_log_create_error(r);
4639 r = sd_bus_message_close_container(m);
4641 return bus_log_create_error(r);
4643 r = sd_bus_call(bus, m, 0, &error, NULL);
4645 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4652 static int snapshot(sd_bus *bus, char **args) {
4653 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4654 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4655 _cleanup_free_ char *n = NULL, *id = NULL;
4659 polkit_agent_open_if_enabled();
4661 if (strv_length(args) > 1)
4662 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4668 r = sd_bus_call_method(
4670 "org.freedesktop.systemd1",
4671 "/org/freedesktop/systemd1",
4672 "org.freedesktop.systemd1.Manager",
4678 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4682 r = sd_bus_message_read(reply, "o", &path);
4684 return bus_log_parse_error(r);
4686 r = sd_bus_get_property_string(
4688 "org.freedesktop.systemd1",
4690 "org.freedesktop.systemd1.Unit",
4695 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4705 static int delete_snapshot(sd_bus *bus, char **args) {
4706 _cleanup_strv_free_ char **names = NULL;
4712 polkit_agent_open_if_enabled();
4714 r = expand_names(bus, args + 1, ".snapshot", &names);
4716 log_error_errno(r, "Failed to expand names: %m");
4718 STRV_FOREACH(name, names) {
4719 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4722 q = sd_bus_call_method(
4724 "org.freedesktop.systemd1",
4725 "/org/freedesktop/systemd1",
4726 "org.freedesktop.systemd1.Manager",
4732 log_error("Failed to remove snapshot %s: %s", *name, bus_error_message(&error, q));
4741 static int daemon_reload(sd_bus *bus, char **args) {
4742 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4746 polkit_agent_open_if_enabled();
4748 if (arg_action == ACTION_RELOAD)
4750 else if (arg_action == ACTION_REEXEC)
4751 method = "Reexecute";
4753 assert(arg_action == ACTION_SYSTEMCTL);
4756 streq(args[0], "clear-jobs") ||
4757 streq(args[0], "cancel") ? "ClearJobs" :
4758 streq(args[0], "daemon-reexec") ? "Reexecute" :
4759 streq(args[0], "reset-failed") ? "ResetFailed" :
4760 streq(args[0], "halt") ? "Halt" :
4761 streq(args[0], "poweroff") ? "PowerOff" :
4762 streq(args[0], "reboot") ? "Reboot" :
4763 streq(args[0], "kexec") ? "KExec" :
4764 streq(args[0], "exit") ? "Exit" :
4765 /* "daemon-reload" */ "Reload";
4768 r = sd_bus_call_method(
4770 "org.freedesktop.systemd1",
4771 "/org/freedesktop/systemd1",
4772 "org.freedesktop.systemd1.Manager",
4777 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4778 /* There's always a fallback possible for
4779 * legacy actions. */
4781 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4782 /* On reexecution, we expect a disconnect, not a
4786 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4788 return r < 0 ? r : 0;
4791 static int reset_failed(sd_bus *bus, char **args) {
4792 _cleanup_strv_free_ char **names = NULL;
4796 if (strv_length(args) <= 1)
4797 return daemon_reload(bus, args);
4799 polkit_agent_open_if_enabled();
4801 r = expand_names(bus, args + 1, NULL, &names);
4803 log_error_errno(r, "Failed to expand names: %m");
4805 STRV_FOREACH(name, names) {
4806 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4808 q = sd_bus_call_method(
4810 "org.freedesktop.systemd1",
4811 "/org/freedesktop/systemd1",
4812 "org.freedesktop.systemd1.Manager",
4818 log_error("Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q));
4827 static int show_environment(sd_bus *bus, char **args) {
4828 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4829 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4833 pager_open_if_enabled();
4835 r = sd_bus_get_property(
4837 "org.freedesktop.systemd1",
4838 "/org/freedesktop/systemd1",
4839 "org.freedesktop.systemd1.Manager",
4845 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4849 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4851 return bus_log_parse_error(r);
4853 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4856 return bus_log_parse_error(r);
4858 r = sd_bus_message_exit_container(reply);
4860 return bus_log_parse_error(r);
4865 static int switch_root(sd_bus *bus, char **args) {
4866 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4867 _cleanup_free_ char *cmdline_init = NULL;
4868 const char *root, *init;
4872 l = strv_length(args);
4873 if (l < 2 || l > 3) {
4874 log_error("Wrong number of arguments.");
4883 r = parse_env_file("/proc/cmdline", WHITESPACE,
4884 "init", &cmdline_init,
4887 log_debug_errno(r, "Failed to parse /proc/cmdline: %m");
4889 init = cmdline_init;
4896 const char *root_systemd_path = NULL, *root_init_path = NULL;
4898 root_systemd_path = strjoina(root, "/" SYSTEMD_BINARY_PATH);
4899 root_init_path = strjoina(root, "/", init);
4901 /* If the passed init is actually the same as the
4902 * systemd binary, then let's suppress it. */
4903 if (files_same(root_init_path, root_systemd_path) > 0)
4907 log_debug("Switching root - root: %s; init: %s", root, strna(init));
4909 r = sd_bus_call_method(
4911 "org.freedesktop.systemd1",
4912 "/org/freedesktop/systemd1",
4913 "org.freedesktop.systemd1.Manager",
4919 log_error("Failed to switch root: %s", bus_error_message(&error, r));
4926 static int set_environment(sd_bus *bus, char **args) {
4927 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4928 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4935 polkit_agent_open_if_enabled();
4937 method = streq(args[0], "set-environment")
4939 : "UnsetEnvironment";
4941 r = sd_bus_message_new_method_call(
4944 "org.freedesktop.systemd1",
4945 "/org/freedesktop/systemd1",
4946 "org.freedesktop.systemd1.Manager",
4949 return bus_log_create_error(r);
4951 r = sd_bus_message_append_strv(m, args + 1);
4953 return bus_log_create_error(r);
4955 r = sd_bus_call(bus, m, 0, &error, NULL);
4957 log_error("Failed to set environment: %s", bus_error_message(&error, r));
4964 static int import_environment(sd_bus *bus, char **args) {
4965 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4966 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4972 polkit_agent_open_if_enabled();
4974 r = sd_bus_message_new_method_call(
4977 "org.freedesktop.systemd1",
4978 "/org/freedesktop/systemd1",
4979 "org.freedesktop.systemd1.Manager",
4982 return bus_log_create_error(r);
4984 if (strv_isempty(args + 1))
4985 r = sd_bus_message_append_strv(m, environ);
4989 r = sd_bus_message_open_container(m, 'a', "s");
4991 return bus_log_create_error(r);
4993 STRV_FOREACH(a, args + 1) {
4995 if (!env_name_is_valid(*a)) {
4996 log_error("Not a valid environment variable name: %s", *a);
5000 STRV_FOREACH(b, environ) {
5003 eq = startswith(*b, *a);
5004 if (eq && *eq == '=') {
5006 r = sd_bus_message_append(m, "s", *b);
5008 return bus_log_create_error(r);
5015 r = sd_bus_message_close_container(m);
5018 return bus_log_create_error(r);
5020 r = sd_bus_call(bus, m, 0, &error, NULL);
5022 log_error("Failed to import environment: %s", bus_error_message(&error, r));
5029 static int enable_sysv_units(const char *verb, char **args) {
5032 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
5034 _cleanup_lookup_paths_free_ LookupPaths paths = {};
5036 if (arg_scope != UNIT_FILE_SYSTEM)
5039 if (!streq(verb, "enable") &&
5040 !streq(verb, "disable") &&
5041 !streq(verb, "is-enabled"))
5044 /* Processes all SysV units, and reshuffles the array so that
5045 * afterwards only the native units remain */
5047 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, arg_root, NULL, NULL, NULL);
5054 _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL;
5055 bool found_native = false, found_sysv;
5057 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
5065 if (!endswith(name, ".service"))
5068 if (path_is_absolute(name))
5071 STRV_FOREACH(k, paths.unit_path) {
5072 _cleanup_free_ char *path = NULL;
5074 path = path_join(arg_root, *k, name);
5078 found_native = access(path, F_OK) >= 0;
5086 p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name);
5090 p[strlen(p) - strlen(".service")] = 0;
5091 found_sysv = access(p, F_OK) >= 0;
5095 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
5097 if (!isempty(arg_root))
5098 argv[c++] = q = strappend("--root=", arg_root);
5100 argv[c++] = basename(p);
5102 streq(verb, "enable") ? "on" :
5103 streq(verb, "disable") ? "off" : "--level=5";
5106 l = strv_join((char**)argv, " ");
5110 log_info("Executing %s", l);
5114 return log_error_errno(errno, "Failed to fork: %m");
5115 else if (pid == 0) {
5118 execv(argv[0], (char**) argv);
5119 _exit(EXIT_FAILURE);
5122 j = wait_for_terminate(pid, &status);
5124 log_error_errno(r, "Failed to wait for child: %m");
5128 if (status.si_code == CLD_EXITED) {
5129 if (streq(verb, "is-enabled")) {
5130 if (status.si_status == 0) {
5139 } else if (status.si_status != 0)
5144 /* Remove this entry, so that we don't try enabling it as native unit */
5147 assert(args[f] == name);
5148 strv_remove(args, name);
5155 static int mangle_names(char **original_names, char ***mangled_names) {
5156 char **i, **l, **name;
5158 l = new(char*, strv_length(original_names) + 1);
5163 STRV_FOREACH(name, original_names) {
5165 /* When enabling units qualified path names are OK,
5166 * too, hence allow them explicitly. */
5171 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5187 static int enable_unit(sd_bus *bus, char **args) {
5188 _cleanup_strv_free_ char **names = NULL;
5189 const char *verb = args[0];
5190 UnitFileChange *changes = NULL;
5191 unsigned n_changes = 0;
5192 int carries_install_info = -1;
5198 r = mangle_names(args+1, &names);
5202 r = enable_sysv_units(verb, names);
5206 /* If the operation was fully executed by the SysV compat,
5207 * let's finish early */
5208 if (strv_isempty(names))
5211 if (!bus || avoid_bus()) {
5212 if (streq(verb, "enable")) {
5213 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5214 carries_install_info = r;
5215 } else if (streq(verb, "disable"))
5216 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5217 else if (streq(verb, "reenable")) {
5218 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5219 carries_install_info = r;
5220 } else if (streq(verb, "link"))
5221 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5222 else if (streq(verb, "preset")) {
5223 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_preset_mode, arg_force, &changes, &n_changes);
5224 carries_install_info = r;
5225 } else if (streq(verb, "mask"))
5226 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5227 else if (streq(verb, "unmask"))
5228 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5230 assert_not_reached("Unknown verb");
5233 log_error_errno(r, "Operation failed: %m");
5238 dump_unit_file_changes(changes, n_changes);
5242 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5243 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5244 int expect_carries_install_info = false;
5245 bool send_force = true, send_preset_mode = false;
5248 polkit_agent_open_if_enabled();
5250 if (streq(verb, "enable")) {
5251 method = "EnableUnitFiles";
5252 expect_carries_install_info = true;
5253 } else if (streq(verb, "disable")) {
5254 method = "DisableUnitFiles";
5256 } else if (streq(verb, "reenable")) {
5257 method = "ReenableUnitFiles";
5258 expect_carries_install_info = true;
5259 } else if (streq(verb, "link"))
5260 method = "LinkUnitFiles";
5261 else if (streq(verb, "preset")) {
5263 if (arg_preset_mode != UNIT_FILE_PRESET_FULL) {
5264 method = "PresetUnitFilesWithMode";
5265 send_preset_mode = true;
5267 method = "PresetUnitFiles";
5269 expect_carries_install_info = true;
5270 } else if (streq(verb, "mask"))
5271 method = "MaskUnitFiles";
5272 else if (streq(verb, "unmask")) {
5273 method = "UnmaskUnitFiles";
5276 assert_not_reached("Unknown verb");
5278 r = sd_bus_message_new_method_call(
5281 "org.freedesktop.systemd1",
5282 "/org/freedesktop/systemd1",
5283 "org.freedesktop.systemd1.Manager",
5286 return bus_log_create_error(r);
5288 r = sd_bus_message_append_strv(m, names);
5290 return bus_log_create_error(r);
5292 if (send_preset_mode) {
5293 r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode));
5295 return bus_log_create_error(r);
5298 r = sd_bus_message_append(m, "b", arg_runtime);
5300 return bus_log_create_error(r);
5303 r = sd_bus_message_append(m, "b", arg_force);
5305 return bus_log_create_error(r);
5308 r = sd_bus_call(bus, m, 0, &error, &reply);
5310 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5314 if (expect_carries_install_info) {
5315 r = sd_bus_message_read(reply, "b", &carries_install_info);
5317 return bus_log_parse_error(r);
5320 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
5324 /* Try to reload if enabled */
5326 r = daemon_reload(bus, args);
5331 if (carries_install_info == 0)
5332 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5333 "using systemctl.\n"
5334 "Possible reasons for having this kind of units are:\n"
5335 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5336 " .wants/ or .requires/ directory.\n"
5337 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5338 " a requirement dependency on it.\n"
5339 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5340 " D-Bus, udev, scripted systemctl call, ...).\n");
5343 unit_file_changes_free(changes, n_changes);
5348 static int add_dependency(sd_bus *bus, char **args) {
5349 _cleanup_strv_free_ char **names = NULL;
5350 _cleanup_free_ char *target = NULL;
5351 const char *verb = args[0];
5358 target = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
5362 r = mangle_names(args+2, &names);
5366 if (streq(verb, "add-wants"))
5368 else if (streq(verb, "add-requires"))
5369 dep = UNIT_REQUIRES;
5371 assert_not_reached("Unknown verb");
5373 if (!bus || avoid_bus()) {
5374 UnitFileChange *changes = NULL;
5375 unsigned n_changes = 0;
5377 r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes);
5380 return log_error_errno(r, "Can't add dependency: %m");
5383 dump_unit_file_changes(changes, n_changes);
5385 unit_file_changes_free(changes, n_changes);
5388 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5389 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5391 polkit_agent_open_if_enabled();
5393 r = sd_bus_message_new_method_call(
5396 "org.freedesktop.systemd1",
5397 "/org/freedesktop/systemd1",
5398 "org.freedesktop.systemd1.Manager",
5399 "AddDependencyUnitFiles");
5401 return bus_log_create_error(r);
5403 r = sd_bus_message_append_strv(m, names);
5405 return bus_log_create_error(r);
5407 r = sd_bus_message_append(m, "ssbb", target, unit_dependency_to_string(dep), arg_runtime, arg_force);
5409 return bus_log_create_error(r);
5411 r = sd_bus_call(bus, m, 0, &error, &reply);
5413 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5417 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
5422 r = daemon_reload(bus, args);
5430 static int preset_all(sd_bus *bus, char **args) {
5431 UnitFileChange *changes = NULL;
5432 unsigned n_changes = 0;
5435 if (!bus || avoid_bus()) {
5437 r = unit_file_preset_all(arg_scope, arg_runtime, arg_root, arg_preset_mode, arg_force, &changes, &n_changes);
5439 log_error_errno(r, "Operation failed: %m");
5444 dump_unit_file_changes(changes, n_changes);
5449 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5450 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5452 polkit_agent_open_if_enabled();
5454 r = sd_bus_call_method(
5456 "org.freedesktop.systemd1",
5457 "/org/freedesktop/systemd1",
5458 "org.freedesktop.systemd1.Manager",
5459 "PresetAllUnitFiles",
5463 unit_file_preset_mode_to_string(arg_preset_mode),
5467 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5471 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
5476 r = daemon_reload(bus, args);
5482 unit_file_changes_free(changes, n_changes);
5487 static int unit_is_enabled(sd_bus *bus, char **args) {
5489 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5490 _cleanup_strv_free_ char **names = NULL;
5495 r = mangle_names(args+1, &names);
5499 r = enable_sysv_units(args[0], names);
5505 if (!bus || avoid_bus()) {
5507 STRV_FOREACH(name, names) {
5508 UnitFileState state;
5510 state = unit_file_get_state(arg_scope, arg_root, *name);
5512 return log_error_errno(state, "Failed to get unit file state for %s: %m", *name);
5514 if (state == UNIT_FILE_ENABLED ||
5515 state == UNIT_FILE_ENABLED_RUNTIME ||
5516 state == UNIT_FILE_STATIC ||
5517 state == UNIT_FILE_INDIRECT)
5521 puts(unit_file_state_to_string(state));
5525 STRV_FOREACH(name, names) {
5526 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5529 r = sd_bus_call_method(
5531 "org.freedesktop.systemd1",
5532 "/org/freedesktop/systemd1",
5533 "org.freedesktop.systemd1.Manager",
5539 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5543 r = sd_bus_message_read(reply, "s", &s);
5545 return bus_log_parse_error(r);
5547 if (STR_IN_SET(s, "enabled", "enabled-runtime", "static", "indirect"))
5558 static int is_system_running(sd_bus *bus, char **args) {
5559 _cleanup_free_ char *state = NULL;
5562 r = sd_bus_get_property_string(
5564 "org.freedesktop.systemd1",
5565 "/org/freedesktop/systemd1",
5566 "org.freedesktop.systemd1.Manager",
5579 return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE;
5582 static int create_edit_temp_file(const char *new_path, const char *original_path, char **ret_tmp_fn) {
5587 assert(original_path);
5590 r = tempfn_random(new_path, &t);
5592 return log_error_errno(r, "Failed to determine temporary filename for \"%s\": %m", new_path);
5594 r = mkdir_parents(new_path, 0755);
5596 log_error_errno(r, "Failed to create directories for \"%s\": %m", new_path);
5601 r = copy_file(original_path, t, 0, 0644, 0);
5605 log_error_errno(r, "Failed to create temporary file \"%s\": %m", t);
5610 log_error_errno(r, "Failed to copy \"%s\" to \"%s\": %m", original_path, t);
5620 static int get_file_to_edit(const char *name, const char *user_home, const char *user_runtime, char **ret_path) {
5621 _cleanup_free_ char *path = NULL, *path2 = NULL, *run = NULL;
5623 switch (arg_scope) {
5624 case UNIT_FILE_SYSTEM:
5625 path = path_join(arg_root, SYSTEM_CONFIG_UNIT_PATH, name);
5627 run = path_join(arg_root, "/run/systemd/system/", name);
5629 case UNIT_FILE_GLOBAL:
5630 path = path_join(arg_root, USER_CONFIG_UNIT_PATH, name);
5632 run = path_join(arg_root, "/run/systemd/user/", name);
5634 case UNIT_FILE_USER:
5636 assert(user_runtime);
5638 path = path_join(arg_root, user_home, name);
5640 path2 = path_join(arg_root, USER_CONFIG_UNIT_PATH, name);
5643 run = path_join(arg_root, user_runtime, name);
5647 assert_not_reached("Invalid scope");
5649 if (!path || (arg_runtime && !run))
5653 if (access(path, F_OK) >= 0)
5654 return log_error_errno(EEXIST, "Refusing to create \"%s\" because it would be overriden by \"%s\" anyway.",
5656 if (path2 && access(path2, F_OK) >= 0)
5657 return log_error_errno(EEXIST, "Refusing to create \"%s\" because it would be overriden by \"%s\" anyway.",
5669 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) {
5670 char *tmp_new_path, *ending;
5675 assert(ret_new_path);
5676 assert(ret_tmp_path);
5678 ending = strjoina(unit_name, ".d/override.conf");
5679 r = get_file_to_edit(ending, user_home, user_runtime, &tmp_new_path);
5683 r = create_edit_temp_file(tmp_new_path, tmp_new_path, &tmp_tmp_path);
5689 *ret_new_path = tmp_new_path;
5690 *ret_tmp_path = tmp_tmp_path;
5695 static int unit_file_create_copy(
5696 const char *unit_name,
5697 const char *fragment_path,
5698 const char *user_home,
5699 const char *user_runtime,
5700 char **ret_new_path,
5701 char **ret_tmp_path) {
5707 assert(fragment_path);
5709 assert(ret_new_path);
5710 assert(ret_tmp_path);
5712 r = get_file_to_edit(unit_name, user_home, user_runtime, &tmp_new_path);
5716 if (!path_equal(fragment_path, tmp_new_path) && access(tmp_new_path, F_OK) == 0) {
5719 r = ask_char(&response, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path, fragment_path);
5724 if (response != 'y') {
5725 log_warning("%s ignored", unit_name);
5731 r = create_edit_temp_file(tmp_new_path, fragment_path, &tmp_tmp_path);
5733 log_error_errno(r, "Failed to create temporary file for \"%s\": %m", tmp_new_path);
5738 *ret_new_path = tmp_new_path;
5739 *ret_tmp_path = tmp_tmp_path;
5744 static int run_editor(char **paths) {
5752 log_error_errno(errno, "Failed to fork: %m");
5759 char **tmp_path, **original_path, *p;
5763 argc = strv_length(paths)/2 + 1;
5764 args = newa(const char*, argc + 1);
5767 STRV_FOREACH_PAIR(original_path, tmp_path, paths) {
5768 args[i] = *tmp_path;
5773 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
5774 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
5775 * we try to execute well known editors
5777 editor = getenv("SYSTEMD_EDITOR");
5779 editor = getenv("EDITOR");
5781 editor = getenv("VISUAL");
5783 if (!isempty(editor)) {
5785 execvp(editor, (char* const*) args);
5788 FOREACH_STRING(p, "nano", "vim", "vi") {
5790 execvp(p, (char* const*) args);
5791 /* We do not fail if the editor doesn't exist
5792 * because we want to try each one of them before
5795 if (errno != ENOENT) {
5796 log_error("Failed to execute %s: %m", editor);
5797 _exit(EXIT_FAILURE);
5801 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
5802 _exit(EXIT_FAILURE);
5805 r = wait_for_terminate_and_warn("editor", pid, true);
5807 return log_error_errno(r, "Failed to wait for child: %m");
5812 static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
5813 _cleanup_free_ char *user_home = NULL;
5814 _cleanup_free_ char *user_runtime = NULL;
5815 _cleanup_lookup_paths_free_ LookupPaths lp = {};
5816 bool avoid_bus_cache;
5823 r = init_home_and_lookup_paths(&user_home, &user_runtime, &lp);
5827 avoid_bus_cache = !bus || avoid_bus();
5829 STRV_FOREACH(name, names) {
5830 _cleanup_free_ char *path = NULL;
5831 char *new_path, *tmp_path;
5833 r = unit_find_paths(bus, *name, avoid_bus_cache, &lp, &path, NULL);
5839 // FIXME: support units with path==NULL (no FragmentPath)
5840 log_error("No fragment exists for %s.", *name);
5845 r = unit_file_create_copy(*name, path, user_home, user_runtime, &new_path, &tmp_path);
5847 r = unit_file_create_dropin(*name, user_home, user_runtime, &new_path, &tmp_path);
5851 r = strv_push_pair(paths, new_path, tmp_path);
5859 static int edit(sd_bus *bus, char **args) {
5860 _cleanup_strv_free_ char **names = NULL;
5861 _cleanup_strv_free_ char **paths = NULL;
5862 char **original, **tmp;
5868 log_error("Cannot edit units if not on a tty");
5872 if (arg_transport != BUS_TRANSPORT_LOCAL) {
5873 log_error("Cannot remotely edit units");
5877 r = expand_names(bus, args + 1, NULL, &names);
5879 return log_error_errno(r, "Failed to expand names: %m");
5881 r = find_paths_to_edit(bus, names, &paths);
5885 if (strv_isempty(paths))
5888 r = run_editor(paths);
5892 STRV_FOREACH_PAIR(original, tmp, paths) {
5893 /* If the temporary file is empty we ignore it.
5894 * It's useful if the user wants to cancel its modification
5896 if (null_or_empty_path(*tmp)) {
5897 log_warning("Editing \"%s\" canceled: temporary file is empty", *original);
5900 r = rename(*tmp, *original);
5902 r = log_error_errno(errno, "Failed to rename \"%s\" to \"%s\": %m", *tmp, *original);
5907 if (!arg_no_reload && bus && !avoid_bus())
5908 r = daemon_reload(bus, args);
5911 STRV_FOREACH_PAIR(original, tmp, paths)
5912 unlink_noerrno(*tmp);
5917 static void systemctl_help(void) {
5919 pager_open_if_enabled();
5921 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
5922 "Query or send control commands to the systemd manager.\n\n"
5923 " -h --help Show this help\n"
5924 " --version Show package version\n"
5925 " --system Connect to system manager\n"
5926 " --user Connect to user service manager\n"
5927 " -H --host=[USER@]HOST\n"
5928 " Operate on remote host\n"
5929 " -M --machine=CONTAINER\n"
5930 " Operate on local container\n"
5931 " -t --type=TYPE List units of a particular type\n"
5932 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
5933 " -p --property=NAME Show only properties by this name\n"
5934 " -a --all Show all loaded units/properties, including dead/empty\n"
5935 " ones. To list all units installed on the system, use\n"
5936 " the 'list-unit-files' command instead.\n"
5937 " -l --full Don't ellipsize unit names on output\n"
5938 " -r --recursive Show unit list of host and local containers\n"
5939 " --reverse Show reverse dependencies with 'list-dependencies'\n"
5940 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
5941 " queueing a new job\n"
5942 " --show-types When showing sockets, explicitly show their type\n"
5943 " -i --ignore-inhibitors\n"
5944 " When shutting down or sleeping, ignore inhibitors\n"
5945 " --kill-who=WHO Who to send signal to\n"
5946 " -s --signal=SIGNAL Which signal to send\n"
5947 " -q --quiet Suppress output\n"
5948 " --no-block Do not wait until operation finished\n"
5949 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5950 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
5951 " --no-legend Do not print a legend (column headers and hints)\n"
5952 " --no-pager Do not pipe output into a pager\n"
5953 " --no-ask-password\n"
5954 " Do not ask for system passwords\n"
5955 " --global Enable/disable unit files globally\n"
5956 " --runtime Enable unit files only temporarily until next reboot\n"
5957 " -f --force When enabling unit files, override existing symlinks\n"
5958 " When shutting down, execute action immediately\n"
5959 " --preset-mode= Apply only enable, only disable, or all presets\n"
5960 " --root=PATH Enable unit files in the specified root directory\n"
5961 " -n --lines=INTEGER Number of journal entries to show\n"
5962 " -o --output=STRING Change journal output mode (short, short-iso,\n"
5963 " short-precise, short-monotonic, verbose,\n"
5964 " export, json, json-pretty, json-sse, cat)\n"
5965 " --plain Print unit dependencies as a list instead of a tree\n\n"
5967 " list-units [PATTERN...] List loaded units\n"
5968 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
5969 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
5970 " start NAME... Start (activate) one or more units\n"
5971 " stop NAME... Stop (deactivate) one or more units\n"
5972 " reload NAME... Reload one or more units\n"
5973 " restart NAME... Start or restart one or more units\n"
5974 " try-restart NAME... Restart one or more units if active\n"
5975 " reload-or-restart NAME... Reload one or more units if possible,\n"
5976 " otherwise start or restart\n"
5977 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
5978 " otherwise restart if active\n"
5979 " isolate NAME Start one unit and stop all others\n"
5980 " kill NAME... Send signal to processes of a unit\n"
5981 " is-active PATTERN... Check whether units are active\n"
5982 " is-failed PATTERN... Check whether units are failed\n"
5983 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
5984 " show [PATTERN...|JOB...] Show properties of one or more\n"
5985 " units/jobs or the manager\n"
5986 " cat PATTERN... Show files and drop-ins of one or more units\n"
5987 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
5988 " help PATTERN...|PID... Show manual for one or more units\n"
5989 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
5991 " list-dependencies [NAME] Recursively show units which are required\n"
5992 " or wanted by this unit or by which this\n"
5993 " unit is required or wanted\n\n"
5994 "Unit File Commands:\n"
5995 " list-unit-files [PATTERN...] List installed unit files\n"
5996 " enable NAME... Enable one or more unit files\n"
5997 " disable NAME... Disable one or more unit files\n"
5998 " reenable NAME... Reenable one or more unit files\n"
5999 " preset NAME... Enable/disable one or more unit files\n"
6000 " based on preset configuration\n"
6001 " preset-all Enable/disable all unit files based on\n"
6002 " preset configuration\n"
6003 " is-enabled NAME... Check whether unit files are enabled\n"
6004 " mask NAME... Mask one or more units\n"
6005 " unmask NAME... Unmask one or more units\n"
6006 " link PATH... Link one or more units files into\n"
6007 " the search path\n"
6008 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6009 " on specified one or more units\n"
6010 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6011 " on specified one or more units\n"
6012 " edit NAME... Edit one or more unit files\n"
6013 " get-default Get the name of the default target\n"
6014 " set-default NAME Set the default target\n\n"
6015 "Machine Commands:\n"
6016 " list-machines [PATTERN...] List local containers and host\n\n"
6018 " list-jobs [PATTERN...] List jobs\n"
6019 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
6020 "Snapshot Commands:\n"
6021 " snapshot [NAME] Create a snapshot\n"
6022 " delete NAME... Remove one or more snapshots\n\n"
6023 "Environment Commands:\n"
6024 " show-environment Dump environment\n"
6025 " set-environment NAME=VALUE... Set one or more environment variables\n"
6026 " unset-environment NAME... Unset one or more environment variables\n"
6027 " import-environment [NAME...] Import all or some environment variables\n\n"
6028 "Manager Lifecycle Commands:\n"
6029 " daemon-reload Reload systemd manager configuration\n"
6030 " daemon-reexec Reexecute systemd manager\n\n"
6031 "System Commands:\n"
6032 " is-system-running Check whether system is fully running\n"
6033 " default Enter system default mode\n"
6034 " rescue Enter system rescue mode\n"
6035 " emergency Enter system emergency mode\n"
6036 " halt Shut down and halt the system\n"
6037 " poweroff Shut down and power-off the system\n"
6038 " reboot [ARG] Shut down and reboot the system\n"
6039 " kexec Shut down and reboot the system with kexec\n"
6040 " exit Request user instance exit\n"
6041 " switch-root ROOT [INIT] Change to a different root file system\n"
6042 " suspend Suspend the system\n"
6043 " hibernate Hibernate the system\n"
6044 " hybrid-sleep Hibernate and suspend the system\n",
6045 program_invocation_short_name);
6048 static void halt_help(void) {
6049 printf("%s [OPTIONS...]%s\n\n"
6050 "%s the system.\n\n"
6051 " --help Show this help\n"
6052 " --halt Halt the machine\n"
6053 " -p --poweroff Switch off the machine\n"
6054 " --reboot Reboot the machine\n"
6055 " -f --force Force immediate halt/power-off/reboot\n"
6056 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
6057 " -d --no-wtmp Don't write wtmp record\n"
6058 " --no-wall Don't send wall message before halt/power-off/reboot\n",
6059 program_invocation_short_name,
6060 arg_action == ACTION_REBOOT ? " [ARG]" : "",
6061 arg_action == ACTION_REBOOT ? "Reboot" :
6062 arg_action == ACTION_POWEROFF ? "Power off" :
6066 static void shutdown_help(void) {
6067 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
6068 "Shut down the system.\n\n"
6069 " --help Show this help\n"
6070 " -H --halt Halt the machine\n"
6071 " -P --poweroff Power-off the machine\n"
6072 " -r --reboot Reboot the machine\n"
6073 " -h Equivalent to --poweroff, overridden by --halt\n"
6074 " -k Don't halt/power-off/reboot, just send warnings\n"
6075 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6076 " -c Cancel a pending shutdown\n",
6077 program_invocation_short_name);
6080 static void telinit_help(void) {
6081 printf("%s [OPTIONS...] {COMMAND}\n\n"
6082 "Send control commands to the init daemon.\n\n"
6083 " --help Show this help\n"
6084 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
6086 " 0 Power-off the machine\n"
6087 " 6 Reboot the machine\n"
6088 " 2, 3, 4, 5 Start runlevelX.target unit\n"
6089 " 1, s, S Enter rescue mode\n"
6090 " q, Q Reload init daemon configuration\n"
6091 " u, U Reexecute init daemon\n",
6092 program_invocation_short_name);
6095 static void runlevel_help(void) {
6096 printf("%s [OPTIONS...]\n\n"
6097 "Prints the previous and current runlevel of the init system.\n\n"
6098 " --help Show this help\n",
6099 program_invocation_short_name);
6102 static void help_types(void) {
6107 puts("Available unit types:");
6108 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
6109 t = unit_type_to_string(i);
6115 static int systemctl_parse_argv(int argc, char *argv[]) {
6124 ARG_IGNORE_DEPENDENCIES,
6136 ARG_NO_ASK_PASSWORD,
6146 static const struct option options[] = {
6147 { "help", no_argument, NULL, 'h' },
6148 { "version", no_argument, NULL, ARG_VERSION },
6149 { "type", required_argument, NULL, 't' },
6150 { "property", required_argument, NULL, 'p' },
6151 { "all", no_argument, NULL, 'a' },
6152 { "reverse", no_argument, NULL, ARG_REVERSE },
6153 { "after", no_argument, NULL, ARG_AFTER },
6154 { "before", no_argument, NULL, ARG_BEFORE },
6155 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
6156 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
6157 { "full", no_argument, NULL, 'l' },
6158 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
6159 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
6160 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
6161 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
6162 { "ignore-inhibitors", no_argument, NULL, 'i' },
6163 { "user", no_argument, NULL, ARG_USER },
6164 { "system", no_argument, NULL, ARG_SYSTEM },
6165 { "global", no_argument, NULL, ARG_GLOBAL },
6166 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
6167 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
6168 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
6169 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6170 { "quiet", no_argument, NULL, 'q' },
6171 { "root", required_argument, NULL, ARG_ROOT },
6172 { "force", no_argument, NULL, ARG_FORCE },
6173 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
6174 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
6175 { "signal", required_argument, NULL, 's' },
6176 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
6177 { "host", required_argument, NULL, 'H' },
6178 { "machine", required_argument, NULL, 'M' },
6179 { "runtime", no_argument, NULL, ARG_RUNTIME },
6180 { "lines", required_argument, NULL, 'n' },
6181 { "output", required_argument, NULL, 'o' },
6182 { "plain", no_argument, NULL, ARG_PLAIN },
6183 { "state", required_argument, NULL, ARG_STATE },
6184 { "recursive", no_argument, NULL, 'r' },
6185 { "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
6194 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
6203 puts(PACKAGE_STRING);
6204 puts(SYSTEMD_FEATURES);
6208 const char *word, *state;
6211 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6212 _cleanup_free_ char *type;
6214 type = strndup(word, size);
6218 if (streq(type, "help")) {
6223 if (unit_type_from_string(type) >= 0) {
6224 if (strv_push(&arg_types, type))
6230 /* It's much nicer to use --state= for
6231 * load states, but let's support this
6232 * in --types= too for compatibility
6233 * with old versions */
6234 if (unit_load_state_from_string(optarg) >= 0) {
6235 if (strv_push(&arg_states, type) < 0)
6241 log_error("Unknown unit type or load state '%s'.", type);
6242 log_info("Use -t help to see a list of allowed values.");
6250 /* Make sure that if the empty property list
6251 was specified, we won't show any properties. */
6252 if (isempty(optarg) && !arg_properties) {
6253 arg_properties = new0(char*, 1);
6254 if (!arg_properties)
6257 const char *word, *state;
6260 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6263 prop = strndup(word, size);
6267 if (strv_consume(&arg_properties, prop) < 0)
6272 /* If the user asked for a particular
6273 * property, show it to him, even if it is
6285 arg_dependency = DEPENDENCY_REVERSE;
6289 arg_dependency = DEPENDENCY_AFTER;
6293 arg_dependency = DEPENDENCY_BEFORE;
6296 case ARG_SHOW_TYPES:
6297 arg_show_types = true;
6301 arg_job_mode = optarg;
6305 arg_job_mode = "fail";
6308 case ARG_IRREVERSIBLE:
6309 arg_job_mode = "replace-irreversibly";
6312 case ARG_IGNORE_DEPENDENCIES:
6313 arg_job_mode = "ignore-dependencies";
6317 arg_scope = UNIT_FILE_USER;
6321 arg_scope = UNIT_FILE_SYSTEM;
6325 arg_scope = UNIT_FILE_GLOBAL;
6329 arg_no_block = true;
6333 arg_no_legend = true;
6337 arg_no_pager = true;
6353 if (strv_extend(&arg_states, "failed") < 0)
6371 arg_no_reload = true;
6375 arg_kill_who = optarg;
6379 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
6380 log_error("Failed to parse signal string %s.", optarg);
6385 case ARG_NO_ASK_PASSWORD:
6386 arg_ask_password = false;
6390 arg_transport = BUS_TRANSPORT_REMOTE;
6395 arg_transport = BUS_TRANSPORT_MACHINE;
6404 if (safe_atou(optarg, &arg_lines) < 0) {
6405 log_error("Failed to parse lines '%s'", optarg);
6411 arg_output = output_mode_from_string(optarg);
6412 if (arg_output < 0) {
6413 log_error("Unknown output '%s'.", optarg);
6419 arg_ignore_inhibitors = true;
6427 const char *word, *state;
6430 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6433 s = strndup(word, size);
6437 if (strv_consume(&arg_states, s) < 0)
6444 if (geteuid() != 0) {
6445 log_error("--recursive requires root privileges.");
6449 arg_recursive = true;
6452 case ARG_PRESET_MODE:
6454 arg_preset_mode = unit_file_preset_mode_from_string(optarg);
6455 if (arg_preset_mode < 0) {
6456 log_error("Failed to parse preset mode: %s.", optarg);
6466 assert_not_reached("Unhandled option");
6469 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
6470 log_error("Cannot access user instance remotely.");
6477 static int halt_parse_argv(int argc, char *argv[]) {
6486 static const struct option options[] = {
6487 { "help", no_argument, NULL, ARG_HELP },
6488 { "halt", no_argument, NULL, ARG_HALT },
6489 { "poweroff", no_argument, NULL, 'p' },
6490 { "reboot", no_argument, NULL, ARG_REBOOT },
6491 { "force", no_argument, NULL, 'f' },
6492 { "wtmp-only", no_argument, NULL, 'w' },
6493 { "no-wtmp", no_argument, NULL, 'd' },
6494 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6503 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
6504 if (runlevel == '0' || runlevel == '6')
6507 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
6515 arg_action = ACTION_HALT;
6519 if (arg_action != ACTION_REBOOT)
6520 arg_action = ACTION_POWEROFF;
6524 arg_action = ACTION_REBOOT;
6546 /* Compatibility nops */
6553 assert_not_reached("Unhandled option");
6556 if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
6557 r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL);
6560 } else if (optind < argc) {
6561 log_error("Too many arguments.");
6568 static int parse_time_spec(const char *t, usec_t *_u) {
6572 if (streq(t, "now"))
6574 else if (!strchr(t, ':')) {
6577 if (safe_atou64(t, &u) < 0)
6580 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
6589 hour = strtol(t, &e, 10);
6590 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
6593 minute = strtol(e+1, &e, 10);
6594 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
6597 n = now(CLOCK_REALTIME);
6598 s = (time_t) (n / USEC_PER_SEC);
6600 assert_se(localtime_r(&s, &tm));
6602 tm.tm_hour = (int) hour;
6603 tm.tm_min = (int) minute;
6606 assert_se(s = mktime(&tm));
6608 *_u = (usec_t) s * USEC_PER_SEC;
6611 *_u += USEC_PER_DAY;
6617 static int shutdown_parse_argv(int argc, char *argv[]) {
6624 static const struct option options[] = {
6625 { "help", no_argument, NULL, ARG_HELP },
6626 { "halt", no_argument, NULL, 'H' },
6627 { "poweroff", no_argument, NULL, 'P' },
6628 { "reboot", no_argument, NULL, 'r' },
6629 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
6630 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6639 while ((c = getopt_long(argc, argv, "HPrhkKt:afFc", options, NULL)) >= 0)
6647 arg_action = ACTION_HALT;
6651 arg_action = ACTION_POWEROFF;
6656 arg_action = ACTION_KEXEC;
6658 arg_action = ACTION_REBOOT;
6662 arg_action = ACTION_KEXEC;
6666 if (arg_action != ACTION_HALT)
6667 arg_action = ACTION_POWEROFF;
6682 /* Compatibility nops */
6686 arg_action = ACTION_CANCEL_SHUTDOWN;
6693 assert_not_reached("Unhandled option");
6696 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
6697 r = parse_time_spec(argv[optind], &arg_when);
6699 log_error("Failed to parse time specification: %s", argv[optind]);
6703 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
6705 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
6706 /* No time argument for shutdown cancel */
6707 arg_wall = argv + optind;
6708 else if (argc > optind + 1)
6709 /* We skip the time argument */
6710 arg_wall = argv + optind + 1;
6717 static int telinit_parse_argv(int argc, char *argv[]) {
6724 static const struct option options[] = {
6725 { "help", no_argument, NULL, ARG_HELP },
6726 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6730 static const struct {
6734 { '0', ACTION_POWEROFF },
6735 { '6', ACTION_REBOOT },
6736 { '1', ACTION_RESCUE },
6737 { '2', ACTION_RUNLEVEL2 },
6738 { '3', ACTION_RUNLEVEL3 },
6739 { '4', ACTION_RUNLEVEL4 },
6740 { '5', ACTION_RUNLEVEL5 },
6741 { 's', ACTION_RESCUE },
6742 { 'S', ACTION_RESCUE },
6743 { 'q', ACTION_RELOAD },
6744 { 'Q', ACTION_RELOAD },
6745 { 'u', ACTION_REEXEC },
6746 { 'U', ACTION_REEXEC }
6755 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6770 assert_not_reached("Unhandled option");
6773 if (optind >= argc) {
6774 log_error("%s: required argument missing.",
6775 program_invocation_short_name);
6779 if (optind + 1 < argc) {
6780 log_error("Too many arguments.");
6784 if (strlen(argv[optind]) != 1) {
6785 log_error("Expected single character argument.");
6789 for (i = 0; i < ELEMENTSOF(table); i++)
6790 if (table[i].from == argv[optind][0])
6793 if (i >= ELEMENTSOF(table)) {
6794 log_error("Unknown command '%s'.", argv[optind]);
6798 arg_action = table[i].to;
6805 static int runlevel_parse_argv(int argc, char *argv[]) {
6811 static const struct option options[] = {
6812 { "help", no_argument, NULL, ARG_HELP },
6821 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6832 assert_not_reached("Unhandled option");
6835 if (optind < argc) {
6836 log_error("Too many arguments.");
6843 static int parse_argv(int argc, char *argv[]) {
6847 if (program_invocation_short_name) {
6849 if (strstr(program_invocation_short_name, "halt")) {
6850 arg_action = ACTION_HALT;
6851 return halt_parse_argv(argc, argv);
6852 } else if (strstr(program_invocation_short_name, "poweroff")) {
6853 arg_action = ACTION_POWEROFF;
6854 return halt_parse_argv(argc, argv);
6855 } else if (strstr(program_invocation_short_name, "reboot")) {
6857 arg_action = ACTION_KEXEC;
6859 arg_action = ACTION_REBOOT;
6860 return halt_parse_argv(argc, argv);
6861 } else if (strstr(program_invocation_short_name, "shutdown")) {
6862 arg_action = ACTION_POWEROFF;
6863 return shutdown_parse_argv(argc, argv);
6864 } else if (strstr(program_invocation_short_name, "init")) {
6866 if (sd_booted() > 0) {
6867 arg_action = _ACTION_INVALID;
6868 return telinit_parse_argv(argc, argv);
6870 /* Hmm, so some other init system is
6871 * running, we need to forward this
6872 * request to it. For now we simply
6873 * guess that it is Upstart. */
6875 execv(TELINIT, argv);
6877 log_error("Couldn't find an alternative telinit implementation to spawn.");
6881 } else if (strstr(program_invocation_short_name, "runlevel")) {
6882 arg_action = ACTION_RUNLEVEL;
6883 return runlevel_parse_argv(argc, argv);
6887 arg_action = ACTION_SYSTEMCTL;
6888 return systemctl_parse_argv(argc, argv);
6891 _pure_ static int action_to_runlevel(void) {
6893 static const char table[_ACTION_MAX] = {
6894 [ACTION_HALT] = '0',
6895 [ACTION_POWEROFF] = '0',
6896 [ACTION_REBOOT] = '6',
6897 [ACTION_RUNLEVEL2] = '2',
6898 [ACTION_RUNLEVEL3] = '3',
6899 [ACTION_RUNLEVEL4] = '4',
6900 [ACTION_RUNLEVEL5] = '5',
6901 [ACTION_RESCUE] = '1'
6904 assert(arg_action < _ACTION_MAX);
6906 return table[arg_action];
6909 static int talk_initctl(void) {
6911 struct init_request request = {
6912 .magic = INIT_MAGIC,
6914 .cmd = INIT_CMD_RUNLVL
6917 _cleanup_close_ int fd = -1;
6921 rl = action_to_runlevel();
6925 request.runlevel = rl;
6927 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
6929 if (errno == ENOENT)
6932 log_error_errno(errno, "Failed to open "INIT_FIFO": %m");
6936 r = loop_write(fd, &request, sizeof(request), false);
6938 return log_error_errno(r, "Failed to write to "INIT_FIFO": %m");
6943 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
6945 static const struct {
6953 int (* const dispatch)(sd_bus *bus, char **args);
6959 { "list-units", MORE, 0, list_units },
6960 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
6961 { "list-sockets", MORE, 1, list_sockets },
6962 { "list-timers", MORE, 1, list_timers },
6963 { "list-jobs", MORE, 1, list_jobs },
6964 { "list-machines", MORE, 1, list_machines },
6965 { "clear-jobs", EQUAL, 1, daemon_reload },
6966 { "cancel", MORE, 2, cancel_job },
6967 { "start", MORE, 2, start_unit },
6968 { "stop", MORE, 2, start_unit },
6969 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6970 { "reload", MORE, 2, start_unit },
6971 { "restart", MORE, 2, start_unit },
6972 { "try-restart", MORE, 2, start_unit },
6973 { "reload-or-restart", MORE, 2, start_unit },
6974 { "reload-or-try-restart", MORE, 2, start_unit },
6975 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
6976 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6977 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
6978 { "isolate", EQUAL, 2, start_unit },
6979 { "kill", MORE, 2, kill_unit },
6980 { "is-active", MORE, 2, check_unit_active },
6981 { "check", MORE, 2, check_unit_active },
6982 { "is-failed", MORE, 2, check_unit_failed },
6983 { "show", MORE, 1, show },
6984 { "cat", MORE, 2, cat, NOBUS },
6985 { "status", MORE, 1, show },
6986 { "help", MORE, 2, show },
6987 { "snapshot", LESS, 2, snapshot },
6988 { "delete", MORE, 2, delete_snapshot },
6989 { "daemon-reload", EQUAL, 1, daemon_reload },
6990 { "daemon-reexec", EQUAL, 1, daemon_reload },
6991 { "show-environment", EQUAL, 1, show_environment },
6992 { "set-environment", MORE, 2, set_environment },
6993 { "unset-environment", MORE, 2, set_environment },
6994 { "import-environment", MORE, 1, import_environment},
6995 { "halt", EQUAL, 1, start_special, FORCE },
6996 { "poweroff", EQUAL, 1, start_special, FORCE },
6997 { "reboot", MORE, 1, start_special, FORCE },
6998 { "kexec", EQUAL, 1, start_special },
6999 { "suspend", EQUAL, 1, start_special },
7000 { "hibernate", EQUAL, 1, start_special },
7001 { "hybrid-sleep", EQUAL, 1, start_special },
7002 { "default", EQUAL, 1, start_special },
7003 { "rescue", EQUAL, 1, start_special },
7004 { "emergency", EQUAL, 1, start_special },
7005 { "exit", EQUAL, 1, start_special },
7006 { "reset-failed", MORE, 1, reset_failed },
7007 { "enable", MORE, 2, enable_unit, NOBUS },
7008 { "disable", MORE, 2, enable_unit, NOBUS },
7009 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
7010 { "reenable", MORE, 2, enable_unit, NOBUS },
7011 { "preset", MORE, 2, enable_unit, NOBUS },
7012 { "preset-all", EQUAL, 1, preset_all, NOBUS },
7013 { "mask", MORE, 2, enable_unit, NOBUS },
7014 { "unmask", MORE, 2, enable_unit, NOBUS },
7015 { "link", MORE, 2, enable_unit, NOBUS },
7016 { "switch-root", MORE, 2, switch_root },
7017 { "list-dependencies", LESS, 2, list_dependencies },
7018 { "set-default", EQUAL, 2, set_default, NOBUS },
7019 { "get-default", EQUAL, 1, get_default, NOBUS },
7020 { "set-property", MORE, 3, set_property },
7021 { "is-system-running", EQUAL, 1, is_system_running },
7022 { "add-wants", MORE, 3, add_dependency, NOBUS },
7023 { "add-requires", MORE, 3, add_dependency, NOBUS },
7024 { "edit", MORE, 2, edit, NOBUS },
7033 left = argc - optind;
7035 /* Special rule: no arguments (left == 0) means "list-units" */
7037 if (streq(argv[optind], "help") && !argv[optind+1]) {
7038 log_error("This command expects one or more "
7039 "unit names. Did you mean --help?");
7043 for (; verb->verb; verb++)
7044 if (streq(argv[optind], verb->verb))
7047 log_error("Unknown operation '%s'.", argv[optind]);
7052 switch (verb->argc_cmp) {
7055 if (left != verb->argc) {
7056 log_error("Invalid number of arguments.");
7063 if (left < verb->argc) {
7064 log_error("Too few arguments.");
7071 if (left > verb->argc) {
7072 log_error("Too many arguments.");
7079 assert_not_reached("Unknown comparison operator.");
7082 /* Require a bus connection for all operations but
7084 if (verb->bus == NOBUS) {
7085 if (!bus && !avoid_bus()) {
7086 log_error_errno(bus_error, "Failed to get D-Bus connection: %m");
7091 if (running_in_chroot() > 0) {
7092 log_info("Running in chroot, ignoring request.");
7096 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
7097 log_error_errno(bus_error, "Failed to get D-Bus connection: %m");
7102 /* Increase max number of open files to 16K if we can, we
7103 * might needs this when browsing journal files, which might
7104 * be split up into many files. */
7105 setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(16384));
7107 return verb->dispatch(bus, argv + optind);
7110 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
7112 struct sd_shutdown_command c = {
7119 union sockaddr_union sockaddr = {
7120 .un.sun_family = AF_UNIX,
7121 .un.sun_path = "/run/systemd/shutdownd",
7124 struct iovec iovec[2] = {{
7125 .iov_base = (char*) &c,
7126 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
7129 struct msghdr msghdr = {
7130 .msg_name = &sockaddr,
7131 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
7132 + strlen("/run/systemd/shutdownd"),
7137 _cleanup_close_ int fd;
7139 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
7143 if (!isempty(message)) {
7144 iovec[1].iov_base = (char*) message;
7145 iovec[1].iov_len = strlen(message);
7146 msghdr.msg_iovlen++;
7149 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
7155 static int reload_with_fallback(sd_bus *bus) {
7158 /* First, try systemd via D-Bus. */
7159 if (daemon_reload(bus, NULL) >= 0)
7163 /* Nothing else worked, so let's try signals */
7164 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
7166 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0)
7167 return log_error_errno(errno, "kill() failed: %m");
7172 static int start_with_fallback(sd_bus *bus) {
7175 /* First, try systemd via D-Bus. */
7176 if (start_unit(bus, NULL) >= 0)
7180 /* Nothing else worked, so let's try
7182 if (talk_initctl() > 0)
7185 log_error("Failed to talk to init daemon.");
7189 warn_wall(arg_action);
7193 static int halt_now(enum action a) {
7195 /* The kernel will automaticall flush ATA disks and suchlike
7196 * on reboot(), but the file systems need to be synce'd
7197 * explicitly in advance. */
7200 /* Make sure C-A-D is handled by the kernel from this point
7202 reboot(RB_ENABLE_CAD);
7207 log_info("Halting.");
7208 reboot(RB_HALT_SYSTEM);
7211 case ACTION_POWEROFF:
7212 log_info("Powering off.");
7213 reboot(RB_POWER_OFF);
7216 case ACTION_REBOOT: {
7217 _cleanup_free_ char *param = NULL;
7219 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
7220 log_info("Rebooting with argument '%s'.", param);
7221 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
7222 LINUX_REBOOT_CMD_RESTART2, param);
7225 log_info("Rebooting.");
7226 reboot(RB_AUTOBOOT);
7231 assert_not_reached("Unknown action.");
7235 static int halt_main(sd_bus *bus) {
7238 r = check_inhibitors(bus, arg_action);
7242 if (geteuid() != 0) {
7243 /* Try logind if we are a normal user and no special
7244 * mode applies. Maybe PolicyKit allows us to shutdown
7247 if (arg_when <= 0 &&
7250 (arg_action == ACTION_POWEROFF ||
7251 arg_action == ACTION_REBOOT)) {
7252 r = reboot_with_logind(bus, arg_action);
7257 log_error("Must be root.");
7262 _cleanup_free_ char *m;
7264 m = strv_join(arg_wall, " ");
7268 r = send_shutdownd(arg_when,
7269 arg_action == ACTION_HALT ? 'H' :
7270 arg_action == ACTION_POWEROFF ? 'P' :
7271 arg_action == ACTION_KEXEC ? 'K' :
7278 log_warning_errno(r, "Failed to talk to shutdownd, proceeding with immediate shutdown: %m");
7280 char date[FORMAT_TIMESTAMP_MAX];
7282 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
7283 format_timestamp(date, sizeof(date), arg_when));
7288 if (!arg_dry && !arg_force)
7289 return start_with_fallback(bus);
7292 if (sd_booted() > 0)
7293 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7295 r = utmp_put_shutdown();
7297 log_warning_errno(r, "Failed to write utmp record: %m");
7304 r = halt_now(arg_action);
7305 log_error_errno(r, "Failed to reboot: %m");
7310 static int runlevel_main(void) {
7311 int r, runlevel, previous;
7313 r = utmp_get_runlevel(&runlevel, &previous);
7320 previous <= 0 ? 'N' : previous,
7321 runlevel <= 0 ? 'N' : runlevel);
7326 int main(int argc, char*argv[]) {
7327 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
7330 setlocale(LC_ALL, "");
7331 log_parse_environment();
7334 /* Explicitly not on_tty() to avoid setting cached value.
7335 * This becomes relevant for piping output which might be
7337 original_stdout_is_tty = isatty(STDOUT_FILENO);
7339 r = parse_argv(argc, argv);
7343 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
7344 * let's shortcut this */
7345 if (arg_action == ACTION_RUNLEVEL) {
7346 r = runlevel_main();
7350 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
7351 log_info("Running in chroot, ignoring request.");
7357 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
7360 sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
7362 /* systemctl_main() will print an error message for the bus
7363 * connection, but only if it needs to */
7365 switch (arg_action) {
7367 case ACTION_SYSTEMCTL:
7368 r = systemctl_main(bus, argc, argv, r);
7372 case ACTION_POWEROFF:
7378 case ACTION_RUNLEVEL2:
7379 case ACTION_RUNLEVEL3:
7380 case ACTION_RUNLEVEL4:
7381 case ACTION_RUNLEVEL5:
7383 case ACTION_EMERGENCY:
7384 case ACTION_DEFAULT:
7385 r = start_with_fallback(bus);
7390 r = reload_with_fallback(bus);
7393 case ACTION_CANCEL_SHUTDOWN: {
7394 _cleanup_free_ char *m = NULL;
7397 m = strv_join(arg_wall, " ");
7404 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
7406 log_warning_errno(r, "Failed to talk to shutdownd, shutdown hasn't been cancelled: %m");
7410 case ACTION_RUNLEVEL:
7411 case _ACTION_INVALID:
7413 assert_not_reached("Unknown action");
7418 ask_password_agent_close();
7419 polkit_agent_close();
7421 strv_free(arg_types);
7422 strv_free(arg_states);
7423 strv_free(arg_properties);
7425 return r < 0 ? EXIT_FAILURE : r;