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) {
304 if (!strv_isempty(patterns)) {
307 STRV_FOREACH(pattern, patterns)
308 if (fnmatch(*pattern, u->id, FNM_NOESCAPE) == 0)
317 dot = strrchr(u->id, '.');
321 if (!strv_find(arg_types, dot+1))
331 if (streq(u->active_state, "inactive") || u->following[0])
337 static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
338 unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
340 unsigned n_shown = 0;
343 max_id_len = strlen("UNIT");
344 load_len = strlen("LOAD");
345 active_len = strlen("ACTIVE");
346 sub_len = strlen("SUB");
347 job_len = strlen("JOB");
350 for (u = unit_infos; u < unit_infos + c; u++) {
351 max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0));
352 load_len = MAX(load_len, strlen(u->load_state));
353 active_len = MAX(active_len, strlen(u->active_state));
354 sub_len = MAX(sub_len, strlen(u->sub_state));
356 if (u->job_id != 0) {
357 job_len = MAX(job_len, strlen(u->job_type));
361 if (!arg_no_legend &&
362 (streq(u->active_state, "failed") ||
363 STR_IN_SET(u->load_state, "error", "not-found", "masked")))
367 if (!arg_full && original_stdout_is_tty) {
370 id_len = MIN(max_id_len, 25u);
371 basic_len = circle_len + 5 + id_len + 5 + active_len + sub_len;
374 basic_len += job_len + 1;
376 if (basic_len < (unsigned) columns()) {
377 unsigned extra_len, incr;
378 extra_len = columns() - basic_len;
380 /* Either UNIT already got 25, or is fully satisfied.
381 * Grant up to 25 to DESC now. */
382 incr = MIN(extra_len, 25u);
386 /* split the remaining space between UNIT and DESC,
387 * but do not give UNIT more than it needs. */
389 incr = MIN(extra_len / 2, max_id_len - id_len);
391 desc_len += extra_len - incr;
397 for (u = unit_infos; u < unit_infos + c; u++) {
398 _cleanup_free_ char *e = NULL, *j = NULL;
399 const char *on_loaded = "", *off_loaded = "";
400 const char *on_active = "", *off_active = "";
401 const char *on_circle = "", *off_circle = "";
405 if (!n_shown && !arg_no_legend) {
410 printf("%-*s %-*s %-*s %-*s ",
413 active_len, "ACTIVE",
417 printf("%-*s ", job_len, "JOB");
419 if (!arg_full && arg_no_pager)
420 printf("%.*s\n", desc_len, "DESCRIPTION");
422 printf("%s\n", "DESCRIPTION");
427 if (STR_IN_SET(u->load_state, "error", "not-found", "masked")) {
428 on_loaded = ansi_highlight_red();
429 on_circle = ansi_highlight_yellow();
430 off_loaded = off_circle = ansi_highlight_off();
434 if (streq(u->active_state, "failed")) {
435 on_circle = on_active = ansi_highlight_red();
436 off_circle = off_active = ansi_highlight_off();
441 j = strjoin(u->machine, ":", u->id, NULL);
450 e = ellipsize(id, id_len, 33);
458 printf("%s%s%s ", on_circle, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_circle);
460 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
461 on_active, id_len, id, off_active,
462 on_loaded, load_len, u->load_state, off_loaded,
463 on_active, active_len, u->active_state,
464 sub_len, u->sub_state, off_active,
465 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
468 printf("%.*s\n", desc_len, u->description);
470 printf("%s\n", u->description);
473 if (!arg_no_legend) {
474 const char *on, *off;
478 "LOAD = Reflects whether the unit definition was properly loaded.\n"
479 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
480 "SUB = The low-level unit activation state, values depend on unit type.");
481 puts(job_count ? "JOB = Pending job for the unit.\n" : "");
482 on = ansi_highlight();
483 off = ansi_highlight_off();
485 on = ansi_highlight_red();
486 off = ansi_highlight_off();
490 printf("%s%u loaded units listed.%s\n"
491 "To show all installed unit files use 'systemctl list-unit-files'.\n",
494 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
495 "To show all installed unit files use 'systemctl list-unit-files'.\n",
502 static int get_unit_list(
506 UnitInfo **unit_infos,
508 sd_bus_message **_reply) {
510 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
511 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
512 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
521 r = sd_bus_message_new_method_call(
524 "org.freedesktop.systemd1",
525 "/org/freedesktop/systemd1",
526 "org.freedesktop.systemd1.Manager",
527 "ListUnitsFiltered");
530 return bus_log_create_error(r);
532 r = sd_bus_message_append_strv(m, arg_states);
534 return bus_log_create_error(r);
536 r = sd_bus_call(bus, m, 0, &error, &reply);
538 log_error("Failed to list units: %s", bus_error_message(&error, r));
542 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
544 return bus_log_parse_error(r);
546 while ((r = bus_parse_unit_info(reply, &u)) > 0) {
549 if (!output_show_unit(&u, patterns))
552 if (!GREEDY_REALLOC(*unit_infos, size, c+1))
555 (*unit_infos)[c++] = u;
558 return bus_log_parse_error(r);
560 r = sd_bus_message_exit_container(reply);
562 return bus_log_parse_error(r);
570 static void message_set_freep(Set **set) {
573 while ((m = set_steal_first(*set)))
574 sd_bus_message_unref(m);
579 static int get_unit_list_recursive(
582 UnitInfo **_unit_infos,
586 _cleanup_free_ UnitInfo *unit_infos = NULL;
587 _cleanup_(message_set_freep) Set *replies;
588 sd_bus_message *reply;
596 replies = set_new(NULL);
600 c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
604 r = set_put(replies, reply);
606 sd_bus_message_unref(reply);
611 _cleanup_strv_free_ char **machines = NULL;
614 r = sd_get_machine_names(&machines);
618 STRV_FOREACH(i, machines) {
619 _cleanup_bus_close_unref_ sd_bus *container = NULL;
622 r = sd_bus_open_system_container(&container, *i);
624 log_error("Failed to connect to container %s: %s", *i, strerror(-r));
628 k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
634 r = set_put(replies, reply);
636 sd_bus_message_unref(reply);
641 *_machines = machines;
646 *_unit_infos = unit_infos;
655 static int list_units(sd_bus *bus, char **args) {
656 _cleanup_free_ UnitInfo *unit_infos = NULL;
657 _cleanup_(message_set_freep) Set *replies = NULL;
658 _cleanup_strv_free_ char **machines = NULL;
661 pager_open_if_enabled();
663 r = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
667 qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
668 return output_units_list(unit_infos, r);
671 static int get_triggered_units(
676 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
679 r = sd_bus_get_property_strv(
681 "org.freedesktop.systemd1",
683 "org.freedesktop.systemd1.Unit",
689 log_error("Failed to determine triggers: %s", bus_error_message(&error, r));
694 static int get_listening(
696 const char* unit_path,
699 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
700 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
701 const char *type, *path;
704 r = sd_bus_get_property(
706 "org.freedesktop.systemd1",
708 "org.freedesktop.systemd1.Socket",
714 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r));
718 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
720 return bus_log_parse_error(r);
722 while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
724 r = strv_extend(listening, type);
728 r = strv_extend(listening, path);
735 return bus_log_parse_error(r);
737 r = sd_bus_message_exit_container(reply);
739 return bus_log_parse_error(r);
751 /* Note: triggered is a list here, although it almost certainly
752 * will always be one unit. Nevertheless, dbus API allows for multiple
753 * values, so let's follow that.*/
756 /* The strv above is shared. free is set only in the first one. */
760 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
766 if (!a->machine && b->machine)
768 if (a->machine && !b->machine)
770 if (a->machine && b->machine) {
771 o = strcasecmp(a->machine, b->machine);
776 o = strcmp(a->path, b->path);
778 o = strcmp(a->type, b->type);
783 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
784 struct socket_info *s;
785 unsigned pathlen = strlen("LISTEN"),
786 typelen = strlen("TYPE") * arg_show_types,
787 socklen = strlen("UNIT"),
788 servlen = strlen("ACTIVATES");
789 const char *on, *off;
791 for (s = socket_infos; s < socket_infos + cs; s++) {
795 socklen = MAX(socklen, strlen(s->id));
797 typelen = MAX(typelen, strlen(s->type));
798 pathlen = MAX(pathlen, strlen(s->path) + (s->machine ? strlen(s->machine)+1 : 0));
800 STRV_FOREACH(a, s->triggered)
801 tmp += strlen(*a) + 2*(a != s->triggered);
802 servlen = MAX(servlen, tmp);
807 printf("%-*s %-*.*s%-*s %s\n",
809 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
813 for (s = socket_infos; s < socket_infos + cs; s++) {
814 _cleanup_free_ char *j = NULL;
819 j = strjoin(s->machine, ":", s->path, NULL);
827 printf("%-*s %-*s %-*s",
828 pathlen, path, typelen, s->type, socklen, s->id);
831 pathlen, path, socklen, s->id);
832 STRV_FOREACH(a, s->triggered)
834 a == s->triggered ? "" : ",", *a);
838 on = ansi_highlight();
839 off = ansi_highlight_off();
843 on = ansi_highlight_red();
844 off = ansi_highlight_off();
847 if (!arg_no_legend) {
848 printf("%s%u sockets listed.%s\n", on, cs, off);
850 printf("Pass --all to see loaded but inactive sockets, too.\n");
856 static int list_sockets(sd_bus *bus, char **args) {
857 _cleanup_(message_set_freep) Set *replies = NULL;
858 _cleanup_strv_free_ char **machines = NULL;
859 _cleanup_free_ UnitInfo *unit_infos = NULL;
860 _cleanup_free_ struct socket_info *socket_infos = NULL;
862 struct socket_info *s;
867 pager_open_if_enabled();
869 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
873 for (u = unit_infos; u < unit_infos + n; u++) {
874 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
877 if (!endswith(u->id, ".socket"))
880 r = get_triggered_units(bus, u->unit_path, &triggered);
884 c = get_listening(bus, u->unit_path, &listening);
890 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
895 for (i = 0; i < c; i++)
896 socket_infos[cs + i] = (struct socket_info) {
897 .machine = u->machine,
899 .type = listening[i*2],
900 .path = listening[i*2 + 1],
901 .triggered = triggered,
902 .own_triggered = i==0,
905 /* from this point on we will cleanup those socket_infos */
908 listening = triggered = NULL; /* avoid cleanup */
911 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
912 (__compar_fn_t) socket_info_compare);
914 output_sockets_list(socket_infos, cs);
917 assert(cs == 0 || socket_infos);
918 for (s = socket_infos; s < socket_infos + cs; s++) {
921 if (s->own_triggered)
922 strv_free(s->triggered);
928 static int get_next_elapse(
931 dual_timestamp *next) {
933 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
941 r = sd_bus_get_property_trivial(
943 "org.freedesktop.systemd1",
945 "org.freedesktop.systemd1.Timer",
946 "NextElapseUSecMonotonic",
951 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
955 r = sd_bus_get_property_trivial(
957 "org.freedesktop.systemd1",
959 "org.freedesktop.systemd1.Timer",
960 "NextElapseUSecRealtime",
965 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
973 static int get_last_trigger(
978 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
985 r = sd_bus_get_property_trivial(
987 "org.freedesktop.systemd1",
989 "org.freedesktop.systemd1.Timer",
995 log_error("Failed to get last trigger time: %s", bus_error_message(&error, r));
1003 const char* machine;
1006 usec_t last_trigger;
1010 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
1016 if (!a->machine && b->machine)
1018 if (a->machine && !b->machine)
1020 if (a->machine && b->machine) {
1021 o = strcasecmp(a->machine, b->machine);
1026 if (a->next_elapse < b->next_elapse)
1028 if (a->next_elapse > b->next_elapse)
1031 return strcmp(a->id, b->id);
1034 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
1035 struct timer_info *t;
1037 nextlen = strlen("NEXT"),
1038 leftlen = strlen("LEFT"),
1039 lastlen = strlen("LAST"),
1040 passedlen = strlen("PASSED"),
1041 unitlen = strlen("UNIT"),
1042 activatelen = strlen("ACTIVATES");
1044 const char *on, *off;
1046 assert(timer_infos || n == 0);
1048 for (t = timer_infos; t < timer_infos + n; t++) {
1052 if (t->next_elapse > 0) {
1053 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1055 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
1056 nextlen = MAX(nextlen, strlen(tstamp) + 1);
1058 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
1059 leftlen = MAX(leftlen, strlen(trel));
1062 if (t->last_trigger > 0) {
1063 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1065 format_timestamp(tstamp, sizeof(tstamp), t->last_trigger);
1066 lastlen = MAX(lastlen, strlen(tstamp) + 1);
1068 format_timestamp_relative(trel, sizeof(trel), t->last_trigger);
1069 passedlen = MAX(passedlen, strlen(trel));
1072 unitlen = MAX(unitlen, strlen(t->id) + (t->machine ? strlen(t->machine)+1 : 0));
1074 STRV_FOREACH(a, t->triggered)
1075 ul += strlen(*a) + 2*(a != t->triggered);
1077 activatelen = MAX(activatelen, ul);
1082 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1086 passedlen, "PASSED",
1090 for (t = timer_infos; t < timer_infos + n; t++) {
1091 _cleanup_free_ char *j = NULL;
1093 char tstamp1[FORMAT_TIMESTAMP_MAX] = "n/a", trel1[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1094 char tstamp2[FORMAT_TIMESTAMP_MAX] = "n/a", trel2[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1097 format_timestamp(tstamp1, sizeof(tstamp1), t->next_elapse);
1098 format_timestamp_relative(trel1, sizeof(trel1), t->next_elapse);
1100 format_timestamp(tstamp2, sizeof(tstamp2), t->last_trigger);
1101 format_timestamp_relative(trel2, sizeof(trel2), t->last_trigger);
1104 j = strjoin(t->machine, ":", t->id, NULL);
1111 printf("%-*s %-*s %-*s %-*s %-*s",
1112 nextlen, tstamp1, leftlen, trel1, lastlen, tstamp2, passedlen, trel2, unitlen, unit);
1114 STRV_FOREACH(a, t->triggered)
1116 a == t->triggered ? "" : ",", *a);
1120 on = ansi_highlight();
1121 off = ansi_highlight_off();
1125 on = ansi_highlight_red();
1126 off = ansi_highlight_off();
1129 if (!arg_no_legend) {
1130 printf("%s%u timers listed.%s\n", on, n, off);
1132 printf("Pass --all to see loaded but inactive timers, too.\n");
1138 static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
1144 if (next->monotonic != USEC_INFINITY && next->monotonic > 0) {
1147 if (next->monotonic > nw->monotonic)
1148 converted = nw->realtime + (next->monotonic - nw->monotonic);
1150 converted = nw->realtime - (nw->monotonic - next->monotonic);
1152 if (next->realtime != USEC_INFINITY && next->realtime > 0)
1153 next_elapse = MIN(converted, next->realtime);
1155 next_elapse = converted;
1158 next_elapse = next->realtime;
1163 static int list_timers(sd_bus *bus, char **args) {
1164 _cleanup_(message_set_freep) Set *replies = NULL;
1165 _cleanup_strv_free_ char **machines = NULL;
1166 _cleanup_free_ struct timer_info *timer_infos = NULL;
1167 _cleanup_free_ UnitInfo *unit_infos = NULL;
1168 struct timer_info *t;
1175 pager_open_if_enabled();
1177 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
1181 dual_timestamp_get(&nw);
1183 for (u = unit_infos; u < unit_infos + n; u++) {
1184 _cleanup_strv_free_ char **triggered = NULL;
1185 dual_timestamp next = {};
1188 if (!endswith(u->id, ".timer"))
1191 r = get_triggered_units(bus, u->unit_path, &triggered);
1195 r = get_next_elapse(bus, u->unit_path, &next);
1199 get_last_trigger(bus, u->unit_path, &last);
1201 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
1206 m = calc_next_elapse(&nw, &next);
1208 timer_infos[c++] = (struct timer_info) {
1209 .machine = u->machine,
1212 .last_trigger = last,
1213 .triggered = triggered,
1216 triggered = NULL; /* avoid cleanup */
1219 qsort_safe(timer_infos, c, sizeof(struct timer_info),
1220 (__compar_fn_t) timer_info_compare);
1222 output_timers_list(timer_infos, c);
1225 for (t = timer_infos; t < timer_infos + c; t++)
1226 strv_free(t->triggered);
1231 static int compare_unit_file_list(const void *a, const void *b) {
1232 const char *d1, *d2;
1233 const UnitFileList *u = a, *v = b;
1235 d1 = strrchr(u->path, '.');
1236 d2 = strrchr(v->path, '.');
1241 r = strcasecmp(d1, d2);
1246 return strcasecmp(basename(u->path), basename(v->path));
1249 static bool output_show_unit_file(const UnitFileList *u, char **patterns) {
1250 if (!strv_isempty(patterns)) {
1253 STRV_FOREACH(pattern, patterns)
1254 if (fnmatch(*pattern, basename(u->path), FNM_NOESCAPE) == 0)
1260 if (!strv_isempty(arg_types)) {
1263 dot = strrchr(u->path, '.');
1267 if (!strv_find(arg_types, dot+1))
1271 if (!strv_isempty(arg_states)) {
1272 if (!strv_find(arg_states, unit_file_state_to_string(u->state)))
1279 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
1280 unsigned max_id_len, id_cols, state_cols;
1281 const UnitFileList *u;
1283 max_id_len = strlen("UNIT FILE");
1284 state_cols = strlen("STATE");
1286 for (u = units; u < units + c; u++) {
1287 max_id_len = MAX(max_id_len, strlen(basename(u->path)));
1288 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1292 unsigned basic_cols;
1294 id_cols = MIN(max_id_len, 25u);
1295 basic_cols = 1 + id_cols + state_cols;
1296 if (basic_cols < (unsigned) columns())
1297 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1299 id_cols = max_id_len;
1302 printf("%-*s %-*s\n",
1303 id_cols, "UNIT FILE",
1304 state_cols, "STATE");
1306 for (u = units; u < units + c; u++) {
1307 _cleanup_free_ char *e = NULL;
1308 const char *on, *off;
1311 if (u->state == UNIT_FILE_MASKED ||
1312 u->state == UNIT_FILE_MASKED_RUNTIME ||
1313 u->state == UNIT_FILE_DISABLED ||
1314 u->state == UNIT_FILE_INVALID) {
1315 on = ansi_highlight_red();
1316 off = ansi_highlight_off();
1317 } else if (u->state == UNIT_FILE_ENABLED) {
1318 on = ansi_highlight_green();
1319 off = ansi_highlight_off();
1323 id = basename(u->path);
1325 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1327 printf("%-*s %s%-*s%s\n",
1328 id_cols, e ? e : id,
1329 on, state_cols, unit_file_state_to_string(u->state), off);
1333 printf("\n%u unit files listed.\n", c);
1336 static int list_unit_files(sd_bus *bus, char **args) {
1337 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1338 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1339 _cleanup_free_ UnitFileList *units = NULL;
1347 pager_open_if_enabled();
1355 h = hashmap_new(&string_hash_ops);
1359 r = unit_file_get_list(arg_scope, arg_root, h);
1361 unit_file_list_free(h);
1362 log_error("Failed to get unit file list: %s", strerror(-r));
1366 n_units = hashmap_size(h);
1368 units = new(UnitFileList, n_units);
1369 if (!units && n_units > 0) {
1370 unit_file_list_free(h);
1374 HASHMAP_FOREACH(u, h, i) {
1375 if (!output_show_unit_file(u, strv_skip_first(args)))
1382 assert(c <= n_units);
1385 r = sd_bus_call_method(
1387 "org.freedesktop.systemd1",
1388 "/org/freedesktop/systemd1",
1389 "org.freedesktop.systemd1.Manager",
1395 log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1399 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1401 return bus_log_parse_error(r);
1403 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1405 if (!GREEDY_REALLOC(units, size, c + 1))
1408 units[c] = (struct UnitFileList) {
1410 unit_file_state_from_string(state)
1413 if (output_show_unit_file(&units[c], strv_skip_first(args)))
1418 return bus_log_parse_error(r);
1420 r = sd_bus_message_exit_container(reply);
1422 return bus_log_parse_error(r);
1425 qsort_safe(units, c, sizeof(UnitFileList), compare_unit_file_list);
1426 output_unit_file_list(units, c);
1429 for (unit = units; unit < units + c; unit++)
1436 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1437 _cleanup_free_ char *n = NULL;
1438 size_t max_len = MAX(columns(),20u);
1444 for (i = level - 1; i >= 0; i--) {
1446 if (len > max_len - 3 && !arg_full) {
1447 printf("%s...\n",max_len % 2 ? "" : " ");
1450 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERTICAL : DRAW_TREE_SPACE));
1454 if (len > max_len - 3 && !arg_full) {
1455 printf("%s...\n",max_len % 2 ? "" : " ");
1459 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
1463 printf("%s\n", name);
1467 n = ellipsize(name, max_len-len, 100);
1475 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1477 static const char *dependencies[_DEPENDENCY_MAX] = {
1478 [DEPENDENCY_FORWARD] = "Requires\0"
1479 "RequiresOverridable\0"
1481 "RequisiteOverridable\0"
1483 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1484 "RequiredByOverridable\0"
1487 [DEPENDENCY_AFTER] = "After\0",
1488 [DEPENDENCY_BEFORE] = "Before\0",
1491 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1492 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1493 _cleanup_strv_free_ char **ret = NULL;
1494 _cleanup_free_ char *path = NULL;
1500 assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
1502 path = unit_dbus_path_from_name(name);
1506 r = sd_bus_call_method(
1508 "org.freedesktop.systemd1",
1510 "org.freedesktop.DBus.Properties",
1514 "s", "org.freedesktop.systemd1.Unit");
1516 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1520 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1522 return bus_log_parse_error(r);
1524 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1527 r = sd_bus_message_read(reply, "s", &prop);
1529 return bus_log_parse_error(r);
1531 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1532 r = sd_bus_message_skip(reply, "v");
1534 return bus_log_parse_error(r);
1537 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1539 return bus_log_parse_error(r);
1541 r = bus_message_read_strv_extend(reply, &ret);
1543 return bus_log_parse_error(r);
1545 r = sd_bus_message_exit_container(reply);
1547 return bus_log_parse_error(r);
1550 r = sd_bus_message_exit_container(reply);
1552 return bus_log_parse_error(r);
1556 return bus_log_parse_error(r);
1558 r = sd_bus_message_exit_container(reply);
1560 return bus_log_parse_error(r);
1568 static int list_dependencies_compare(const void *_a, const void *_b) {
1569 const char **a = (const char**) _a, **b = (const char**) _b;
1571 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1573 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1576 return strcasecmp(*a, *b);
1579 static int list_dependencies_one(
1584 unsigned int branches) {
1586 _cleanup_strv_free_ char **deps = NULL;
1594 r = strv_extend(units, name);
1598 r = list_dependencies_get_dependencies(bus, name, &deps);
1602 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1604 STRV_FOREACH(c, deps) {
1607 if (strv_contains(*units, *c)) {
1609 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1616 state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true);
1618 printf("%s%s%s ", ansi_highlight_green(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1620 printf("%s%s%s ", ansi_highlight_red(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1622 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1626 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1627 r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1634 strv_remove(*units, name);
1639 static int list_dependencies(sd_bus *bus, char **args) {
1640 _cleanup_strv_free_ char **units = NULL;
1641 _cleanup_free_ char *unit = NULL;
1647 unit = unit_name_mangle(args[1], MANGLE_NOGLOB);
1652 u = SPECIAL_DEFAULT_TARGET;
1654 pager_open_if_enabled();
1658 return list_dependencies_one(bus, u, 0, &units, 0);
1661 struct machine_info {
1665 char *control_group;
1666 uint32_t n_failed_units;
1671 static const struct bus_properties_map machine_info_property_map[] = {
1672 { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
1673 { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
1674 { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
1675 { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
1676 { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
1680 static void free_machines_list(struct machine_info *machine_infos, int n) {
1686 for (i = 0; i < n; i++) {
1687 free(machine_infos[i].name);
1688 free(machine_infos[i].state);
1689 free(machine_infos[i].control_group);
1692 free(machine_infos);
1695 static int compare_machine_info(const void *a, const void *b) {
1696 const struct machine_info *u = a, *v = b;
1698 if (u->is_host != v->is_host)
1699 return u->is_host > v->is_host ? -1 : 1;
1701 return strcasecmp(u->name, v->name);
1704 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1705 _cleanup_bus_close_unref_ sd_bus *container = NULL;
1711 r = sd_bus_open_system_container(&container, mi->name);
1718 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi);
1725 static bool output_show_machine(const char *name, char **patterns) {
1730 if (strv_isempty(patterns))
1733 STRV_FOREACH(i, patterns)
1734 if (fnmatch(*i, name, FNM_NOESCAPE) == 0)
1740 static int get_machine_list(
1742 struct machine_info **_machine_infos,
1745 struct machine_info *machine_infos = NULL;
1746 _cleanup_strv_free_ char **m = NULL;
1747 _cleanup_free_ char *hn = NULL;
1752 hn = gethostname_malloc();
1756 if (output_show_machine(hn, patterns)) {
1757 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1760 machine_infos[c].is_host = true;
1761 machine_infos[c].name = hn;
1764 get_machine_properties(bus, &machine_infos[c]);
1768 sd_get_machine_names(&m);
1769 STRV_FOREACH(i, m) {
1770 _cleanup_free_ char *class = NULL;
1772 if (!output_show_machine(*i, patterns))
1775 sd_machine_get_class(*i, &class);
1776 if (!streq_ptr(class, "container"))
1779 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1780 free_machines_list(machine_infos, c);
1784 machine_infos[c].is_host = false;
1785 machine_infos[c].name = strdup(*i);
1786 if (!machine_infos[c].name) {
1787 free_machines_list(machine_infos, c);
1791 get_machine_properties(NULL, &machine_infos[c]);
1795 *_machine_infos = machine_infos;
1799 static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1800 struct machine_info *m;
1803 namelen = sizeof("NAME") - 1,
1804 statelen = sizeof("STATE") - 1,
1805 failedlen = sizeof("FAILED") - 1,
1806 jobslen = sizeof("JOBS") - 1;
1808 assert(machine_infos || n == 0);
1810 for (m = machine_infos; m < machine_infos + n; m++) {
1811 namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
1812 statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
1813 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
1814 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
1816 if (!arg_no_legend && !streq_ptr(m->state, "running"))
1820 if (!arg_no_legend) {
1824 printf("%-*s %-*s %-*s %-*s\n",
1827 failedlen, "FAILED",
1831 for (m = machine_infos; m < machine_infos + n; m++) {
1832 const char *on_state = "", *off_state = "";
1833 const char *on_failed = "", *off_failed = "";
1834 bool circle = false;
1836 if (streq_ptr(m->state, "degraded")) {
1837 on_state = ansi_highlight_red();
1838 off_state = ansi_highlight_off();
1840 } else if (!streq_ptr(m->state, "running")) {
1841 on_state = ansi_highlight_yellow();
1842 off_state = ansi_highlight_off();
1846 if (m->n_failed_units > 0) {
1847 on_failed = ansi_highlight_red();
1848 off_failed = ansi_highlight_off();
1850 on_failed = off_failed = "";
1853 printf("%s%s%s ", on_state, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_state);
1856 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1857 (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
1858 on_state, statelen, strna(m->state), off_state,
1859 on_failed, failedlen, m->n_failed_units, off_failed,
1860 jobslen, m->n_jobs);
1862 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1863 namelen, strna(m->name),
1864 on_state, statelen, strna(m->state), off_state,
1865 on_failed, failedlen, m->n_failed_units, off_failed,
1866 jobslen, m->n_jobs);
1870 printf("\n%u machines listed.\n", n);
1873 static int list_machines(sd_bus *bus, char **args) {
1874 struct machine_info *machine_infos = NULL;
1879 if (geteuid() != 0) {
1880 log_error("Must be root.");
1884 pager_open_if_enabled();
1886 r = get_machine_list(bus, &machine_infos, strv_skip_first(args));
1890 qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
1891 output_machines_list(machine_infos, r);
1892 free_machines_list(machine_infos, r);
1897 static int get_default(sd_bus *bus, char **args) {
1898 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1899 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1900 _cleanup_free_ char *_path = NULL;
1904 if (!bus || avoid_bus()) {
1905 r = unit_file_get_default(arg_scope, arg_root, &_path);
1907 log_error("Failed to get default target: %s", strerror(-r));
1913 r = sd_bus_call_method(
1915 "org.freedesktop.systemd1",
1916 "/org/freedesktop/systemd1",
1917 "org.freedesktop.systemd1.Manager",
1923 log_error("Failed to get default target: %s", bus_error_message(&error, -r));
1927 r = sd_bus_message_read(reply, "s", &path);
1929 return bus_log_parse_error(r);
1933 printf("%s\n", path);
1938 static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) {
1941 assert(changes || n_changes == 0);
1943 for (i = 0; i < n_changes; i++) {
1944 if (changes[i].type == UNIT_FILE_SYMLINK)
1945 log_info("Created symlink from %s to %s.", changes[i].path, changes[i].source);
1947 log_info("Removed symlink %s.", changes[i].path);
1951 static int deserialize_and_dump_unit_file_changes(sd_bus_message *m) {
1952 const char *type, *path, *source;
1955 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1957 return bus_log_parse_error(r);
1959 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1961 if (streq(type, "symlink"))
1962 log_info("Created symlink from %s to %s.", path, source);
1964 log_info("Removed symlink %s.", path);
1968 return bus_log_parse_error(r);
1970 r = sd_bus_message_exit_container(m);
1972 return bus_log_parse_error(r);
1977 static int set_default(sd_bus *bus, char **args) {
1978 _cleanup_free_ char *unit = NULL;
1979 UnitFileChange *changes = NULL;
1980 unsigned n_changes = 0;
1983 unit = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
1987 if (!bus || avoid_bus()) {
1988 r = unit_file_set_default(arg_scope, arg_root, unit, true, &changes, &n_changes);
1990 log_error("Failed to set default target: %s", strerror(-r));
1995 dump_unit_file_changes(changes, n_changes);
1999 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
2000 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2002 r = sd_bus_message_new_method_call(
2005 "org.freedesktop.systemd1",
2006 "/org/freedesktop/systemd1",
2007 "org.freedesktop.systemd1.Manager",
2008 "SetDefaultTarget");
2010 return bus_log_create_error(r);
2012 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2014 return bus_log_create_error(r);
2016 r = sd_bus_message_append(m, "sb", unit, 1);
2018 return bus_log_create_error(r);
2020 r = sd_bus_call(bus, m, 0, &error, &reply);
2022 log_error("Failed to set default target: %s", bus_error_message(&error, -r));
2026 r = deserialize_and_dump_unit_file_changes(reply);
2030 /* Try to reload if enabled */
2032 r = daemon_reload(bus, args);
2037 unit_file_changes_free(changes, n_changes);
2044 const char *name, *type, *state;
2047 static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
2048 unsigned id_len, unit_len, type_len, state_len;
2049 const struct job_info *j;
2050 const char *on, *off;
2051 bool shorten = false;
2053 assert(n == 0 || jobs);
2056 on = ansi_highlight_green();
2057 off = ansi_highlight_off();
2059 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
2063 pager_open_if_enabled();
2065 id_len = strlen("JOB");
2066 unit_len = strlen("UNIT");
2067 type_len = strlen("TYPE");
2068 state_len = strlen("STATE");
2070 for (j = jobs; j < jobs + n; j++) {
2071 uint32_t id = j->id;
2072 assert(j->name && j->type && j->state);
2074 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
2075 unit_len = MAX(unit_len, strlen(j->name));
2076 type_len = MAX(type_len, strlen(j->type));
2077 state_len = MAX(state_len, strlen(j->state));
2080 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
2081 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
2086 printf("%*s %-*s %-*s %-*s\n",
2090 state_len, "STATE");
2092 for (j = jobs; j < jobs + n; j++) {
2093 _cleanup_free_ char *e = NULL;
2095 if (streq(j->state, "running")) {
2096 on = ansi_highlight();
2097 off = ansi_highlight_off();
2101 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
2102 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2104 on, unit_len, e ? e : j->name, off,
2106 on, state_len, j->state, off);
2109 if (!arg_no_legend) {
2110 on = ansi_highlight();
2111 off = ansi_highlight_off();
2113 printf("\n%s%u jobs listed%s.\n", on, n, off);
2117 static bool output_show_job(struct job_info *job, char **patterns) {
2122 if (strv_isempty(patterns))
2125 STRV_FOREACH(pattern, patterns)
2126 if (fnmatch(*pattern, job->name, FNM_NOESCAPE) == 0)
2131 static int list_jobs(sd_bus *bus, char **args) {
2132 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2133 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2134 const char *name, *type, *state, *job_path, *unit_path;
2135 _cleanup_free_ struct job_info *jobs = NULL;
2140 bool skipped = false;
2142 r = sd_bus_call_method(
2144 "org.freedesktop.systemd1",
2145 "/org/freedesktop/systemd1",
2146 "org.freedesktop.systemd1.Manager",
2152 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
2156 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2158 return bus_log_parse_error(r);
2160 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
2161 struct job_info job = { id, name, type, state };
2163 if (!output_show_job(&job, strv_skip_first(args))) {
2168 if (!GREEDY_REALLOC(jobs, size, c + 1))
2174 return bus_log_parse_error(r);
2176 r = sd_bus_message_exit_container(reply);
2178 return bus_log_parse_error(r);
2180 output_jobs_list(jobs, c, skipped);
2184 static int cancel_job(sd_bus *bus, char **args) {
2185 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2191 if (strv_length(args) <= 1)
2192 return daemon_reload(bus, args);
2194 STRV_FOREACH(name, args+1) {
2195 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2199 q = safe_atou32(*name, &id);
2201 log_error("Failed to parse job id \"%s\": %s", *name, strerror(-q));
2205 q = sd_bus_message_new_method_call(
2208 "org.freedesktop.systemd1",
2209 "/org/freedesktop/systemd1",
2210 "org.freedesktop.systemd1.Manager",
2213 return bus_log_create_error(q);
2215 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2217 return bus_log_create_error(1);
2219 q = sd_bus_message_append(m, "u", id);
2221 return bus_log_create_error(q);
2223 q = sd_bus_call(bus, m, 0, &error, NULL);
2225 log_error("Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, q));
2234 static int need_daemon_reload(sd_bus *bus, const char *unit) {
2235 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2239 /* We ignore all errors here, since this is used to show a
2242 /* We don't use unit_dbus_path_from_name() directly since we
2243 * don't want to load the unit if it isn't loaded. */
2245 r = sd_bus_call_method(
2247 "org.freedesktop.systemd1",
2248 "/org/freedesktop/systemd1",
2249 "org.freedesktop.systemd1.Manager",
2257 r = sd_bus_message_read(reply, "o", &path);
2261 r = sd_bus_get_property_trivial(
2263 "org.freedesktop.systemd1",
2265 "org.freedesktop.systemd1.Unit",
2275 typedef struct WaitData {
2282 static int wait_filter(sd_bus *bus, sd_bus_message *m, void *data, sd_bus_error *error) {
2289 log_debug("Got D-Bus request: %s.%s() on %s",
2290 sd_bus_message_get_interface(m),
2291 sd_bus_message_get_member(m),
2292 sd_bus_message_get_path(m));
2294 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
2295 log_error("Warning! D-Bus connection terminated.");
2297 } else if (sd_bus_message_is_signal(m, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
2299 const char *path, *result, *unit;
2303 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
2305 ret = set_remove(d->set, (char*) path);
2311 if (!isempty(result))
2312 d->result = strdup(result);
2315 d->name = strdup(unit);
2320 r = sd_bus_message_read(m, "uos", &id, &path, &result);
2322 ret = set_remove(d->set, (char*) path);
2329 d->result = strdup(result);
2335 bus_log_parse_error(r);
2341 static int enable_wait_for_jobs(sd_bus *bus) {
2346 r = sd_bus_add_match(
2350 "sender='org.freedesktop.systemd1',"
2351 "interface='org.freedesktop.systemd1.Manager',"
2352 "member='JobRemoved',"
2353 "path='/org/freedesktop/systemd1'",
2356 log_error("Failed to add match");
2360 /* This is slightly dirty, since we don't undo the match registrations. */
2364 static int bus_process_wait(sd_bus *bus) {
2368 r = sd_bus_process(bus, NULL);
2373 r = sd_bus_wait(bus, (uint64_t) -1);
2379 static int check_wait_response(WaitData *d) {
2385 if (streq(d->result, "timeout"))
2386 log_error("Job for %s timed out.", strna(d->name));
2387 else if (streq(d->result, "canceled"))
2388 log_error("Job for %s canceled.", strna(d->name));
2389 else if (streq(d->result, "dependency"))
2390 log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
2391 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
2395 quotes = chars_intersect(d->name, SHELL_NEED_QUOTES);
2397 log_error("Job for %s failed. See \"systemctl status %s%s%s\" and \"journalctl -xe\" for details.",
2399 quotes ? "'" : "", d->name, quotes ? "'" : "");
2401 log_error("Job failed. See \"journalctl -xe\" for details.");
2405 if (streq(d->result, "timeout"))
2407 else if (streq(d->result, "canceled"))
2409 else if (streq(d->result, "dependency"))
2411 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2417 static int wait_for_jobs(sd_bus *bus, Set *s) {
2418 _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
2419 WaitData d = { .set = s };
2425 q = sd_bus_add_filter(bus, &slot, wait_filter, &d);
2429 while (!set_isempty(s)) {
2430 q = bus_process_wait(bus);
2432 log_error("Failed to wait for response: %s", strerror(-q));
2437 q = check_wait_response(&d);
2438 /* Return the first error as it is most likely to be
2440 if (q < 0 && r == 0)
2442 log_debug("Got result %s/%s for job %s",
2443 strna(d.result), strerror(-q), strna(d.name));
2456 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2457 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2458 _cleanup_free_ char *n = NULL, *state = NULL;
2464 n = unit_name_mangle(name, MANGLE_NOGLOB);
2468 /* We don't use unit_dbus_path_from_name() directly since we
2469 * don't want to load the unit if it isn't loaded. */
2471 r = sd_bus_call_method(
2473 "org.freedesktop.systemd1",
2474 "/org/freedesktop/systemd1",
2475 "org.freedesktop.systemd1.Manager",
2486 r = sd_bus_message_read(reply, "o", &path);
2488 return bus_log_parse_error(r);
2490 r = sd_bus_get_property_string(
2492 "org.freedesktop.systemd1",
2494 "org.freedesktop.systemd1.Unit",
2507 return nulstr_contains(good_states, state);
2510 static int check_triggering_units(
2514 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2515 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2516 _cleanup_strv_free_ char **triggered_by = NULL;
2517 bool print_warning_label = true;
2521 n = unit_name_mangle(name, MANGLE_NOGLOB);
2525 path = unit_dbus_path_from_name(n);
2529 r = sd_bus_get_property_string(
2531 "org.freedesktop.systemd1",
2533 "org.freedesktop.systemd1.Unit",
2538 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2542 if (streq(state, "masked"))
2545 r = sd_bus_get_property_strv(
2547 "org.freedesktop.systemd1",
2549 "org.freedesktop.systemd1.Unit",
2554 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2558 STRV_FOREACH(i, triggered_by) {
2559 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2561 log_error("Failed to check unit: %s", strerror(-r));
2568 if (print_warning_label) {
2569 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2570 print_warning_label = false;
2573 log_warning(" %s", *i);
2579 static const struct {
2582 } unit_actions[] = {
2583 { "start", "StartUnit" },
2584 { "stop", "StopUnit" },
2585 { "condstop", "StopUnit" },
2586 { "reload", "ReloadUnit" },
2587 { "restart", "RestartUnit" },
2588 { "try-restart", "TryRestartUnit" },
2589 { "condrestart", "TryRestartUnit" },
2590 { "reload-or-restart", "ReloadOrRestartUnit" },
2591 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2592 { "condreload", "ReloadOrTryRestartUnit" },
2593 { "force-reload", "ReloadOrTryRestartUnit" }
2596 static const char *verb_to_method(const char *verb) {
2599 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2600 if (streq_ptr(unit_actions[i].verb, verb))
2601 return unit_actions[i].method;
2606 static const char *method_to_verb(const char *method) {
2609 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2610 if (streq_ptr(unit_actions[i].method, method))
2611 return unit_actions[i].verb;
2616 static int start_unit_one(
2621 sd_bus_error *error,
2624 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2633 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2635 r = sd_bus_message_new_method_call(
2638 "org.freedesktop.systemd1",
2639 "/org/freedesktop/systemd1",
2640 "org.freedesktop.systemd1.Manager",
2643 return bus_log_create_error(r);
2645 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2647 return bus_log_create_error(r);
2649 r = sd_bus_message_append(m, "ss", name, mode);
2651 return bus_log_create_error(r);
2653 r = sd_bus_call(bus, m, 0, error, &reply);
2657 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2658 /* There's always a fallback possible for
2659 * legacy actions. */
2660 return -EADDRNOTAVAIL;
2662 verb = method_to_verb(method);
2664 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2668 r = sd_bus_message_read(reply, "o", &path);
2670 return bus_log_parse_error(r);
2672 if (need_daemon_reload(bus, name) > 0)
2673 log_warning("Warning: Unit file of %s changed on disk, 'systemctl%s daemon-reload' recommended.",
2674 name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2683 log_debug("Adding %s to the set", p);
2684 r = set_consume(s, p);
2692 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2694 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2698 STRV_FOREACH(name, names) {
2702 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2704 t = unit_name_mangle(*name, MANGLE_GLOB);
2708 if (string_is_glob(t))
2709 r = strv_consume(&globs, t);
2711 r = strv_consume(&mangled, t);
2716 /* Query the manager only if any of the names are a glob, since
2717 * this is fairly expensive */
2718 if (!strv_isempty(globs)) {
2719 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2720 _cleanup_free_ UnitInfo *unit_infos = NULL;
2722 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2726 for (i = 0; i < r; i++)
2727 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2732 mangled = NULL; /* do not free */
2737 static const struct {
2741 } action_table[_ACTION_MAX] = {
2742 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2743 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2744 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2745 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2746 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
2747 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
2748 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
2749 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
2750 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2751 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2752 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2753 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2754 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2755 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2756 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2759 static enum action verb_to_action(const char *verb) {
2762 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2763 if (streq_ptr(action_table[i].verb, verb))
2766 return _ACTION_INVALID;
2769 static int start_unit(sd_bus *bus, char **args) {
2770 _cleanup_set_free_free_ Set *s = NULL;
2771 _cleanup_strv_free_ char **names = NULL;
2772 const char *method, *mode, *one_name, *suffix = NULL;
2778 ask_password_agent_open_if_enabled();
2780 if (arg_action == ACTION_SYSTEMCTL) {
2782 method = verb_to_method(args[0]);
2783 action = verb_to_action(args[0]);
2785 if (streq(args[0], "isolate")) {
2789 mode = action_table[action].mode ?: arg_job_mode;
2791 one_name = action_table[action].target;
2793 assert(arg_action < ELEMENTSOF(action_table));
2794 assert(action_table[arg_action].target);
2796 method = "StartUnit";
2798 mode = action_table[arg_action].mode;
2799 one_name = action_table[arg_action].target;
2803 names = strv_new(one_name, NULL);
2805 r = expand_names(bus, args + 1, suffix, &names);
2807 log_error("Failed to expand names: %s", strerror(-r));
2810 if (!arg_no_block) {
2811 r = enable_wait_for_jobs(bus);
2813 log_error("Could not watch jobs: %s", strerror(-r));
2817 s = set_new(&string_hash_ops);
2822 STRV_FOREACH(name, names) {
2823 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2826 q = start_unit_one(bus, method, *name, mode, &error, s);
2827 if (r >= 0 && q < 0)
2828 r = translate_bus_error_to_exit_status(q, &error);
2831 if (!arg_no_block) {
2834 q = wait_for_jobs(bus, s);
2838 /* When stopping units, warn if they can still be triggered by
2839 * another active unit (socket, path, timer) */
2840 if (!arg_quiet && streq(method, "StopUnit"))
2841 STRV_FOREACH(name, names)
2842 check_triggering_units(bus, *name);
2848 /* Ask systemd-logind, which might grant access to unprivileged users
2849 * through PolicyKit */
2850 static int reboot_with_logind(sd_bus *bus, enum action a) {
2852 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2859 polkit_agent_open_if_enabled();
2867 case ACTION_POWEROFF:
2868 method = "PowerOff";
2871 case ACTION_SUSPEND:
2875 case ACTION_HIBERNATE:
2876 method = "Hibernate";
2879 case ACTION_HYBRID_SLEEP:
2880 method = "HybridSleep";
2887 r = sd_bus_call_method(
2889 "org.freedesktop.login1",
2890 "/org/freedesktop/login1",
2891 "org.freedesktop.login1.Manager",
2895 "b", arg_ask_password);
2897 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2905 static int check_inhibitors(sd_bus *bus, enum action a) {
2907 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2908 _cleanup_strv_free_ char **sessions = NULL;
2909 const char *what, *who, *why, *mode;
2918 if (arg_ignore_inhibitors || arg_force > 0)
2930 r = sd_bus_call_method(
2932 "org.freedesktop.login1",
2933 "/org/freedesktop/login1",
2934 "org.freedesktop.login1.Manager",
2940 /* If logind is not around, then there are no inhibitors... */
2943 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2945 return bus_log_parse_error(r);
2947 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2948 _cleanup_free_ char *comm = NULL, *user = NULL;
2949 _cleanup_strv_free_ char **sv = NULL;
2951 if (!streq(mode, "block"))
2954 sv = strv_split(what, ":");
2958 if (!strv_contains(sv,
2960 a == ACTION_POWEROFF ||
2961 a == ACTION_REBOOT ||
2962 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2965 get_process_comm(pid, &comm);
2966 user = uid_to_name(uid);
2968 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
2969 who, pid, strna(comm), strna(user), why);
2974 return bus_log_parse_error(r);
2976 r = sd_bus_message_exit_container(reply);
2978 return bus_log_parse_error(r);
2980 /* Check for current sessions */
2981 sd_get_sessions(&sessions);
2982 STRV_FOREACH(s, sessions) {
2983 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2985 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2988 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2991 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2994 sd_session_get_tty(*s, &tty);
2995 sd_session_get_seat(*s, &seat);
2996 sd_session_get_service(*s, &service);
2997 user = uid_to_name(uid);
2999 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
3006 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3007 action_table[a].verb);
3015 static int start_special(sd_bus *bus, char **args) {
3021 a = verb_to_action(args[0]);
3023 r = check_inhibitors(bus, a);
3027 if (arg_force >= 2 && geteuid() != 0) {
3028 log_error("Must be root.");
3032 if (arg_force >= 2 &&
3033 (a == ACTION_HALT ||
3034 a == ACTION_POWEROFF ||
3035 a == ACTION_REBOOT))
3038 if (arg_force >= 1 &&
3039 (a == ACTION_HALT ||
3040 a == ACTION_POWEROFF ||
3041 a == ACTION_REBOOT ||
3042 a == ACTION_KEXEC ||
3044 return daemon_reload(bus, args);
3046 /* first try logind, to allow authentication with polkit */
3047 if (geteuid() != 0 &&
3048 (a == ACTION_POWEROFF ||
3049 a == ACTION_REBOOT ||
3050 a == ACTION_SUSPEND ||
3051 a == ACTION_HIBERNATE ||
3052 a == ACTION_HYBRID_SLEEP)) {
3053 r = reboot_with_logind(bus, a);
3058 r = start_unit(bus, args);
3059 if (r == EXIT_SUCCESS)
3065 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
3066 _cleanup_strv_free_ char **names = NULL;
3073 r = expand_names(bus, args, NULL, &names);
3075 log_error("Failed to expand names: %s", strerror(-r));
3079 STRV_FOREACH(name, names) {
3082 state = check_one_unit(bus, *name, good_states, arg_quiet);
3092 static int check_unit_active(sd_bus *bus, char **args) {
3093 /* According to LSB: 3, "program is not running" */
3094 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
3097 static int check_unit_failed(sd_bus *bus, char **args) {
3098 return check_unit_generic(bus, 1, "failed\0", args + 1);
3101 static int kill_unit(sd_bus *bus, char **args) {
3102 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3103 _cleanup_strv_free_ char **names = NULL;
3111 arg_kill_who = "all";
3113 r = expand_names(bus, args + 1, NULL, &names);
3115 log_error("Failed to expand names: %s", strerror(-r));
3117 STRV_FOREACH(name, names) {
3118 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3120 q = sd_bus_message_new_method_call(
3123 "org.freedesktop.systemd1",
3124 "/org/freedesktop/systemd1",
3125 "org.freedesktop.systemd1.Manager",
3128 return bus_log_create_error(q);
3130 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
3132 return bus_log_create_error(q);
3134 q = sd_bus_message_append(m, "ssi", *names, arg_kill_who, arg_signal);
3136 return bus_log_create_error(q);
3138 q = sd_bus_call(bus, m, 0, &error, NULL);
3140 log_error("Failed to kill unit %s: %s", *names, bus_error_message(&error, q));
3149 typedef struct ExecStatusInfo {
3157 usec_t start_timestamp;
3158 usec_t exit_timestamp;
3163 LIST_FIELDS(struct ExecStatusInfo, exec);
3166 static void exec_status_info_free(ExecStatusInfo *i) {
3175 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3176 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3179 int32_t code, status;
3185 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3187 return bus_log_parse_error(r);
3191 r = sd_bus_message_read(m, "s", &path);
3193 return bus_log_parse_error(r);
3195 i->path = strdup(path);
3199 r = sd_bus_message_read_strv(m, &i->argv);
3201 return bus_log_parse_error(r);
3203 r = sd_bus_message_read(m,
3206 &start_timestamp, &start_timestamp_monotonic,
3207 &exit_timestamp, &exit_timestamp_monotonic,
3211 return bus_log_parse_error(r);
3214 i->start_timestamp = (usec_t) start_timestamp;
3215 i->exit_timestamp = (usec_t) exit_timestamp;
3216 i->pid = (pid_t) pid;
3220 r = sd_bus_message_exit_container(m);
3222 return bus_log_parse_error(r);
3227 typedef struct UnitStatusInfo {
3229 const char *load_state;
3230 const char *active_state;
3231 const char *sub_state;
3232 const char *unit_file_state;
3234 const char *description;
3235 const char *following;
3237 char **documentation;
3239 const char *fragment_path;
3240 const char *source_path;
3241 const char *control_group;
3243 char **dropin_paths;
3245 const char *load_error;
3248 usec_t inactive_exit_timestamp;
3249 usec_t inactive_exit_timestamp_monotonic;
3250 usec_t active_enter_timestamp;
3251 usec_t active_exit_timestamp;
3252 usec_t inactive_enter_timestamp;
3254 bool need_daemon_reload;
3259 const char *status_text;
3260 const char *pid_file;
3264 usec_t start_timestamp;
3265 usec_t exit_timestamp;
3267 int exit_code, exit_status;
3269 usec_t condition_timestamp;
3270 bool condition_result;
3271 bool failed_condition_trigger;
3272 bool failed_condition_negate;
3273 const char *failed_condition;
3274 const char *failed_condition_param;
3277 unsigned n_accepted;
3278 unsigned n_connections;
3281 /* Pairs of type, path */
3285 const char *sysfs_path;
3287 /* Mount, Automount */
3293 LIST_HEAD(ExecStatusInfo, exec);
3296 static void print_status_info(
3301 const char *active_on, *active_off, *on, *off, *ss;
3303 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3304 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3307 arg_all * OUTPUT_SHOW_ALL |
3308 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
3309 on_tty() * OUTPUT_COLOR |
3310 !arg_quiet * OUTPUT_WARN_CUTOFF |
3311 arg_full * OUTPUT_FULL_WIDTH;
3316 /* This shows pretty information about a unit. See
3317 * print_property() for a low-level property printer */
3319 if (streq_ptr(i->active_state, "failed")) {
3320 active_on = ansi_highlight_red();
3321 active_off = ansi_highlight_off();
3322 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3323 active_on = ansi_highlight_green();
3324 active_off = ansi_highlight_off();
3326 active_on = active_off = "";
3328 printf("%s%s%s %s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3330 if (i->description && !streq_ptr(i->id, i->description))
3331 printf(" - %s", i->description);
3336 printf(" Follow: unit currently follows state of %s\n", i->following);
3338 if (streq_ptr(i->load_state, "error")) {
3339 on = ansi_highlight_red();
3340 off = ansi_highlight_off();
3344 path = i->source_path ? i->source_path : i->fragment_path;
3347 printf(" Loaded: %s%s%s (Reason: %s)\n",
3348 on, strna(i->load_state), off, i->load_error);
3349 else if (path && i->unit_file_state)
3350 printf(" Loaded: %s%s%s (%s; %s)\n",
3351 on, strna(i->load_state), off, path, i->unit_file_state);
3353 printf(" Loaded: %s%s%s (%s)\n",
3354 on, strna(i->load_state), off, path);
3356 printf(" Loaded: %s%s%s\n",
3357 on, strna(i->load_state), off);
3359 if (!strv_isempty(i->dropin_paths)) {
3360 _cleanup_free_ char *dir = NULL;
3364 STRV_FOREACH(dropin, i->dropin_paths) {
3365 if (! dir || last) {
3366 printf(dir ? " " : " Drop-In: ");
3371 if (path_get_parent(*dropin, &dir) < 0) {
3376 printf("%s\n %s", dir,
3377 draw_special_char(DRAW_TREE_RIGHT));
3380 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3382 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3386 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3388 printf(" Active: %s%s (%s)%s",
3389 active_on, strna(i->active_state), ss, active_off);
3391 printf(" Active: %s%s%s",
3392 active_on, strna(i->active_state), active_off);
3394 if (!isempty(i->result) && !streq(i->result, "success"))
3395 printf(" (Result: %s)", i->result);
3397 timestamp = (streq_ptr(i->active_state, "active") ||
3398 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
3399 (streq_ptr(i->active_state, "inactive") ||
3400 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
3401 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
3402 i->active_exit_timestamp;
3404 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3405 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3408 printf(" since %s; %s\n", s2, s1);
3410 printf(" since %s\n", s2);
3414 if (!i->condition_result && i->condition_timestamp > 0) {
3415 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3416 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3418 printf(" start condition failed at %s%s%s\n",
3419 s2, s1 ? "; " : "", s1 ? s1 : "");
3420 if (i->failed_condition_trigger)
3421 printf(" none of the trigger conditions were met\n");
3422 else if (i->failed_condition)
3423 printf(" %s=%s%s was not met\n",
3424 i->failed_condition,
3425 i->failed_condition_negate ? "!" : "",
3426 i->failed_condition_param);
3430 printf(" Device: %s\n", i->sysfs_path);
3432 printf(" Where: %s\n", i->where);
3434 printf(" What: %s\n", i->what);
3436 STRV_FOREACH(t, i->documentation)
3437 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3439 STRV_FOREACH_PAIR(t, t2, i->listen)
3440 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3443 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3445 LIST_FOREACH(exec, p, i->exec) {
3446 _cleanup_free_ char *argv = NULL;
3449 /* Only show exited processes here */
3453 argv = strv_join(p->argv, " ");
3454 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
3456 good = is_clean_exit_lsb(p->code, p->status, NULL);
3458 on = ansi_highlight_red();
3459 off = ansi_highlight_off();
3463 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3465 if (p->code == CLD_EXITED) {
3468 printf("status=%i", p->status);
3470 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3475 printf("signal=%s", signal_to_string(p->status));
3477 printf(")%s\n", off);
3479 if (i->main_pid == p->pid &&
3480 i->start_timestamp == p->start_timestamp &&
3481 i->exit_timestamp == p->start_timestamp)
3482 /* Let's not show this twice */
3485 if (p->pid == i->control_pid)
3489 if (i->main_pid > 0 || i->control_pid > 0) {
3490 if (i->main_pid > 0) {
3491 printf(" Main PID: "PID_FMT, i->main_pid);
3494 _cleanup_free_ char *comm = NULL;
3495 get_process_comm(i->main_pid, &comm);
3497 printf(" (%s)", comm);
3498 } else if (i->exit_code > 0) {
3499 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3501 if (i->exit_code == CLD_EXITED) {
3504 printf("status=%i", i->exit_status);
3506 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3511 printf("signal=%s", signal_to_string(i->exit_status));
3515 if (i->control_pid > 0)
3519 if (i->control_pid > 0) {
3520 _cleanup_free_ char *c = NULL;
3522 printf(" %8s: "PID_FMT, i->main_pid ? "" : " Control", i->control_pid);
3524 get_process_comm(i->control_pid, &c);
3533 printf(" Status: \"%s\"\n", i->status_text);
3534 if (i->status_errno > 0)
3535 printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
3537 if (i->control_group &&
3538 (i->main_pid > 0 || i->control_pid > 0 ||
3539 ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_CONTAINER) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3542 printf(" CGroup: %s\n", i->control_group);
3544 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
3547 static const char prefix[] = " ";
3550 if (c > sizeof(prefix) - 1)
3551 c -= sizeof(prefix) - 1;
3555 if (i->main_pid > 0)
3556 extra[k++] = i->main_pid;
3558 if (i->control_pid > 0)
3559 extra[k++] = i->control_pid;
3561 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, flags);
3565 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3566 show_journal_by_unit(stdout,
3570 i->inactive_exit_timestamp_monotonic,
3573 flags | OUTPUT_BEGIN_NEWLINE,
3574 arg_scope == UNIT_FILE_SYSTEM,
3578 if (i->need_daemon_reload)
3579 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
3580 ansi_highlight_red(),
3581 ansi_highlight_off(),
3582 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
3585 static void show_unit_help(UnitStatusInfo *i) {
3590 if (!i->documentation) {
3591 log_info("Documentation for %s not known.", i->id);
3595 STRV_FOREACH(p, i->documentation)
3596 if (startswith(*p, "man:"))
3597 show_man_page(*p + 4, false);
3599 log_info("Can't show: %s", *p);
3602 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3609 switch (contents[0]) {
3611 case SD_BUS_TYPE_STRING: {
3614 r = sd_bus_message_read(m, "s", &s);
3616 return bus_log_parse_error(r);
3619 if (streq(name, "Id"))
3621 else if (streq(name, "LoadState"))
3623 else if (streq(name, "ActiveState"))
3624 i->active_state = s;
3625 else if (streq(name, "SubState"))
3627 else if (streq(name, "Description"))
3629 else if (streq(name, "FragmentPath"))
3630 i->fragment_path = s;
3631 else if (streq(name, "SourcePath"))
3634 else if (streq(name, "DefaultControlGroup")) {
3636 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3638 i->control_group = e;
3641 else if (streq(name, "ControlGroup"))
3642 i->control_group = s;
3643 else if (streq(name, "StatusText"))
3645 else if (streq(name, "PIDFile"))
3647 else if (streq(name, "SysFSPath"))
3649 else if (streq(name, "Where"))
3651 else if (streq(name, "What"))
3653 else if (streq(name, "Following"))
3655 else if (streq(name, "UnitFileState"))
3656 i->unit_file_state = s;
3657 else if (streq(name, "Result"))
3664 case SD_BUS_TYPE_BOOLEAN: {
3667 r = sd_bus_message_read(m, "b", &b);
3669 return bus_log_parse_error(r);
3671 if (streq(name, "Accept"))
3673 else if (streq(name, "NeedDaemonReload"))
3674 i->need_daemon_reload = b;
3675 else if (streq(name, "ConditionResult"))
3676 i->condition_result = b;
3681 case SD_BUS_TYPE_UINT32: {
3684 r = sd_bus_message_read(m, "u", &u);
3686 return bus_log_parse_error(r);
3688 if (streq(name, "MainPID")) {
3690 i->main_pid = (pid_t) u;
3693 } else if (streq(name, "ControlPID"))
3694 i->control_pid = (pid_t) u;
3695 else if (streq(name, "ExecMainPID")) {
3697 i->main_pid = (pid_t) u;
3698 } else if (streq(name, "NAccepted"))
3700 else if (streq(name, "NConnections"))
3701 i->n_connections = u;
3706 case SD_BUS_TYPE_INT32: {
3709 r = sd_bus_message_read(m, "i", &j);
3711 return bus_log_parse_error(r);
3713 if (streq(name, "ExecMainCode"))
3714 i->exit_code = (int) j;
3715 else if (streq(name, "ExecMainStatus"))
3716 i->exit_status = (int) j;
3717 else if (streq(name, "StatusErrno"))
3718 i->status_errno = (int) j;
3723 case SD_BUS_TYPE_UINT64: {
3726 r = sd_bus_message_read(m, "t", &u);
3728 return bus_log_parse_error(r);
3730 if (streq(name, "ExecMainStartTimestamp"))
3731 i->start_timestamp = (usec_t) u;
3732 else if (streq(name, "ExecMainExitTimestamp"))
3733 i->exit_timestamp = (usec_t) u;
3734 else if (streq(name, "ActiveEnterTimestamp"))
3735 i->active_enter_timestamp = (usec_t) u;
3736 else if (streq(name, "InactiveEnterTimestamp"))
3737 i->inactive_enter_timestamp = (usec_t) u;
3738 else if (streq(name, "InactiveExitTimestamp"))
3739 i->inactive_exit_timestamp = (usec_t) u;
3740 else if (streq(name, "InactiveExitTimestampMonotonic"))
3741 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3742 else if (streq(name, "ActiveExitTimestamp"))
3743 i->active_exit_timestamp = (usec_t) u;
3744 else if (streq(name, "ConditionTimestamp"))
3745 i->condition_timestamp = (usec_t) u;
3750 case SD_BUS_TYPE_ARRAY:
3752 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3753 _cleanup_free_ ExecStatusInfo *info = NULL;
3755 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3757 return bus_log_parse_error(r);
3759 info = new0(ExecStatusInfo, 1);
3763 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3765 info->name = strdup(name);
3769 LIST_PREPEND(exec, i->exec, info);
3771 info = new0(ExecStatusInfo, 1);
3777 return bus_log_parse_error(r);
3779 r = sd_bus_message_exit_container(m);
3781 return bus_log_parse_error(r);
3785 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3786 const char *type, *path;
3788 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3790 return bus_log_parse_error(r);
3792 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3794 r = strv_extend(&i->listen, type);
3798 r = strv_extend(&i->listen, path);
3803 return bus_log_parse_error(r);
3805 r = sd_bus_message_exit_container(m);
3807 return bus_log_parse_error(r);
3811 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3813 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3815 return bus_log_parse_error(r);
3817 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3819 r = sd_bus_message_read_strv(m, &i->documentation);
3821 return bus_log_parse_error(r);
3823 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3824 const char *cond, *param;
3825 int trigger, negate;
3828 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3830 return bus_log_parse_error(r);
3832 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3833 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3834 if (state < 0 && (!trigger || !i->failed_condition)) {
3835 i->failed_condition = cond;
3836 i->failed_condition_trigger = trigger;
3837 i->failed_condition_negate = negate;
3838 i->failed_condition_param = param;
3842 return bus_log_parse_error(r);
3844 r = sd_bus_message_exit_container(m);
3846 return bus_log_parse_error(r);
3853 case SD_BUS_TYPE_STRUCT_BEGIN:
3855 if (streq(name, "LoadError")) {
3856 const char *n, *message;
3858 r = sd_bus_message_read(m, "(ss)", &n, &message);
3860 return bus_log_parse_error(r);
3862 if (!isempty(message))
3863 i->load_error = message;
3876 r = sd_bus_message_skip(m, contents);
3878 return bus_log_parse_error(r);
3883 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3889 /* This is a low-level property printer, see
3890 * print_status_info() for the nicer output */
3892 if (arg_properties && !strv_find(arg_properties, name)) {
3893 /* skip what we didn't read */
3894 r = sd_bus_message_skip(m, contents);
3898 switch (contents[0]) {
3900 case SD_BUS_TYPE_STRUCT_BEGIN:
3902 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3905 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3907 return bus_log_parse_error(r);
3910 printf("%s=%"PRIu32"\n", name, u);
3912 printf("%s=\n", name);
3916 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3919 r = sd_bus_message_read(m, "(so)", &s, NULL);
3921 return bus_log_parse_error(r);
3923 if (arg_all || !isempty(s))
3924 printf("%s=%s\n", name, s);
3928 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3929 const char *a = NULL, *b = NULL;
3931 r = sd_bus_message_read(m, "(ss)", &a, &b);
3933 return bus_log_parse_error(r);
3935 if (arg_all || !isempty(a) || !isempty(b))
3936 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3939 } else if (streq_ptr(name, "SystemCallFilter")) {
3940 _cleanup_strv_free_ char **l = NULL;
3943 r = sd_bus_message_enter_container(m, 'r', "bas");
3945 return bus_log_parse_error(r);
3947 r = sd_bus_message_read(m, "b", &whitelist);
3949 return bus_log_parse_error(r);
3951 r = sd_bus_message_read_strv(m, &l);
3953 return bus_log_parse_error(r);
3955 r = sd_bus_message_exit_container(m);
3957 return bus_log_parse_error(r);
3959 if (arg_all || whitelist || !strv_isempty(l)) {
3963 fputs(name, stdout);
3969 STRV_FOREACH(i, l) {
3977 fputc('\n', stdout);
3985 case SD_BUS_TYPE_ARRAY:
3987 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
3991 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
3993 return bus_log_parse_error(r);
3995 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
3996 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3999 return bus_log_parse_error(r);
4001 r = sd_bus_message_exit_container(m);
4003 return bus_log_parse_error(r);
4007 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
4008 const char *type, *path;
4010 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4012 return bus_log_parse_error(r);
4014 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4015 printf("%s=%s\n", type, path);
4017 return bus_log_parse_error(r);
4019 r = sd_bus_message_exit_container(m);
4021 return bus_log_parse_error(r);
4025 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
4026 const char *type, *path;
4028 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4030 return bus_log_parse_error(r);
4032 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4033 printf("Listen%s=%s\n", type, path);
4035 return bus_log_parse_error(r);
4037 r = sd_bus_message_exit_container(m);
4039 return bus_log_parse_error(r);
4043 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
4045 uint64_t value, next_elapse;
4047 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
4049 return bus_log_parse_error(r);
4051 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
4052 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
4054 printf("%s={ value=%s ; next_elapse=%s }\n",
4056 format_timespan(timespan1, sizeof(timespan1), value, 0),
4057 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
4060 return bus_log_parse_error(r);
4062 r = sd_bus_message_exit_container(m);
4064 return bus_log_parse_error(r);
4068 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
4069 ExecStatusInfo info = {};
4071 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
4073 return bus_log_parse_error(r);
4075 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
4076 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
4077 _cleanup_free_ char *tt;
4079 tt = strv_join(info.argv, " ");
4081 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",
4085 yes_no(info.ignore),
4086 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
4087 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
4089 sigchld_code_to_string(info.code),
4091 info.code == CLD_EXITED ? "" : "/",
4092 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
4095 strv_free(info.argv);
4099 r = sd_bus_message_exit_container(m);
4101 return bus_log_parse_error(r);
4105 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
4106 const char *path, *rwm;
4108 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4110 return bus_log_parse_error(r);
4112 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
4113 printf("%s=%s %s\n", name, strna(path), strna(rwm));
4115 return bus_log_parse_error(r);
4117 r = sd_bus_message_exit_container(m);
4119 return bus_log_parse_error(r);
4123 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
4127 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4129 return bus_log_parse_error(r);
4131 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4132 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
4134 return bus_log_parse_error(r);
4136 r = sd_bus_message_exit_container(m);
4138 return bus_log_parse_error(r);
4142 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
4146 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4148 return bus_log_parse_error(r);
4150 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4151 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
4153 return bus_log_parse_error(r);
4155 r = sd_bus_message_exit_container(m);
4157 return bus_log_parse_error(r);
4165 r = bus_print_property(name, m, arg_all);
4167 return bus_log_parse_error(r);
4170 r = sd_bus_message_skip(m, contents);
4172 return bus_log_parse_error(r);
4175 printf("%s=[unprintable]\n", name);
4181 static int show_one(
4185 bool show_properties,
4189 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4190 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4191 UnitStatusInfo info = {};
4198 log_debug("Showing one %s", path);
4200 r = sd_bus_call_method(
4202 "org.freedesktop.systemd1",
4204 "org.freedesktop.DBus.Properties",
4210 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4214 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4216 return bus_log_parse_error(r);
4223 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4224 const char *name, *contents;
4226 r = sd_bus_message_read(reply, "s", &name);
4228 return bus_log_parse_error(r);
4230 r = sd_bus_message_peek_type(reply, NULL, &contents);
4232 return bus_log_parse_error(r);
4234 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4236 return bus_log_parse_error(r);
4238 if (show_properties)
4239 r = print_property(name, reply, contents);
4241 r = status_property(name, reply, &info, contents);
4245 r = sd_bus_message_exit_container(reply);
4247 return bus_log_parse_error(r);
4249 r = sd_bus_message_exit_container(reply);
4251 return bus_log_parse_error(r);
4254 return bus_log_parse_error(r);
4256 r = sd_bus_message_exit_container(reply);
4258 return bus_log_parse_error(r);
4262 if (!show_properties) {
4263 if (streq(verb, "help"))
4264 show_unit_help(&info);
4266 print_status_info(&info, ellipsized);
4269 strv_free(info.documentation);
4270 strv_free(info.dropin_paths);
4271 strv_free(info.listen);
4273 if (!streq_ptr(info.active_state, "active") &&
4274 !streq_ptr(info.active_state, "reloading") &&
4275 streq(verb, "status")) {
4276 /* According to LSB: "program not running" */
4277 /* 0: program is running or service is OK
4278 * 1: program is dead and /run PID file exists
4279 * 2: program is dead and /run/lock lock file exists
4280 * 3: program is not running
4281 * 4: program or service status is unknown
4283 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4289 while ((p = info.exec)) {
4290 LIST_REMOVE(exec, info.exec, p);
4291 exec_status_info_free(p);
4297 static int get_unit_dbus_path_by_pid(
4302 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4303 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4307 r = sd_bus_call_method(
4309 "org.freedesktop.systemd1",
4310 "/org/freedesktop/systemd1",
4311 "org.freedesktop.systemd1.Manager",
4317 log_error("Failed to get unit for PID "PID_FMT": %s", pid, bus_error_message(&error, r));
4321 r = sd_bus_message_read(reply, "o", &u);
4323 return bus_log_parse_error(r);
4333 static int show_all(
4336 bool show_properties,
4340 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4341 _cleanup_free_ UnitInfo *unit_infos = NULL;
4346 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4350 pager_open_if_enabled();
4354 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4356 for (u = unit_infos; u < unit_infos + c; u++) {
4357 _cleanup_free_ char *p = NULL;
4359 p = unit_dbus_path_from_name(u->id);
4363 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4366 else if (r > 0 && ret == 0)
4373 static int show_system_status(sd_bus *bus) {
4374 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4375 _cleanup_free_ char *hn = NULL;
4376 struct machine_info mi = {};
4377 const char *on, *off;
4380 hn = gethostname_malloc();
4384 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4386 log_error("Failed to read server status: %s", strerror(-r));
4390 if (streq_ptr(mi.state, "degraded")) {
4391 on = ansi_highlight_red();
4392 off = ansi_highlight_off();
4393 } else if (!streq_ptr(mi.state, "running")) {
4394 on = ansi_highlight_yellow();
4395 off = ansi_highlight_off();
4399 printf("%s%s%s %s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4401 printf(" State: %s%s%s\n",
4402 on, strna(mi.state), off);
4404 printf(" Jobs: %u queued\n", mi.n_jobs);
4405 printf(" Failed: %u units\n", mi.n_failed_units);
4407 printf(" Since: %s; %s\n",
4408 format_timestamp(since2, sizeof(since2), mi.timestamp),
4409 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4411 printf(" CGroup: %s\n", mi.control_group ?: "/");
4412 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
4414 arg_all * OUTPUT_SHOW_ALL |
4415 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
4416 on_tty() * OUTPUT_COLOR |
4417 !arg_quiet * OUTPUT_WARN_CUTOFF |
4418 arg_full * OUTPUT_FULL_WIDTH;
4420 static const char prefix[] = " ";
4424 if (c > sizeof(prefix) - 1)
4425 c -= sizeof(prefix) - 1;
4429 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
4433 free(mi.control_group);
4438 static int show(sd_bus *bus, char **args) {
4439 bool show_properties, show_status, new_line = false;
4440 bool ellipsized = false;
4446 show_properties = streq(args[0], "show");
4447 show_status = streq(args[0], "status");
4449 if (show_properties)
4450 pager_open_if_enabled();
4452 /* If no argument is specified inspect the manager itself */
4454 if (show_properties && strv_length(args) <= 1)
4455 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4457 if (show_status && strv_length(args) <= 1) {
4459 pager_open_if_enabled();
4460 show_system_status(bus);
4464 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4466 _cleanup_free_ char **patterns = NULL;
4469 STRV_FOREACH(name, args + 1) {
4470 _cleanup_free_ char *unit = NULL;
4473 if (safe_atou32(*name, &id) < 0) {
4474 if (strv_push(&patterns, *name) < 0)
4478 } else if (show_properties) {
4479 /* Interpret as job id */
4480 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4484 /* Interpret as PID */
4485 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4492 r = show_one(args[0], bus, unit, show_properties,
4493 &new_line, &ellipsized);
4496 else if (r > 0 && ret == 0)
4500 if (!strv_isempty(patterns)) {
4501 _cleanup_strv_free_ char **names = NULL;
4503 r = expand_names(bus, patterns, NULL, &names);
4505 log_error("Failed to expand names: %s", strerror(-r));
4507 STRV_FOREACH(name, names) {
4508 _cleanup_free_ char *unit;
4510 unit = unit_dbus_path_from_name(*name);
4514 r = show_one(args[0], bus, unit, show_properties,
4515 &new_line, &ellipsized);
4518 else if (r > 0 && ret == 0)
4524 if (ellipsized && !arg_quiet)
4525 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4530 static int cat(sd_bus *bus, char **args) {
4531 _cleanup_strv_free_ char **names = NULL;
4539 r = expand_names(bus, args + 1, NULL, &names);
4541 log_error("Failed to expand names: %s", strerror(-r));
4543 pager_open_if_enabled();
4545 STRV_FOREACH(name, names) {
4546 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4547 _cleanup_strv_free_ char **dropin_paths = NULL;
4548 _cleanup_free_ char *fragment_path = NULL, *unit = NULL;
4551 unit = unit_dbus_path_from_name(*name);
4555 if (need_daemon_reload(bus, *name) > 0)
4556 log_warning("Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'.",
4557 *name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
4559 r = sd_bus_get_property_string(
4561 "org.freedesktop.systemd1",
4563 "org.freedesktop.systemd1.Unit",
4568 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
4572 r = sd_bus_get_property_strv(
4574 "org.freedesktop.systemd1",
4576 "org.freedesktop.systemd1.Unit",
4581 log_warning("Failed to get DropInPaths: %s", bus_error_message(&error, r));
4590 if (!isempty(fragment_path)) {
4591 printf("%s# %s%s\n",
4592 ansi_highlight_blue(),
4594 ansi_highlight_off());
4597 r = sendfile_full(STDOUT_FILENO, fragment_path);
4599 log_warning("Failed to cat %s: %s", fragment_path, strerror(-r));
4604 STRV_FOREACH(path, dropin_paths) {
4605 printf("%s%s# %s%s\n",
4606 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4607 ansi_highlight_blue(),
4609 ansi_highlight_off());
4612 r = sendfile_full(STDOUT_FILENO, *path);
4614 log_warning("Failed to cat %s: %s", *path, strerror(-r));
4620 return r < 0 ? r : 0;
4623 static int set_property(sd_bus *bus, char **args) {
4624 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4625 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4626 _cleanup_free_ char *n = NULL;
4630 r = sd_bus_message_new_method_call(
4633 "org.freedesktop.systemd1",
4634 "/org/freedesktop/systemd1",
4635 "org.freedesktop.systemd1.Manager",
4636 "SetUnitProperties");
4638 return bus_log_create_error(r);
4640 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4642 return bus_log_create_error(r);
4644 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4648 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4650 return bus_log_create_error(r);
4652 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4654 return bus_log_create_error(r);
4656 STRV_FOREACH(i, args + 2) {
4657 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4659 return bus_log_create_error(r);
4661 r = bus_append_unit_property_assignment(m, *i);
4665 r = sd_bus_message_close_container(m);
4667 return bus_log_create_error(r);
4670 r = sd_bus_message_close_container(m);
4672 return bus_log_create_error(r);
4674 r = sd_bus_call(bus, m, 0, &error, NULL);
4676 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4683 static int snapshot(sd_bus *bus, char **args) {
4684 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4685 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
4686 _cleanup_free_ char *n = NULL, *id = NULL;
4690 if (strv_length(args) > 1)
4691 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4697 r = sd_bus_message_new_method_call(
4700 "org.freedesktop.systemd1",
4701 "/org/freedesktop/systemd1",
4702 "org.freedesktop.systemd1.Manager",
4705 return bus_log_create_error(r);
4707 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4709 return bus_log_create_error(r);
4711 r = sd_bus_message_append(m, "sb", n, false);
4713 return bus_log_create_error(r);
4715 r = sd_bus_call(bus, m, 0, &error, &reply);
4717 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4721 r = sd_bus_message_read(reply, "o", &path);
4723 return bus_log_parse_error(r);
4725 r = sd_bus_get_property_string(
4727 "org.freedesktop.systemd1",
4729 "org.freedesktop.systemd1.Unit",
4734 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4744 static int delete_snapshot(sd_bus *bus, char **args) {
4745 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4746 _cleanup_strv_free_ char **names = NULL;
4752 r = expand_names(bus, args + 1, ".snapshot", &names);
4754 log_error("Failed to expand names: %s", strerror(-r));
4756 STRV_FOREACH(name, names) {
4757 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4760 q = sd_bus_message_new_method_call(
4763 "org.freedesktop.systemd1",
4764 "/org/freedesktop/systemd1",
4765 "org.freedesktop.systemd1.Manager",
4768 return bus_log_create_error(q);
4770 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4772 return bus_log_create_error(q);
4774 q = sd_bus_message_append(m, "s", *name);
4776 return bus_log_create_error(q);
4778 q = sd_bus_call(bus, m, 0, &error, NULL);
4780 log_error("Failed to remove snapshot %s: %s", *name, bus_error_message(&error, q));
4789 static int daemon_reload(sd_bus *bus, char **args) {
4790 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4791 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4795 if (arg_action == ACTION_RELOAD)
4797 else if (arg_action == ACTION_REEXEC)
4798 method = "Reexecute";
4800 assert(arg_action == ACTION_SYSTEMCTL);
4803 streq(args[0], "clear-jobs") ||
4804 streq(args[0], "cancel") ? "ClearJobs" :
4805 streq(args[0], "daemon-reexec") ? "Reexecute" :
4806 streq(args[0], "reset-failed") ? "ResetFailed" :
4807 streq(args[0], "halt") ? "Halt" :
4808 streq(args[0], "poweroff") ? "PowerOff" :
4809 streq(args[0], "reboot") ? "Reboot" :
4810 streq(args[0], "kexec") ? "KExec" :
4811 streq(args[0], "exit") ? "Exit" :
4812 /* "daemon-reload" */ "Reload";
4815 r = sd_bus_message_new_method_call(
4818 "org.freedesktop.systemd1",
4819 "/org/freedesktop/systemd1",
4820 "org.freedesktop.systemd1.Manager",
4823 return bus_log_create_error(r);
4825 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4827 return bus_log_create_error(r);
4829 r = sd_bus_call(bus, m, 0, &error, NULL);
4830 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4831 /* There's always a fallback possible for
4832 * legacy actions. */
4834 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4835 /* On reexecution, we expect a disconnect, not a
4839 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4841 return r < 0 ? r : 0;
4844 static int reset_failed(sd_bus *bus, char **args) {
4845 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4846 _cleanup_strv_free_ char **names = NULL;
4850 if (strv_length(args) <= 1)
4851 return daemon_reload(bus, args);
4853 r = expand_names(bus, args + 1, NULL, &names);
4855 log_error("Failed to expand names: %s", strerror(-r));
4857 STRV_FOREACH(name, names) {
4858 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4860 q = sd_bus_message_new_method_call(
4863 "org.freedesktop.systemd1",
4864 "/org/freedesktop/systemd1",
4865 "org.freedesktop.systemd1.Manager",
4868 return bus_log_create_error(q);
4870 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4872 return bus_log_create_error(q);
4874 q = sd_bus_message_append(m, "s", *name);
4876 return bus_log_create_error(q);
4878 q = sd_bus_call(bus, m, 0, &error, NULL);
4880 log_error("Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q));
4889 static int show_environment(sd_bus *bus, char **args) {
4890 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4891 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4895 pager_open_if_enabled();
4897 r = sd_bus_get_property(
4899 "org.freedesktop.systemd1",
4900 "/org/freedesktop/systemd1",
4901 "org.freedesktop.systemd1.Manager",
4907 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4911 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4913 return bus_log_parse_error(r);
4915 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4918 return bus_log_parse_error(r);
4920 r = sd_bus_message_exit_container(reply);
4922 return bus_log_parse_error(r);
4927 static int switch_root(sd_bus *bus, char **args) {
4928 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4929 _cleanup_free_ char *cmdline_init = NULL;
4930 const char *root, *init;
4934 l = strv_length(args);
4935 if (l < 2 || l > 3) {
4936 log_error("Wrong number of arguments.");
4945 r = parse_env_file("/proc/cmdline", WHITESPACE,
4946 "init", &cmdline_init,
4949 log_debug("Failed to parse /proc/cmdline: %s", strerror(-r));
4951 init = cmdline_init;
4958 const char *root_systemd_path = NULL, *root_init_path = NULL;
4960 root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
4961 root_init_path = strappenda(root, "/", init);
4963 /* If the passed init is actually the same as the
4964 * systemd binary, then let's suppress it. */
4965 if (files_same(root_init_path, root_systemd_path) > 0)
4969 log_debug("Switching root - root: %s; init: %s", root, strna(init));
4971 r = sd_bus_call_method(
4973 "org.freedesktop.systemd1",
4974 "/org/freedesktop/systemd1",
4975 "org.freedesktop.systemd1.Manager",
4981 log_error("Failed to switch root: %s", bus_error_message(&error, r));
4988 static int set_environment(sd_bus *bus, char **args) {
4989 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4990 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4997 method = streq(args[0], "set-environment")
4999 : "UnsetEnvironment";
5001 r = sd_bus_message_new_method_call(
5004 "org.freedesktop.systemd1",
5005 "/org/freedesktop/systemd1",
5006 "org.freedesktop.systemd1.Manager",
5009 return bus_log_create_error(r);
5011 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5013 return bus_log_create_error(r);
5015 r = sd_bus_message_append_strv(m, args + 1);
5017 return bus_log_create_error(r);
5019 r = sd_bus_call(bus, m, 0, &error, NULL);
5021 log_error("Failed to set environment: %s", bus_error_message(&error, r));
5028 static int import_environment(sd_bus *bus, char **args) {
5029 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5030 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
5036 r = sd_bus_message_new_method_call(
5039 "org.freedesktop.systemd1",
5040 "/org/freedesktop/systemd1",
5041 "org.freedesktop.systemd1.Manager",
5044 return bus_log_create_error(r);
5046 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5048 return bus_log_create_error(r);
5050 if (strv_isempty(args + 1))
5051 r = sd_bus_message_append_strv(m, environ);
5055 r = sd_bus_message_open_container(m, 'a', "s");
5057 return bus_log_create_error(r);
5059 STRV_FOREACH(a, args + 1) {
5061 if (!env_name_is_valid(*a)) {
5062 log_error("Not a valid environment variable name: %s", *a);
5066 STRV_FOREACH(b, environ) {
5069 eq = startswith(*b, *a);
5070 if (eq && *eq == '=') {
5072 r = sd_bus_message_append(m, "s", *b);
5074 return bus_log_create_error(r);
5081 r = sd_bus_message_close_container(m);
5084 return bus_log_create_error(r);
5086 r = sd_bus_call(bus, m, 0, &error, NULL);
5088 log_error("Failed to import environment: %s", bus_error_message(&error, r));
5095 static int enable_sysv_units(const char *verb, char **args) {
5098 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
5099 unsigned f = 1, t = 1;
5100 _cleanup_lookup_paths_free_ LookupPaths paths = {};
5102 if (arg_scope != UNIT_FILE_SYSTEM)
5105 if (!streq(verb, "enable") &&
5106 !streq(verb, "disable") &&
5107 !streq(verb, "is-enabled"))
5110 /* Processes all SysV units, and reshuffles the array so that
5111 * afterwards only the native units remain */
5113 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, arg_root, NULL, NULL, NULL);
5118 for (f = 0; args[f]; f++) {
5120 _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL;
5121 bool found_native = false, found_sysv;
5123 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
5131 if (!endswith(name, ".service"))
5134 if (path_is_absolute(name))
5137 STRV_FOREACH(k, paths.unit_path) {
5138 _cleanup_free_ char *path = NULL;
5140 path = path_join(arg_root, *k, name);
5144 found_native = access(path, F_OK) >= 0;
5152 p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name);
5156 p[strlen(p) - strlen(".service")] = 0;
5157 found_sysv = access(p, F_OK) >= 0;
5161 /* Mark this entry, so that we don't try enabling it as native unit */
5162 args[f] = (char*) "";
5164 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
5166 if (!isempty(arg_root))
5167 argv[c++] = q = strappend("--root=", arg_root);
5169 argv[c++] = basename(p);
5171 streq(verb, "enable") ? "on" :
5172 streq(verb, "disable") ? "off" : "--level=5";
5175 l = strv_join((char**)argv, " ");
5179 log_info("Executing %s", l);
5183 log_error("Failed to fork: %m");
5185 } else if (pid == 0) {
5188 execv(argv[0], (char**) argv);
5189 _exit(EXIT_FAILURE);
5192 j = wait_for_terminate(pid, &status);
5194 log_error("Failed to wait for child: %s", strerror(-r));
5198 if (status.si_code == CLD_EXITED) {
5199 if (streq(verb, "is-enabled")) {
5200 if (status.si_status == 0) {
5209 } else if (status.si_status != 0)
5215 /* Drop all SysV units */
5216 for (f = 0, t = 0; args[f]; f++) {
5218 if (isempty(args[f]))
5221 args[t++] = args[f];
5230 static int mangle_names(char **original_names, char ***mangled_names) {
5231 char **i, **l, **name;
5233 l = new(char*, strv_length(original_names) + 1);
5238 STRV_FOREACH(name, original_names) {
5240 /* When enabling units qualified path names are OK,
5241 * too, hence allow them explicitly. */
5246 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5262 static int enable_unit(sd_bus *bus, char **args) {
5263 _cleanup_strv_free_ char **names = NULL;
5264 const char *verb = args[0];
5265 UnitFileChange *changes = NULL;
5266 unsigned n_changes = 0;
5267 int carries_install_info = -1;
5273 r = mangle_names(args+1, &names);
5277 r = enable_sysv_units(verb, names);
5281 /* If the operation was fully executed by the SysV compat,
5282 * let's finish early */
5283 if (strv_isempty(names))
5286 if (!bus || avoid_bus()) {
5287 if (streq(verb, "enable")) {
5288 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5289 carries_install_info = r;
5290 } else if (streq(verb, "disable"))
5291 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5292 else if (streq(verb, "reenable")) {
5293 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5294 carries_install_info = r;
5295 } else if (streq(verb, "link"))
5296 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5297 else if (streq(verb, "preset")) {
5298 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_preset_mode, arg_force, &changes, &n_changes);
5299 carries_install_info = r;
5300 } else if (streq(verb, "mask"))
5301 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5302 else if (streq(verb, "unmask"))
5303 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5305 assert_not_reached("Unknown verb");
5308 log_error("Operation failed: %s", strerror(-r));
5313 dump_unit_file_changes(changes, n_changes);
5317 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5318 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5319 int expect_carries_install_info = false;
5320 bool send_force = true, send_preset_mode = false;
5323 if (streq(verb, "enable")) {
5324 method = "EnableUnitFiles";
5325 expect_carries_install_info = true;
5326 } else if (streq(verb, "disable")) {
5327 method = "DisableUnitFiles";
5329 } else if (streq(verb, "reenable")) {
5330 method = "ReenableUnitFiles";
5331 expect_carries_install_info = true;
5332 } else if (streq(verb, "link"))
5333 method = "LinkUnitFiles";
5334 else if (streq(verb, "preset")) {
5336 if (arg_preset_mode != UNIT_FILE_PRESET_FULL) {
5337 method = "PresetUnitFilesWithMode";
5338 send_preset_mode = true;
5340 method = "PresetUnitFiles";
5342 expect_carries_install_info = true;
5343 } else if (streq(verb, "mask"))
5344 method = "MaskUnitFiles";
5345 else if (streq(verb, "unmask")) {
5346 method = "UnmaskUnitFiles";
5349 assert_not_reached("Unknown verb");
5351 r = sd_bus_message_new_method_call(
5354 "org.freedesktop.systemd1",
5355 "/org/freedesktop/systemd1",
5356 "org.freedesktop.systemd1.Manager",
5359 return bus_log_create_error(r);
5361 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5363 return bus_log_create_error(r);
5365 r = sd_bus_message_append_strv(m, names);
5367 return bus_log_create_error(r);
5369 if (send_preset_mode) {
5370 r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode));
5372 return bus_log_create_error(r);
5375 r = sd_bus_message_append(m, "b", arg_runtime);
5377 return bus_log_create_error(r);
5380 r = sd_bus_message_append(m, "b", arg_force);
5382 return bus_log_create_error(r);
5385 r = sd_bus_call(bus, m, 0, &error, &reply);
5387 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5391 if (expect_carries_install_info) {
5392 r = sd_bus_message_read(reply, "b", &carries_install_info);
5394 return bus_log_parse_error(r);
5397 r = deserialize_and_dump_unit_file_changes(reply);
5401 /* Try to reload if enabled */
5403 r = daemon_reload(bus, args);
5408 if (carries_install_info == 0)
5409 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5410 "using systemctl.\n"
5411 "Possible reasons for having this kind of units are:\n"
5412 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5413 " .wants/ or .requires/ directory.\n"
5414 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5415 " a requirement dependency on it.\n"
5416 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5417 " D-Bus, udev, scripted systemctl call, ...).\n");
5420 unit_file_changes_free(changes, n_changes);
5425 static int add_dependency(sd_bus *bus, char **args) {
5426 _cleanup_strv_free_ char **names = NULL;
5427 _cleanup_free_ char *target = NULL;
5428 const char *verb = args[0];
5435 target = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
5439 r = mangle_names(args+2, &names);
5443 if (streq(verb, "add-wants"))
5445 else if (streq(verb, "add-requires"))
5446 dep = UNIT_REQUIRES;
5448 assert_not_reached("Unknown verb");
5450 if (!bus || avoid_bus()) {
5451 UnitFileChange *changes = NULL;
5452 unsigned n_changes = 0;
5454 r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes);
5457 log_error("Can't add dependency: %s", strerror(-r));
5462 dump_unit_file_changes(changes, n_changes);
5464 unit_file_changes_free(changes, n_changes);
5467 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5468 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5470 r = sd_bus_message_new_method_call(
5473 "org.freedesktop.systemd1",
5474 "/org/freedesktop/systemd1",
5475 "org.freedesktop.systemd1.Manager",
5476 "AddDependencyUnitFiles");
5478 return bus_log_create_error(r);
5480 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5482 return bus_log_create_error(r);
5484 r = sd_bus_message_append_strv(m, names);
5486 return bus_log_create_error(r);
5488 r = sd_bus_message_append(m, "ssbb", target, unit_dependency_to_string(dep), arg_runtime, arg_force);
5490 return bus_log_create_error(r);
5492 r = sd_bus_call(bus, m, 0, &error, &reply);
5494 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5498 r = deserialize_and_dump_unit_file_changes(reply);
5503 r = daemon_reload(bus, args);
5511 static int preset_all(sd_bus *bus, char **args) {
5512 UnitFileChange *changes = NULL;
5513 unsigned n_changes = 0;
5516 if (!bus || avoid_bus()) {
5518 r = unit_file_preset_all(arg_scope, arg_runtime, arg_root, arg_preset_mode, arg_force, &changes, &n_changes);
5520 log_error("Operation failed: %s", strerror(-r));
5525 dump_unit_file_changes(changes, n_changes);
5530 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
5531 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5533 r = sd_bus_message_new_method_call(
5536 "org.freedesktop.systemd1",
5537 "/org/freedesktop/systemd1",
5538 "org.freedesktop.systemd1.Manager",
5539 "PresetAllUnitFiles");
5541 return bus_log_create_error(r);
5543 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5545 return bus_log_create_error(r);
5547 r = sd_bus_message_append(
5550 unit_file_preset_mode_to_string(arg_preset_mode),
5554 return bus_log_create_error(r);
5556 r = sd_bus_call(bus, m, 0, &error, &reply);
5558 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5562 r = deserialize_and_dump_unit_file_changes(reply);
5567 r = daemon_reload(bus, args);
5573 unit_file_changes_free(changes, n_changes);
5578 static int unit_is_enabled(sd_bus *bus, char **args) {
5580 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5581 _cleanup_strv_free_ char **names = NULL;
5586 r = mangle_names(args+1, &names);
5590 r = enable_sysv_units(args[0], names);
5596 if (!bus || avoid_bus()) {
5598 STRV_FOREACH(name, names) {
5599 UnitFileState state;
5601 state = unit_file_get_state(arg_scope, arg_root, *name);
5603 log_error("Failed to get unit file state for %s: %s", *name, strerror(-state));
5607 if (state == UNIT_FILE_ENABLED ||
5608 state == UNIT_FILE_ENABLED_RUNTIME ||
5609 state == UNIT_FILE_STATIC)
5613 puts(unit_file_state_to_string(state));
5617 STRV_FOREACH(name, names) {
5618 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5621 r = sd_bus_call_method(
5623 "org.freedesktop.systemd1",
5624 "/org/freedesktop/systemd1",
5625 "org.freedesktop.systemd1.Manager",
5631 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5635 r = sd_bus_message_read(reply, "s", &s);
5637 return bus_log_parse_error(r);
5639 if (streq(s, "enabled") ||
5640 streq(s, "enabled-runtime") ||
5652 static int is_system_running(sd_bus *bus, char **args) {
5653 _cleanup_free_ char *state = NULL;
5656 r = sd_bus_get_property_string(
5658 "org.freedesktop.systemd1",
5659 "/org/freedesktop/systemd1",
5660 "org.freedesktop.systemd1.Manager",
5673 return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE;
5676 static void systemctl_help(void) {
5678 pager_open_if_enabled();
5680 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
5681 "Query or send control commands to the systemd manager.\n\n"
5682 " -h --help Show this help\n"
5683 " --version Show package version\n"
5684 " --system Connect to system manager\n"
5685 " --user Connect to user service manager\n"
5686 " -H --host=[USER@]HOST\n"
5687 " Operate on remote host\n"
5688 " -M --machine=CONTAINER\n"
5689 " Operate on local container\n"
5690 " -t --type=TYPE List only units of a particular type\n"
5691 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
5692 " -p --property=NAME Show only properties by this name\n"
5693 " -a --all Show all loaded units/properties, including dead/empty\n"
5694 " ones. To list all units installed on the system, use\n"
5695 " the 'list-unit-files' command instead.\n"
5696 " -l --full Don't ellipsize unit names on output\n"
5697 " -r --recursive Show unit list of host and local containers\n"
5698 " --reverse Show reverse dependencies with 'list-dependencies'\n"
5699 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
5700 " queueing a new job\n"
5701 " --show-types When showing sockets, explicitly show their type\n"
5702 " -i --ignore-inhibitors\n"
5703 " When shutting down or sleeping, ignore inhibitors\n"
5704 " --kill-who=WHO Who to send signal to\n"
5705 " -s --signal=SIGNAL Which signal to send\n"
5706 " -q --quiet Suppress output\n"
5707 " --no-block Do not wait until operation finished\n"
5708 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5709 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
5711 " --no-legend Do not print a legend (column headers and hints)\n"
5712 " --no-pager Do not pipe output into a pager\n"
5713 " --no-ask-password\n"
5714 " Do not ask for system passwords\n"
5715 " --global Enable/disable unit files globally\n"
5716 " --runtime Enable unit files only temporarily until next reboot\n"
5717 " -f --force When enabling unit files, override existing symlinks\n"
5718 " When shutting down, execute action immediately\n"
5719 " --preset-mode= Specifies whether fully apply presets, or only enable,\n"
5720 " or only disable\n"
5721 " --root=PATH Enable unit files in the specified root directory\n"
5722 " -n --lines=INTEGER Number of journal entries to show\n"
5723 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
5724 " verbose, export, json, json-pretty, json-sse, cat)\n"
5725 " --plain Print unit dependencies as a list instead of a tree\n\n"
5727 " list-units [PATTERN...] List loaded units\n"
5728 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
5729 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
5730 " start NAME... Start (activate) one or more units\n"
5731 " stop NAME... Stop (deactivate) one or more units\n"
5732 " reload NAME... Reload one or more units\n"
5733 " restart NAME... Start or restart one or more units\n"
5734 " try-restart NAME... Restart one or more units if active\n"
5735 " reload-or-restart NAME... Reload one or more units if possible,\n"
5736 " otherwise start or restart\n"
5737 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
5738 " otherwise restart if active\n"
5739 " isolate NAME Start one unit and stop all others\n"
5740 " kill NAME... Send signal to processes of a unit\n"
5741 " is-active PATTERN... Check whether units are active\n"
5742 " is-failed PATTERN... Check whether units are failed\n"
5743 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
5744 " show [PATTERN...|JOB...] Show properties of one or more\n"
5745 " units/jobs or the manager\n"
5746 " cat PATTERN... Show files and drop-ins of one or more units\n"
5747 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
5748 " help PATTERN...|PID... Show manual for one or more units\n"
5749 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
5751 " list-dependencies [NAME] Recursively show units which are required\n"
5752 " or wanted by this unit or by which this\n"
5753 " unit is required or wanted\n\n"
5754 "Unit File Commands:\n"
5755 " list-unit-files [PATTERN...] List installed unit files\n"
5756 " enable NAME... Enable one or more unit files\n"
5757 " disable NAME... Disable one or more unit files\n"
5758 " reenable NAME... Reenable one or more unit files\n"
5759 " preset NAME... Enable/disable one or more unit files\n"
5760 " based on preset configuration\n"
5761 " preset-all Enable/disable all unit files based on\n"
5762 " preset configuration\n"
5763 " is-enabled NAME... Check whether unit files are enabled\n\n"
5764 " mask NAME... Mask one or more units\n"
5765 " unmask NAME... Unmask one or more units\n"
5766 " link PATH... Link one or more units files into\n"
5767 " the search path\n"
5768 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
5769 " on specified one or more units\n"
5770 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
5771 " on specified one or more units\n"
5772 " get-default Get the name of the default target\n"
5773 " set-default NAME Set the default target\n\n"
5774 "Machine Commands:\n"
5775 " list-machines [PATTERN...] List local containers and host\n\n"
5777 " list-jobs [PATTERN...] List jobs\n"
5778 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
5779 "Snapshot Commands:\n"
5780 " snapshot [NAME] Create a snapshot\n"
5781 " delete NAME... Remove one or more snapshots\n\n"
5782 "Environment Commands:\n"
5783 " show-environment Dump environment\n"
5784 " set-environment NAME=VALUE... Set one or more environment variables\n"
5785 " unset-environment NAME... Unset one or more environment variables\n"
5786 " import-environment NAME... Import all, one or more environment variables\n\n"
5787 "Manager Lifecycle Commands:\n"
5788 " daemon-reload Reload systemd manager configuration\n"
5789 " daemon-reexec Reexecute systemd manager\n\n"
5790 "System Commands:\n"
5791 " is-system-running Check whether system is fully running\n"
5792 " default Enter system default mode\n"
5793 " rescue Enter system rescue mode\n"
5794 " emergency Enter system emergency mode\n"
5795 " halt Shut down and halt the system\n"
5796 " poweroff Shut down and power-off the system\n"
5797 " reboot [ARG] Shut down and reboot the system\n"
5798 " kexec Shut down and reboot the system with kexec\n"
5799 " exit Request user instance exit\n"
5800 " switch-root ROOT [INIT] Change to a different root file system\n"
5801 " suspend Suspend the system\n"
5802 " hibernate Hibernate the system\n"
5803 " hybrid-sleep Hibernate and suspend the system\n",
5804 program_invocation_short_name);
5807 static void halt_help(void) {
5808 printf("%s [OPTIONS...]%s\n\n"
5809 "%s the system.\n\n"
5810 " --help Show this help\n"
5811 " --halt Halt the machine\n"
5812 " -p --poweroff Switch off the machine\n"
5813 " --reboot Reboot the machine\n"
5814 " -f --force Force immediate halt/power-off/reboot\n"
5815 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
5816 " -d --no-wtmp Don't write wtmp record\n"
5817 " --no-wall Don't send wall message before halt/power-off/reboot\n",
5818 program_invocation_short_name,
5819 arg_action == ACTION_REBOOT ? " [ARG]" : "",
5820 arg_action == ACTION_REBOOT ? "Reboot" :
5821 arg_action == ACTION_POWEROFF ? "Power off" :
5825 static void shutdown_help(void) {
5826 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
5827 "Shut down the system.\n\n"
5828 " --help Show this help\n"
5829 " -H --halt Halt the machine\n"
5830 " -P --poweroff Power-off the machine\n"
5831 " -r --reboot Reboot the machine\n"
5832 " -h Equivalent to --poweroff, overridden by --halt\n"
5833 " -k Don't halt/power-off/reboot, just send warnings\n"
5834 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5835 " -c Cancel a pending shutdown\n",
5836 program_invocation_short_name);
5839 static void telinit_help(void) {
5840 printf("%s [OPTIONS...] {COMMAND}\n\n"
5841 "Send control commands to the init daemon.\n\n"
5842 " --help Show this help\n"
5843 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
5845 " 0 Power-off the machine\n"
5846 " 6 Reboot the machine\n"
5847 " 2, 3, 4, 5 Start runlevelX.target unit\n"
5848 " 1, s, S Enter rescue mode\n"
5849 " q, Q Reload init daemon configuration\n"
5850 " u, U Reexecute init daemon\n",
5851 program_invocation_short_name);
5854 static void runlevel_help(void) {
5855 printf("%s [OPTIONS...]\n\n"
5856 "Prints the previous and current runlevel of the init system.\n\n"
5857 " --help Show this help\n",
5858 program_invocation_short_name);
5861 static void help_types(void) {
5866 puts("Available unit types:");
5867 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
5868 t = unit_type_to_string(i);
5874 static int systemctl_parse_argv(int argc, char *argv[]) {
5883 ARG_IGNORE_DEPENDENCIES,
5895 ARG_NO_ASK_PASSWORD,
5905 static const struct option options[] = {
5906 { "help", no_argument, NULL, 'h' },
5907 { "version", no_argument, NULL, ARG_VERSION },
5908 { "type", required_argument, NULL, 't' },
5909 { "property", required_argument, NULL, 'p' },
5910 { "all", no_argument, NULL, 'a' },
5911 { "reverse", no_argument, NULL, ARG_REVERSE },
5912 { "after", no_argument, NULL, ARG_AFTER },
5913 { "before", no_argument, NULL, ARG_BEFORE },
5914 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
5915 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
5916 { "full", no_argument, NULL, 'l' },
5917 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
5918 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
5919 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
5920 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
5921 { "ignore-inhibitors", no_argument, NULL, 'i' },
5922 { "user", no_argument, NULL, ARG_USER },
5923 { "system", no_argument, NULL, ARG_SYSTEM },
5924 { "global", no_argument, NULL, ARG_GLOBAL },
5925 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
5926 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
5927 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
5928 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5929 { "quiet", no_argument, NULL, 'q' },
5930 { "root", required_argument, NULL, ARG_ROOT },
5931 { "force", no_argument, NULL, ARG_FORCE },
5932 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
5933 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
5934 { "signal", required_argument, NULL, 's' },
5935 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
5936 { "host", required_argument, NULL, 'H' },
5937 { "machine", required_argument, NULL, 'M' },
5938 { "runtime", no_argument, NULL, ARG_RUNTIME },
5939 { "lines", required_argument, NULL, 'n' },
5940 { "output", required_argument, NULL, 'o' },
5941 { "plain", no_argument, NULL, ARG_PLAIN },
5942 { "state", required_argument, NULL, ARG_STATE },
5943 { "recursive", no_argument, NULL, 'r' },
5944 { "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
5953 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
5962 puts(PACKAGE_STRING);
5963 puts(SYSTEMD_FEATURES);
5967 const char *word, *state;
5970 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5971 _cleanup_free_ char *type;
5973 type = strndup(word, size);
5977 if (streq(type, "help")) {
5982 if (unit_type_from_string(type) >= 0) {
5983 if (strv_push(&arg_types, type))
5989 /* It's much nicer to use --state= for
5990 * load states, but let's support this
5991 * in --types= too for compatibility
5992 * with old versions */
5993 if (unit_load_state_from_string(optarg) >= 0) {
5994 if (strv_push(&arg_states, type) < 0)
6000 log_error("Unknown unit type or load state '%s'.", type);
6001 log_info("Use -t help to see a list of allowed values.");
6009 /* Make sure that if the empty property list
6010 was specified, we won't show any properties. */
6011 if (isempty(optarg) && !arg_properties) {
6012 arg_properties = new0(char*, 1);
6013 if (!arg_properties)
6016 const char *word, *state;
6019 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6022 prop = strndup(word, size);
6026 if (strv_consume(&arg_properties, prop) < 0)
6031 /* If the user asked for a particular
6032 * property, show it to him, even if it is
6044 arg_dependency = DEPENDENCY_REVERSE;
6048 arg_dependency = DEPENDENCY_AFTER;
6052 arg_dependency = DEPENDENCY_BEFORE;
6055 case ARG_SHOW_TYPES:
6056 arg_show_types = true;
6060 arg_job_mode = optarg;
6064 arg_job_mode = "fail";
6067 case ARG_IRREVERSIBLE:
6068 arg_job_mode = "replace-irreversibly";
6071 case ARG_IGNORE_DEPENDENCIES:
6072 arg_job_mode = "ignore-dependencies";
6076 arg_scope = UNIT_FILE_USER;
6080 arg_scope = UNIT_FILE_SYSTEM;
6084 arg_scope = UNIT_FILE_GLOBAL;
6088 arg_no_block = true;
6092 arg_no_legend = true;
6096 arg_no_pager = true;
6112 if (strv_extend(&arg_states, "failed") < 0)
6130 arg_no_reload = true;
6134 arg_kill_who = optarg;
6138 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
6139 log_error("Failed to parse signal string %s.", optarg);
6144 case ARG_NO_ASK_PASSWORD:
6145 arg_ask_password = false;
6149 arg_transport = BUS_TRANSPORT_REMOTE;
6154 arg_transport = BUS_TRANSPORT_CONTAINER;
6163 if (safe_atou(optarg, &arg_lines) < 0) {
6164 log_error("Failed to parse lines '%s'", optarg);
6170 arg_output = output_mode_from_string(optarg);
6171 if (arg_output < 0) {
6172 log_error("Unknown output '%s'.", optarg);
6178 arg_ignore_inhibitors = true;
6186 const char *word, *state;
6189 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6192 s = strndup(word, size);
6196 if (strv_consume(&arg_states, s) < 0)
6203 if (geteuid() != 0) {
6204 log_error("--recursive requires root privileges.");
6208 arg_recursive = true;
6211 case ARG_PRESET_MODE:
6213 arg_preset_mode = unit_file_preset_mode_from_string(optarg);
6214 if (arg_preset_mode < 0) {
6215 log_error("Failed to parse preset mode: %s.", optarg);
6225 assert_not_reached("Unhandled option");
6228 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
6229 log_error("Cannot access user instance remotely.");
6236 static int halt_parse_argv(int argc, char *argv[]) {
6245 static const struct option options[] = {
6246 { "help", no_argument, NULL, ARG_HELP },
6247 { "halt", no_argument, NULL, ARG_HALT },
6248 { "poweroff", no_argument, NULL, 'p' },
6249 { "reboot", no_argument, NULL, ARG_REBOOT },
6250 { "force", no_argument, NULL, 'f' },
6251 { "wtmp-only", no_argument, NULL, 'w' },
6252 { "no-wtmp", no_argument, NULL, 'd' },
6253 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6262 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
6263 if (runlevel == '0' || runlevel == '6')
6266 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
6274 arg_action = ACTION_HALT;
6278 if (arg_action != ACTION_REBOOT)
6279 arg_action = ACTION_POWEROFF;
6283 arg_action = ACTION_REBOOT;
6305 /* Compatibility nops */
6312 assert_not_reached("Unhandled option");
6315 if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
6316 r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL);
6319 } else if (optind < argc) {
6320 log_error("Too many arguments.");
6327 static int parse_time_spec(const char *t, usec_t *_u) {
6331 if (streq(t, "now"))
6333 else if (!strchr(t, ':')) {
6336 if (safe_atou64(t, &u) < 0)
6339 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
6348 hour = strtol(t, &e, 10);
6349 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
6352 minute = strtol(e+1, &e, 10);
6353 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
6356 n = now(CLOCK_REALTIME);
6357 s = (time_t) (n / USEC_PER_SEC);
6359 assert_se(localtime_r(&s, &tm));
6361 tm.tm_hour = (int) hour;
6362 tm.tm_min = (int) minute;
6365 assert_se(s = mktime(&tm));
6367 *_u = (usec_t) s * USEC_PER_SEC;
6370 *_u += USEC_PER_DAY;
6376 static int shutdown_parse_argv(int argc, char *argv[]) {
6383 static const struct option options[] = {
6384 { "help", no_argument, NULL, ARG_HELP },
6385 { "halt", no_argument, NULL, 'H' },
6386 { "poweroff", no_argument, NULL, 'P' },
6387 { "reboot", no_argument, NULL, 'r' },
6388 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
6389 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6398 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0)
6406 arg_action = ACTION_HALT;
6410 arg_action = ACTION_POWEROFF;
6415 arg_action = ACTION_KEXEC;
6417 arg_action = ACTION_REBOOT;
6421 arg_action = ACTION_KEXEC;
6425 if (arg_action != ACTION_HALT)
6426 arg_action = ACTION_POWEROFF;
6439 /* Compatibility nops */
6443 arg_action = ACTION_CANCEL_SHUTDOWN;
6450 assert_not_reached("Unhandled option");
6453 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
6454 r = parse_time_spec(argv[optind], &arg_when);
6456 log_error("Failed to parse time specification: %s", argv[optind]);
6460 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
6462 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
6463 /* No time argument for shutdown cancel */
6464 arg_wall = argv + optind;
6465 else if (argc > optind + 1)
6466 /* We skip the time argument */
6467 arg_wall = argv + optind + 1;
6474 static int telinit_parse_argv(int argc, char *argv[]) {
6481 static const struct option options[] = {
6482 { "help", no_argument, NULL, ARG_HELP },
6483 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6487 static const struct {
6491 { '0', ACTION_POWEROFF },
6492 { '6', ACTION_REBOOT },
6493 { '1', ACTION_RESCUE },
6494 { '2', ACTION_RUNLEVEL2 },
6495 { '3', ACTION_RUNLEVEL3 },
6496 { '4', ACTION_RUNLEVEL4 },
6497 { '5', ACTION_RUNLEVEL5 },
6498 { 's', ACTION_RESCUE },
6499 { 'S', ACTION_RESCUE },
6500 { 'q', ACTION_RELOAD },
6501 { 'Q', ACTION_RELOAD },
6502 { 'u', ACTION_REEXEC },
6503 { 'U', ACTION_REEXEC }
6512 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6527 assert_not_reached("Unhandled option");
6530 if (optind >= argc) {
6531 log_error("%s: required argument missing.",
6532 program_invocation_short_name);
6536 if (optind + 1 < argc) {
6537 log_error("Too many arguments.");
6541 if (strlen(argv[optind]) != 1) {
6542 log_error("Expected single character argument.");
6546 for (i = 0; i < ELEMENTSOF(table); i++)
6547 if (table[i].from == argv[optind][0])
6550 if (i >= ELEMENTSOF(table)) {
6551 log_error("Unknown command '%s'.", argv[optind]);
6555 arg_action = table[i].to;
6562 static int runlevel_parse_argv(int argc, char *argv[]) {
6568 static const struct option options[] = {
6569 { "help", no_argument, NULL, ARG_HELP },
6578 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6589 assert_not_reached("Unhandled option");
6592 if (optind < argc) {
6593 log_error("Too many arguments.");
6600 static int parse_argv(int argc, char *argv[]) {
6604 if (program_invocation_short_name) {
6606 if (strstr(program_invocation_short_name, "halt")) {
6607 arg_action = ACTION_HALT;
6608 return halt_parse_argv(argc, argv);
6609 } else if (strstr(program_invocation_short_name, "poweroff")) {
6610 arg_action = ACTION_POWEROFF;
6611 return halt_parse_argv(argc, argv);
6612 } else if (strstr(program_invocation_short_name, "reboot")) {
6614 arg_action = ACTION_KEXEC;
6616 arg_action = ACTION_REBOOT;
6617 return halt_parse_argv(argc, argv);
6618 } else if (strstr(program_invocation_short_name, "shutdown")) {
6619 arg_action = ACTION_POWEROFF;
6620 return shutdown_parse_argv(argc, argv);
6621 } else if (strstr(program_invocation_short_name, "init")) {
6623 if (sd_booted() > 0) {
6624 arg_action = _ACTION_INVALID;
6625 return telinit_parse_argv(argc, argv);
6627 /* Hmm, so some other init system is
6628 * running, we need to forward this
6629 * request to it. For now we simply
6630 * guess that it is Upstart. */
6632 execv(TELINIT, argv);
6634 log_error("Couldn't find an alternative telinit implementation to spawn.");
6638 } else if (strstr(program_invocation_short_name, "runlevel")) {
6639 arg_action = ACTION_RUNLEVEL;
6640 return runlevel_parse_argv(argc, argv);
6644 arg_action = ACTION_SYSTEMCTL;
6645 return systemctl_parse_argv(argc, argv);
6648 _pure_ static int action_to_runlevel(void) {
6650 static const char table[_ACTION_MAX] = {
6651 [ACTION_HALT] = '0',
6652 [ACTION_POWEROFF] = '0',
6653 [ACTION_REBOOT] = '6',
6654 [ACTION_RUNLEVEL2] = '2',
6655 [ACTION_RUNLEVEL3] = '3',
6656 [ACTION_RUNLEVEL4] = '4',
6657 [ACTION_RUNLEVEL5] = '5',
6658 [ACTION_RESCUE] = '1'
6661 assert(arg_action < _ACTION_MAX);
6663 return table[arg_action];
6666 static int talk_initctl(void) {
6668 struct init_request request = {
6669 .magic = INIT_MAGIC,
6671 .cmd = INIT_CMD_RUNLVL
6674 _cleanup_close_ int fd = -1;
6678 rl = action_to_runlevel();
6682 request.runlevel = rl;
6684 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
6686 if (errno == ENOENT)
6689 log_error("Failed to open "INIT_FIFO": %m");
6694 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
6696 log_error("Failed to write to "INIT_FIFO": %m");
6697 return errno > 0 ? -errno : -EIO;
6703 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
6705 static const struct {
6713 int (* const dispatch)(sd_bus *bus, char **args);
6719 { "list-units", MORE, 0, list_units },
6720 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
6721 { "list-sockets", MORE, 1, list_sockets },
6722 { "list-timers", MORE, 1, list_timers },
6723 { "list-jobs", MORE, 1, list_jobs },
6724 { "list-machines", MORE, 1, list_machines },
6725 { "clear-jobs", EQUAL, 1, daemon_reload },
6726 { "cancel", MORE, 2, cancel_job },
6727 { "start", MORE, 2, start_unit },
6728 { "stop", MORE, 2, start_unit },
6729 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6730 { "reload", MORE, 2, start_unit },
6731 { "restart", MORE, 2, start_unit },
6732 { "try-restart", MORE, 2, start_unit },
6733 { "reload-or-restart", MORE, 2, start_unit },
6734 { "reload-or-try-restart", MORE, 2, start_unit },
6735 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
6736 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6737 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
6738 { "isolate", EQUAL, 2, start_unit },
6739 { "kill", MORE, 2, kill_unit },
6740 { "is-active", MORE, 2, check_unit_active },
6741 { "check", MORE, 2, check_unit_active },
6742 { "is-failed", MORE, 2, check_unit_failed },
6743 { "show", MORE, 1, show },
6744 { "cat", MORE, 2, cat },
6745 { "status", MORE, 1, show },
6746 { "help", MORE, 2, show },
6747 { "snapshot", LESS, 2, snapshot },
6748 { "delete", MORE, 2, delete_snapshot },
6749 { "daemon-reload", EQUAL, 1, daemon_reload },
6750 { "daemon-reexec", EQUAL, 1, daemon_reload },
6751 { "show-environment", EQUAL, 1, show_environment },
6752 { "set-environment", MORE, 2, set_environment },
6753 { "unset-environment", MORE, 2, set_environment },
6754 { "import-environment", MORE, 1, import_environment},
6755 { "halt", EQUAL, 1, start_special, FORCE },
6756 { "poweroff", EQUAL, 1, start_special, FORCE },
6757 { "reboot", EQUAL, 1, start_special, FORCE },
6758 { "kexec", EQUAL, 1, start_special },
6759 { "suspend", EQUAL, 1, start_special },
6760 { "hibernate", EQUAL, 1, start_special },
6761 { "hybrid-sleep", EQUAL, 1, start_special },
6762 { "default", EQUAL, 1, start_special },
6763 { "rescue", EQUAL, 1, start_special },
6764 { "emergency", EQUAL, 1, start_special },
6765 { "exit", EQUAL, 1, start_special },
6766 { "reset-failed", MORE, 1, reset_failed },
6767 { "enable", MORE, 2, enable_unit, NOBUS },
6768 { "disable", MORE, 2, enable_unit, NOBUS },
6769 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
6770 { "reenable", MORE, 2, enable_unit, NOBUS },
6771 { "preset", MORE, 2, enable_unit, NOBUS },
6772 { "preset-all", EQUAL, 1, preset_all, NOBUS },
6773 { "mask", MORE, 2, enable_unit, NOBUS },
6774 { "unmask", MORE, 2, enable_unit, NOBUS },
6775 { "link", MORE, 2, enable_unit, NOBUS },
6776 { "switch-root", MORE, 2, switch_root },
6777 { "list-dependencies", LESS, 2, list_dependencies },
6778 { "set-default", EQUAL, 2, set_default, NOBUS },
6779 { "get-default", EQUAL, 1, get_default, NOBUS },
6780 { "set-property", MORE, 3, set_property },
6781 { "is-system-running", EQUAL, 1, is_system_running },
6782 { "add-wants", MORE, 3, add_dependency, NOBUS },
6783 { "add-requires", MORE, 3, add_dependency, NOBUS },
6792 left = argc - optind;
6794 /* Special rule: no arguments (left == 0) means "list-units" */
6796 if (streq(argv[optind], "help") && !argv[optind+1]) {
6797 log_error("This command expects one or more "
6798 "unit names. Did you mean --help?");
6802 for (; verb->verb; verb++)
6803 if (streq(argv[optind], verb->verb))
6806 log_error("Unknown operation '%s'.", argv[optind]);
6811 switch (verb->argc_cmp) {
6814 if (left != verb->argc) {
6815 log_error("Invalid number of arguments.");
6822 if (left < verb->argc) {
6823 log_error("Too few arguments.");
6830 if (left > verb->argc) {
6831 log_error("Too many arguments.");
6838 assert_not_reached("Unknown comparison operator.");
6841 /* Require a bus connection for all operations but
6843 if (verb->bus == NOBUS) {
6844 if (!bus && !avoid_bus()) {
6845 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6850 if (running_in_chroot() > 0) {
6851 log_info("Running in chroot, ignoring request.");
6855 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
6856 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6861 return verb->dispatch(bus, argv + optind);
6864 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
6866 struct sd_shutdown_command c = {
6873 union sockaddr_union sockaddr = {
6874 .un.sun_family = AF_UNIX,
6875 .un.sun_path = "/run/systemd/shutdownd",
6878 struct iovec iovec[2] = {{
6879 .iov_base = (char*) &c,
6880 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
6883 struct msghdr msghdr = {
6884 .msg_name = &sockaddr,
6885 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
6886 + strlen("/run/systemd/shutdownd"),
6891 _cleanup_close_ int fd;
6893 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
6897 if (!isempty(message)) {
6898 iovec[1].iov_base = (char*) message;
6899 iovec[1].iov_len = strlen(message);
6900 msghdr.msg_iovlen++;
6903 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
6909 static int reload_with_fallback(sd_bus *bus) {
6912 /* First, try systemd via D-Bus. */
6913 if (daemon_reload(bus, NULL) >= 0)
6917 /* Nothing else worked, so let's try signals */
6918 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
6920 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
6921 log_error("kill() failed: %m");
6928 static int start_with_fallback(sd_bus *bus) {
6931 /* First, try systemd via D-Bus. */
6932 if (start_unit(bus, NULL) >= 0)
6936 /* Nothing else worked, so let's try
6938 if (talk_initctl() > 0)
6941 log_error("Failed to talk to init daemon.");
6945 warn_wall(arg_action);
6949 static int halt_now(enum action a) {
6951 /* Make sure C-A-D is handled by the kernel from this
6953 reboot(RB_ENABLE_CAD);
6958 log_info("Halting.");
6959 reboot(RB_HALT_SYSTEM);
6962 case ACTION_POWEROFF:
6963 log_info("Powering off.");
6964 reboot(RB_POWER_OFF);
6967 case ACTION_REBOOT: {
6968 _cleanup_free_ char *param = NULL;
6970 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
6971 log_info("Rebooting with argument '%s'.", param);
6972 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
6973 LINUX_REBOOT_CMD_RESTART2, param);
6976 log_info("Rebooting.");
6977 reboot(RB_AUTOBOOT);
6982 assert_not_reached("Unknown action.");
6986 static int halt_main(sd_bus *bus) {
6989 r = check_inhibitors(bus, arg_action);
6993 if (geteuid() != 0) {
6994 /* Try logind if we are a normal user and no special
6995 * mode applies. Maybe PolicyKit allows us to shutdown
6998 if (arg_when <= 0 &&
7001 (arg_action == ACTION_POWEROFF ||
7002 arg_action == ACTION_REBOOT)) {
7003 r = reboot_with_logind(bus, arg_action);
7008 log_error("Must be root.");
7013 _cleanup_free_ char *m;
7015 m = strv_join(arg_wall, " ");
7019 r = send_shutdownd(arg_when,
7020 arg_action == ACTION_HALT ? 'H' :
7021 arg_action == ACTION_POWEROFF ? 'P' :
7022 arg_action == ACTION_KEXEC ? 'K' :
7029 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
7031 char date[FORMAT_TIMESTAMP_MAX];
7033 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
7034 format_timestamp(date, sizeof(date), arg_when));
7039 if (!arg_dry && !arg_force)
7040 return start_with_fallback(bus);
7043 if (sd_booted() > 0)
7044 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7046 r = utmp_put_shutdown();
7048 log_warning("Failed to write utmp record: %s", strerror(-r));
7055 r = halt_now(arg_action);
7056 log_error("Failed to reboot: %s", strerror(-r));
7061 static int runlevel_main(void) {
7062 int r, runlevel, previous;
7064 r = utmp_get_runlevel(&runlevel, &previous);
7071 previous <= 0 ? 'N' : previous,
7072 runlevel <= 0 ? 'N' : runlevel);
7077 int main(int argc, char*argv[]) {
7078 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
7081 setlocale(LC_ALL, "");
7082 log_parse_environment();
7085 /* Explicitly not on_tty() to avoid setting cached value.
7086 * This becomes relevant for piping output which might be
7088 original_stdout_is_tty = isatty(STDOUT_FILENO);
7090 r = parse_argv(argc, argv);
7094 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
7095 * let's shortcut this */
7096 if (arg_action == ACTION_RUNLEVEL) {
7097 r = runlevel_main();
7101 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
7102 log_info("Running in chroot, ignoring request.");
7108 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
7110 /* systemctl_main() will print an error message for the bus
7111 * connection, but only if it needs to */
7113 switch (arg_action) {
7115 case ACTION_SYSTEMCTL:
7116 r = systemctl_main(bus, argc, argv, r);
7120 case ACTION_POWEROFF:
7126 case ACTION_RUNLEVEL2:
7127 case ACTION_RUNLEVEL3:
7128 case ACTION_RUNLEVEL4:
7129 case ACTION_RUNLEVEL5:
7131 case ACTION_EMERGENCY:
7132 case ACTION_DEFAULT:
7133 r = start_with_fallback(bus);
7138 r = reload_with_fallback(bus);
7141 case ACTION_CANCEL_SHUTDOWN: {
7142 _cleanup_free_ char *m = NULL;
7145 m = strv_join(arg_wall, " ");
7152 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
7154 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
7158 case ACTION_RUNLEVEL:
7159 case _ACTION_INVALID:
7161 assert_not_reached("Unknown action");
7166 ask_password_agent_close();
7167 polkit_agent_close();
7169 strv_free(arg_types);
7170 strv_free(arg_states);
7171 strv_free(arg_properties);
7173 return r < 0 ? EXIT_FAILURE : r;