1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Marc-Antoine Perennou
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/reboot.h>
24 #include <linux/reboot.h>
25 #include <sys/syscall.h>
32 #include <sys/ioctl.h>
36 #include <sys/socket.h>
39 #include <sys/prctl.h>
42 #include "sd-daemon.h"
43 #include "sd-shutdown.h"
50 #include "utmp-wtmp.h"
53 #include "path-util.h"
55 #include "cgroup-show.h"
56 #include "cgroup-util.h"
58 #include "path-lookup.h"
59 #include "conf-parser.h"
60 #include "exit-status.h"
62 #include "unit-name.h"
64 #include "spawn-ask-password-agent.h"
65 #include "spawn-polkit-agent.h"
67 #include "logs-show.h"
68 #include "socket-util.h"
73 #include "bus-message.h"
74 #include "bus-error.h"
75 #include "bus-common-errors.h"
79 static char **arg_types = NULL;
80 static char **arg_states = NULL;
81 static char **arg_properties = NULL;
82 static bool arg_all = false;
83 static enum dependency {
89 } arg_dependency = DEPENDENCY_FORWARD;
90 static const char *arg_job_mode = "replace";
91 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
92 static bool arg_no_block = false;
93 static bool arg_no_legend = false;
94 static bool arg_no_pager = false;
95 static bool arg_no_wtmp = false;
96 static bool arg_no_wall = false;
97 static bool arg_no_reload = false;
98 static bool arg_show_types = false;
99 static bool arg_ignore_inhibitors = false;
100 static bool arg_dry = false;
101 static bool arg_quiet = false;
102 static bool arg_full = false;
103 static bool arg_recursive = false;
104 static int arg_force = 0;
105 static bool arg_ask_password = true;
106 static bool arg_runtime = false;
107 static UnitFilePresetMode arg_preset_mode = UNIT_FILE_PRESET_FULL;
108 static char **arg_wall = NULL;
109 static const char *arg_kill_who = NULL;
110 static int arg_signal = SIGTERM;
111 static const char *arg_root = NULL;
112 static usec_t arg_when = 0;
134 ACTION_CANCEL_SHUTDOWN,
136 } arg_action = ACTION_SYSTEMCTL;
137 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
138 static char *arg_host = NULL;
139 static unsigned arg_lines = 10;
140 static OutputMode arg_output = OUTPUT_SHORT;
141 static bool arg_plain = false;
143 static bool original_stdout_is_tty;
145 static int daemon_reload(sd_bus *bus, char **args);
146 static int halt_now(enum action a);
147 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet);
149 static char** strv_skip_first(char **strv) {
150 if (strv_length(strv) > 0)
155 static void pager_open_if_enabled(void) {
163 static void ask_password_agent_open_if_enabled(void) {
165 /* Open the password agent as a child process if necessary */
167 if (!arg_ask_password)
170 if (arg_scope != UNIT_FILE_SYSTEM)
173 if (arg_transport != BUS_TRANSPORT_LOCAL)
176 ask_password_agent_open();
180 static void polkit_agent_open_if_enabled(void) {
182 /* Open the polkit agent as a child process if necessary */
184 if (!arg_ask_password)
187 if (arg_scope != UNIT_FILE_SYSTEM)
190 if (arg_transport != BUS_TRANSPORT_LOCAL)
197 static OutputFlags get_output_flags(void) {
199 arg_all * OUTPUT_SHOW_ALL |
200 arg_full * OUTPUT_FULL_WIDTH |
201 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
202 on_tty() * OUTPUT_COLOR |
203 !arg_quiet * OUTPUT_WARN_CUTOFF;
206 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
209 if (!sd_bus_error_is_set(error))
212 if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) ||
213 sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
214 sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
215 sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
216 return EXIT_NOPERMISSION;
218 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
219 return EXIT_NOTINSTALLED;
221 if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
222 sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED))
223 return EXIT_NOTIMPLEMENTED;
225 if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
226 return EXIT_NOTCONFIGURED;
234 static void warn_wall(enum action a) {
235 static const char *table[_ACTION_MAX] = {
236 [ACTION_HALT] = "The system is going down for system halt NOW!",
237 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
238 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
239 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
240 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
241 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
242 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
249 _cleanup_free_ char *p;
251 p = strv_join(arg_wall, " ");
258 utmp_wall(p, NULL, NULL);
266 utmp_wall(table[a], NULL, NULL);
269 static bool avoid_bus(void) {
271 if (running_in_chroot() > 0)
274 if (sd_booted() <= 0)
277 if (!isempty(arg_root))
280 if (arg_scope == UNIT_FILE_GLOBAL)
286 static int compare_unit_info(const void *a, const void *b) {
287 const UnitInfo *u = a, *v = b;
291 /* First, order by machine */
292 if (!u->machine && v->machine)
294 if (u->machine && !v->machine)
296 if (u->machine && v->machine) {
297 r = strcasecmp(u->machine, v->machine);
302 /* Second, order by unit type */
303 d1 = strrchr(u->id, '.');
304 d2 = strrchr(v->id, '.');
306 r = strcasecmp(d1, d2);
311 /* Third, order by name */
312 return strcasecmp(u->id, v->id);
315 static bool output_show_unit(const UnitInfo *u, char **patterns) {
316 if (!strv_isempty(patterns)) {
319 STRV_FOREACH(pattern, patterns)
320 if (fnmatch(*pattern, u->id, FNM_NOESCAPE) == 0)
329 dot = strrchr(u->id, '.');
333 if (!strv_find(arg_types, dot+1))
343 if (streq(u->active_state, "inactive") || u->following[0])
349 static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
350 unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
352 unsigned n_shown = 0;
355 max_id_len = strlen("UNIT");
356 load_len = strlen("LOAD");
357 active_len = strlen("ACTIVE");
358 sub_len = strlen("SUB");
359 job_len = strlen("JOB");
362 for (u = unit_infos; u < unit_infos + c; u++) {
363 max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0));
364 load_len = MAX(load_len, strlen(u->load_state));
365 active_len = MAX(active_len, strlen(u->active_state));
366 sub_len = MAX(sub_len, strlen(u->sub_state));
368 if (u->job_id != 0) {
369 job_len = MAX(job_len, strlen(u->job_type));
373 if (!arg_no_legend &&
374 (streq(u->active_state, "failed") ||
375 STR_IN_SET(u->load_state, "error", "not-found", "masked")))
379 if (!arg_full && original_stdout_is_tty) {
382 id_len = MIN(max_id_len, 25u);
383 basic_len = circle_len + 5 + id_len + 5 + active_len + sub_len;
386 basic_len += job_len + 1;
388 if (basic_len < (unsigned) columns()) {
389 unsigned extra_len, incr;
390 extra_len = columns() - basic_len;
392 /* Either UNIT already got 25, or is fully satisfied.
393 * Grant up to 25 to DESC now. */
394 incr = MIN(extra_len, 25u);
398 /* split the remaining space between UNIT and DESC,
399 * but do not give UNIT more than it needs. */
401 incr = MIN(extra_len / 2, max_id_len - id_len);
403 desc_len += extra_len - incr;
409 for (u = unit_infos; u < unit_infos + c; u++) {
410 _cleanup_free_ char *e = NULL, *j = NULL;
411 const char *on_loaded = "", *off_loaded = "";
412 const char *on_active = "", *off_active = "";
413 const char *on_circle = "", *off_circle = "";
417 if (!n_shown && !arg_no_legend) {
422 printf("%-*s %-*s %-*s %-*s ",
425 active_len, "ACTIVE",
429 printf("%-*s ", job_len, "JOB");
431 if (!arg_full && arg_no_pager)
432 printf("%.*s\n", desc_len, "DESCRIPTION");
434 printf("%s\n", "DESCRIPTION");
439 if (STR_IN_SET(u->load_state, "error", "not-found", "masked")) {
440 on_loaded = ansi_highlight_red();
441 on_circle = ansi_highlight_yellow();
442 off_loaded = off_circle = ansi_highlight_off();
446 if (streq(u->active_state, "failed")) {
447 on_circle = on_active = ansi_highlight_red();
448 off_circle = off_active = ansi_highlight_off();
453 j = strjoin(u->machine, ":", u->id, NULL);
462 e = ellipsize(id, id_len, 33);
470 printf("%s%s%s ", on_circle, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_circle);
472 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
473 on_active, id_len, id, off_active,
474 on_loaded, load_len, u->load_state, off_loaded,
475 on_active, active_len, u->active_state,
476 sub_len, u->sub_state, off_active,
477 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
480 printf("%.*s\n", desc_len, u->description);
482 printf("%s\n", u->description);
485 if (!arg_no_legend) {
486 const char *on, *off;
490 "LOAD = Reflects whether the unit definition was properly loaded.\n"
491 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
492 "SUB = The low-level unit activation state, values depend on unit type.");
493 puts(job_count ? "JOB = Pending job for the unit.\n" : "");
494 on = ansi_highlight();
495 off = ansi_highlight_off();
497 on = ansi_highlight_red();
498 off = ansi_highlight_off();
502 printf("%s%u loaded units listed.%s\n"
503 "To show all installed unit files use 'systemctl list-unit-files'.\n",
506 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
507 "To show all installed unit files use 'systemctl list-unit-files'.\n",
514 static int get_unit_list(
518 UnitInfo **unit_infos,
520 sd_bus_message **_reply) {
522 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
523 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
524 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
533 r = sd_bus_message_new_method_call(
536 "org.freedesktop.systemd1",
537 "/org/freedesktop/systemd1",
538 "org.freedesktop.systemd1.Manager",
539 "ListUnitsFiltered");
542 return bus_log_create_error(r);
544 r = sd_bus_message_append_strv(m, arg_states);
546 return bus_log_create_error(r);
548 r = sd_bus_call(bus, m, 0, &error, &reply);
550 log_error("Failed to list units: %s", bus_error_message(&error, r));
554 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
556 return bus_log_parse_error(r);
558 while ((r = bus_parse_unit_info(reply, &u)) > 0) {
561 if (!output_show_unit(&u, patterns))
564 if (!GREEDY_REALLOC(*unit_infos, size, c+1))
567 (*unit_infos)[c++] = u;
570 return bus_log_parse_error(r);
572 r = sd_bus_message_exit_container(reply);
574 return bus_log_parse_error(r);
582 static void message_set_freep(Set **set) {
585 while ((m = set_steal_first(*set)))
586 sd_bus_message_unref(m);
591 static int get_unit_list_recursive(
594 UnitInfo **_unit_infos,
598 _cleanup_free_ UnitInfo *unit_infos = NULL;
599 _cleanup_(message_set_freep) Set *replies;
600 sd_bus_message *reply;
608 replies = set_new(NULL);
612 c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
616 r = set_put(replies, reply);
618 sd_bus_message_unref(reply);
623 _cleanup_strv_free_ char **machines = NULL;
626 r = sd_get_machine_names(&machines);
630 STRV_FOREACH(i, machines) {
631 _cleanup_bus_close_unref_ sd_bus *container = NULL;
634 r = sd_bus_open_system_machine(&container, *i);
636 log_error_errno(r, "Failed to connect to container %s: %m", *i);
640 k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
646 r = set_put(replies, reply);
648 sd_bus_message_unref(reply);
653 *_machines = machines;
658 *_unit_infos = unit_infos;
667 static int list_units(sd_bus *bus, char **args) {
668 _cleanup_free_ UnitInfo *unit_infos = NULL;
669 _cleanup_(message_set_freep) Set *replies = NULL;
670 _cleanup_strv_free_ char **machines = NULL;
673 pager_open_if_enabled();
675 r = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
679 qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
680 return output_units_list(unit_infos, r);
683 static int get_triggered_units(
688 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
691 r = sd_bus_get_property_strv(
693 "org.freedesktop.systemd1",
695 "org.freedesktop.systemd1.Unit",
701 log_error("Failed to determine triggers: %s", bus_error_message(&error, r));
706 static int get_listening(
708 const char* unit_path,
711 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
712 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
713 const char *type, *path;
716 r = sd_bus_get_property(
718 "org.freedesktop.systemd1",
720 "org.freedesktop.systemd1.Socket",
726 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r));
730 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
732 return bus_log_parse_error(r);
734 while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
736 r = strv_extend(listening, type);
740 r = strv_extend(listening, path);
747 return bus_log_parse_error(r);
749 r = sd_bus_message_exit_container(reply);
751 return bus_log_parse_error(r);
763 /* Note: triggered is a list here, although it almost certainly
764 * will always be one unit. Nevertheless, dbus API allows for multiple
765 * values, so let's follow that. */
768 /* The strv above is shared. free is set only in the first one. */
772 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
778 if (!a->machine && b->machine)
780 if (a->machine && !b->machine)
782 if (a->machine && b->machine) {
783 o = strcasecmp(a->machine, b->machine);
788 o = strcmp(a->path, b->path);
790 o = strcmp(a->type, b->type);
795 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
796 struct socket_info *s;
797 unsigned pathlen = strlen("LISTEN"),
798 typelen = strlen("TYPE") * arg_show_types,
799 socklen = strlen("UNIT"),
800 servlen = strlen("ACTIVATES");
801 const char *on, *off;
803 for (s = socket_infos; s < socket_infos + cs; s++) {
807 socklen = MAX(socklen, strlen(s->id));
809 typelen = MAX(typelen, strlen(s->type));
810 pathlen = MAX(pathlen, strlen(s->path) + (s->machine ? strlen(s->machine)+1 : 0));
812 STRV_FOREACH(a, s->triggered)
813 tmp += strlen(*a) + 2*(a != s->triggered);
814 servlen = MAX(servlen, tmp);
819 printf("%-*s %-*.*s%-*s %s\n",
821 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
825 for (s = socket_infos; s < socket_infos + cs; s++) {
826 _cleanup_free_ char *j = NULL;
831 j = strjoin(s->machine, ":", s->path, NULL);
839 printf("%-*s %-*s %-*s",
840 pathlen, path, typelen, s->type, socklen, s->id);
843 pathlen, path, socklen, s->id);
844 STRV_FOREACH(a, s->triggered)
846 a == s->triggered ? "" : ",", *a);
850 on = ansi_highlight();
851 off = ansi_highlight_off();
855 on = ansi_highlight_red();
856 off = ansi_highlight_off();
859 if (!arg_no_legend) {
860 printf("%s%u sockets listed.%s\n", on, cs, off);
862 printf("Pass --all to see loaded but inactive sockets, too.\n");
868 static int list_sockets(sd_bus *bus, char **args) {
869 _cleanup_(message_set_freep) Set *replies = NULL;
870 _cleanup_strv_free_ char **machines = NULL;
871 _cleanup_free_ UnitInfo *unit_infos = NULL;
872 _cleanup_free_ struct socket_info *socket_infos = NULL;
874 struct socket_info *s;
879 pager_open_if_enabled();
881 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
885 for (u = unit_infos; u < unit_infos + n; u++) {
886 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
889 if (!endswith(u->id, ".socket"))
892 r = get_triggered_units(bus, u->unit_path, &triggered);
896 c = get_listening(bus, u->unit_path, &listening);
902 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
907 for (i = 0; i < c; i++)
908 socket_infos[cs + i] = (struct socket_info) {
909 .machine = u->machine,
911 .type = listening[i*2],
912 .path = listening[i*2 + 1],
913 .triggered = triggered,
914 .own_triggered = i==0,
917 /* from this point on we will cleanup those socket_infos */
920 listening = triggered = NULL; /* avoid cleanup */
923 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
924 (__compar_fn_t) socket_info_compare);
926 output_sockets_list(socket_infos, cs);
929 assert(cs == 0 || socket_infos);
930 for (s = socket_infos; s < socket_infos + cs; s++) {
933 if (s->own_triggered)
934 strv_free(s->triggered);
940 static int get_next_elapse(
943 dual_timestamp *next) {
945 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
953 r = sd_bus_get_property_trivial(
955 "org.freedesktop.systemd1",
957 "org.freedesktop.systemd1.Timer",
958 "NextElapseUSecMonotonic",
963 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
967 r = sd_bus_get_property_trivial(
969 "org.freedesktop.systemd1",
971 "org.freedesktop.systemd1.Timer",
972 "NextElapseUSecRealtime",
977 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
985 static int get_last_trigger(
990 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
997 r = sd_bus_get_property_trivial(
999 "org.freedesktop.systemd1",
1001 "org.freedesktop.systemd1.Timer",
1007 log_error("Failed to get last trigger time: %s", bus_error_message(&error, r));
1015 const char* machine;
1018 usec_t last_trigger;
1022 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
1028 if (!a->machine && b->machine)
1030 if (a->machine && !b->machine)
1032 if (a->machine && b->machine) {
1033 o = strcasecmp(a->machine, b->machine);
1038 if (a->next_elapse < b->next_elapse)
1040 if (a->next_elapse > b->next_elapse)
1043 return strcmp(a->id, b->id);
1046 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
1047 struct timer_info *t;
1049 nextlen = strlen("NEXT"),
1050 leftlen = strlen("LEFT"),
1051 lastlen = strlen("LAST"),
1052 passedlen = strlen("PASSED"),
1053 unitlen = strlen("UNIT"),
1054 activatelen = strlen("ACTIVATES");
1056 const char *on, *off;
1058 assert(timer_infos || n == 0);
1060 for (t = timer_infos; t < timer_infos + n; t++) {
1064 if (t->next_elapse > 0) {
1065 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1067 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
1068 nextlen = MAX(nextlen, strlen(tstamp) + 1);
1070 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
1071 leftlen = MAX(leftlen, strlen(trel));
1074 if (t->last_trigger > 0) {
1075 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1077 format_timestamp(tstamp, sizeof(tstamp), t->last_trigger);
1078 lastlen = MAX(lastlen, strlen(tstamp) + 1);
1080 format_timestamp_relative(trel, sizeof(trel), t->last_trigger);
1081 passedlen = MAX(passedlen, strlen(trel));
1084 unitlen = MAX(unitlen, strlen(t->id) + (t->machine ? strlen(t->machine)+1 : 0));
1086 STRV_FOREACH(a, t->triggered)
1087 ul += strlen(*a) + 2*(a != t->triggered);
1089 activatelen = MAX(activatelen, ul);
1094 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1098 passedlen, "PASSED",
1102 for (t = timer_infos; t < timer_infos + n; t++) {
1103 _cleanup_free_ char *j = NULL;
1105 char tstamp1[FORMAT_TIMESTAMP_MAX] = "n/a", trel1[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1106 char tstamp2[FORMAT_TIMESTAMP_MAX] = "n/a", trel2[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1109 format_timestamp(tstamp1, sizeof(tstamp1), t->next_elapse);
1110 format_timestamp_relative(trel1, sizeof(trel1), t->next_elapse);
1112 format_timestamp(tstamp2, sizeof(tstamp2), t->last_trigger);
1113 format_timestamp_relative(trel2, sizeof(trel2), t->last_trigger);
1116 j = strjoin(t->machine, ":", t->id, NULL);
1123 printf("%-*s %-*s %-*s %-*s %-*s",
1124 nextlen, tstamp1, leftlen, trel1, lastlen, tstamp2, passedlen, trel2, unitlen, unit);
1126 STRV_FOREACH(a, t->triggered)
1128 a == t->triggered ? "" : ",", *a);
1132 on = ansi_highlight();
1133 off = ansi_highlight_off();
1137 on = ansi_highlight_red();
1138 off = ansi_highlight_off();
1141 if (!arg_no_legend) {
1142 printf("%s%u timers listed.%s\n", on, n, off);
1144 printf("Pass --all to see loaded but inactive timers, too.\n");
1150 static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
1156 if (next->monotonic != USEC_INFINITY && next->monotonic > 0) {
1159 if (next->monotonic > nw->monotonic)
1160 converted = nw->realtime + (next->monotonic - nw->monotonic);
1162 converted = nw->realtime - (nw->monotonic - next->monotonic);
1164 if (next->realtime != USEC_INFINITY && next->realtime > 0)
1165 next_elapse = MIN(converted, next->realtime);
1167 next_elapse = converted;
1170 next_elapse = next->realtime;
1175 static int list_timers(sd_bus *bus, char **args) {
1176 _cleanup_(message_set_freep) Set *replies = NULL;
1177 _cleanup_strv_free_ char **machines = NULL;
1178 _cleanup_free_ struct timer_info *timer_infos = NULL;
1179 _cleanup_free_ UnitInfo *unit_infos = NULL;
1180 struct timer_info *t;
1187 pager_open_if_enabled();
1189 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
1193 dual_timestamp_get(&nw);
1195 for (u = unit_infos; u < unit_infos + n; u++) {
1196 _cleanup_strv_free_ char **triggered = NULL;
1197 dual_timestamp next = {};
1200 if (!endswith(u->id, ".timer"))
1203 r = get_triggered_units(bus, u->unit_path, &triggered);
1207 r = get_next_elapse(bus, u->unit_path, &next);
1211 get_last_trigger(bus, u->unit_path, &last);
1213 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
1218 m = calc_next_elapse(&nw, &next);
1220 timer_infos[c++] = (struct timer_info) {
1221 .machine = u->machine,
1224 .last_trigger = last,
1225 .triggered = triggered,
1228 triggered = NULL; /* avoid cleanup */
1231 qsort_safe(timer_infos, c, sizeof(struct timer_info),
1232 (__compar_fn_t) timer_info_compare);
1234 output_timers_list(timer_infos, c);
1237 for (t = timer_infos; t < timer_infos + c; t++)
1238 strv_free(t->triggered);
1243 static int compare_unit_file_list(const void *a, const void *b) {
1244 const char *d1, *d2;
1245 const UnitFileList *u = a, *v = b;
1247 d1 = strrchr(u->path, '.');
1248 d2 = strrchr(v->path, '.');
1253 r = strcasecmp(d1, d2);
1258 return strcasecmp(basename(u->path), basename(v->path));
1261 static bool output_show_unit_file(const UnitFileList *u, char **patterns) {
1262 if (!strv_isempty(patterns)) {
1265 STRV_FOREACH(pattern, patterns)
1266 if (fnmatch(*pattern, basename(u->path), FNM_NOESCAPE) == 0)
1272 if (!strv_isempty(arg_types)) {
1275 dot = strrchr(u->path, '.');
1279 if (!strv_find(arg_types, dot+1))
1283 if (!strv_isempty(arg_states)) {
1284 if (!strv_find(arg_states, unit_file_state_to_string(u->state)))
1291 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
1292 unsigned max_id_len, id_cols, state_cols;
1293 const UnitFileList *u;
1295 max_id_len = strlen("UNIT FILE");
1296 state_cols = strlen("STATE");
1298 for (u = units; u < units + c; u++) {
1299 max_id_len = MAX(max_id_len, strlen(basename(u->path)));
1300 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1304 unsigned basic_cols;
1306 id_cols = MIN(max_id_len, 25u);
1307 basic_cols = 1 + id_cols + state_cols;
1308 if (basic_cols < (unsigned) columns())
1309 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1311 id_cols = max_id_len;
1314 printf("%-*s %-*s\n",
1315 id_cols, "UNIT FILE",
1316 state_cols, "STATE");
1318 for (u = units; u < units + c; u++) {
1319 _cleanup_free_ char *e = NULL;
1320 const char *on, *off;
1323 if (u->state == UNIT_FILE_MASKED ||
1324 u->state == UNIT_FILE_MASKED_RUNTIME ||
1325 u->state == UNIT_FILE_DISABLED ||
1326 u->state == UNIT_FILE_INVALID) {
1327 on = ansi_highlight_red();
1328 off = ansi_highlight_off();
1329 } else if (u->state == UNIT_FILE_ENABLED) {
1330 on = ansi_highlight_green();
1331 off = ansi_highlight_off();
1335 id = basename(u->path);
1337 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1339 printf("%-*s %s%-*s%s\n",
1340 id_cols, e ? e : id,
1341 on, state_cols, unit_file_state_to_string(u->state), off);
1345 printf("\n%u unit files listed.\n", c);
1348 static int list_unit_files(sd_bus *bus, char **args) {
1349 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1350 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1351 _cleanup_free_ UnitFileList *units = NULL;
1359 pager_open_if_enabled();
1367 h = hashmap_new(&string_hash_ops);
1371 r = unit_file_get_list(arg_scope, arg_root, h);
1373 unit_file_list_free(h);
1374 log_error_errno(r, "Failed to get unit file list: %m");
1378 n_units = hashmap_size(h);
1380 units = new(UnitFileList, n_units);
1381 if (!units && n_units > 0) {
1382 unit_file_list_free(h);
1386 HASHMAP_FOREACH(u, h, i) {
1387 if (!output_show_unit_file(u, strv_skip_first(args)))
1394 assert(c <= n_units);
1397 r = sd_bus_call_method(
1399 "org.freedesktop.systemd1",
1400 "/org/freedesktop/systemd1",
1401 "org.freedesktop.systemd1.Manager",
1407 log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1411 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1413 return bus_log_parse_error(r);
1415 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1417 if (!GREEDY_REALLOC(units, size, c + 1))
1420 units[c] = (struct UnitFileList) {
1422 unit_file_state_from_string(state)
1425 if (output_show_unit_file(&units[c], strv_skip_first(args)))
1430 return bus_log_parse_error(r);
1432 r = sd_bus_message_exit_container(reply);
1434 return bus_log_parse_error(r);
1437 qsort_safe(units, c, sizeof(UnitFileList), compare_unit_file_list);
1438 output_unit_file_list(units, c);
1441 for (unit = units; unit < units + c; unit++)
1448 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1449 _cleanup_free_ char *n = NULL;
1450 size_t max_len = MAX(columns(),20u);
1456 for (i = level - 1; i >= 0; i--) {
1458 if (len > max_len - 3 && !arg_full) {
1459 printf("%s...\n",max_len % 2 ? "" : " ");
1462 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERTICAL : DRAW_TREE_SPACE));
1466 if (len > max_len - 3 && !arg_full) {
1467 printf("%s...\n",max_len % 2 ? "" : " ");
1471 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
1475 printf("%s\n", name);
1479 n = ellipsize(name, max_len-len, 100);
1487 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1489 static const char *dependencies[_DEPENDENCY_MAX] = {
1490 [DEPENDENCY_FORWARD] = "Requires\0"
1491 "RequiresOverridable\0"
1493 "RequisiteOverridable\0"
1496 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1497 "RequiredByOverridable\0"
1501 [DEPENDENCY_AFTER] = "After\0",
1502 [DEPENDENCY_BEFORE] = "Before\0",
1505 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1506 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1507 _cleanup_strv_free_ char **ret = NULL;
1508 _cleanup_free_ char *path = NULL;
1514 assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
1516 path = unit_dbus_path_from_name(name);
1520 r = sd_bus_call_method(
1522 "org.freedesktop.systemd1",
1524 "org.freedesktop.DBus.Properties",
1528 "s", "org.freedesktop.systemd1.Unit");
1530 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1534 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1536 return bus_log_parse_error(r);
1538 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1541 r = sd_bus_message_read(reply, "s", &prop);
1543 return bus_log_parse_error(r);
1545 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1546 r = sd_bus_message_skip(reply, "v");
1548 return bus_log_parse_error(r);
1551 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1553 return bus_log_parse_error(r);
1555 r = bus_message_read_strv_extend(reply, &ret);
1557 return bus_log_parse_error(r);
1559 r = sd_bus_message_exit_container(reply);
1561 return bus_log_parse_error(r);
1564 r = sd_bus_message_exit_container(reply);
1566 return bus_log_parse_error(r);
1570 return bus_log_parse_error(r);
1572 r = sd_bus_message_exit_container(reply);
1574 return bus_log_parse_error(r);
1582 static int list_dependencies_compare(const void *_a, const void *_b) {
1583 const char **a = (const char**) _a, **b = (const char**) _b;
1585 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1587 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1590 return strcasecmp(*a, *b);
1593 static int list_dependencies_one(
1598 unsigned int branches) {
1600 _cleanup_strv_free_ char **deps = NULL;
1608 r = strv_extend(units, name);
1612 r = list_dependencies_get_dependencies(bus, name, &deps);
1616 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1618 STRV_FOREACH(c, deps) {
1621 if (strv_contains(*units, *c)) {
1623 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1630 state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true);
1632 printf("%s%s%s ", ansi_highlight_green(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1634 printf("%s%s%s ", ansi_highlight_red(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1636 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1640 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1641 r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1648 strv_remove(*units, name);
1653 static int list_dependencies(sd_bus *bus, char **args) {
1654 _cleanup_strv_free_ char **units = NULL;
1655 _cleanup_free_ char *unit = NULL;
1661 unit = unit_name_mangle(args[1], MANGLE_NOGLOB);
1666 u = SPECIAL_DEFAULT_TARGET;
1668 pager_open_if_enabled();
1672 return list_dependencies_one(bus, u, 0, &units, 0);
1675 struct machine_info {
1679 char *control_group;
1680 uint32_t n_failed_units;
1685 static const struct bus_properties_map machine_info_property_map[] = {
1686 { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
1687 { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
1688 { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
1689 { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
1690 { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
1694 static void free_machines_list(struct machine_info *machine_infos, int n) {
1700 for (i = 0; i < n; i++) {
1701 free(machine_infos[i].name);
1702 free(machine_infos[i].state);
1703 free(machine_infos[i].control_group);
1706 free(machine_infos);
1709 static int compare_machine_info(const void *a, const void *b) {
1710 const struct machine_info *u = a, *v = b;
1712 if (u->is_host != v->is_host)
1713 return u->is_host > v->is_host ? -1 : 1;
1715 return strcasecmp(u->name, v->name);
1718 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1719 _cleanup_bus_close_unref_ sd_bus *container = NULL;
1725 r = sd_bus_open_system_machine(&container, mi->name);
1732 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi);
1739 static bool output_show_machine(const char *name, char **patterns) {
1744 if (strv_isempty(patterns))
1747 STRV_FOREACH(i, patterns)
1748 if (fnmatch(*i, name, FNM_NOESCAPE) == 0)
1754 static int get_machine_list(
1756 struct machine_info **_machine_infos,
1759 struct machine_info *machine_infos = NULL;
1760 _cleanup_strv_free_ char **m = NULL;
1761 _cleanup_free_ char *hn = NULL;
1766 hn = gethostname_malloc();
1770 if (output_show_machine(hn, patterns)) {
1771 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1774 machine_infos[c].is_host = true;
1775 machine_infos[c].name = hn;
1778 get_machine_properties(bus, &machine_infos[c]);
1782 sd_get_machine_names(&m);
1783 STRV_FOREACH(i, m) {
1784 _cleanup_free_ char *class = NULL;
1786 if (!output_show_machine(*i, patterns))
1789 sd_machine_get_class(*i, &class);
1790 if (!streq_ptr(class, "container"))
1793 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1794 free_machines_list(machine_infos, c);
1798 machine_infos[c].is_host = false;
1799 machine_infos[c].name = strdup(*i);
1800 if (!machine_infos[c].name) {
1801 free_machines_list(machine_infos, c);
1805 get_machine_properties(NULL, &machine_infos[c]);
1809 *_machine_infos = machine_infos;
1813 static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1814 struct machine_info *m;
1817 namelen = sizeof("NAME") - 1,
1818 statelen = sizeof("STATE") - 1,
1819 failedlen = sizeof("FAILED") - 1,
1820 jobslen = sizeof("JOBS") - 1;
1822 assert(machine_infos || n == 0);
1824 for (m = machine_infos; m < machine_infos + n; m++) {
1825 namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
1826 statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
1827 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
1828 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
1830 if (!arg_no_legend && !streq_ptr(m->state, "running"))
1834 if (!arg_no_legend) {
1838 printf("%-*s %-*s %-*s %-*s\n",
1841 failedlen, "FAILED",
1845 for (m = machine_infos; m < machine_infos + n; m++) {
1846 const char *on_state = "", *off_state = "";
1847 const char *on_failed = "", *off_failed = "";
1848 bool circle = false;
1850 if (streq_ptr(m->state, "degraded")) {
1851 on_state = ansi_highlight_red();
1852 off_state = ansi_highlight_off();
1854 } else if (!streq_ptr(m->state, "running")) {
1855 on_state = ansi_highlight_yellow();
1856 off_state = ansi_highlight_off();
1860 if (m->n_failed_units > 0) {
1861 on_failed = ansi_highlight_red();
1862 off_failed = ansi_highlight_off();
1864 on_failed = off_failed = "";
1867 printf("%s%s%s ", on_state, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_state);
1870 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1871 (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
1872 on_state, statelen, strna(m->state), off_state,
1873 on_failed, failedlen, m->n_failed_units, off_failed,
1874 jobslen, m->n_jobs);
1876 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1877 namelen, strna(m->name),
1878 on_state, statelen, strna(m->state), off_state,
1879 on_failed, failedlen, m->n_failed_units, off_failed,
1880 jobslen, m->n_jobs);
1884 printf("\n%u machines listed.\n", n);
1887 static int list_machines(sd_bus *bus, char **args) {
1888 struct machine_info *machine_infos = NULL;
1893 if (geteuid() != 0) {
1894 log_error("Must be root.");
1898 pager_open_if_enabled();
1900 r = get_machine_list(bus, &machine_infos, strv_skip_first(args));
1904 qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
1905 output_machines_list(machine_infos, r);
1906 free_machines_list(machine_infos, r);
1911 static int get_default(sd_bus *bus, char **args) {
1912 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1913 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1914 _cleanup_free_ char *_path = NULL;
1918 if (!bus || avoid_bus()) {
1919 r = unit_file_get_default(arg_scope, arg_root, &_path);
1921 return log_error_errno(r, "Failed to get default target: %m");
1925 r = sd_bus_call_method(
1927 "org.freedesktop.systemd1",
1928 "/org/freedesktop/systemd1",
1929 "org.freedesktop.systemd1.Manager",
1935 log_error("Failed to get default target: %s", bus_error_message(&error, -r));
1939 r = sd_bus_message_read(reply, "s", &path);
1941 return bus_log_parse_error(r);
1945 printf("%s\n", path);
1950 static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) {
1953 assert(changes || n_changes == 0);
1955 for (i = 0; i < n_changes; i++) {
1956 if (changes[i].type == UNIT_FILE_SYMLINK)
1957 log_info("Created symlink from %s to %s.", changes[i].path, changes[i].source);
1959 log_info("Removed symlink %s.", changes[i].path);
1963 static int set_default(sd_bus *bus, char **args) {
1964 _cleanup_free_ char *unit = NULL;
1965 UnitFileChange *changes = NULL;
1966 unsigned n_changes = 0;
1969 unit = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
1973 if (!bus || avoid_bus()) {
1974 r = unit_file_set_default(arg_scope, arg_root, unit, true, &changes, &n_changes);
1976 return log_error_errno(r, "Failed to set default target: %m");
1979 dump_unit_file_changes(changes, n_changes);
1983 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1984 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1986 r = sd_bus_message_new_method_call(
1989 "org.freedesktop.systemd1",
1990 "/org/freedesktop/systemd1",
1991 "org.freedesktop.systemd1.Manager",
1992 "SetDefaultTarget");
1994 return bus_log_create_error(r);
1996 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
1998 return bus_log_create_error(r);
2000 r = sd_bus_message_append(m, "sb", unit, 1);
2002 return bus_log_create_error(r);
2004 r = sd_bus_call(bus, m, 0, &error, &reply);
2006 log_error("Failed to set default target: %s", bus_error_message(&error, -r));
2010 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
2014 /* Try to reload if enabled */
2016 r = daemon_reload(bus, args);
2021 unit_file_changes_free(changes, n_changes);
2028 const char *name, *type, *state;
2031 static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
2032 unsigned id_len, unit_len, type_len, state_len;
2033 const struct job_info *j;
2034 const char *on, *off;
2035 bool shorten = false;
2037 assert(n == 0 || jobs);
2040 on = ansi_highlight_green();
2041 off = ansi_highlight_off();
2043 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
2047 pager_open_if_enabled();
2049 id_len = strlen("JOB");
2050 unit_len = strlen("UNIT");
2051 type_len = strlen("TYPE");
2052 state_len = strlen("STATE");
2054 for (j = jobs; j < jobs + n; j++) {
2055 uint32_t id = j->id;
2056 assert(j->name && j->type && j->state);
2058 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
2059 unit_len = MAX(unit_len, strlen(j->name));
2060 type_len = MAX(type_len, strlen(j->type));
2061 state_len = MAX(state_len, strlen(j->state));
2064 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
2065 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
2070 printf("%*s %-*s %-*s %-*s\n",
2074 state_len, "STATE");
2076 for (j = jobs; j < jobs + n; j++) {
2077 _cleanup_free_ char *e = NULL;
2079 if (streq(j->state, "running")) {
2080 on = ansi_highlight();
2081 off = ansi_highlight_off();
2085 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
2086 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2088 on, unit_len, e ? e : j->name, off,
2090 on, state_len, j->state, off);
2093 if (!arg_no_legend) {
2094 on = ansi_highlight();
2095 off = ansi_highlight_off();
2097 printf("\n%s%u jobs listed%s.\n", on, n, off);
2101 static bool output_show_job(struct job_info *job, char **patterns) {
2106 if (strv_isempty(patterns))
2109 STRV_FOREACH(pattern, patterns)
2110 if (fnmatch(*pattern, job->name, FNM_NOESCAPE) == 0)
2115 static int list_jobs(sd_bus *bus, char **args) {
2116 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2117 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2118 const char *name, *type, *state, *job_path, *unit_path;
2119 _cleanup_free_ struct job_info *jobs = NULL;
2124 bool skipped = false;
2126 r = sd_bus_call_method(
2128 "org.freedesktop.systemd1",
2129 "/org/freedesktop/systemd1",
2130 "org.freedesktop.systemd1.Manager",
2136 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
2140 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2142 return bus_log_parse_error(r);
2144 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
2145 struct job_info job = { id, name, type, state };
2147 if (!output_show_job(&job, strv_skip_first(args))) {
2152 if (!GREEDY_REALLOC(jobs, size, c + 1))
2158 return bus_log_parse_error(r);
2160 r = sd_bus_message_exit_container(reply);
2162 return bus_log_parse_error(r);
2164 output_jobs_list(jobs, c, skipped);
2168 static int cancel_job(sd_bus *bus, char **args) {
2169 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2175 if (strv_length(args) <= 1)
2176 return daemon_reload(bus, args);
2178 STRV_FOREACH(name, args+1) {
2179 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2183 q = safe_atou32(*name, &id);
2185 return log_error_errno(q, "Failed to parse job id \"%s\": %m", *name);
2187 q = sd_bus_message_new_method_call(
2190 "org.freedesktop.systemd1",
2191 "/org/freedesktop/systemd1",
2192 "org.freedesktop.systemd1.Manager",
2195 return bus_log_create_error(q);
2197 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2199 return bus_log_create_error(1);
2201 q = sd_bus_message_append(m, "u", id);
2203 return bus_log_create_error(q);
2205 q = sd_bus_call(bus, m, 0, &error, NULL);
2207 log_error("Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, q));
2216 static int need_daemon_reload(sd_bus *bus, const char *unit) {
2217 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2221 /* We ignore all errors here, since this is used to show a
2224 /* We don't use unit_dbus_path_from_name() directly since we
2225 * don't want to load the unit if it isn't loaded. */
2227 r = sd_bus_call_method(
2229 "org.freedesktop.systemd1",
2230 "/org/freedesktop/systemd1",
2231 "org.freedesktop.systemd1.Manager",
2239 r = sd_bus_message_read(reply, "o", &path);
2243 r = sd_bus_get_property_trivial(
2245 "org.freedesktop.systemd1",
2247 "org.freedesktop.systemd1.Unit",
2257 static void warn_unit_file_changed(const char *name) {
2258 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2259 ansi_highlight_red(),
2260 ansi_highlight_off(),
2262 arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2265 static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **unit_path) {
2272 STRV_FOREACH(p, lp->unit_path) {
2273 _cleanup_free_ char *path;
2275 path = path_join(arg_root, *p, unit_name);
2279 if (access(path, F_OK) == 0) {
2289 static int unit_find_paths(sd_bus *bus,
2290 const char *unit_name,
2291 bool avoid_bus_cache,
2293 char **fragment_path,
2294 char ***dropin_paths) {
2298 * Finds where the unit is defined on disk. Returns 0 if the unit
2299 * is not found. Returns 1 if it is found, and sets
2300 * - the path to the unit in *path, if it exists on disk,
2301 * - and a strv of existing drop-ins in *dropins,
2302 * if the arg is not NULL and any dropins were found.
2306 assert(fragment_path);
2309 if (!avoid_bus_cache && !unit_name_is_template(unit_name)) {
2310 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2311 _cleanup_free_ char *unit = NULL;
2312 _cleanup_free_ char *path = NULL;
2313 _cleanup_strv_free_ char **dropins = NULL;
2315 unit = unit_dbus_path_from_name(unit_name);
2319 if (need_daemon_reload(bus, unit_name) > 0)
2320 warn_unit_file_changed(unit_name);
2322 r = sd_bus_get_property_string(
2324 "org.freedesktop.systemd1",
2326 "org.freedesktop.systemd1.Unit",
2331 return log_error_errno(r, "Failed to get FragmentPath: %s", bus_error_message(&error, r));
2333 r = sd_bus_get_property_strv(
2335 "org.freedesktop.systemd1",
2337 "org.freedesktop.systemd1.Unit",
2342 return log_error_errno(r, "Failed to get DropInPaths: %s", bus_error_message(&error, r));
2345 if (!isempty(path)) {
2346 *fragment_path = path;
2351 if (dropin_paths && !strv_isempty(dropins)) {
2352 *dropin_paths = dropins;
2357 _cleanup_set_free_ Set *names;
2359 names = set_new(NULL);
2363 r = set_put(names, unit_name);
2367 r = unit_file_find_path(lp, unit_name, fragment_path);
2372 _cleanup_free_ char *template;
2374 template = unit_name_template(unit_name);
2378 if (!streq(template, unit_name)) {
2379 r = unit_file_find_path(lp, template, fragment_path);
2386 r = unit_file_find_dropin_paths(lp->unit_path, NULL, names, dropin_paths);
2392 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2393 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2394 _cleanup_free_ char *n = NULL, *state = NULL;
2400 n = unit_name_mangle(name, MANGLE_NOGLOB);
2404 /* We don't use unit_dbus_path_from_name() directly since we
2405 * don't want to load the unit if it isn't loaded. */
2407 r = sd_bus_call_method(
2409 "org.freedesktop.systemd1",
2410 "/org/freedesktop/systemd1",
2411 "org.freedesktop.systemd1.Manager",
2422 r = sd_bus_message_read(reply, "o", &path);
2424 return bus_log_parse_error(r);
2426 r = sd_bus_get_property_string(
2428 "org.freedesktop.systemd1",
2430 "org.freedesktop.systemd1.Unit",
2443 return nulstr_contains(good_states, state);
2446 static int check_triggering_units(
2450 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2451 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2452 _cleanup_strv_free_ char **triggered_by = NULL;
2453 bool print_warning_label = true;
2457 n = unit_name_mangle(name, MANGLE_NOGLOB);
2461 path = unit_dbus_path_from_name(n);
2465 r = sd_bus_get_property_string(
2467 "org.freedesktop.systemd1",
2469 "org.freedesktop.systemd1.Unit",
2474 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2478 if (streq(state, "masked"))
2481 r = sd_bus_get_property_strv(
2483 "org.freedesktop.systemd1",
2485 "org.freedesktop.systemd1.Unit",
2490 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2494 STRV_FOREACH(i, triggered_by) {
2495 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2497 return log_error_errno(r, "Failed to check unit: %m");
2502 if (print_warning_label) {
2503 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2504 print_warning_label = false;
2507 log_warning(" %s", *i);
2513 static const struct {
2516 } unit_actions[] = {
2517 { "start", "StartUnit" },
2518 { "stop", "StopUnit" },
2519 { "condstop", "StopUnit" },
2520 { "reload", "ReloadUnit" },
2521 { "restart", "RestartUnit" },
2522 { "try-restart", "TryRestartUnit" },
2523 { "condrestart", "TryRestartUnit" },
2524 { "reload-or-restart", "ReloadOrRestartUnit" },
2525 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2526 { "condreload", "ReloadOrTryRestartUnit" },
2527 { "force-reload", "ReloadOrTryRestartUnit" }
2530 static const char *verb_to_method(const char *verb) {
2533 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2534 if (streq_ptr(unit_actions[i].verb, verb))
2535 return unit_actions[i].method;
2540 static const char *method_to_verb(const char *method) {
2543 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2544 if (streq_ptr(unit_actions[i].method, method))
2545 return unit_actions[i].verb;
2550 static int start_unit_one(
2555 sd_bus_error *error,
2556 BusWaitForJobs *w) {
2558 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2567 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2569 r = sd_bus_message_new_method_call(
2572 "org.freedesktop.systemd1",
2573 "/org/freedesktop/systemd1",
2574 "org.freedesktop.systemd1.Manager",
2577 return bus_log_create_error(r);
2579 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2581 return bus_log_create_error(r);
2583 r = sd_bus_message_append(m, "ss", name, mode);
2585 return bus_log_create_error(r);
2587 r = sd_bus_call(bus, m, 0, error, &reply);
2591 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2592 /* There's always a fallback possible for
2593 * legacy actions. */
2594 return -EADDRNOTAVAIL;
2596 verb = method_to_verb(method);
2598 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2602 r = sd_bus_message_read(reply, "o", &path);
2604 return bus_log_parse_error(r);
2606 if (need_daemon_reload(bus, name) > 0)
2607 warn_unit_file_changed(name);
2610 log_debug("Adding %s to the set", path);
2611 r = bus_wait_for_jobs_add(w, path);
2619 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2621 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2625 STRV_FOREACH(name, names) {
2629 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2631 t = unit_name_mangle(*name, MANGLE_GLOB);
2635 if (string_is_glob(t))
2636 r = strv_consume(&globs, t);
2638 r = strv_consume(&mangled, t);
2643 /* Query the manager only if any of the names are a glob, since
2644 * this is fairly expensive */
2645 if (!strv_isempty(globs)) {
2646 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2647 _cleanup_free_ UnitInfo *unit_infos = NULL;
2650 return log_error_errno(ENOTSUP, "Unit name globbing without bus is not implemented.");
2652 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2656 for (i = 0; i < r; i++)
2657 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2662 mangled = NULL; /* do not free */
2667 static const struct {
2671 } action_table[_ACTION_MAX] = {
2672 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2673 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2674 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2675 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2676 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
2677 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
2678 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
2679 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
2680 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2681 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2682 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2683 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2684 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2685 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2686 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2689 static enum action verb_to_action(const char *verb) {
2692 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2693 if (streq_ptr(action_table[i].verb, verb))
2696 return _ACTION_INVALID;
2699 static int start_unit(sd_bus *bus, char **args) {
2700 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
2701 const char *method, *mode, *one_name, *suffix = NULL;
2702 _cleanup_strv_free_ char **names = NULL;
2708 ask_password_agent_open_if_enabled();
2710 if (arg_action == ACTION_SYSTEMCTL) {
2712 method = verb_to_method(args[0]);
2713 action = verb_to_action(args[0]);
2715 if (streq(args[0], "isolate")) {
2719 mode = action_table[action].mode ?: arg_job_mode;
2721 one_name = action_table[action].target;
2723 assert(arg_action < ELEMENTSOF(action_table));
2724 assert(action_table[arg_action].target);
2726 method = "StartUnit";
2728 mode = action_table[arg_action].mode;
2729 one_name = action_table[arg_action].target;
2733 names = strv_new(one_name, NULL);
2735 r = expand_names(bus, args + 1, suffix, &names);
2737 log_error_errno(r, "Failed to expand names: %m");
2740 if (!arg_no_block) {
2741 r = bus_wait_for_jobs_new(bus, &w);
2743 return log_error_errno(r, "Could not watch jobs: %m");
2746 STRV_FOREACH(name, names) {
2747 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2750 q = start_unit_one(bus, method, *name, mode, &error, w);
2751 if (r >= 0 && q < 0)
2752 r = translate_bus_error_to_exit_status(q, &error);
2755 if (!arg_no_block) {
2758 q = bus_wait_for_jobs(w, arg_quiet);
2762 /* When stopping units, warn if they can still be triggered by
2763 * another active unit (socket, path, timer) */
2764 if (!arg_quiet && streq(method, "StopUnit"))
2765 STRV_FOREACH(name, names)
2766 check_triggering_units(bus, *name);
2772 /* Ask systemd-logind, which might grant access to unprivileged users
2773 * through PolicyKit */
2774 static int reboot_with_logind(sd_bus *bus, enum action a) {
2776 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2783 polkit_agent_open_if_enabled();
2791 case ACTION_POWEROFF:
2792 method = "PowerOff";
2795 case ACTION_SUSPEND:
2799 case ACTION_HIBERNATE:
2800 method = "Hibernate";
2803 case ACTION_HYBRID_SLEEP:
2804 method = "HybridSleep";
2811 r = sd_bus_call_method(
2813 "org.freedesktop.login1",
2814 "/org/freedesktop/login1",
2815 "org.freedesktop.login1.Manager",
2819 "b", arg_ask_password);
2821 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2829 static int check_inhibitors(sd_bus *bus, enum action a) {
2831 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2832 _cleanup_strv_free_ char **sessions = NULL;
2833 const char *what, *who, *why, *mode;
2842 if (arg_ignore_inhibitors || arg_force > 0)
2854 r = sd_bus_call_method(
2856 "org.freedesktop.login1",
2857 "/org/freedesktop/login1",
2858 "org.freedesktop.login1.Manager",
2864 /* If logind is not around, then there are no inhibitors... */
2867 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2869 return bus_log_parse_error(r);
2871 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2872 _cleanup_free_ char *comm = NULL, *user = NULL;
2873 _cleanup_strv_free_ char **sv = NULL;
2875 if (!streq(mode, "block"))
2878 sv = strv_split(what, ":");
2882 if (!strv_contains(sv,
2884 a == ACTION_POWEROFF ||
2885 a == ACTION_REBOOT ||
2886 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2889 get_process_comm(pid, &comm);
2890 user = uid_to_name(uid);
2892 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
2893 who, pid, strna(comm), strna(user), why);
2898 return bus_log_parse_error(r);
2900 r = sd_bus_message_exit_container(reply);
2902 return bus_log_parse_error(r);
2904 /* Check for current sessions */
2905 sd_get_sessions(&sessions);
2906 STRV_FOREACH(s, sessions) {
2907 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2909 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2912 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2915 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2918 sd_session_get_tty(*s, &tty);
2919 sd_session_get_seat(*s, &seat);
2920 sd_session_get_service(*s, &service);
2921 user = uid_to_name(uid);
2923 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2930 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2931 action_table[a].verb);
2939 static int start_special(sd_bus *bus, char **args) {
2945 a = verb_to_action(args[0]);
2947 r = check_inhibitors(bus, a);
2951 if (arg_force >= 2 && geteuid() != 0) {
2952 log_error("Must be root.");
2956 if (arg_force >= 2 &&
2957 (a == ACTION_HALT ||
2958 a == ACTION_POWEROFF ||
2959 a == ACTION_REBOOT))
2962 if (arg_force >= 1 &&
2963 (a == ACTION_HALT ||
2964 a == ACTION_POWEROFF ||
2965 a == ACTION_REBOOT ||
2966 a == ACTION_KEXEC ||
2968 return daemon_reload(bus, args);
2970 /* first try logind, to allow authentication with polkit */
2971 if (geteuid() != 0 &&
2972 (a == ACTION_POWEROFF ||
2973 a == ACTION_REBOOT ||
2974 a == ACTION_SUSPEND ||
2975 a == ACTION_HIBERNATE ||
2976 a == ACTION_HYBRID_SLEEP)) {
2977 r = reboot_with_logind(bus, a);
2978 if (r >= 0 || IN_SET(r, -ENOTSUP, -EINPROGRESS))
2982 r = start_unit(bus, args);
2983 if (r == EXIT_SUCCESS)
2989 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
2990 _cleanup_strv_free_ char **names = NULL;
2997 r = expand_names(bus, args, NULL, &names);
2999 return log_error_errno(r, "Failed to expand names: %m");
3001 STRV_FOREACH(name, names) {
3004 state = check_one_unit(bus, *name, good_states, arg_quiet);
3014 static int check_unit_active(sd_bus *bus, char **args) {
3015 /* According to LSB: 3, "program is not running" */
3016 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
3019 static int check_unit_failed(sd_bus *bus, char **args) {
3020 return check_unit_generic(bus, 1, "failed\0", args + 1);
3023 static int kill_unit(sd_bus *bus, char **args) {
3024 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3025 _cleanup_strv_free_ char **names = NULL;
3033 arg_kill_who = "all";
3035 r = expand_names(bus, args + 1, NULL, &names);
3037 log_error_errno(r, "Failed to expand names: %m");
3039 STRV_FOREACH(name, names) {
3040 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3042 q = sd_bus_message_new_method_call(
3045 "org.freedesktop.systemd1",
3046 "/org/freedesktop/systemd1",
3047 "org.freedesktop.systemd1.Manager",
3050 return bus_log_create_error(q);
3052 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
3054 return bus_log_create_error(q);
3056 q = sd_bus_message_append(m, "ssi", *names, arg_kill_who, arg_signal);
3058 return bus_log_create_error(q);
3060 q = sd_bus_call(bus, m, 0, &error, NULL);
3062 log_error("Failed to kill unit %s: %s", *names, bus_error_message(&error, q));
3071 typedef struct ExecStatusInfo {
3079 usec_t start_timestamp;
3080 usec_t exit_timestamp;
3085 LIST_FIELDS(struct ExecStatusInfo, exec);
3088 static void exec_status_info_free(ExecStatusInfo *i) {
3097 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3098 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3101 int32_t code, status;
3107 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3109 return bus_log_parse_error(r);
3113 r = sd_bus_message_read(m, "s", &path);
3115 return bus_log_parse_error(r);
3117 i->path = strdup(path);
3121 r = sd_bus_message_read_strv(m, &i->argv);
3123 return bus_log_parse_error(r);
3125 r = sd_bus_message_read(m,
3128 &start_timestamp, &start_timestamp_monotonic,
3129 &exit_timestamp, &exit_timestamp_monotonic,
3133 return bus_log_parse_error(r);
3136 i->start_timestamp = (usec_t) start_timestamp;
3137 i->exit_timestamp = (usec_t) exit_timestamp;
3138 i->pid = (pid_t) pid;
3142 r = sd_bus_message_exit_container(m);
3144 return bus_log_parse_error(r);
3149 typedef struct UnitStatusInfo {
3151 const char *load_state;
3152 const char *active_state;
3153 const char *sub_state;
3154 const char *unit_file_state;
3155 const char *unit_file_preset;
3157 const char *description;
3158 const char *following;
3160 char **documentation;