1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Marc-Antoine Perennou
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/reboot.h>
24 #include <linux/reboot.h>
25 #include <sys/syscall.h>
32 #include <sys/ioctl.h>
36 #include <sys/socket.h>
39 #include <sys/prctl.h>
42 #include "sd-daemon.h"
43 #include "sd-shutdown.h"
50 #include "utmp-wtmp.h"
53 #include "path-util.h"
55 #include "cgroup-show.h"
56 #include "cgroup-util.h"
58 #include "path-lookup.h"
59 #include "conf-parser.h"
60 #include "exit-status.h"
62 #include "unit-name.h"
64 #include "spawn-ask-password-agent.h"
65 #include "spawn-polkit-agent.h"
67 #include "logs-show.h"
68 #include "socket-util.h"
72 #include "bus-message.h"
73 #include "bus-error.h"
74 #include "bus-errors.h"
76 static char **arg_types = NULL;
77 static char **arg_states = NULL;
78 static char **arg_properties = NULL;
79 static bool arg_all = false;
80 static enum dependency {
86 } arg_dependency = DEPENDENCY_FORWARD;
87 static const char *arg_job_mode = "replace";
88 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
89 static bool arg_no_block = false;
90 static bool arg_no_legend = false;
91 static bool arg_no_pager = false;
92 static bool arg_no_wtmp = false;
93 static bool arg_no_wall = false;
94 static bool arg_no_reload = false;
95 static bool arg_show_types = false;
96 static bool arg_ignore_inhibitors = false;
97 static bool arg_dry = false;
98 static bool arg_quiet = false;
99 static bool arg_full = false;
100 static bool arg_recursive = false;
101 static int arg_force = 0;
102 static bool arg_ask_password = true;
103 static bool arg_runtime = false;
104 static UnitFilePresetMode arg_preset_mode = UNIT_FILE_PRESET_FULL;
105 static char **arg_wall = NULL;
106 static const char *arg_kill_who = NULL;
107 static int arg_signal = SIGTERM;
108 static const char *arg_root = NULL;
109 static usec_t arg_when = 0;
131 ACTION_CANCEL_SHUTDOWN,
133 } arg_action = ACTION_SYSTEMCTL;
134 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
135 static char *arg_host = NULL;
136 static unsigned arg_lines = 10;
137 static OutputMode arg_output = OUTPUT_SHORT;
138 static bool arg_plain = false;
140 static bool original_stdout_is_tty;
142 static int daemon_reload(sd_bus *bus, char **args);
143 static int halt_now(enum action a);
144 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet);
146 static char** strv_skip_first(char **strv) {
147 if (strv_length(strv) > 0)
152 static void pager_open_if_enabled(void) {
160 static void ask_password_agent_open_if_enabled(void) {
162 /* Open the password agent as a child process if necessary */
164 if (!arg_ask_password)
167 if (arg_scope != UNIT_FILE_SYSTEM)
170 if (arg_transport != BUS_TRANSPORT_LOCAL)
173 ask_password_agent_open();
177 static void polkit_agent_open_if_enabled(void) {
179 /* Open the polkit agent as a child process if necessary */
181 if (!arg_ask_password)
184 if (arg_scope != UNIT_FILE_SYSTEM)
187 if (arg_transport != BUS_TRANSPORT_LOCAL)
194 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
197 if (!sd_bus_error_is_set(error))
200 if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) ||
201 sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
202 sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
203 sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
204 return EXIT_NOPERMISSION;
206 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
207 return EXIT_NOTINSTALLED;
209 if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
210 sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED))
211 return EXIT_NOTIMPLEMENTED;
213 if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
214 return EXIT_NOTCONFIGURED;
222 static void warn_wall(enum action a) {
223 static const char *table[_ACTION_MAX] = {
224 [ACTION_HALT] = "The system is going down for system halt NOW!",
225 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
226 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
227 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
228 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
229 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
230 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
237 _cleanup_free_ char *p;
239 p = strv_join(arg_wall, " ");
246 utmp_wall(p, NULL, NULL);
254 utmp_wall(table[a], NULL, NULL);
257 static bool avoid_bus(void) {
259 if (running_in_chroot() > 0)
262 if (sd_booted() <= 0)
265 if (!isempty(arg_root))
268 if (arg_scope == UNIT_FILE_GLOBAL)
274 static int compare_unit_info(const void *a, const void *b) {
275 const UnitInfo *u = a, *v = b;
279 /* First, order by machine */
280 if (!u->machine && v->machine)
282 if (u->machine && !v->machine)
284 if (u->machine && v->machine) {
285 r = strcasecmp(u->machine, v->machine);
290 /* Second, order by unit type */
291 d1 = strrchr(u->id, '.');
292 d2 = strrchr(v->id, '.');
294 r = strcasecmp(d1, d2);
299 /* Third, order by name */
300 return strcasecmp(u->id, v->id);
303 static bool output_show_unit(const UnitInfo *u, char **patterns) {
306 if (!strv_isempty(patterns)) {
309 STRV_FOREACH(pattern, patterns)
310 if (fnmatch(*pattern, u->id, FNM_NOESCAPE) == 0)
315 return (!arg_types || ((dot = strrchr(u->id, '.')) &&
316 strv_find(arg_types, dot+1))) &&
317 (arg_all || !(streq(u->active_state, "inactive")
318 || u->following[0]) || u->job_id > 0);
321 static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
322 unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
324 unsigned n_shown = 0;
327 max_id_len = strlen("UNIT");
328 load_len = strlen("LOAD");
329 active_len = strlen("ACTIVE");
330 sub_len = strlen("SUB");
331 job_len = strlen("JOB");
334 for (u = unit_infos; u < unit_infos + c; u++) {
335 max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0));
336 load_len = MAX(load_len, strlen(u->load_state));
337 active_len = MAX(active_len, strlen(u->active_state));
338 sub_len = MAX(sub_len, strlen(u->sub_state));
340 if (u->job_id != 0) {
341 job_len = MAX(job_len, strlen(u->job_type));
345 if (!arg_no_legend &&
346 (streq(u->active_state, "failed") ||
347 STR_IN_SET(u->load_state, "error", "not-found", "masked")))
351 if (!arg_full && original_stdout_is_tty) {
354 id_len = MIN(max_id_len, 25u);
355 basic_len = circle_len + 5 + id_len + 5 + active_len + sub_len;
358 basic_len += job_len + 1;
360 if (basic_len < (unsigned) columns()) {
361 unsigned extra_len, incr;
362 extra_len = columns() - basic_len;
364 /* Either UNIT already got 25, or is fully satisfied.
365 * Grant up to 25 to DESC now. */
366 incr = MIN(extra_len, 25u);
370 /* split the remaining space between UNIT and DESC,
371 * but do not give UNIT more than it needs. */
373 incr = MIN(extra_len / 2, max_id_len - id_len);
375 desc_len += extra_len - incr;
381 for (u = unit_infos; u < unit_infos + c; u++) {
382 _cleanup_free_ char *e = NULL, *j = NULL;
383 const char *on_loaded = "", *off_loaded = "";
384 const char *on_active = "", *off_active = "";
385 const char *on_circle = "", *off_circle = "";
389 if (!n_shown && !arg_no_legend) {
394 printf("%-*s %-*s %-*s %-*s ",
397 active_len, "ACTIVE",
401 printf("%-*s ", job_len, "JOB");
403 if (!arg_full && arg_no_pager)
404 printf("%.*s\n", desc_len, "DESCRIPTION");
406 printf("%s\n", "DESCRIPTION");
411 if (STR_IN_SET(u->load_state, "error", "not-found", "masked")) {
412 on_loaded = ansi_highlight_red();
413 on_circle = ansi_highlight_yellow();
414 off_loaded = off_circle = ansi_highlight_off();
418 if (streq(u->active_state, "failed")) {
419 on_circle = on_active = ansi_highlight_red();
420 off_circle = off_active = ansi_highlight_off();
425 j = strjoin(u->machine, ":", u->id, NULL);
434 e = ellipsize(id, id_len, 33);
442 printf("%s%s%s ", on_circle, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_circle);
444 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
445 on_active, id_len, id, off_active,
446 on_loaded, load_len, u->load_state, off_loaded,
447 on_active, active_len, u->active_state,
448 sub_len, u->sub_state, off_active,
449 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
452 printf("%.*s\n", desc_len, u->description);
454 printf("%s\n", u->description);
457 if (!arg_no_legend) {
458 const char *on, *off;
462 "LOAD = Reflects whether the unit definition was properly loaded.\n"
463 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
464 "SUB = The low-level unit activation state, values depend on unit type.");
465 puts(job_count ? "JOB = Pending job for the unit.\n" : "");
466 on = ansi_highlight();
467 off = ansi_highlight_off();
469 on = ansi_highlight_red();
470 off = ansi_highlight_off();
474 printf("%s%u loaded units listed.%s\n"
475 "To show all installed unit files use 'systemctl list-unit-files'.\n",
478 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
479 "To show all installed unit files use 'systemctl list-unit-files'.\n",
486 static int get_unit_list(
490 UnitInfo **unit_infos,
492 sd_bus_message **_reply) {
494 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
495 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
496 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
505 r = sd_bus_message_new_method_call(
508 "org.freedesktop.systemd1",
509 "/org/freedesktop/systemd1",
510 "org.freedesktop.systemd1.Manager",
511 "ListUnitsFiltered");
514 return bus_log_create_error(r);
516 r = sd_bus_message_append_strv(m, arg_states);
518 return bus_log_create_error(r);
520 r = sd_bus_call(bus, m, 0, &error, &reply);
522 log_error("Failed to list units: %s", bus_error_message(&error, r));
526 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
528 return bus_log_parse_error(r);
530 while ((r = bus_parse_unit_info(reply, &u)) > 0) {
533 if (!output_show_unit(&u, patterns))
536 if (!GREEDY_REALLOC(*unit_infos, size, c+1))
539 (*unit_infos)[c++] = u;
542 return bus_log_parse_error(r);
544 r = sd_bus_message_exit_container(reply);
546 return bus_log_parse_error(r);
554 static void message_set_freep(Set **set) {
557 while ((m = set_steal_first(*set)))
558 sd_bus_message_unref(m);
563 static int get_unit_list_recursive(
566 UnitInfo **_unit_infos,
570 _cleanup_free_ UnitInfo *unit_infos = NULL;
571 _cleanup_(message_set_freep) Set *replies;
572 sd_bus_message *reply;
580 replies = set_new(NULL);
584 c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
588 r = set_put(replies, reply);
590 sd_bus_message_unref(reply);
595 _cleanup_strv_free_ char **machines = NULL;
598 r = sd_get_machine_names(&machines);
602 STRV_FOREACH(i, machines) {
603 _cleanup_bus_close_unref_ sd_bus *container = NULL;
606 r = sd_bus_open_system_container(&container, *i);
608 log_error("Failed to connect to container %s: %s", *i, strerror(-r));
612 k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
618 r = set_put(replies, reply);
620 sd_bus_message_unref(reply);
625 *_machines = machines;
630 *_unit_infos = unit_infos;
639 static int list_units(sd_bus *bus, char **args) {
640 _cleanup_free_ UnitInfo *unit_infos = NULL;
641 _cleanup_(message_set_freep) Set *replies = NULL;
642 _cleanup_strv_free_ char **machines = NULL;
645 pager_open_if_enabled();
647 r = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
651 qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
652 return output_units_list(unit_infos, r);
655 static int get_triggered_units(
660 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
663 r = sd_bus_get_property_strv(
665 "org.freedesktop.systemd1",
667 "org.freedesktop.systemd1.Unit",
673 log_error("Failed to determine triggers: %s", bus_error_message(&error, r));
678 static int get_listening(
680 const char* unit_path,
683 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
684 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
685 const char *type, *path;
688 r = sd_bus_get_property(
690 "org.freedesktop.systemd1",
692 "org.freedesktop.systemd1.Socket",
698 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r));
702 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
704 return bus_log_parse_error(r);
706 while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
708 r = strv_extend(listening, type);
712 r = strv_extend(listening, path);
719 return bus_log_parse_error(r);
721 r = sd_bus_message_exit_container(reply);
723 return bus_log_parse_error(r);
735 /* Note: triggered is a list here, although it almost certainly
736 * will always be one unit. Nevertheless, dbus API allows for multiple
737 * values, so let's follow that.*/
740 /* The strv above is shared. free is set only in the first one. */
744 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
750 if (!a->machine && b->machine)
752 if (a->machine && !b->machine)
754 if (a->machine && b->machine) {
755 o = strcasecmp(a->machine, b->machine);
760 o = strcmp(a->path, b->path);
762 o = strcmp(a->type, b->type);
767 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
768 struct socket_info *s;
769 unsigned pathlen = strlen("LISTEN"),
770 typelen = strlen("TYPE") * arg_show_types,
771 socklen = strlen("UNIT"),
772 servlen = strlen("ACTIVATES");
773 const char *on, *off;
775 for (s = socket_infos; s < socket_infos + cs; s++) {
779 socklen = MAX(socklen, strlen(s->id));
781 typelen = MAX(typelen, strlen(s->type));
782 pathlen = MAX(pathlen, strlen(s->path) + (s->machine ? strlen(s->machine)+1 : 0));
784 STRV_FOREACH(a, s->triggered)
785 tmp += strlen(*a) + 2*(a != s->triggered);
786 servlen = MAX(servlen, tmp);
791 printf("%-*s %-*.*s%-*s %s\n",
793 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
797 for (s = socket_infos; s < socket_infos + cs; s++) {
798 _cleanup_free_ char *j = NULL;
803 j = strjoin(s->machine, ":", s->path, NULL);
811 printf("%-*s %-*s %-*s",
812 pathlen, path, typelen, s->type, socklen, s->id);
815 pathlen, path, socklen, s->id);
816 STRV_FOREACH(a, s->triggered)
818 a == s->triggered ? "" : ",", *a);
822 on = ansi_highlight();
823 off = ansi_highlight_off();
827 on = ansi_highlight_red();
828 off = ansi_highlight_off();
831 if (!arg_no_legend) {
832 printf("%s%u sockets listed.%s\n", on, cs, off);
834 printf("Pass --all to see loaded but inactive sockets, too.\n");
840 static int list_sockets(sd_bus *bus, char **args) {
841 _cleanup_(message_set_freep) Set *replies = NULL;
842 _cleanup_strv_free_ char **machines = NULL;
843 _cleanup_free_ UnitInfo *unit_infos = NULL;
844 _cleanup_free_ struct socket_info *socket_infos = NULL;
846 struct socket_info *s;
851 pager_open_if_enabled();
853 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
857 for (u = unit_infos; u < unit_infos + n; u++) {
858 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
861 if (!endswith(u->id, ".socket"))
864 r = get_triggered_units(bus, u->unit_path, &triggered);
868 c = get_listening(bus, u->unit_path, &listening);
874 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
879 for (i = 0; i < c; i++)
880 socket_infos[cs + i] = (struct socket_info) {
881 .machine = u->machine,
883 .type = listening[i*2],
884 .path = listening[i*2 + 1],
885 .triggered = triggered,
886 .own_triggered = i==0,
889 /* from this point on we will cleanup those socket_infos */
892 listening = triggered = NULL; /* avoid cleanup */
895 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
896 (__compar_fn_t) socket_info_compare);
898 output_sockets_list(socket_infos, cs);
901 assert(cs == 0 || socket_infos);
902 for (s = socket_infos; s < socket_infos + cs; s++) {
905 if (s->own_triggered)
906 strv_free(s->triggered);
912 static int get_next_elapse(
915 dual_timestamp *next) {
917 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
925 r = sd_bus_get_property_trivial(
927 "org.freedesktop.systemd1",
929 "org.freedesktop.systemd1.Timer",
930 "NextElapseUSecMonotonic",
935 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
939 r = sd_bus_get_property_trivial(
941 "org.freedesktop.systemd1",
943 "org.freedesktop.systemd1.Timer",
944 "NextElapseUSecRealtime",
949 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
957 static int get_last_trigger(
962 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
969 r = sd_bus_get_property_trivial(
971 "org.freedesktop.systemd1",
973 "org.freedesktop.systemd1.Timer",
979 log_error("Failed to get last trigger time: %s", bus_error_message(&error, r));
994 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
1000 if (!a->machine && b->machine)
1002 if (a->machine && !b->machine)
1004 if (a->machine && b->machine) {
1005 o = strcasecmp(a->machine, b->machine);
1010 if (a->next_elapse < b->next_elapse)
1012 if (a->next_elapse > b->next_elapse)
1015 return strcmp(a->id, b->id);
1018 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
1019 struct timer_info *t;
1021 nextlen = strlen("NEXT"),
1022 leftlen = strlen("LEFT"),
1023 lastlen = strlen("LAST"),
1024 passedlen = strlen("PASSED"),
1025 unitlen = strlen("UNIT"),
1026 activatelen = strlen("ACTIVATES");
1028 const char *on, *off;
1030 assert(timer_infos || n == 0);
1032 for (t = timer_infos; t < timer_infos + n; t++) {
1036 if (t->next_elapse > 0) {
1037 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1039 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
1040 nextlen = MAX(nextlen, strlen(tstamp) + 1);
1042 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
1043 leftlen = MAX(leftlen, strlen(trel));
1046 if (t->last_trigger > 0) {
1047 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1049 format_timestamp(tstamp, sizeof(tstamp), t->last_trigger);
1050 lastlen = MAX(lastlen, strlen(tstamp) + 1);
1052 format_timestamp_relative(trel, sizeof(trel), t->last_trigger);
1053 passedlen = MAX(passedlen, strlen(trel));
1056 unitlen = MAX(unitlen, strlen(t->id) + (t->machine ? strlen(t->machine)+1 : 0));
1058 STRV_FOREACH(a, t->triggered)
1059 ul += strlen(*a) + 2*(a != t->triggered);
1061 activatelen = MAX(activatelen, ul);
1066 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1070 passedlen, "PASSED",
1074 for (t = timer_infos; t < timer_infos + n; t++) {
1075 _cleanup_free_ char *j = NULL;
1077 char tstamp1[FORMAT_TIMESTAMP_MAX] = "n/a", trel1[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1078 char tstamp2[FORMAT_TIMESTAMP_MAX] = "n/a", trel2[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1081 format_timestamp(tstamp1, sizeof(tstamp1), t->next_elapse);
1082 format_timestamp_relative(trel1, sizeof(trel1), t->next_elapse);
1084 format_timestamp(tstamp2, sizeof(tstamp2), t->last_trigger);
1085 format_timestamp_relative(trel2, sizeof(trel2), t->last_trigger);
1088 j = strjoin(t->machine, ":", t->id, NULL);
1095 printf("%-*s %-*s %-*s %-*s %-*s",
1096 nextlen, tstamp1, leftlen, trel1, lastlen, tstamp2, passedlen, trel2, unitlen, unit);
1098 STRV_FOREACH(a, t->triggered)
1100 a == t->triggered ? "" : ",", *a);
1104 on = ansi_highlight();
1105 off = ansi_highlight_off();
1109 on = ansi_highlight_red();
1110 off = ansi_highlight_off();
1113 if (!arg_no_legend) {
1114 printf("%s%u timers listed.%s\n", on, n, off);
1116 printf("Pass --all to see loaded but inactive timers, too.\n");
1122 static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
1128 if (next->monotonic != USEC_INFINITY && next->monotonic > 0) {
1131 if (next->monotonic > nw->monotonic)
1132 converted = nw->realtime + (next->monotonic - nw->monotonic);
1134 converted = nw->realtime - (nw->monotonic - next->monotonic);
1136 if (next->realtime != USEC_INFINITY && next->realtime > 0)
1137 next_elapse = MIN(converted, next->realtime);
1139 next_elapse = converted;
1142 next_elapse = next->realtime;
1147 static int list_timers(sd_bus *bus, char **args) {
1148 _cleanup_(message_set_freep) Set *replies = NULL;
1149 _cleanup_strv_free_ char **machines = NULL;
1150 _cleanup_free_ struct timer_info *timer_infos = NULL;
1151 _cleanup_free_ UnitInfo *unit_infos = NULL;
1152 struct timer_info *t;
1159 pager_open_if_enabled();
1161 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
1165 dual_timestamp_get(&nw);
1167 for (u = unit_infos; u < unit_infos + n; u++) {
1168 _cleanup_strv_free_ char **triggered = NULL;
1169 dual_timestamp next = {};
1172 if (!endswith(u->id, ".timer"))
1175 r = get_triggered_units(bus, u->unit_path, &triggered);
1179 r = get_next_elapse(bus, u->unit_path, &next);
1183 get_last_trigger(bus, u->unit_path, &last);
1185 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
1190 m = calc_next_elapse(&nw, &next);
1192 timer_infos[c++] = (struct timer_info) {
1193 .machine = u->machine,
1196 .last_trigger = last,
1197 .triggered = triggered,
1200 triggered = NULL; /* avoid cleanup */
1203 qsort_safe(timer_infos, c, sizeof(struct timer_info),
1204 (__compar_fn_t) timer_info_compare);
1206 output_timers_list(timer_infos, c);
1209 for (t = timer_infos; t < timer_infos + c; t++)
1210 strv_free(t->triggered);
1215 static int compare_unit_file_list(const void *a, const void *b) {
1216 const char *d1, *d2;
1217 const UnitFileList *u = a, *v = b;
1219 d1 = strrchr(u->path, '.');
1220 d2 = strrchr(v->path, '.');
1225 r = strcasecmp(d1, d2);
1230 return strcasecmp(basename(u->path), basename(v->path));
1233 static bool output_show_unit_file(const UnitFileList *u, char **patterns) {
1236 if (!strv_isempty(patterns)) {
1239 STRV_FOREACH(pattern, patterns)
1240 if (fnmatch(*pattern, basename(u->path), FNM_NOESCAPE) == 0)
1245 return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
1248 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
1249 unsigned max_id_len, id_cols, state_cols;
1250 const UnitFileList *u;
1252 max_id_len = strlen("UNIT FILE");
1253 state_cols = strlen("STATE");
1255 for (u = units; u < units + c; u++) {
1256 max_id_len = MAX(max_id_len, strlen(basename(u->path)));
1257 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1261 unsigned basic_cols;
1263 id_cols = MIN(max_id_len, 25u);
1264 basic_cols = 1 + id_cols + state_cols;
1265 if (basic_cols < (unsigned) columns())
1266 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1268 id_cols = max_id_len;
1271 printf("%-*s %-*s\n",
1272 id_cols, "UNIT FILE",
1273 state_cols, "STATE");
1275 for (u = units; u < units + c; u++) {
1276 _cleanup_free_ char *e = NULL;
1277 const char *on, *off;
1280 if (u->state == UNIT_FILE_MASKED ||
1281 u->state == UNIT_FILE_MASKED_RUNTIME ||
1282 u->state == UNIT_FILE_DISABLED ||
1283 u->state == UNIT_FILE_INVALID) {
1284 on = ansi_highlight_red();
1285 off = ansi_highlight_off();
1286 } else if (u->state == UNIT_FILE_ENABLED) {
1287 on = ansi_highlight_green();
1288 off = ansi_highlight_off();
1292 id = basename(u->path);
1294 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1296 printf("%-*s %s%-*s%s\n",
1297 id_cols, e ? e : id,
1298 on, state_cols, unit_file_state_to_string(u->state), off);
1302 printf("\n%u unit files listed.\n", c);
1305 static int list_unit_files(sd_bus *bus, char **args) {
1306 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1307 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1308 _cleanup_free_ UnitFileList *units = NULL;
1316 pager_open_if_enabled();
1324 h = hashmap_new(&string_hash_ops);
1328 r = unit_file_get_list(arg_scope, arg_root, h);
1330 unit_file_list_free(h);
1331 log_error("Failed to get unit file list: %s", strerror(-r));
1335 n_units = hashmap_size(h);
1337 units = new(UnitFileList, n_units);
1338 if (!units && n_units > 0) {
1339 unit_file_list_free(h);
1343 HASHMAP_FOREACH(u, h, i) {
1344 if (!output_show_unit_file(u, strv_skip_first(args)))
1351 assert(c <= n_units);
1354 r = sd_bus_call_method(
1356 "org.freedesktop.systemd1",
1357 "/org/freedesktop/systemd1",
1358 "org.freedesktop.systemd1.Manager",
1364 log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1368 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1370 return bus_log_parse_error(r);
1372 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1374 if (!GREEDY_REALLOC(units, size, c + 1))
1377 units[c] = (struct UnitFileList) {
1379 unit_file_state_from_string(state)
1382 if (output_show_unit_file(&units[c], strv_skip_first(args)))
1387 return bus_log_parse_error(r);
1389 r = sd_bus_message_exit_container(reply);
1391 return bus_log_parse_error(r);
1394 qsort_safe(units, c, sizeof(UnitFileList), compare_unit_file_list);
1395 output_unit_file_list(units, c);
1398 for (unit = units; unit < units + c; unit++)
1405 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1406 _cleanup_free_ char *n = NULL;
1407 size_t max_len = MAX(columns(),20u);
1413 for (i = level - 1; i >= 0; i--) {
1415 if (len > max_len - 3 && !arg_full) {
1416 printf("%s...\n",max_len % 2 ? "" : " ");
1419 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERTICAL : DRAW_TREE_SPACE));
1423 if (len > max_len - 3 && !arg_full) {
1424 printf("%s...\n",max_len % 2 ? "" : " ");
1428 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
1432 printf("%s\n", name);
1436 n = ellipsize(name, max_len-len, 100);
1444 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1446 static const char *dependencies[_DEPENDENCY_MAX] = {
1447 [DEPENDENCY_FORWARD] = "Requires\0"
1448 "RequiresOverridable\0"
1450 "RequisiteOverridable\0"
1452 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1453 "RequiredByOverridable\0"
1456 [DEPENDENCY_AFTER] = "After\0",
1457 [DEPENDENCY_BEFORE] = "Before\0",
1460 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1461 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1462 _cleanup_strv_free_ char **ret = NULL;
1463 _cleanup_free_ char *path = NULL;
1469 assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
1471 path = unit_dbus_path_from_name(name);
1475 r = sd_bus_call_method(
1477 "org.freedesktop.systemd1",
1479 "org.freedesktop.DBus.Properties",
1483 "s", "org.freedesktop.systemd1.Unit");
1485 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1489 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1491 return bus_log_parse_error(r);
1493 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1496 r = sd_bus_message_read(reply, "s", &prop);
1498 return bus_log_parse_error(r);
1500 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1501 r = sd_bus_message_skip(reply, "v");
1503 return bus_log_parse_error(r);
1506 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1508 return bus_log_parse_error(r);
1510 r = bus_message_read_strv_extend(reply, &ret);
1512 return bus_log_parse_error(r);
1514 r = sd_bus_message_exit_container(reply);
1516 return bus_log_parse_error(r);
1519 r = sd_bus_message_exit_container(reply);
1521 return bus_log_parse_error(r);
1525 return bus_log_parse_error(r);
1527 r = sd_bus_message_exit_container(reply);
1529 return bus_log_parse_error(r);
1537 static int list_dependencies_compare(const void *_a, const void *_b) {
1538 const char **a = (const char**) _a, **b = (const char**) _b;
1540 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1542 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1545 return strcasecmp(*a, *b);
1548 static int list_dependencies_one(
1553 unsigned int branches) {
1555 _cleanup_strv_free_ char **deps = NULL;
1563 r = strv_extend(units, name);
1567 r = list_dependencies_get_dependencies(bus, name, &deps);
1571 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1573 STRV_FOREACH(c, deps) {
1576 if (strv_contains(*units, *c)) {
1578 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1585 state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true);
1587 printf("%s%s%s ", ansi_highlight_green(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1589 printf("%s%s%s ", ansi_highlight_red(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1591 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1595 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1596 r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1603 strv_remove(*units, name);
1608 static int list_dependencies(sd_bus *bus, char **args) {
1609 _cleanup_strv_free_ char **units = NULL;
1610 _cleanup_free_ char *unit = NULL;
1616 unit = unit_name_mangle(args[1], MANGLE_NOGLOB);
1621 u = SPECIAL_DEFAULT_TARGET;
1623 pager_open_if_enabled();
1627 return list_dependencies_one(bus, u, 0, &units, 0);
1630 struct machine_info {
1634 char *control_group;
1635 uint32_t n_failed_units;
1640 static const struct bus_properties_map machine_info_property_map[] = {
1641 { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
1642 { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
1643 { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
1644 { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
1645 { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
1649 static void free_machines_list(struct machine_info *machine_infos, int n) {
1655 for (i = 0; i < n; i++) {
1656 free(machine_infos[i].name);
1657 free(machine_infos[i].state);
1658 free(machine_infos[i].control_group);
1661 free(machine_infos);
1664 static int compare_machine_info(const void *a, const void *b) {
1665 const struct machine_info *u = a, *v = b;
1667 if (u->is_host != v->is_host)
1668 return u->is_host > v->is_host ? -1 : 1;
1670 return strcasecmp(u->name, v->name);
1673 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1674 _cleanup_bus_close_unref_ sd_bus *container = NULL;
1680 r = sd_bus_open_system_container(&container, mi->name);
1687 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi);
1694 static bool output_show_machine(const char *name, char **patterns) {
1699 if (strv_isempty(patterns))
1702 STRV_FOREACH(i, patterns)
1703 if (fnmatch(*i, name, FNM_NOESCAPE) == 0)
1709 static int get_machine_list(
1711 struct machine_info **_machine_infos,
1714 struct machine_info *machine_infos = NULL;
1715 _cleanup_strv_free_ char **m = NULL;
1716 _cleanup_free_ char *hn = NULL;
1721 hn = gethostname_malloc();
1725 if (output_show_machine(hn, patterns)) {
1726 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1729 machine_infos[c].is_host = true;
1730 machine_infos[c].name = hn;
1733 get_machine_properties(bus, &machine_infos[c]);
1737 sd_get_machine_names(&m);
1738 STRV_FOREACH(i, m) {
1739 _cleanup_free_ char *class = NULL;
1741 if (!output_show_machine(*i, patterns))
1744 sd_machine_get_class(*i, &class);
1745 if (!streq_ptr(class, "container"))
1748 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1749 free_machines_list(machine_infos, c);
1753 machine_infos[c].is_host = false;
1754 machine_infos[c].name = strdup(*i);
1755 if (!machine_infos[c].name) {
1756 free_machines_list(machine_infos, c);
1760 get_machine_properties(NULL, &machine_infos[c]);
1764 *_machine_infos = machine_infos;
1768 static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1769 struct machine_info *m;
1772 namelen = sizeof("NAME") - 1,
1773 statelen = sizeof("STATE") - 1,
1774 failedlen = sizeof("FAILED") - 1,
1775 jobslen = sizeof("JOBS") - 1;
1777 assert(machine_infos || n == 0);
1779 for (m = machine_infos; m < machine_infos + n; m++) {
1780 namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
1781 statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
1782 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
1783 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
1785 if (!arg_no_legend && !streq_ptr(m->state, "running"))
1789 if (!arg_no_legend) {
1793 printf("%-*s %-*s %-*s %-*s\n",
1796 failedlen, "FAILED",
1800 for (m = machine_infos; m < machine_infos + n; m++) {
1801 const char *on_state = "", *off_state = "";
1802 const char *on_failed = "", *off_failed = "";
1803 bool circle = false;
1805 if (streq_ptr(m->state, "degraded")) {
1806 on_state = ansi_highlight_red();
1807 off_state = ansi_highlight_off();
1809 } else if (!streq_ptr(m->state, "running")) {
1810 on_state = ansi_highlight_yellow();
1811 off_state = ansi_highlight_off();
1815 if (m->n_failed_units > 0) {
1816 on_failed = ansi_highlight_red();
1817 off_failed = ansi_highlight_off();
1819 on_failed = off_failed = "";
1822 printf("%s%s%s ", on_state, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_state);
1825 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1826 (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
1827 on_state, statelen, strna(m->state), off_state,
1828 on_failed, failedlen, m->n_failed_units, off_failed,
1829 jobslen, m->n_jobs);
1831 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1832 namelen, strna(m->name),
1833 on_state, statelen, strna(m->state), off_state,
1834 on_failed, failedlen, m->n_failed_units, off_failed,
1835 jobslen, m->n_jobs);
1839 printf("\n%u machines listed.\n", n);
1842 static int list_machines(sd_bus *bus, char **args) {
1843 struct machine_info *machine_infos = NULL;
1848 if (geteuid() != 0) {
1849 log_error("Must be root.");
1853 pager_open_if_enabled();
1855 r = get_machine_list(bus, &machine_infos, strv_skip_first(args));
1859 qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
1860 output_machines_list(machine_infos, r);
1861 free_machines_list(machine_infos, r);
1866 static int get_default(sd_bus *bus, char **args) {
1867 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1868 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1869 _cleanup_free_ char *_path = NULL;
1873 if (!bus || avoid_bus()) {
1874 r = unit_file_get_default(arg_scope, arg_root, &_path);
1876 log_error("Failed to get default target: %s", strerror(-r));
1882 r = sd_bus_call_method(
1884 "org.freedesktop.systemd1",
1885 "/org/freedesktop/systemd1",
1886 "org.freedesktop.systemd1.Manager",
1892 log_error("Failed to get default target: %s", bus_error_message(&error, -r));
1896 r = sd_bus_message_read(reply, "s", &path);
1898 return bus_log_parse_error(r);
1902 printf("%s\n", path);
1907 static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) {
1910 assert(changes || n_changes == 0);
1912 for (i = 0; i < n_changes; i++) {
1913 if (changes[i].type == UNIT_FILE_SYMLINK)
1914 log_info("Created symlink from %s to %s.", changes[i].path, changes[i].source);
1916 log_info("Removed symlink %s.", changes[i].path);
1920 static int deserialize_and_dump_unit_file_changes(sd_bus_message *m) {
1921 const char *type, *path, *source;
1924 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1926 return bus_log_parse_error(r);
1928 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1930 if (streq(type, "symlink"))
1931 log_info("Created symlink from %s to %s.", path, source);
1933 log_info("Removed symlink %s.", path);
1937 return bus_log_parse_error(r);
1939 r = sd_bus_message_exit_container(m);
1941 return bus_log_parse_error(r);
1946 static int set_default(sd_bus *bus, char **args) {
1947 _cleanup_free_ char *unit = NULL;
1948 UnitFileChange *changes = NULL;
1949 unsigned n_changes = 0;
1952 unit = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
1956 if (!bus || avoid_bus()) {
1957 r = unit_file_set_default(arg_scope, arg_root, unit, true, &changes, &n_changes);
1959 log_error("Failed to set default target: %s", strerror(-r));
1964 dump_unit_file_changes(changes, n_changes);
1968 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1969 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1971 r = sd_bus_message_new_method_call(
1974 "org.freedesktop.systemd1",
1975 "/org/freedesktop/systemd1",
1976 "org.freedesktop.systemd1.Manager",
1977 "SetDefaultTarget");
1979 return bus_log_create_error(r);
1981 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
1983 return bus_log_create_error(r);
1985 r = sd_bus_message_append(m, "sb", unit, 1);
1987 return bus_log_create_error(r);
1989 r = sd_bus_call(bus, m, 0, &error, &reply);
1991 log_error("Failed to set default target: %s", bus_error_message(&error, -r));
1995 r = deserialize_and_dump_unit_file_changes(reply);
1999 /* Try to reload if enabled */
2001 r = daemon_reload(bus, args);
2006 unit_file_changes_free(changes, n_changes);
2013 const char *name, *type, *state;
2016 static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
2017 unsigned id_len, unit_len, type_len, state_len;
2018 const struct job_info *j;
2019 const char *on, *off;
2020 bool shorten = false;
2022 assert(n == 0 || jobs);
2025 on = ansi_highlight_green();
2026 off = ansi_highlight_off();
2028 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
2032 pager_open_if_enabled();
2034 id_len = strlen("JOB");
2035 unit_len = strlen("UNIT");
2036 type_len = strlen("TYPE");
2037 state_len = strlen("STATE");
2039 for (j = jobs; j < jobs + n; j++) {
2040 uint32_t id = j->id;
2041 assert(j->name && j->type && j->state);
2043 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
2044 unit_len = MAX(unit_len, strlen(j->name));
2045 type_len = MAX(type_len, strlen(j->type));
2046 state_len = MAX(state_len, strlen(j->state));
2049 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
2050 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
2055 printf("%*s %-*s %-*s %-*s\n",
2059 state_len, "STATE");
2061 for (j = jobs; j < jobs + n; j++) {
2062 _cleanup_free_ char *e = NULL;
2064 if (streq(j->state, "running")) {
2065 on = ansi_highlight();
2066 off = ansi_highlight_off();
2070 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
2071 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2073 on, unit_len, e ? e : j->name, off,
2075 on, state_len, j->state, off);
2078 if (!arg_no_legend) {
2079 on = ansi_highlight();
2080 off = ansi_highlight_off();
2082 printf("\n%s%u jobs listed%s.\n", on, n, off);
2086 static bool output_show_job(struct job_info *job, char **patterns) {
2091 if (strv_isempty(patterns))
2094 STRV_FOREACH(pattern, patterns)
2095 if (fnmatch(*pattern, job->name, FNM_NOESCAPE) == 0)
2100 static int list_jobs(sd_bus *bus, char **args) {
2101 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2102 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2103 const char *name, *type, *state, *job_path, *unit_path;
2104 _cleanup_free_ struct job_info *jobs = NULL;
2109 bool skipped = false;
2111 r = sd_bus_call_method(
2113 "org.freedesktop.systemd1",
2114 "/org/freedesktop/systemd1",
2115 "org.freedesktop.systemd1.Manager",
2121 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
2125 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2127 return bus_log_parse_error(r);
2129 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
2130 struct job_info job = { id, name, type, state };
2132 if (!output_show_job(&job, strv_skip_first(args))) {
2137 if (!GREEDY_REALLOC(jobs, size, c + 1))
2143 return bus_log_parse_error(r);
2145 r = sd_bus_message_exit_container(reply);
2147 return bus_log_parse_error(r);
2149 output_jobs_list(jobs, c, skipped);
2153 static int cancel_job(sd_bus *bus, char **args) {
2154 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2160 if (strv_length(args) <= 1)
2161 return daemon_reload(bus, args);
2163 STRV_FOREACH(name, args+1) {
2164 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2168 q = safe_atou32(*name, &id);
2170 log_error("Failed to parse job id \"%s\": %s", *name, strerror(-q));
2174 q = sd_bus_message_new_method_call(
2177 "org.freedesktop.systemd1",
2178 "/org/freedesktop/systemd1",
2179 "org.freedesktop.systemd1.Manager",
2182 return bus_log_create_error(q);
2184 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2186 return bus_log_create_error(1);
2188 q = sd_bus_message_append(m, "u", id);
2190 return bus_log_create_error(q);
2192 q = sd_bus_call(bus, m, 0, &error, NULL);
2194 log_error("Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, q));
2203 static int need_daemon_reload(sd_bus *bus, const char *unit) {
2204 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2208 /* We ignore all errors here, since this is used to show a
2211 /* We don't use unit_dbus_path_from_name() directly since we
2212 * don't want to load the unit if it isn't loaded. */
2214 r = sd_bus_call_method(
2216 "org.freedesktop.systemd1",
2217 "/org/freedesktop/systemd1",
2218 "org.freedesktop.systemd1.Manager",
2226 r = sd_bus_message_read(reply, "o", &path);
2230 r = sd_bus_get_property_trivial(
2232 "org.freedesktop.systemd1",
2234 "org.freedesktop.systemd1.Unit",
2244 typedef struct WaitData {
2251 static int wait_filter(sd_bus *bus, sd_bus_message *m, void *data, sd_bus_error *error) {
2258 log_debug("Got D-Bus request: %s.%s() on %s",
2259 sd_bus_message_get_interface(m),
2260 sd_bus_message_get_member(m),
2261 sd_bus_message_get_path(m));
2263 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
2264 log_error("Warning! D-Bus connection terminated.");
2266 } else if (sd_bus_message_is_signal(m, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
2268 const char *path, *result, *unit;
2272 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
2274 ret = set_remove(d->set, (char*) path);
2280 if (!isempty(result))
2281 d->result = strdup(result);
2284 d->name = strdup(unit);
2289 r = sd_bus_message_read(m, "uos", &id, &path, &result);
2291 ret = set_remove(d->set, (char*) path);
2298 d->result = strdup(result);
2304 bus_log_parse_error(r);
2310 static int enable_wait_for_jobs(sd_bus *bus) {
2315 r = sd_bus_add_match(
2319 "sender='org.freedesktop.systemd1',"
2320 "interface='org.freedesktop.systemd1.Manager',"
2321 "member='JobRemoved',"
2322 "path='/org/freedesktop/systemd1'",
2325 log_error("Failed to add match");
2329 /* This is slightly dirty, since we don't undo the match registrations. */
2333 static int bus_process_wait(sd_bus *bus) {
2337 r = sd_bus_process(bus, NULL);
2342 r = sd_bus_wait(bus, (uint64_t) -1);
2348 static int check_wait_response(WaitData *d) {
2354 if (streq(d->result, "timeout"))
2355 log_error("Job for %s timed out.", strna(d->name));
2356 else if (streq(d->result, "canceled"))
2357 log_error("Job for %s canceled.", strna(d->name));
2358 else if (streq(d->result, "dependency"))
2359 log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
2360 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
2364 quotes = chars_intersect(d->name, SHELL_NEED_QUOTES);
2366 log_error("Job for %s failed. See \"systemctl status %s%s%s\" and \"journalctl -xe\" for details.",
2368 quotes ? "'" : "", d->name, quotes ? "'" : "");
2370 log_error("Job failed. See \"journalctl -xe\" for details.");
2374 if (streq(d->result, "timeout"))
2376 else if (streq(d->result, "canceled"))
2378 else if (streq(d->result, "dependency"))
2380 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2386 static int wait_for_jobs(sd_bus *bus, Set *s) {
2387 _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
2388 WaitData d = { .set = s };
2394 q = sd_bus_add_filter(bus, &slot, wait_filter, &d);
2398 while (!set_isempty(s)) {
2399 q = bus_process_wait(bus);
2401 log_error("Failed to wait for response: %s", strerror(-q));
2406 q = check_wait_response(&d);
2407 /* Return the first error as it is most likely to be
2409 if (q < 0 && r == 0)
2411 log_debug("Got result %s/%s for job %s",
2412 strna(d.result), strerror(-q), strna(d.name));
2425 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2426 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2427 _cleanup_free_ char *n = NULL, *state = NULL;
2433 n = unit_name_mangle(name, MANGLE_NOGLOB);
2437 /* We don't use unit_dbus_path_from_name() directly since we
2438 * don't want to load the unit if it isn't loaded. */
2440 r = sd_bus_call_method(
2442 "org.freedesktop.systemd1",
2443 "/org/freedesktop/systemd1",
2444 "org.freedesktop.systemd1.Manager",
2455 r = sd_bus_message_read(reply, "o", &path);
2457 return bus_log_parse_error(r);
2459 r = sd_bus_get_property_string(
2461 "org.freedesktop.systemd1",
2463 "org.freedesktop.systemd1.Unit",
2476 return nulstr_contains(good_states, state);
2479 static int check_triggering_units(
2483 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2484 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2485 _cleanup_strv_free_ char **triggered_by = NULL;
2486 bool print_warning_label = true;
2490 n = unit_name_mangle(name, MANGLE_NOGLOB);
2494 path = unit_dbus_path_from_name(n);
2498 r = sd_bus_get_property_string(
2500 "org.freedesktop.systemd1",
2502 "org.freedesktop.systemd1.Unit",
2507 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2511 if (streq(state, "masked"))
2514 r = sd_bus_get_property_strv(
2516 "org.freedesktop.systemd1",
2518 "org.freedesktop.systemd1.Unit",
2523 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2527 STRV_FOREACH(i, triggered_by) {
2528 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2530 log_error("Failed to check unit: %s", strerror(-r));
2537 if (print_warning_label) {
2538 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2539 print_warning_label = false;
2542 log_warning(" %s", *i);
2548 static const struct {
2551 } unit_actions[] = {
2552 { "start", "StartUnit" },
2553 { "stop", "StopUnit" },
2554 { "condstop", "StopUnit" },
2555 { "reload", "ReloadUnit" },
2556 { "restart", "RestartUnit" },
2557 { "try-restart", "TryRestartUnit" },
2558 { "condrestart", "TryRestartUnit" },
2559 { "reload-or-restart", "ReloadOrRestartUnit" },
2560 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2561 { "condreload", "ReloadOrTryRestartUnit" },
2562 { "force-reload", "ReloadOrTryRestartUnit" }
2565 static const char *verb_to_method(const char *verb) {
2568 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2569 if (streq_ptr(unit_actions[i].verb, verb))
2570 return unit_actions[i].method;
2575 static const char *method_to_verb(const char *method) {
2578 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2579 if (streq_ptr(unit_actions[i].method, method))
2580 return unit_actions[i].verb;
2585 static int start_unit_one(
2590 sd_bus_error *error,
2593 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2602 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2604 r = sd_bus_message_new_method_call(
2607 "org.freedesktop.systemd1",
2608 "/org/freedesktop/systemd1",
2609 "org.freedesktop.systemd1.Manager",
2612 return bus_log_create_error(r);
2614 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2616 return bus_log_create_error(r);
2618 r = sd_bus_message_append(m, "ss", name, mode);
2620 return bus_log_create_error(r);
2622 r = sd_bus_call(bus, m, 0, error, &reply);
2626 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2627 /* There's always a fallback possible for
2628 * legacy actions. */
2629 return -EADDRNOTAVAIL;
2631 verb = method_to_verb(method);
2633 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2637 r = sd_bus_message_read(reply, "o", &path);
2639 return bus_log_parse_error(r);
2641 if (need_daemon_reload(bus, name) > 0)
2642 log_warning("Warning: Unit file of %s changed on disk, 'systemctl%s daemon-reload' recommended.",
2643 name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2652 log_debug("Adding %s to the set", p);
2653 r = set_consume(s, p);
2661 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2663 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2667 STRV_FOREACH(name, names) {
2671 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2673 t = unit_name_mangle(*name, MANGLE_GLOB);
2677 if (string_is_glob(t))
2678 r = strv_consume(&globs, t);
2680 r = strv_consume(&mangled, t);
2685 /* Query the manager only if any of the names are a glob, since
2686 * this is fairly expensive */
2687 if (!strv_isempty(globs)) {
2688 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2689 _cleanup_free_ UnitInfo *unit_infos = NULL;
2691 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2695 for (i = 0; i < r; i++)
2696 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2701 mangled = NULL; /* do not free */
2706 static const struct {
2710 } action_table[_ACTION_MAX] = {
2711 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2712 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2713 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2714 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2715 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
2716 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
2717 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
2718 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
2719 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2720 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2721 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2722 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2723 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2724 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2725 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2728 static enum action verb_to_action(const char *verb) {
2731 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2732 if (streq_ptr(action_table[i].verb, verb))
2735 return _ACTION_INVALID;
2738 static int start_unit(sd_bus *bus, char **args) {
2739 _cleanup_set_free_free_ Set *s = NULL;
2740 _cleanup_strv_free_ char **names = NULL;
2741 const char *method, *mode, *one_name, *suffix = NULL;
2747 ask_password_agent_open_if_enabled();
2749 if (arg_action == ACTION_SYSTEMCTL) {
2751 method = verb_to_method(args[0]);
2752 action = verb_to_action(args[0]);
2754 if (streq(args[0], "isolate")) {
2758 mode = action_table[action].mode ?: arg_job_mode;
2760 one_name = action_table[action].target;
2762 assert(arg_action < ELEMENTSOF(action_table));
2763 assert(action_table[arg_action].target);
2765 method = "StartUnit";
2767 mode = action_table[arg_action].mode;
2768 one_name = action_table[arg_action].target;
2772 names = strv_new(one_name, NULL);
2774 r = expand_names(bus, args + 1, suffix, &names);
2776 log_error("Failed to expand names: %s", strerror(-r));
2779 if (!arg_no_block) {
2780 r = enable_wait_for_jobs(bus);
2782 log_error("Could not watch jobs: %s", strerror(-r));
2786 s = set_new(&string_hash_ops);
2791 STRV_FOREACH(name, names) {
2792 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2795 q = start_unit_one(bus, method, *name, mode, &error, s);
2796 if (r >= 0 && q < 0)
2797 r = translate_bus_error_to_exit_status(q, &error);
2800 if (!arg_no_block) {
2803 q = wait_for_jobs(bus, s);
2807 /* When stopping units, warn if they can still be triggered by
2808 * another active unit (socket, path, timer) */
2809 if (!arg_quiet && streq(method, "StopUnit"))
2810 STRV_FOREACH(name, names)
2811 check_triggering_units(bus, *name);
2817 /* Ask systemd-logind, which might grant access to unprivileged users
2818 * through PolicyKit */
2819 static int reboot_with_logind(sd_bus *bus, enum action a) {
2821 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2828 polkit_agent_open_if_enabled();
2836 case ACTION_POWEROFF:
2837 method = "PowerOff";
2840 case ACTION_SUSPEND:
2844 case ACTION_HIBERNATE:
2845 method = "Hibernate";
2848 case ACTION_HYBRID_SLEEP:
2849 method = "HybridSleep";
2856 r = sd_bus_call_method(
2858 "org.freedesktop.login1",
2859 "/org/freedesktop/login1",
2860 "org.freedesktop.login1.Manager",
2864 "b", arg_ask_password);
2866 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2874 static int check_inhibitors(sd_bus *bus, enum action a) {
2876 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2877 _cleanup_strv_free_ char **sessions = NULL;
2878 const char *what, *who, *why, *mode;
2887 if (arg_ignore_inhibitors || arg_force > 0)
2899 r = sd_bus_call_method(
2901 "org.freedesktop.login1",
2902 "/org/freedesktop/login1",
2903 "org.freedesktop.login1.Manager",
2909 /* If logind is not around, then there are no inhibitors... */
2912 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2914 return bus_log_parse_error(r);
2916 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2917 _cleanup_free_ char *comm = NULL, *user = NULL;
2918 _cleanup_strv_free_ char **sv = NULL;
2920 if (!streq(mode, "block"))
2923 sv = strv_split(what, ":");
2927 if (!strv_contains(sv,
2929 a == ACTION_POWEROFF ||
2930 a == ACTION_REBOOT ||
2931 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2934 get_process_comm(pid, &comm);
2935 user = uid_to_name(uid);
2937 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
2938 who, pid, strna(comm), strna(user), why);
2943 return bus_log_parse_error(r);
2945 r = sd_bus_message_exit_container(reply);
2947 return bus_log_parse_error(r);
2949 /* Check for current sessions */
2950 sd_get_sessions(&sessions);
2951 STRV_FOREACH(s, sessions) {
2952 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2954 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2957 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2960 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2963 sd_session_get_tty(*s, &tty);
2964 sd_session_get_seat(*s, &seat);
2965 sd_session_get_service(*s, &service);
2966 user = uid_to_name(uid);
2968 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2975 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2976 action_table[a].verb);
2984 static int start_special(sd_bus *bus, char **args) {
2990 a = verb_to_action(args[0]);
2992 r = check_inhibitors(bus, a);
2996 if (arg_force >= 2 && geteuid() != 0) {
2997 log_error("Must be root.");
3001 if (arg_force >= 2 &&
3002 (a == ACTION_HALT ||
3003 a == ACTION_POWEROFF ||
3004 a == ACTION_REBOOT))
3007 if (arg_force >= 1 &&
3008 (a == ACTION_HALT ||
3009 a == ACTION_POWEROFF ||
3010 a == ACTION_REBOOT ||
3011 a == ACTION_KEXEC ||
3013 return daemon_reload(bus, args);
3015 /* first try logind, to allow authentication with polkit */
3016 if (geteuid() != 0 &&
3017 (a == ACTION_POWEROFF ||
3018 a == ACTION_REBOOT ||
3019 a == ACTION_SUSPEND ||
3020 a == ACTION_HIBERNATE ||
3021 a == ACTION_HYBRID_SLEEP)) {
3022 r = reboot_with_logind(bus, a);
3027 r = start_unit(bus, args);
3028 if (r == EXIT_SUCCESS)
3034 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
3035 _cleanup_strv_free_ char **names = NULL;
3042 r = expand_names(bus, args, NULL, &names);
3044 log_error("Failed to expand names: %s", strerror(-r));
3048 STRV_FOREACH(name, names) {
3051 state = check_one_unit(bus, *name, good_states, arg_quiet);
3061 static int check_unit_active(sd_bus *bus, char **args) {
3062 /* According to LSB: 3, "program is not running" */
3063 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
3066 static int check_unit_failed(sd_bus *bus, char **args) {
3067 return check_unit_generic(bus, 1, "failed\0", args + 1);
3070 static int kill_unit(sd_bus *bus, char **args) {
3071 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3072 _cleanup_strv_free_ char **names = NULL;
3080 arg_kill_who = "all";
3082 r = expand_names(bus, args + 1, NULL, &names);
3084 log_error("Failed to expand names: %s", strerror(-r));
3086 STRV_FOREACH(name, names) {
3087 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3089 q = sd_bus_message_new_method_call(
3092 "org.freedesktop.systemd1",
3093 "/org/freedesktop/systemd1",
3094 "org.freedesktop.systemd1.Manager",
3097 return bus_log_create_error(q);
3099 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
3101 return bus_log_create_error(q);
3103 q = sd_bus_message_append(m, "ssi", *names, arg_kill_who, arg_signal);
3105 return bus_log_create_error(q);
3107 q = sd_bus_call(bus, m, 0, &error, NULL);
3109 log_error("Failed to kill unit %s: %s", *names, bus_error_message(&error, q));
3118 typedef struct ExecStatusInfo {
3126 usec_t start_timestamp;
3127 usec_t exit_timestamp;
3132 LIST_FIELDS(struct ExecStatusInfo, exec);
3135 static void exec_status_info_free(ExecStatusInfo *i) {
3144 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3145 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3148 int32_t code, status;
3154 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3156 return bus_log_parse_error(r);
3160 r = sd_bus_message_read(m, "s", &path);
3162 return bus_log_parse_error(r);
3164 i->path = strdup(path);
3168 r = sd_bus_message_read_strv(m, &i->argv);
3170 return bus_log_parse_error(r);
3172 r = sd_bus_message_read(m,
3175 &start_timestamp, &start_timestamp_monotonic,
3176 &exit_timestamp, &exit_timestamp_monotonic,
3180 return bus_log_parse_error(r);
3183 i->start_timestamp = (usec_t) start_timestamp;
3184 i->exit_timestamp = (usec_t) exit_timestamp;
3185 i->pid = (pid_t) pid;
3189 r = sd_bus_message_exit_container(m);
3191 return bus_log_parse_error(r);
3196 typedef struct UnitStatusInfo {
3198 const char *load_state;
3199 const char *active_state;
3200 const char *sub_state;
3201 const char *unit_file_state;
3203 const char *description;
3204 const char *following;
3206 char **documentation;
3208 const char *fragment_path;
3209 const char *source_path;
3210 const char *control_group;
3212 char **dropin_paths;
3214 const char *load_error;
3217 usec_t inactive_exit_timestamp;
3218 usec_t inactive_exit_timestamp_monotonic;
3219 usec_t active_enter_timestamp;
3220 usec_t active_exit_timestamp;
3221 usec_t inactive_enter_timestamp;
3223 bool need_daemon_reload;
3228 const char *status_text;
3229 const char *pid_file;
3233 usec_t start_timestamp;
3234 usec_t exit_timestamp;
3236 int exit_code, exit_status;
3238 usec_t condition_timestamp;
3239 bool condition_result;
3240 bool failed_condition_trigger;
3241 bool failed_condition_negate;
3242 const char *failed_condition;
3243 const char *failed_condition_param;
3246 unsigned n_accepted;
3247 unsigned n_connections;
3250 /* Pairs of type, path */
3254 const char *sysfs_path;
3256 /* Mount, Automount */
3262 LIST_HEAD(ExecStatusInfo, exec);
3265 static void print_status_info(
3270 const char *active_on, *active_off, *on, *off, *ss;
3272 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3273 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3276 arg_all * OUTPUT_SHOW_ALL |
3277 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
3278 on_tty() * OUTPUT_COLOR |
3279 !arg_quiet * OUTPUT_WARN_CUTOFF |
3280 arg_full * OUTPUT_FULL_WIDTH;
3285 /* This shows pretty information about a unit. See
3286 * print_property() for a low-level property printer */
3288 if (streq_ptr(i->active_state, "failed")) {
3289 active_on = ansi_highlight_red();
3290 active_off = ansi_highlight_off();
3291 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3292 active_on = ansi_highlight_green();
3293 active_off = ansi_highlight_off();
3295 active_on = active_off = "";
3297 printf("%s%s%s %s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3299 if (i->description && !streq_ptr(i->id, i->description))
3300 printf(" - %s", i->description);
3305 printf(" Follow: unit currently follows state of %s\n", i->following);
3307 if (streq_ptr(i->load_state, "error")) {
3308 on = ansi_highlight_red();
3309 off = ansi_highlight_off();
3313 path = i->source_path ? i->source_path : i->fragment_path;
3316 printf(" Loaded: %s%s%s (Reason: %s)\n",
3317 on, strna(i->load_state), off, i->load_error);
3318 else if (path && i->unit_file_state)
3319 printf(" Loaded: %s%s%s (%s; %s)\n",
3320 on, strna(i->load_state), off, path, i->unit_file_state);
3322 printf(" Loaded: %s%s%s (%s)\n",
3323 on, strna(i->load_state), off, path);
3325 printf(" Loaded: %s%s%s\n",
3326 on, strna(i->load_state), off);
3328 if (!strv_isempty(i->dropin_paths)) {
3329 _cleanup_free_ char *dir = NULL;
3333 STRV_FOREACH(dropin, i->dropin_paths) {
3334 if (! dir || last) {
3335 printf(dir ? " " : " Drop-In: ");
3340 if (path_get_parent(*dropin, &dir) < 0) {
3345 printf("%s\n %s", dir,
3346 draw_special_char(DRAW_TREE_RIGHT));
3349 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3351 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3355 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3357 printf(" Active: %s%s (%s)%s",
3358 active_on, strna(i->active_state), ss, active_off);
3360 printf(" Active: %s%s%s",
3361 active_on, strna(i->active_state), active_off);
3363 if (!isempty(i->result) && !streq(i->result, "success"))
3364 printf(" (Result: %s)", i->result);
3366 timestamp = (streq_ptr(i->active_state, "active") ||
3367 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
3368 (streq_ptr(i->active_state, "inactive") ||
3369 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
3370 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
3371 i->active_exit_timestamp;
3373 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3374 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3377 printf(" since %s; %s\n", s2, s1);
3379 printf(" since %s\n", s2);
3383 if (!i->condition_result && i->condition_timestamp > 0) {
3384 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3385 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3387 printf(" start condition failed at %s%s%s\n",
3388 s2, s1 ? "; " : "", s1 ? s1 : "");
3389 if (i->failed_condition_trigger)
3390 printf(" none of the trigger conditions were met\n");
3391 else if (i->failed_condition)
3392 printf(" %s=%s%s was not met\n",
3393 i->failed_condition,
3394 i->failed_condition_negate ? "!" : "",
3395 i->failed_condition_param);
3399 printf(" Device: %s\n", i->sysfs_path);
3401 printf(" Where: %s\n", i->where);
3403 printf(" What: %s\n", i->what);
3405 STRV_FOREACH(t, i->documentation)
3406 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3408 STRV_FOREACH_PAIR(t, t2, i->listen)
3409 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3412 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3414 LIST_FOREACH(exec, p, i->exec) {
3415 _cleanup_free_ char *argv = NULL;
3418 /* Only show exited processes here */
3422 argv = strv_join(p->argv, " ");
3423 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
3425 good = is_clean_exit_lsb(p->code, p->status, NULL);
3427 on = ansi_highlight_red();
3428 off = ansi_highlight_off();
3432 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3434 if (p->code == CLD_EXITED) {
3437 printf("status=%i", p->status);
3439 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3444 printf("signal=%s", signal_to_string(p->status));
3446 printf(")%s\n", off);
3448 if (i->main_pid == p->pid &&
3449 i->start_timestamp == p->start_timestamp &&
3450 i->exit_timestamp == p->start_timestamp)
3451 /* Let's not show this twice */
3454 if (p->pid == i->control_pid)
3458 if (i->main_pid > 0 || i->control_pid > 0) {
3459 if (i->main_pid > 0) {
3460 printf(" Main PID: "PID_FMT, i->main_pid);
3463 _cleanup_free_ char *comm = NULL;
3464 get_process_comm(i->main_pid, &comm);
3466 printf(" (%s)", comm);
3467 } else if (i->exit_code > 0) {
3468 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3470 if (i->exit_code == CLD_EXITED) {
3473 printf("status=%i", i->exit_status);
3475 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3480 printf("signal=%s", signal_to_string(i->exit_status));
3484 if (i->control_pid > 0)
3488 if (i->control_pid > 0) {
3489 _cleanup_free_ char *c = NULL;
3491 printf(" %8s: "PID_FMT, i->main_pid ? "" : " Control", i->control_pid);
3493 get_process_comm(i->control_pid, &c);
3502 printf(" Status: \"%s\"\n", i->status_text);
3503 if (i->status_errno > 0)
3504 printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
3506 if (i->control_group &&
3507 (i->main_pid > 0 || i->control_pid > 0 ||
3508 ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_CONTAINER) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3511 printf(" CGroup: %s\n", i->control_group);
3513 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
3516 static const char prefix[] = " ";
3519 if (c > sizeof(prefix) - 1)
3520 c -= sizeof(prefix) - 1;
3524 if (i->main_pid > 0)
3525 extra[k++] = i->main_pid;
3527 if (i->control_pid > 0)
3528 extra[k++] = i->control_pid;
3530 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, flags);
3534 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3535 show_journal_by_unit(stdout,
3539 i->inactive_exit_timestamp_monotonic,
3542 flags | OUTPUT_BEGIN_NEWLINE,
3543 arg_scope == UNIT_FILE_SYSTEM,
3547 if (i->need_daemon_reload)
3548 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
3549 ansi_highlight_red(),
3550 ansi_highlight_off(),
3551 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
3554 static void show_unit_help(UnitStatusInfo *i) {
3559 if (!i->documentation) {
3560 log_info("Documentation for %s not known.", i->id);
3564 STRV_FOREACH(p, i->documentation)
3565 if (startswith(*p, "man:"))
3566 show_man_page(*p + 4, false);
3568 log_info("Can't show: %s", *p);
3571 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3578 switch (contents[0]) {
3580 case SD_BUS_TYPE_STRING: {
3583 r = sd_bus_message_read(m, "s", &s);
3585 return bus_log_parse_error(r);
3588 if (streq(name, "Id"))
3590 else if (streq(name, "LoadState"))
3592 else if (streq(name, "ActiveState"))
3593 i->active_state = s;
3594 else if (streq(name, "SubState"))
3596 else if (streq(name, "Description"))
3598 else if (streq(name, "FragmentPath"))
3599 i->fragment_path = s;
3600 else if (streq(name, "SourcePath"))
3603 else if (streq(name, "DefaultControlGroup")) {
3605 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3607 i->control_group = e;
3610 else if (streq(name, "ControlGroup"))
3611 i->control_group = s;
3612 else if (streq(name, "StatusText"))
3614 else if (streq(name, "PIDFile"))
3616 else if (streq(name, "SysFSPath"))
3618 else if (streq(name, "Where"))
3620 else if (streq(name, "What"))
3622 else if (streq(name, "Following"))
3624 else if (streq(name, "UnitFileState"))
3625 i->unit_file_state = s;
3626 else if (streq(name, "Result"))
3633 case SD_BUS_TYPE_BOOLEAN: {
3636 r = sd_bus_message_read(m, "b", &b);
3638 return bus_log_parse_error(r);
3640 if (streq(name, "Accept"))
3642 else if (streq(name, "NeedDaemonReload"))
3643 i->need_daemon_reload = b;
3644 else if (streq(name, "ConditionResult"))
3645 i->condition_result = b;
3650 case SD_BUS_TYPE_UINT32: {
3653 r = sd_bus_message_read(m, "u", &u);
3655 return bus_log_parse_error(r);
3657 if (streq(name, "MainPID")) {
3659 i->main_pid = (pid_t) u;
3662 } else if (streq(name, "ControlPID"))
3663 i->control_pid = (pid_t) u;
3664 else if (streq(name, "ExecMainPID")) {
3666 i->main_pid = (pid_t) u;
3667 } else if (streq(name, "NAccepted"))
3669 else if (streq(name, "NConnections"))
3670 i->n_connections = u;
3675 case SD_BUS_TYPE_INT32: {
3678 r = sd_bus_message_read(m, "i", &j);
3680 return bus_log_parse_error(r);
3682 if (streq(name, "ExecMainCode"))
3683 i->exit_code = (int) j;
3684 else if (streq(name, "ExecMainStatus"))
3685 i->exit_status = (int) j;
3686 else if (streq(name, "StatusErrno"))
3687 i->status_errno = (int) j;
3692 case SD_BUS_TYPE_UINT64: {
3695 r = sd_bus_message_read(m, "t", &u);
3697 return bus_log_parse_error(r);
3699 if (streq(name, "ExecMainStartTimestamp"))
3700 i->start_timestamp = (usec_t) u;
3701 else if (streq(name, "ExecMainExitTimestamp"))
3702 i->exit_timestamp = (usec_t) u;
3703 else if (streq(name, "ActiveEnterTimestamp"))
3704 i->active_enter_timestamp = (usec_t) u;
3705 else if (streq(name, "InactiveEnterTimestamp"))
3706 i->inactive_enter_timestamp = (usec_t) u;
3707 else if (streq(name, "InactiveExitTimestamp"))
3708 i->inactive_exit_timestamp = (usec_t) u;
3709 else if (streq(name, "InactiveExitTimestampMonotonic"))
3710 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3711 else if (streq(name, "ActiveExitTimestamp"))
3712 i->active_exit_timestamp = (usec_t) u;
3713 else if (streq(name, "ConditionTimestamp"))
3714 i->condition_timestamp = (usec_t) u;
3719 case SD_BUS_TYPE_ARRAY:
3721 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3722 _cleanup_free_ ExecStatusInfo *info = NULL;
3724 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3726 return bus_log_parse_error(r);
3728 info = new0(ExecStatusInfo, 1);
3732 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3734 info->name = strdup(name);
3738 LIST_PREPEND(exec, i->exec, info);
3740 info = new0(ExecStatusInfo, 1);
3746 return bus_log_parse_error(r);
3748 r = sd_bus_message_exit_container(m);
3750 return bus_log_parse_error(r);
3754 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3755 const char *type, *path;
3757 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3759 return bus_log_parse_error(r);
3761 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3763 r = strv_extend(&i->listen, type);
3767 r = strv_extend(&i->listen, path);
3772 return bus_log_parse_error(r);
3774 r = sd_bus_message_exit_container(m);
3776 return bus_log_parse_error(r);
3780 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3782 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3784 return bus_log_parse_error(r);
3786 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3788 r = sd_bus_message_read_strv(m, &i->documentation);
3790 return bus_log_parse_error(r);
3792 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3793 const char *cond, *param;
3794 int trigger, negate;
3797 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3799 return bus_log_parse_error(r);
3801 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3802 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3803 if (state < 0 && (!trigger || !i->failed_condition)) {
3804 i->failed_condition = cond;
3805 i->failed_condition_trigger = trigger;
3806 i->failed_condition_negate = negate;
3807 i->failed_condition_param = param;
3811 return bus_log_parse_error(r);
3813 r = sd_bus_message_exit_container(m);
3815 return bus_log_parse_error(r);
3822 case SD_BUS_TYPE_STRUCT_BEGIN:
3824 if (streq(name, "LoadError")) {
3825 const char *n, *message;
3827 r = sd_bus_message_read(m, "(ss)", &n, &message);
3829 return bus_log_parse_error(r);
3831 if (!isempty(message))
3832 i->load_error = message;
3845 r = sd_bus_message_skip(m, contents);
3847 return bus_log_parse_error(r);
3852 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3858 /* This is a low-level property printer, see
3859 * print_status_info() for the nicer output */
3861 if (arg_properties && !strv_find(arg_properties, name)) {
3862 /* skip what we didn't read */
3863 r = sd_bus_message_skip(m, contents);
3867 switch (contents[0]) {
3869 case SD_BUS_TYPE_STRUCT_BEGIN:
3871 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3874 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3876 return bus_log_parse_error(r);
3879 printf("%s=%"PRIu32"\n", name, u);
3881 printf("%s=\n", name);
3885 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3888 r = sd_bus_message_read(m, "(so)", &s, NULL);
3890 return bus_log_parse_error(r);
3892 if (arg_all || !isempty(s))
3893 printf("%s=%s\n", name, s);
3897 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3898 const char *a = NULL, *b = NULL;
3900 r = sd_bus_message_read(m, "(ss)", &a, &b);
3902 return bus_log_parse_error(r);
3904 if (arg_all || !isempty(a) || !isempty(b))
3905 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3908 } else if (streq_ptr(name, "SystemCallFilter")) {
3909 _cleanup_strv_free_ char **l = NULL;
3912 r = sd_bus_message_enter_container(m, 'r', "bas");
3914 return bus_log_parse_error(r);
3916 r = sd_bus_message_read(m, "b", &whitelist);
3918 return bus_log_parse_error(r);
3920 r = sd_bus_message_read_strv(m, &l);
3922 return bus_log_parse_error(r);
3924 r = sd_bus_message_exit_container(m);
3926 return bus_log_parse_error(r);
3928 if (arg_all || whitelist || !strv_isempty(l)) {
3932 fputs(name, stdout);
3938 STRV_FOREACH(i, l) {
3946 fputc('\n', stdout);
3954 case SD_BUS_TYPE_ARRAY:
3956 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
3960 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
3962 return bus_log_parse_error(r);
3964 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
3965 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3968 return bus_log_parse_error(r);
3970 r = sd_bus_message_exit_container(m);
3972 return bus_log_parse_error(r);
3976 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
3977 const char *type, *path;
3979 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3981 return bus_log_parse_error(r);
3983 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3984 printf("%s=%s\n", type, path);
3986 return bus_log_parse_error(r);
3988 r = sd_bus_message_exit_container(m);
3990 return bus_log_parse_error(r);
3994 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3995 const char *type, *path;
3997 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3999 return bus_log_parse_error(r);
4001 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4002 printf("Listen%s=%s\n", type, path);
4004 return bus_log_parse_error(r);
4006 r = sd_bus_message_exit_container(m);
4008 return bus_log_parse_error(r);
4012 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
4014 uint64_t value, next_elapse;
4016 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
4018 return bus_log_parse_error(r);
4020 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
4021 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
4023 printf("%s={ value=%s ; next_elapse=%s }\n",
4025 format_timespan(timespan1, sizeof(timespan1), value, 0),
4026 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
4029 return bus_log_parse_error(r);
4031 r = sd_bus_message_exit_container(m);
4033 return bus_log_parse_error(r);
4037 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
4038 ExecStatusInfo info = {};
4040 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
4042 return bus_log_parse_error(r);
4044 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
4045 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
4046 _cleanup_free_ char *tt;
4048 tt = strv_join(info.argv, " ");
4050 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",
4054 yes_no(info.ignore),
4055 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
4056 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
4058 sigchld_code_to_string(info.code),
4060 info.code == CLD_EXITED ? "" : "/",
4061 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
4064 strv_free(info.argv);
4068 r = sd_bus_message_exit_container(m);
4070 return bus_log_parse_error(r);
4074 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
4075 const char *path, *rwm;
4077 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4079 return bus_log_parse_error(r);
4081 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
4082 printf("%s=%s %s\n", name, strna(path), strna(rwm));
4084 return bus_log_parse_error(r);
4086 r = sd_bus_message_exit_container(m);
4088 return bus_log_parse_error(r);
4092 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
4096 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4098 return bus_log_parse_error(r);
4100 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4101 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
4103 return bus_log_parse_error(r);
4105 r = sd_bus_message_exit_container(m);
4107 return bus_log_parse_error(r);
4111 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
4115 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4117 return bus_log_parse_error(r);
4119 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4120 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
4122 return bus_log_parse_error(r);
4124 r = sd_bus_message_exit_container(m);
4126 return bus_log_parse_error(r);
4134 r = bus_print_property(name, m, arg_all);
4136 return bus_log_parse_error(r);
4139 r = sd_bus_message_skip(m, contents);
4141 return bus_log_parse_error(r);
4144 printf("%s=[unprintable]\n", name);
4150 static int show_one(
4154 bool show_properties,
4158 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4159 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4160 UnitStatusInfo info = {};
4167 log_debug("Showing one %s", path);
4169 r = sd_bus_call_method(
4171 "org.freedesktop.systemd1",
4173 "org.freedesktop.DBus.Properties",
4179 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4183 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4185 return bus_log_parse_error(r);
4192 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4193 const char *name, *contents;
4195 r = sd_bus_message_read(reply, "s", &name);
4197 return bus_log_parse_error(r);
4199 r = sd_bus_message_peek_type(reply, NULL, &contents);
4201 return bus_log_parse_error(r);
4203 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4205 return bus_log_parse_error(r);
4207 if (show_properties)
4208 r = print_property(name, reply, contents);
4210 r = status_property(name, reply, &info, contents);
4214 r = sd_bus_message_exit_container(reply);
4216 return bus_log_parse_error(r);
4218 r = sd_bus_message_exit_container(reply);
4220 return bus_log_parse_error(r);
4223 return bus_log_parse_error(r);
4225 r = sd_bus_message_exit_container(reply);
4227 return bus_log_parse_error(r);
4231 if (!show_properties) {
4232 if (streq(verb, "help"))
4233 show_unit_help(&info);
4235 print_status_info(&info, ellipsized);
4238 strv_free(info.documentation);
4239 strv_free(info.dropin_paths);
4240 strv_free(info.listen);
4242 if (!streq_ptr(info.active_state, "active") &&
4243 !streq_ptr(info.active_state, "reloading") &&
4244 streq(verb, "status")) {
4245 /* According to LSB: "program not running" */
4246 /* 0: program is running or service is OK
4247 * 1: program is dead and /run PID file exists
4248 * 2: program is dead and /run/lock lock file exists
4249 * 3: program is not running
4250 * 4: program or service status is unknown
4252 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4258 while ((p = info.exec)) {
4259 LIST_REMOVE(exec, info.exec, p);
4260 exec_status_info_free(p);
4266 static int get_unit_dbus_path_by_pid(
4271 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4272 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4276 r = sd_bus_call_method(
4278 "org.freedesktop.systemd1",
4279 "/org/freedesktop/systemd1",
4280 "org.freedesktop.systemd1.Manager",
4286 log_error("Failed to get unit for PID "PID_FMT": %s", pid, bus_error_message(&error, r));
4290 r = sd_bus_message_read(reply, "o", &u);
4292 return bus_log_parse_error(r);
4302 static int show_all(
4305 bool show_properties,
4309 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4310 _cleanup_free_ UnitInfo *unit_infos = NULL;
4315 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4319 pager_open_if_enabled();
4323 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4325 for (u = unit_infos; u < unit_infos + c; u++) {
4326 _cleanup_free_ char *p = NULL;
4328 p = unit_dbus_path_from_name(u->id);
4332 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4335 else if (r > 0 && ret == 0)
4342 static int show_system_status(sd_bus *bus) {
4343 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4344 _cleanup_free_ char *hn = NULL;
4345 struct machine_info mi = {};
4346 const char *on, *off;
4349 hn = gethostname_malloc();
4353 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4355 log_error("Failed to read server status: %s", strerror(-r));
4359 if (streq_ptr(mi.state, "degraded")) {
4360 on = ansi_highlight_red();
4361 off = ansi_highlight_off();
4362 } else if (!streq_ptr(mi.state, "running")) {
4363 on = ansi_highlight_yellow();
4364 off = ansi_highlight_off();
4368 printf("%s%s%s %s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4370 printf(" State: %s%s%s\n",
4371 on, strna(mi.state), off);
4373 printf(" Jobs: %u queued\n", mi.n_jobs);
4374 printf(" Failed: %u units\n", mi.n_failed_units);
4376 printf(" Since: %s; %s\n",
4377 format_timestamp(since2, sizeof(since2), mi.timestamp),
4378 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4380 printf(" CGroup: %s\n", mi.control_group ?: "/");
4381 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
4383 arg_all * OUTPUT_SHOW_ALL |
4384 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
4385 on_tty() * OUTPUT_COLOR |
4386 !arg_quiet * OUTPUT_WARN_CUTOFF |
4387 arg_full * OUTPUT_FULL_WIDTH;
4389 static const char prefix[] = " ";
4393 if (c > sizeof(prefix) - 1)
4394 c -= sizeof(prefix) - 1;
4398 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
4402 free(mi.control_group);
4407 static int show(sd_bus *bus, char **args) {
4408 bool show_properties, show_status, new_line = false;
4409 bool ellipsized = false;
4415 show_properties = streq(args[0], "show");
4416 show_status = streq(args[0], "status");
4418 if (show_properties)
4419 pager_open_if_enabled();
4421 /* If no argument is specified inspect the manager itself */
4423 if (show_properties && strv_length(args) <= 1)
4424 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4426 if (show_status && strv_length(args) <= 1) {
4428 pager_open_if_enabled();
4429 show_system_status(bus);
4433 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4435 _cleanup_free_ char **patterns = NULL;
4438 STRV_FOREACH(name, args + 1) {
4439 _cleanup_free_ char *unit = NULL;
4442 if (safe_atou32(*name, &id) < 0) {
4443 if (strv_push(&patterns, *name) < 0)
4447 } else if (show_properties) {
4448 /* Interpret as job id */
4449 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4453 /* Interpret as PID */
4454 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4461 r = show_one(args[0], bus, unit, show_properties,
4462 &new_line, &ellipsized);
4465 else if (r > 0 && ret == 0)
4469 if (!strv_isempty(patterns)) {
4470 _cleanup_strv_free_ char **names = NULL;
4472 r = expand_names(bus, patterns, NULL, &names);
4474 log_error("Failed to expand names: %s", strerror(-r));
4476 STRV_FOREACH(name, names) {
4477 _cleanup_free_ char *unit;
4479 unit = unit_dbus_path_from_name(*name);
4483 r = show_one(args[0], bus, unit, show_properties,
4484 &new_line, &ellipsized);
4487 else if (r > 0 && ret == 0)
4493 if (ellipsized && !arg_quiet)
4494 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4499 static int cat(sd_bus *bus, char **args) {
4500 _cleanup_strv_free_ char **names = NULL;
4508 r = expand_names(bus, args + 1, NULL, &names);
4510 log_error("Failed to expand names: %s", strerror(-r));
4512 pager_open_if_enabled();
4514 STRV_FOREACH(name, names) {
4515 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4516 _cleanup_strv_free_ char **dropin_paths = NULL;
4517 _cleanup_free_ char *fragment_path = NULL, *unit = NULL;
4520 unit = unit_dbus_path_from_name(*name);
4524 if (need_daemon_reload(bus, *name) > 0)
4525 log_warning("Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'.",
4526 *name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
4528 r = sd_bus_get_property_string(
4530 "org.freedesktop.systemd1",
4532 "org.freedesktop.systemd1.Unit",
4537 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
4541 r = sd_bus_get_property_strv(
4543 "org.freedesktop.systemd1",
4545 "org.freedesktop.systemd1.Unit",
4550 log_warning("Failed to get DropInPaths: %s", bus_error_message(&error, r));
4559 if (!isempty(fragment_path)) {
4560 printf("%s# %s%s\n",
4561 ansi_highlight_blue(),
4563 ansi_highlight_off());
4566 r = sendfile_full(STDOUT_FILENO, fragment_path);
4568 log_warning("Failed to cat %s: %s", fragment_path, strerror(-r));
4573 STRV_FOREACH(path, dropin_paths) {
4574 printf("%s%s# %s%s\n",
4575 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4576 ansi_highlight_blue(),
4578 ansi_highlight_off());
4581 r = sendfile_full(STDOUT_FILENO, *path);
4583 log_warning("Failed to cat %s: %s", *path, strerror(-r));
4589 return r < 0 ? r : 0;
4592 static int set_property(sd_bus *bus, char **args) {
4593 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4594 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4595 _cleanup_free_ char *n = NULL;
4599 r = sd_bus_message_new_method_call(
4602 "org.freedesktop.systemd1",
4603 "/org/freedesktop/systemd1",
4604 "org.freedesktop.systemd1.Manager",
4605 "SetUnitProperties");
4607 return bus_log_create_error(r);
4609 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
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 *m = NULL, *reply = NULL;
4655 _cleanup_free_ char *n = NULL, *id = NULL;
4659 if (strv_length(args) > 1)
4660 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4666 r = sd_bus_message_new_method_call(
4669 "org.freedesktop.systemd1",
4670 "/org/freedesktop/systemd1",
4671 "org.freedesktop.systemd1.Manager",
4674 return bus_log_create_error(r);
4676 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4678 return bus_log_create_error(r);
4680 r = sd_bus_message_append(m, "sb", n, false);
4682 return bus_log_create_error(r);
4684 r = sd_bus_call(bus, m, 0, &error, &reply);
4686 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4690 r = sd_bus_message_read(reply, "o", &path);
4692 return bus_log_parse_error(r);
4694 r = sd_bus_get_property_string(
4696 "org.freedesktop.systemd1",
4698 "org.freedesktop.systemd1.Unit",
4703 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4713 static int delete_snapshot(sd_bus *bus, char **args) {
4714 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4715 _cleanup_strv_free_ char **names = NULL;
4721 r = expand_names(bus, args + 1, ".snapshot", &names);
4723 log_error("Failed to expand names: %s", strerror(-r));
4725 STRV_FOREACH(name, names) {
4726 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4729 q = sd_bus_message_new_method_call(
4732 "org.freedesktop.systemd1",
4733 "/org/freedesktop/systemd1",
4734 "org.freedesktop.systemd1.Manager",
4737 return bus_log_create_error(q);
4739 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4741 return bus_log_create_error(q);
4743 q = sd_bus_message_append(m, "s", *name);
4745 return bus_log_create_error(q);
4747 q = sd_bus_call(bus, m, 0, &error, NULL);
4749 log_error("Failed to remove snapshot %s: %s", *name, bus_error_message(&error, q));
4758 static int daemon_reload(sd_bus *bus, char **args) {
4759 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4760 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4764 if (arg_action == ACTION_RELOAD)
4766 else if (arg_action == ACTION_REEXEC)
4767 method = "Reexecute";
4769 assert(arg_action == ACTION_SYSTEMCTL);
4772 streq(args[0], "clear-jobs") ||
4773 streq(args[0], "cancel") ? "ClearJobs" :
4774 streq(args[0], "daemon-reexec") ? "Reexecute" :
4775 streq(args[0], "reset-failed") ? "ResetFailed" :
4776 streq(args[0], "halt") ? "Halt" :
4777 streq(args[0], "poweroff") ? "PowerOff" :
4778 streq(args[0], "reboot") ? "Reboot" :
4779 streq(args[0], "kexec") ? "KExec" :
4780 streq(args[0], "exit") ? "Exit" :
4781 /* "daemon-reload" */ "Reload";
4784 r = sd_bus_message_new_method_call(
4787 "org.freedesktop.systemd1",
4788 "/org/freedesktop/systemd1",
4789 "org.freedesktop.systemd1.Manager",
4792 return bus_log_create_error(r);
4794 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4796 return bus_log_create_error(r);
4798 r = sd_bus_call(bus, m, 0, &error, NULL);
4799 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4800 /* There's always a fallback possible for
4801 * legacy actions. */
4803 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4804 /* On reexecution, we expect a disconnect, not a
4808 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4810 return r < 0 ? r : 0;
4813 static int reset_failed(sd_bus *bus, char **args) {
4814 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4815 _cleanup_strv_free_ char **names = NULL;
4819 if (strv_length(args) <= 1)
4820 return daemon_reload(bus, args);
4822 r = expand_names(bus, args + 1, NULL, &names);
4824 log_error("Failed to expand names: %s", strerror(-r));
4826 STRV_FOREACH(name, names) {
4827 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4829 q = sd_bus_message_new_method_call(
4832 "org.freedesktop.systemd1",
4833 "/org/freedesktop/systemd1",
4834 "org.freedesktop.systemd1.Manager",
4837 return bus_log_create_error(q);
4839 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4841 return bus_log_create_error(q);
4843 q = sd_bus_message_append(m, "s", *name);
4845 return bus_log_create_error(q);
4847 q = sd_bus_call(bus, m, 0, &error, NULL);
4849 log_error("Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q));
4858 static int show_environment(sd_bus *bus, char **args) {
4859 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4860 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4864 pager_open_if_enabled();
4866 r = sd_bus_get_property(
4868 "org.freedesktop.systemd1",
4869 "/org/freedesktop/systemd1",
4870 "org.freedesktop.systemd1.Manager",
4876 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4880 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4882 return bus_log_parse_error(r);
4884 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4887 return bus_log_parse_error(r);
4889 r = sd_bus_message_exit_container(reply);
4891 return bus_log_parse_error(r);
4896 static int switch_root(sd_bus *bus, char **args) {
4897 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4898 _cleanup_free_ char *cmdline_init = NULL;
4899 const char *root, *init;
4903 l = strv_length(args);
4904 if (l < 2 || l > 3) {
4905 log_error("Wrong number of arguments.");
4914 r = parse_env_file("/proc/cmdline", WHITESPACE,
4915 "init", &cmdline_init,
4918 log_debug("Failed to parse /proc/cmdline: %s", strerror(-r));
4920 init = cmdline_init;
4927 const char *root_systemd_path = NULL, *root_init_path = NULL;
4929 root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
4930 root_init_path = strappenda(root, "/", init);
4932 /* If the passed init is actually the same as the
4933 * systemd binary, then let's suppress it. */
4934 if (files_same(root_init_path, root_systemd_path) > 0)
4938 log_debug("Switching root - root: %s; init: %s", root, strna(init));
4940 r = sd_bus_call_method(
4942 "org.freedesktop.systemd1",
4943 "/org/freedesktop/systemd1",
4944 "org.freedesktop.systemd1.Manager",
4950 log_error("Failed to switch root: %s", bus_error_message(&error, r));
4957 static int set_environment(sd_bus *bus, char **args) {
4958 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4959 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4966 method = streq(args[0], "set-environment")
4968 : "UnsetEnvironment";
4970 r = sd_bus_message_new_method_call(
4973 "org.freedesktop.systemd1",
4974 "/org/freedesktop/systemd1",
4975 "org.freedesktop.systemd1.Manager",
4978 return bus_log_create_error(r);
4980 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4982 return bus_log_create_error(r);
4984 r = sd_bus_message_append_strv(m, args + 1);
4986 return bus_log_create_error(r);
4988 r = sd_bus_call(bus, m, 0, &error, NULL);
4990 log_error("Failed to set environment: %s", bus_error_message(&error, r));
4997 static int import_environment(sd_bus *bus, char **args) {
4998 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4999 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
5005 r = sd_bus_message_new_method_call(
5008 "org.freedesktop.systemd1",
5009 "/org/freedesktop/systemd1",
5010 "org.freedesktop.systemd1.Manager",
5013 return bus_log_create_error(r);
5015 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5017 return bus_log_create_error(r);
5019 if (strv_isempty(args + 1))
5020 r = sd_bus_message_append_strv(m, environ);
5024 r = sd_bus_message_open_container(m, 'a', "s");
5026 return bus_log_create_error(r);
5028 STRV_FOREACH(a, args + 1) {
5030 if (!env_name_is_valid(*a)) {
5031 log_error("Not a valid environment variable name: %s", *a);
5035 STRV_FOREACH(b, environ) {
5038 eq = startswith(*b, *a);
5039 if (eq && *eq == '=') {
5041 r = sd_bus_message_append(m, "s", *b);
5043 return bus_log_create_error(r);
5050 r = sd_bus_message_close_container(m);
5053 return bus_log_create_error(r);
5055 r = sd_bus_call(bus, m, 0, &error, NULL);
5057 log_error("Failed to import environment: %s", bus_error_message(&error, r));
5064 static int enable_sysv_units(const char *verb, char **args) {
5067 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
5068 unsigned f = 1, t = 1;
5069 _cleanup_lookup_paths_free_ LookupPaths paths = {};
5071 if (arg_scope != UNIT_FILE_SYSTEM)
5074 if (!streq(verb, "enable") &&
5075 !streq(verb, "disable") &&
5076 !streq(verb, "is-enabled"))
5079 /* Processes all SysV units, and reshuffles the array so that
5080 * afterwards only the native units remain */
5082 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, arg_root, NULL, NULL, NULL);
5087 for (f = 0; args[f]; f++) {
5089 _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL;
5090 bool found_native = false, found_sysv;
5092 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
5100 if (!endswith(name, ".service"))
5103 if (path_is_absolute(name))
5106 STRV_FOREACH(k, paths.unit_path) {
5107 _cleanup_free_ char *path = NULL;
5109 path = path_join(arg_root, *k, name);
5113 found_native = access(path, F_OK) >= 0;
5121 p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name);
5125 p[strlen(p) - strlen(".service")] = 0;
5126 found_sysv = access(p, F_OK) >= 0;
5130 /* Mark this entry, so that we don't try enabling it as native unit */
5131 args[f] = (char*) "";
5133 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
5135 if (!isempty(arg_root))
5136 argv[c++] = q = strappend("--root=", arg_root);
5138 argv[c++] = basename(p);
5140 streq(verb, "enable") ? "on" :
5141 streq(verb, "disable") ? "off" : "--level=5";
5144 l = strv_join((char**)argv, " ");
5148 log_info("Executing %s", l);
5152 log_error("Failed to fork: %m");
5154 } else if (pid == 0) {
5157 execv(argv[0], (char**) argv);
5158 _exit(EXIT_FAILURE);
5161 j = wait_for_terminate(pid, &status);
5163 log_error("Failed to wait for child: %s", strerror(-r));
5167 if (status.si_code == CLD_EXITED) {
5168 if (streq(verb, "is-enabled")) {
5169 if (status.si_status == 0) {
5178 } else if (status.si_status != 0)
5184 /* Drop all SysV units */
5185 for (f = 0, t = 0; args[f]; f++) {
5187 if (isempty(args[f]))
5190 args[t++] = args[f];
5199 static int mangle_names(char **original_names, char ***mangled_names) {
5200 char **i, **l, **name;
5202 l = new(char*, strv_length(original_names) + 1);
5207 STRV_FOREACH(name, original_names) {
5209 /* When enabling units qualified path names are OK,
5210 * too, hence allow them explicitly. */
5215 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5231 static int enable_unit(sd_bus *bus, char **args) {
5232 _cleanup_strv_free_ char **names = NULL;
5233 const char *verb = args[0];
5234 UnitFileChange *changes = NULL;
5235 unsigned n_changes = 0;
5236 int carries_install_info = -1;
5242 r = mangle_names(args+1, &names);
5246 r = enable_sysv_units(verb, names);
5250 /* If the operation was fully executed by the SysV compat,
5251 * let's finish early */
5252 if (strv_isempty(names))
5255 if (!bus || avoid_bus()) {
5256 if (streq(verb, "enable")) {
5257 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5258 carries_install_info = r;
5259 } else if (streq(verb, "disable"))
5260 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5261 else if (streq(verb, "reenable")) {
5262 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5263 carries_install_info = r;
5264 } else if (streq(verb, "link"))
5265 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5266 else if (streq(verb, "preset")) {
5267 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_preset_mode, arg_force, &changes, &n_changes);
5268 carries_install_info = r;
5269 } else if (streq(verb, "mask"))
5270 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5271 else if (streq(verb, "unmask"))
5272 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5274 assert_not_reached("Unknown verb");
5277 log_error("Operation failed: %s", strerror(-r));
5282 dump_unit_file_changes(changes, n_changes);
5286 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5287 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5288 int expect_carries_install_info = false;
5289 bool send_force = true, send_preset_mode = false;
5292 if (streq(verb, "enable")) {
5293 method = "EnableUnitFiles";
5294 expect_carries_install_info = true;
5295 } else if (streq(verb, "disable")) {
5296 method = "DisableUnitFiles";
5298 } else if (streq(verb, "reenable")) {
5299 method = "ReenableUnitFiles";
5300 expect_carries_install_info = true;
5301 } else if (streq(verb, "link"))
5302 method = "LinkUnitFiles";
5303 else if (streq(verb, "preset")) {
5305 if (arg_preset_mode != UNIT_FILE_PRESET_FULL) {
5306 method = "PresetUnitFilesWithMode";
5307 send_preset_mode = true;
5309 method = "PresetUnitFiles";
5311 expect_carries_install_info = true;
5312 } else if (streq(verb, "mask"))
5313 method = "MaskUnitFiles";
5314 else if (streq(verb, "unmask")) {
5315 method = "UnmaskUnitFiles";
5318 assert_not_reached("Unknown verb");
5320 r = sd_bus_message_new_method_call(
5323 "org.freedesktop.systemd1",
5324 "/org/freedesktop/systemd1",
5325 "org.freedesktop.systemd1.Manager",
5328 return bus_log_create_error(r);
5330 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5332 return bus_log_create_error(r);
5334 r = sd_bus_message_append_strv(m, names);
5336 return bus_log_create_error(r);
5338 if (send_preset_mode) {
5339 r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode));
5341 return bus_log_create_error(r);
5344 r = sd_bus_message_append(m, "b", arg_runtime);
5346 return bus_log_create_error(r);
5349 r = sd_bus_message_append(m, "b", arg_force);
5351 return bus_log_create_error(r);
5354 r = sd_bus_call(bus, m, 0, &error, &reply);
5356 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5360 if (expect_carries_install_info) {
5361 r = sd_bus_message_read(reply, "b", &carries_install_info);
5363 return bus_log_parse_error(r);
5366 r = deserialize_and_dump_unit_file_changes(reply);
5370 /* Try to reload if enabled */
5372 r = daemon_reload(bus, args);
5377 if (carries_install_info == 0)
5378 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5379 "using systemctl.\n"
5380 "Possible reasons for having this kind of units are:\n"
5381 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5382 " .wants/ or .requires/ directory.\n"
5383 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5384 " a requirement dependency on it.\n"
5385 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5386 " D-Bus, udev, scripted systemctl call, ...).\n");
5389 unit_file_changes_free(changes, n_changes);
5394 static int add_dependency(sd_bus *bus, char **args) {
5395 _cleanup_strv_free_ char **names = NULL;
5396 _cleanup_free_ char *target = NULL;
5397 const char *verb = args[0];
5404 target = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
5408 r = mangle_names(args+2, &names);
5412 if (streq(verb, "add-wants"))
5414 else if (streq(verb, "add-requires"))
5415 dep = UNIT_REQUIRES;
5417 assert_not_reached("Unknown verb");
5419 if (!bus || avoid_bus()) {
5420 UnitFileChange *changes = NULL;
5421 unsigned n_changes = 0;
5423 r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes);
5426 log_error("Can't add dependency: %s", strerror(-r));
5431 dump_unit_file_changes(changes, n_changes);
5433 unit_file_changes_free(changes, n_changes);
5436 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5437 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5439 r = sd_bus_message_new_method_call(
5442 "org.freedesktop.systemd1",
5443 "/org/freedesktop/systemd1",
5444 "org.freedesktop.systemd1.Manager",
5445 "AddDependencyUnitFiles");
5447 return bus_log_create_error(r);
5449 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5451 return bus_log_create_error(r);
5453 r = sd_bus_message_append_strv(m, names);
5455 return bus_log_create_error(r);
5457 r = sd_bus_message_append(m, "ssbb", target, unit_dependency_to_string(dep), arg_runtime, arg_force);
5459 return bus_log_create_error(r);
5461 r = sd_bus_call(bus, m, 0, &error, &reply);
5463 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5467 r = deserialize_and_dump_unit_file_changes(reply);
5472 r = daemon_reload(bus, args);
5480 static int preset_all(sd_bus *bus, char **args) {
5481 UnitFileChange *changes = NULL;
5482 unsigned n_changes = 0;
5485 if (!bus || avoid_bus()) {
5487 r = unit_file_preset_all(arg_scope, arg_runtime, arg_root, arg_preset_mode, arg_force, &changes, &n_changes);
5489 log_error("Operation failed: %s", strerror(-r));
5494 dump_unit_file_changes(changes, n_changes);
5499 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
5500 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5502 r = sd_bus_message_new_method_call(
5505 "org.freedesktop.systemd1",
5506 "/org/freedesktop/systemd1",
5507 "org.freedesktop.systemd1.Manager",
5508 "PresetAllUnitFiles");
5510 return bus_log_create_error(r);
5512 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5514 return bus_log_create_error(r);
5516 r = sd_bus_message_append(
5519 unit_file_preset_mode_to_string(arg_preset_mode),
5523 return bus_log_create_error(r);
5525 r = sd_bus_call(bus, m, 0, &error, &reply);
5527 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5531 r = deserialize_and_dump_unit_file_changes(reply);
5536 r = daemon_reload(bus, args);
5542 unit_file_changes_free(changes, n_changes);
5547 static int unit_is_enabled(sd_bus *bus, char **args) {
5549 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5550 _cleanup_strv_free_ char **names = NULL;
5555 r = mangle_names(args+1, &names);
5559 r = enable_sysv_units(args[0], names);
5565 if (!bus || avoid_bus()) {
5567 STRV_FOREACH(name, names) {
5568 UnitFileState state;
5570 state = unit_file_get_state(arg_scope, arg_root, *name);
5572 log_error("Failed to get unit file state for %s: %s", *name, strerror(-state));
5576 if (state == UNIT_FILE_ENABLED ||
5577 state == UNIT_FILE_ENABLED_RUNTIME ||
5578 state == UNIT_FILE_STATIC)
5582 puts(unit_file_state_to_string(state));
5586 STRV_FOREACH(name, names) {
5587 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5590 r = sd_bus_call_method(
5592 "org.freedesktop.systemd1",
5593 "/org/freedesktop/systemd1",
5594 "org.freedesktop.systemd1.Manager",
5600 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5604 r = sd_bus_message_read(reply, "s", &s);
5606 return bus_log_parse_error(r);
5608 if (streq(s, "enabled") ||
5609 streq(s, "enabled-runtime") ||
5621 static int is_system_running(sd_bus *bus, char **args) {
5622 _cleanup_free_ char *state = NULL;
5625 r = sd_bus_get_property_string(
5627 "org.freedesktop.systemd1",
5628 "/org/freedesktop/systemd1",
5629 "org.freedesktop.systemd1.Manager",
5642 return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE;
5645 static void systemctl_help(void) {
5647 pager_open_if_enabled();
5649 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
5650 "Query or send control commands to the systemd manager.\n\n"
5651 " -h --help Show this help\n"
5652 " --version Show package version\n"
5653 " --system Connect to system manager\n"
5654 " --user Connect to user service manager\n"
5655 " -H --host=[USER@]HOST\n"
5656 " Operate on remote host\n"
5657 " -M --machine=CONTAINER\n"
5658 " Operate on local container\n"
5659 " -t --type=TYPE List only units of a particular type\n"
5660 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
5661 " -p --property=NAME Show only properties by this name\n"
5662 " -a --all Show all loaded units/properties, including dead/empty\n"
5663 " ones. To list all units installed on the system, use\n"
5664 " the 'list-unit-files' command instead.\n"
5665 " -l --full Don't ellipsize unit names on output\n"
5666 " -r --recursive Show unit list of host and local containers\n"
5667 " --reverse Show reverse dependencies with 'list-dependencies'\n"
5668 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
5669 " queueing a new job\n"
5670 " --show-types When showing sockets, explicitly show their type\n"
5671 " -i --ignore-inhibitors\n"
5672 " When shutting down or sleeping, ignore inhibitors\n"
5673 " --kill-who=WHO Who to send signal to\n"
5674 " -s --signal=SIGNAL Which signal to send\n"
5675 " -q --quiet Suppress output\n"
5676 " --no-block Do not wait until operation finished\n"
5677 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5678 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
5680 " --no-legend Do not print a legend (column headers and hints)\n"
5681 " --no-pager Do not pipe output into a pager\n"
5682 " --no-ask-password\n"
5683 " Do not ask for system passwords\n"
5684 " --global Enable/disable unit files globally\n"
5685 " --runtime Enable unit files only temporarily until next reboot\n"
5686 " -f --force When enabling unit files, override existing symlinks\n"
5687 " When shutting down, execute action immediately\n"
5688 " --preset-mode= Specifies whether fully apply presets, or only enable,\n"
5689 " or only disable\n"
5690 " --root=PATH Enable unit files in the specified root directory\n"
5691 " -n --lines=INTEGER Number of journal entries to show\n"
5692 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
5693 " verbose, export, json, json-pretty, json-sse, cat)\n"
5694 " --plain Print unit dependencies as a list instead of a tree\n\n"
5696 " list-units [PATTERN...] List loaded units\n"
5697 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
5698 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
5699 " start NAME... Start (activate) one or more units\n"
5700 " stop NAME... Stop (deactivate) one or more units\n"
5701 " reload NAME... Reload one or more units\n"
5702 " restart NAME... Start or restart one or more units\n"
5703 " try-restart NAME... Restart one or more units if active\n"
5704 " reload-or-restart NAME... Reload one or more units if possible,\n"
5705 " otherwise start or restart\n"
5706 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
5707 " otherwise restart if active\n"
5708 " isolate NAME Start one unit and stop all others\n"
5709 " kill NAME... Send signal to processes of a unit\n"
5710 " is-active PATTERN... Check whether units are active\n"
5711 " is-failed PATTERN... Check whether units are failed\n"
5712 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
5713 " show [PATTERN...|JOB...] Show properties of one or more\n"
5714 " units/jobs or the manager\n"
5715 " cat PATTERN... Show files and drop-ins of one or more units\n"
5716 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
5717 " help PATTERN...|PID... Show manual for one or more units\n"
5718 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
5720 " list-dependencies [NAME] Recursively show units which are required\n"
5721 " or wanted by this unit or by which this\n"
5722 " unit is required or wanted\n\n"
5723 "Unit File Commands:\n"
5724 " list-unit-files [PATTERN...] List installed unit files\n"
5725 " enable NAME... Enable one or more unit files\n"
5726 " disable NAME... Disable one or more unit files\n"
5727 " reenable NAME... Reenable one or more unit files\n"
5728 " preset NAME... Enable/disable one or more unit files\n"
5729 " based on preset configuration\n"
5730 " preset-all Enable/disable all unit files based on\n"
5731 " preset configuration\n"
5732 " is-enabled NAME... Check whether unit files are enabled\n\n"
5733 " mask NAME... Mask one or more units\n"
5734 " unmask NAME... Unmask one or more units\n"
5735 " link PATH... Link one or more units files into\n"
5736 " the search path\n"
5737 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
5738 " on specified one or more units\n"
5739 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
5740 " on specified one or more units\n"
5741 " get-default Get the name of the default target\n"
5742 " set-default NAME Set the default target\n\n"
5743 "Machine Commands:\n"
5744 " list-machines [PATTERN...] List local containers and host\n\n"
5746 " list-jobs [PATTERN...] List jobs\n"
5747 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
5748 "Snapshot Commands:\n"
5749 " snapshot [NAME] Create a snapshot\n"
5750 " delete NAME... Remove one or more snapshots\n\n"
5751 "Environment Commands:\n"
5752 " show-environment Dump environment\n"
5753 " set-environment NAME=VALUE... Set one or more environment variables\n"
5754 " unset-environment NAME... Unset one or more environment variables\n"
5755 " import-environment NAME... Import all, one or more environment variables\n\n"
5756 "Manager Lifecycle Commands:\n"
5757 " daemon-reload Reload systemd manager configuration\n"
5758 " daemon-reexec Reexecute systemd manager\n\n"
5759 "System Commands:\n"
5760 " is-system-running Check whether system is fully running\n"
5761 " default Enter system default mode\n"
5762 " rescue Enter system rescue mode\n"
5763 " emergency Enter system emergency mode\n"
5764 " halt Shut down and halt the system\n"
5765 " poweroff Shut down and power-off the system\n"
5766 " reboot [ARG] Shut down and reboot the system\n"
5767 " kexec Shut down and reboot the system with kexec\n"
5768 " exit Request user instance exit\n"
5769 " switch-root ROOT [INIT] Change to a different root file system\n"
5770 " suspend Suspend the system\n"
5771 " hibernate Hibernate the system\n"
5772 " hybrid-sleep Hibernate and suspend the system\n",
5773 program_invocation_short_name);
5776 static void halt_help(void) {
5777 printf("%s [OPTIONS...]%s\n\n"
5778 "%s the system.\n\n"
5779 " --help Show this help\n"
5780 " --halt Halt the machine\n"
5781 " -p --poweroff Switch off the machine\n"
5782 " --reboot Reboot the machine\n"
5783 " -f --force Force immediate halt/power-off/reboot\n"
5784 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
5785 " -d --no-wtmp Don't write wtmp record\n"
5786 " --no-wall Don't send wall message before halt/power-off/reboot\n",
5787 program_invocation_short_name,
5788 arg_action == ACTION_REBOOT ? " [ARG]" : "",
5789 arg_action == ACTION_REBOOT ? "Reboot" :
5790 arg_action == ACTION_POWEROFF ? "Power off" :
5794 static void shutdown_help(void) {
5795 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
5796 "Shut down the system.\n\n"
5797 " --help Show this help\n"
5798 " -H --halt Halt the machine\n"
5799 " -P --poweroff Power-off the machine\n"
5800 " -r --reboot Reboot the machine\n"
5801 " -h Equivalent to --poweroff, overridden by --halt\n"
5802 " -k Don't halt/power-off/reboot, just send warnings\n"
5803 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5804 " -c Cancel a pending shutdown\n",
5805 program_invocation_short_name);
5808 static void telinit_help(void) {
5809 printf("%s [OPTIONS...] {COMMAND}\n\n"
5810 "Send control commands to the init daemon.\n\n"
5811 " --help Show this help\n"
5812 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
5814 " 0 Power-off the machine\n"
5815 " 6 Reboot the machine\n"
5816 " 2, 3, 4, 5 Start runlevelX.target unit\n"
5817 " 1, s, S Enter rescue mode\n"
5818 " q, Q Reload init daemon configuration\n"
5819 " u, U Reexecute init daemon\n",
5820 program_invocation_short_name);
5823 static void runlevel_help(void) {
5824 printf("%s [OPTIONS...]\n\n"
5825 "Prints the previous and current runlevel of the init system.\n\n"
5826 " --help Show this help\n",
5827 program_invocation_short_name);
5830 static void help_types(void) {
5835 puts("Available unit types:");
5836 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
5837 t = unit_type_to_string(i);
5843 static int systemctl_parse_argv(int argc, char *argv[]) {
5852 ARG_IGNORE_DEPENDENCIES,
5864 ARG_NO_ASK_PASSWORD,
5874 static const struct option options[] = {
5875 { "help", no_argument, NULL, 'h' },
5876 { "version", no_argument, NULL, ARG_VERSION },
5877 { "type", required_argument, NULL, 't' },
5878 { "property", required_argument, NULL, 'p' },
5879 { "all", no_argument, NULL, 'a' },
5880 { "reverse", no_argument, NULL, ARG_REVERSE },
5881 { "after", no_argument, NULL, ARG_AFTER },
5882 { "before", no_argument, NULL, ARG_BEFORE },
5883 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
5884 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
5885 { "full", no_argument, NULL, 'l' },
5886 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
5887 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
5888 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
5889 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
5890 { "ignore-inhibitors", no_argument, NULL, 'i' },
5891 { "user", no_argument, NULL, ARG_USER },
5892 { "system", no_argument, NULL, ARG_SYSTEM },
5893 { "global", no_argument, NULL, ARG_GLOBAL },
5894 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
5895 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
5896 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
5897 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5898 { "quiet", no_argument, NULL, 'q' },
5899 { "root", required_argument, NULL, ARG_ROOT },
5900 { "force", no_argument, NULL, ARG_FORCE },
5901 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
5902 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
5903 { "signal", required_argument, NULL, 's' },
5904 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
5905 { "host", required_argument, NULL, 'H' },
5906 { "machine", required_argument, NULL, 'M' },
5907 { "runtime", no_argument, NULL, ARG_RUNTIME },
5908 { "lines", required_argument, NULL, 'n' },
5909 { "output", required_argument, NULL, 'o' },
5910 { "plain", no_argument, NULL, ARG_PLAIN },
5911 { "state", required_argument, NULL, ARG_STATE },
5912 { "recursive", no_argument, NULL, 'r' },
5913 { "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
5922 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
5931 puts(PACKAGE_STRING);
5932 puts(SYSTEMD_FEATURES);
5936 const char *word, *state;
5939 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5940 _cleanup_free_ char *type;
5942 type = strndup(word, size);
5946 if (streq(type, "help")) {
5951 if (unit_type_from_string(type) >= 0) {
5952 if (strv_push(&arg_types, type))
5958 /* It's much nicer to use --state= for
5959 * load states, but let's support this
5960 * in --types= too for compatibility
5961 * with old versions */
5962 if (unit_load_state_from_string(optarg) >= 0) {
5963 if (strv_push(&arg_states, type) < 0)
5969 log_error("Unknown unit type or load state '%s'.", type);
5970 log_info("Use -t help to see a list of allowed values.");
5978 /* Make sure that if the empty property list
5979 was specified, we won't show any properties. */
5980 if (isempty(optarg) && !arg_properties) {
5981 arg_properties = new0(char*, 1);
5982 if (!arg_properties)
5985 const char *word, *state;
5988 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5991 prop = strndup(word, size);
5995 if (strv_consume(&arg_properties, prop) < 0)
6000 /* If the user asked for a particular
6001 * property, show it to him, even if it is
6013 arg_dependency = DEPENDENCY_REVERSE;
6017 arg_dependency = DEPENDENCY_AFTER;
6021 arg_dependency = DEPENDENCY_BEFORE;
6024 case ARG_SHOW_TYPES:
6025 arg_show_types = true;
6029 arg_job_mode = optarg;
6033 arg_job_mode = "fail";
6036 case ARG_IRREVERSIBLE:
6037 arg_job_mode = "replace-irreversibly";
6040 case ARG_IGNORE_DEPENDENCIES:
6041 arg_job_mode = "ignore-dependencies";
6045 arg_scope = UNIT_FILE_USER;
6049 arg_scope = UNIT_FILE_SYSTEM;
6053 arg_scope = UNIT_FILE_GLOBAL;
6057 arg_no_block = true;
6061 arg_no_legend = true;
6065 arg_no_pager = true;
6081 if (strv_extend(&arg_states, "failed") < 0)
6099 arg_no_reload = true;
6103 arg_kill_who = optarg;
6107 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
6108 log_error("Failed to parse signal string %s.", optarg);
6113 case ARG_NO_ASK_PASSWORD:
6114 arg_ask_password = false;
6118 arg_transport = BUS_TRANSPORT_REMOTE;
6123 arg_transport = BUS_TRANSPORT_CONTAINER;
6132 if (safe_atou(optarg, &arg_lines) < 0) {
6133 log_error("Failed to parse lines '%s'", optarg);
6139 arg_output = output_mode_from_string(optarg);
6140 if (arg_output < 0) {
6141 log_error("Unknown output '%s'.", optarg);
6147 arg_ignore_inhibitors = true;
6155 const char *word, *state;
6158 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6161 s = strndup(word, size);
6165 if (strv_consume(&arg_states, s) < 0)
6172 if (geteuid() != 0) {
6173 log_error("--recursive requires root privileges.");
6177 arg_recursive = true;
6180 case ARG_PRESET_MODE:
6182 arg_preset_mode = unit_file_preset_mode_from_string(optarg);
6183 if (arg_preset_mode < 0) {
6184 log_error("Failed to parse preset mode: %s.", optarg);
6194 assert_not_reached("Unhandled option");
6197 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
6198 log_error("Cannot access user instance remotely.");
6205 static int halt_parse_argv(int argc, char *argv[]) {
6214 static const struct option options[] = {
6215 { "help", no_argument, NULL, ARG_HELP },
6216 { "halt", no_argument, NULL, ARG_HALT },
6217 { "poweroff", no_argument, NULL, 'p' },
6218 { "reboot", no_argument, NULL, ARG_REBOOT },
6219 { "force", no_argument, NULL, 'f' },
6220 { "wtmp-only", no_argument, NULL, 'w' },
6221 { "no-wtmp", no_argument, NULL, 'd' },
6222 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6231 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
6232 if (runlevel == '0' || runlevel == '6')
6235 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
6243 arg_action = ACTION_HALT;
6247 if (arg_action != ACTION_REBOOT)
6248 arg_action = ACTION_POWEROFF;
6252 arg_action = ACTION_REBOOT;
6274 /* Compatibility nops */
6281 assert_not_reached("Unhandled option");
6284 if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
6285 r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL);
6288 } else if (optind < argc) {
6289 log_error("Too many arguments.");
6296 static int parse_time_spec(const char *t, usec_t *_u) {
6300 if (streq(t, "now"))
6302 else if (!strchr(t, ':')) {
6305 if (safe_atou64(t, &u) < 0)
6308 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
6317 hour = strtol(t, &e, 10);
6318 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
6321 minute = strtol(e+1, &e, 10);
6322 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
6325 n = now(CLOCK_REALTIME);
6326 s = (time_t) (n / USEC_PER_SEC);
6328 assert_se(localtime_r(&s, &tm));
6330 tm.tm_hour = (int) hour;
6331 tm.tm_min = (int) minute;
6334 assert_se(s = mktime(&tm));
6336 *_u = (usec_t) s * USEC_PER_SEC;
6339 *_u += USEC_PER_DAY;
6345 static int shutdown_parse_argv(int argc, char *argv[]) {
6352 static const struct option options[] = {
6353 { "help", no_argument, NULL, ARG_HELP },
6354 { "halt", no_argument, NULL, 'H' },
6355 { "poweroff", no_argument, NULL, 'P' },
6356 { "reboot", no_argument, NULL, 'r' },
6357 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
6358 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6367 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0)
6375 arg_action = ACTION_HALT;
6379 arg_action = ACTION_POWEROFF;
6384 arg_action = ACTION_KEXEC;
6386 arg_action = ACTION_REBOOT;
6390 arg_action = ACTION_KEXEC;
6394 if (arg_action != ACTION_HALT)
6395 arg_action = ACTION_POWEROFF;
6408 /* Compatibility nops */
6412 arg_action = ACTION_CANCEL_SHUTDOWN;
6419 assert_not_reached("Unhandled option");
6422 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
6423 r = parse_time_spec(argv[optind], &arg_when);
6425 log_error("Failed to parse time specification: %s", argv[optind]);
6429 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
6431 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
6432 /* No time argument for shutdown cancel */
6433 arg_wall = argv + optind;
6434 else if (argc > optind + 1)
6435 /* We skip the time argument */
6436 arg_wall = argv + optind + 1;
6443 static int telinit_parse_argv(int argc, char *argv[]) {
6450 static const struct option options[] = {
6451 { "help", no_argument, NULL, ARG_HELP },
6452 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6456 static const struct {
6460 { '0', ACTION_POWEROFF },
6461 { '6', ACTION_REBOOT },
6462 { '1', ACTION_RESCUE },
6463 { '2', ACTION_RUNLEVEL2 },
6464 { '3', ACTION_RUNLEVEL3 },
6465 { '4', ACTION_RUNLEVEL4 },
6466 { '5', ACTION_RUNLEVEL5 },
6467 { 's', ACTION_RESCUE },
6468 { 'S', ACTION_RESCUE },
6469 { 'q', ACTION_RELOAD },
6470 { 'Q', ACTION_RELOAD },
6471 { 'u', ACTION_REEXEC },
6472 { 'U', ACTION_REEXEC }
6481 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6496 assert_not_reached("Unhandled option");
6499 if (optind >= argc) {
6500 log_error("%s: required argument missing.",
6501 program_invocation_short_name);
6505 if (optind + 1 < argc) {
6506 log_error("Too many arguments.");
6510 if (strlen(argv[optind]) != 1) {
6511 log_error("Expected single character argument.");
6515 for (i = 0; i < ELEMENTSOF(table); i++)
6516 if (table[i].from == argv[optind][0])
6519 if (i >= ELEMENTSOF(table)) {
6520 log_error("Unknown command '%s'.", argv[optind]);
6524 arg_action = table[i].to;
6531 static int runlevel_parse_argv(int argc, char *argv[]) {
6537 static const struct option options[] = {
6538 { "help", no_argument, NULL, ARG_HELP },
6547 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6558 assert_not_reached("Unhandled option");
6561 if (optind < argc) {
6562 log_error("Too many arguments.");
6569 static int parse_argv(int argc, char *argv[]) {
6573 if (program_invocation_short_name) {
6575 if (strstr(program_invocation_short_name, "halt")) {
6576 arg_action = ACTION_HALT;
6577 return halt_parse_argv(argc, argv);
6578 } else if (strstr(program_invocation_short_name, "poweroff")) {
6579 arg_action = ACTION_POWEROFF;
6580 return halt_parse_argv(argc, argv);
6581 } else if (strstr(program_invocation_short_name, "reboot")) {
6583 arg_action = ACTION_KEXEC;
6585 arg_action = ACTION_REBOOT;
6586 return halt_parse_argv(argc, argv);
6587 } else if (strstr(program_invocation_short_name, "shutdown")) {
6588 arg_action = ACTION_POWEROFF;
6589 return shutdown_parse_argv(argc, argv);
6590 } else if (strstr(program_invocation_short_name, "init")) {
6592 if (sd_booted() > 0) {
6593 arg_action = _ACTION_INVALID;
6594 return telinit_parse_argv(argc, argv);
6596 /* Hmm, so some other init system is
6597 * running, we need to forward this
6598 * request to it. For now we simply
6599 * guess that it is Upstart. */
6601 execv(TELINIT, argv);
6603 log_error("Couldn't find an alternative telinit implementation to spawn.");
6607 } else if (strstr(program_invocation_short_name, "runlevel")) {
6608 arg_action = ACTION_RUNLEVEL;
6609 return runlevel_parse_argv(argc, argv);
6613 arg_action = ACTION_SYSTEMCTL;
6614 return systemctl_parse_argv(argc, argv);
6617 _pure_ static int action_to_runlevel(void) {
6619 static const char table[_ACTION_MAX] = {
6620 [ACTION_HALT] = '0',
6621 [ACTION_POWEROFF] = '0',
6622 [ACTION_REBOOT] = '6',
6623 [ACTION_RUNLEVEL2] = '2',
6624 [ACTION_RUNLEVEL3] = '3',
6625 [ACTION_RUNLEVEL4] = '4',
6626 [ACTION_RUNLEVEL5] = '5',
6627 [ACTION_RESCUE] = '1'
6630 assert(arg_action < _ACTION_MAX);
6632 return table[arg_action];
6635 static int talk_initctl(void) {
6637 struct init_request request = {
6638 .magic = INIT_MAGIC,
6640 .cmd = INIT_CMD_RUNLVL
6643 _cleanup_close_ int fd = -1;
6647 rl = action_to_runlevel();
6651 request.runlevel = rl;
6653 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
6655 if (errno == ENOENT)
6658 log_error("Failed to open "INIT_FIFO": %m");
6663 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
6665 log_error("Failed to write to "INIT_FIFO": %m");
6666 return errno > 0 ? -errno : -EIO;
6672 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
6674 static const struct {
6682 int (* const dispatch)(sd_bus *bus, char **args);
6688 { "list-units", MORE, 0, list_units },
6689 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
6690 { "list-sockets", MORE, 1, list_sockets },
6691 { "list-timers", MORE, 1, list_timers },
6692 { "list-jobs", MORE, 1, list_jobs },
6693 { "list-machines", MORE, 1, list_machines },
6694 { "clear-jobs", EQUAL, 1, daemon_reload },
6695 { "cancel", MORE, 2, cancel_job },
6696 { "start", MORE, 2, start_unit },
6697 { "stop", MORE, 2, start_unit },
6698 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6699 { "reload", MORE, 2, start_unit },
6700 { "restart", MORE, 2, start_unit },
6701 { "try-restart", MORE, 2, start_unit },
6702 { "reload-or-restart", MORE, 2, start_unit },
6703 { "reload-or-try-restart", MORE, 2, start_unit },
6704 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
6705 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6706 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
6707 { "isolate", EQUAL, 2, start_unit },
6708 { "kill", MORE, 2, kill_unit },
6709 { "is-active", MORE, 2, check_unit_active },
6710 { "check", MORE, 2, check_unit_active },
6711 { "is-failed", MORE, 2, check_unit_failed },
6712 { "show", MORE, 1, show },
6713 { "cat", MORE, 2, cat },
6714 { "status", MORE, 1, show },
6715 { "help", MORE, 2, show },
6716 { "snapshot", LESS, 2, snapshot },
6717 { "delete", MORE, 2, delete_snapshot },
6718 { "daemon-reload", EQUAL, 1, daemon_reload },
6719 { "daemon-reexec", EQUAL, 1, daemon_reload },
6720 { "show-environment", EQUAL, 1, show_environment },
6721 { "set-environment", MORE, 2, set_environment },
6722 { "unset-environment", MORE, 2, set_environment },
6723 { "import-environment", MORE, 1, import_environment},
6724 { "halt", EQUAL, 1, start_special, FORCE },
6725 { "poweroff", EQUAL, 1, start_special, FORCE },
6726 { "reboot", EQUAL, 1, start_special, FORCE },
6727 { "kexec", EQUAL, 1, start_special },
6728 { "suspend", EQUAL, 1, start_special },
6729 { "hibernate", EQUAL, 1, start_special },
6730 { "hybrid-sleep", EQUAL, 1, start_special },
6731 { "default", EQUAL, 1, start_special },
6732 { "rescue", EQUAL, 1, start_special },
6733 { "emergency", EQUAL, 1, start_special },
6734 { "exit", EQUAL, 1, start_special },
6735 { "reset-failed", MORE, 1, reset_failed },
6736 { "enable", MORE, 2, enable_unit, NOBUS },
6737 { "disable", MORE, 2, enable_unit, NOBUS },
6738 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
6739 { "reenable", MORE, 2, enable_unit, NOBUS },
6740 { "preset", MORE, 2, enable_unit, NOBUS },
6741 { "preset-all", EQUAL, 1, preset_all, NOBUS },
6742 { "mask", MORE, 2, enable_unit, NOBUS },
6743 { "unmask", MORE, 2, enable_unit, NOBUS },
6744 { "link", MORE, 2, enable_unit, NOBUS },
6745 { "switch-root", MORE, 2, switch_root },
6746 { "list-dependencies", LESS, 2, list_dependencies },
6747 { "set-default", EQUAL, 2, set_default, NOBUS },
6748 { "get-default", EQUAL, 1, get_default, NOBUS },
6749 { "set-property", MORE, 3, set_property },
6750 { "is-system-running", EQUAL, 1, is_system_running },
6751 { "add-wants", MORE, 3, add_dependency, NOBUS },
6752 { "add-requires", MORE, 3, add_dependency, NOBUS },
6761 left = argc - optind;
6763 /* Special rule: no arguments (left == 0) means "list-units" */
6765 if (streq(argv[optind], "help") && !argv[optind+1]) {
6766 log_error("This command expects one or more "
6767 "unit names. Did you mean --help?");
6771 for (; verb->verb; verb++)
6772 if (streq(argv[optind], verb->verb))
6775 log_error("Unknown operation '%s'.", argv[optind]);
6780 switch (verb->argc_cmp) {
6783 if (left != verb->argc) {
6784 log_error("Invalid number of arguments.");
6791 if (left < verb->argc) {
6792 log_error("Too few arguments.");
6799 if (left > verb->argc) {
6800 log_error("Too many arguments.");
6807 assert_not_reached("Unknown comparison operator.");
6810 /* Require a bus connection for all operations but
6812 if (verb->bus == NOBUS) {
6813 if (!bus && !avoid_bus()) {
6814 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6819 if (running_in_chroot() > 0) {
6820 log_info("Running in chroot, ignoring request.");
6824 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
6825 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6830 return verb->dispatch(bus, argv + optind);
6833 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
6835 struct sd_shutdown_command c = {
6842 union sockaddr_union sockaddr = {
6843 .un.sun_family = AF_UNIX,
6844 .un.sun_path = "/run/systemd/shutdownd",
6847 struct iovec iovec[2] = {{
6848 .iov_base = (char*) &c,
6849 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
6852 struct msghdr msghdr = {
6853 .msg_name = &sockaddr,
6854 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
6855 + strlen("/run/systemd/shutdownd"),
6860 _cleanup_close_ int fd;
6862 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
6866 if (!isempty(message)) {
6867 iovec[1].iov_base = (char*) message;
6868 iovec[1].iov_len = strlen(message);
6869 msghdr.msg_iovlen++;
6872 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
6878 static int reload_with_fallback(sd_bus *bus) {
6881 /* First, try systemd via D-Bus. */
6882 if (daemon_reload(bus, NULL) >= 0)
6886 /* Nothing else worked, so let's try signals */
6887 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
6889 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
6890 log_error("kill() failed: %m");
6897 static int start_with_fallback(sd_bus *bus) {
6900 /* First, try systemd via D-Bus. */
6901 if (start_unit(bus, NULL) >= 0)
6905 /* Nothing else worked, so let's try
6907 if (talk_initctl() > 0)
6910 log_error("Failed to talk to init daemon.");
6914 warn_wall(arg_action);
6918 static int halt_now(enum action a) {
6920 /* Make sure C-A-D is handled by the kernel from this
6922 reboot(RB_ENABLE_CAD);
6927 log_info("Halting.");
6928 reboot(RB_HALT_SYSTEM);
6931 case ACTION_POWEROFF:
6932 log_info("Powering off.");
6933 reboot(RB_POWER_OFF);
6936 case ACTION_REBOOT: {
6937 _cleanup_free_ char *param = NULL;
6939 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
6940 log_info("Rebooting with argument '%s'.", param);
6941 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
6942 LINUX_REBOOT_CMD_RESTART2, param);
6945 log_info("Rebooting.");
6946 reboot(RB_AUTOBOOT);
6951 assert_not_reached("Unknown action.");
6955 static int halt_main(sd_bus *bus) {
6958 r = check_inhibitors(bus, arg_action);
6962 if (geteuid() != 0) {
6963 /* Try logind if we are a normal user and no special
6964 * mode applies. Maybe PolicyKit allows us to shutdown
6967 if (arg_when <= 0 &&
6970 (arg_action == ACTION_POWEROFF ||
6971 arg_action == ACTION_REBOOT)) {
6972 r = reboot_with_logind(bus, arg_action);
6977 log_error("Must be root.");
6982 _cleanup_free_ char *m;
6984 m = strv_join(arg_wall, " ");
6988 r = send_shutdownd(arg_when,
6989 arg_action == ACTION_HALT ? 'H' :
6990 arg_action == ACTION_POWEROFF ? 'P' :
6991 arg_action == ACTION_KEXEC ? 'K' :
6998 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
7000 char date[FORMAT_TIMESTAMP_MAX];
7002 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
7003 format_timestamp(date, sizeof(date), arg_when));
7008 if (!arg_dry && !arg_force)
7009 return start_with_fallback(bus);
7012 if (sd_booted() > 0)
7013 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7015 r = utmp_put_shutdown();
7017 log_warning("Failed to write utmp record: %s", strerror(-r));
7024 r = halt_now(arg_action);
7025 log_error("Failed to reboot: %s", strerror(-r));
7030 static int runlevel_main(void) {
7031 int r, runlevel, previous;
7033 r = utmp_get_runlevel(&runlevel, &previous);
7040 previous <= 0 ? 'N' : previous,
7041 runlevel <= 0 ? 'N' : runlevel);
7046 int main(int argc, char*argv[]) {
7047 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
7050 setlocale(LC_ALL, "");
7051 log_parse_environment();
7054 /* Explicitly not on_tty() to avoid setting cached value.
7055 * This becomes relevant for piping output which might be
7057 original_stdout_is_tty = isatty(STDOUT_FILENO);
7059 r = parse_argv(argc, argv);
7063 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
7064 * let's shortcut this */
7065 if (arg_action == ACTION_RUNLEVEL) {
7066 r = runlevel_main();
7070 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
7071 log_info("Running in chroot, ignoring request.");
7077 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
7079 /* systemctl_main() will print an error message for the bus
7080 * connection, but only if it needs to */
7082 switch (arg_action) {
7084 case ACTION_SYSTEMCTL:
7085 r = systemctl_main(bus, argc, argv, r);
7089 case ACTION_POWEROFF:
7095 case ACTION_RUNLEVEL2:
7096 case ACTION_RUNLEVEL3:
7097 case ACTION_RUNLEVEL4:
7098 case ACTION_RUNLEVEL5:
7100 case ACTION_EMERGENCY:
7101 case ACTION_DEFAULT:
7102 r = start_with_fallback(bus);
7107 r = reload_with_fallback(bus);
7110 case ACTION_CANCEL_SHUTDOWN: {
7111 _cleanup_free_ char *m = NULL;
7114 m = strv_join(arg_wall, " ");
7121 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
7123 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
7127 case ACTION_RUNLEVEL:
7128 case _ACTION_INVALID:
7130 assert_not_reached("Unknown action");
7135 ask_password_agent_close();
7136 polkit_agent_close();
7138 strv_free(arg_types);
7139 strv_free(arg_states);
7140 strv_free(arg_properties);
7142 return r < 0 ? EXIT_FAILURE : r;