1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Marc-Antoine Perennou
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/reboot.h>
24 #include <linux/reboot.h>
25 #include <sys/syscall.h>
32 #include <sys/ioctl.h>
36 #include <sys/socket.h>
39 #include <sys/prctl.h>
42 #include "sd-daemon.h"
43 #include "sd-shutdown.h"
50 #include "utmp-wtmp.h"
53 #include "path-util.h"
55 #include "cgroup-show.h"
56 #include "cgroup-util.h"
58 #include "path-lookup.h"
59 #include "conf-parser.h"
60 #include "exit-status.h"
62 #include "unit-name.h"
64 #include "spawn-ask-password-agent.h"
65 #include "spawn-polkit-agent.h"
67 #include "logs-show.h"
68 #include "socket-util.h"
72 #include "bus-message.h"
73 #include "bus-error.h"
74 #include "bus-errors.h"
76 static char **arg_types = NULL;
77 static char **arg_states = NULL;
78 static char **arg_properties = NULL;
79 static bool arg_all = false;
80 static enum dependency {
86 } arg_dependency = DEPENDENCY_FORWARD;
87 static const char *arg_job_mode = "replace";
88 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
89 static bool arg_no_block = false;
90 static bool arg_no_legend = false;
91 static bool arg_no_pager = false;
92 static bool arg_no_wtmp = false;
93 static bool arg_no_wall = false;
94 static bool arg_no_reload = false;
95 static bool arg_show_types = false;
96 static bool arg_ignore_inhibitors = false;
97 static bool arg_dry = false;
98 static bool arg_quiet = false;
99 static bool arg_full = false;
100 static bool arg_recursive = false;
101 static int arg_force = 0;
102 static bool arg_ask_password = true;
103 static bool arg_runtime = false;
104 static UnitFilePresetMode arg_preset_mode = UNIT_FILE_PRESET_FULL;
105 static char **arg_wall = NULL;
106 static const char *arg_kill_who = NULL;
107 static int arg_signal = SIGTERM;
108 static const char *arg_root = NULL;
109 static usec_t arg_when = 0;
131 ACTION_CANCEL_SHUTDOWN,
133 } arg_action = ACTION_SYSTEMCTL;
134 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
135 static char *arg_host = NULL;
136 static unsigned arg_lines = 10;
137 static OutputMode arg_output = OUTPUT_SHORT;
138 static bool arg_plain = false;
140 static bool original_stdout_is_tty;
142 static int daemon_reload(sd_bus *bus, char **args);
143 static int halt_now(enum action a);
144 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet);
146 static char** strv_skip_first(char **strv) {
147 if (strv_length(strv) > 0)
152 static void pager_open_if_enabled(void) {
160 static void ask_password_agent_open_if_enabled(void) {
162 /* Open the password agent as a child process if necessary */
164 if (!arg_ask_password)
167 if (arg_scope != UNIT_FILE_SYSTEM)
170 if (arg_transport != BUS_TRANSPORT_LOCAL)
173 ask_password_agent_open();
177 static void polkit_agent_open_if_enabled(void) {
179 /* Open the polkit agent as a child process if necessary */
181 if (!arg_ask_password)
184 if (arg_scope != UNIT_FILE_SYSTEM)
187 if (arg_transport != BUS_TRANSPORT_LOCAL)
194 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
197 if (!sd_bus_error_is_set(error))
200 if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) ||
201 sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
202 sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
203 sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
204 return EXIT_NOPERMISSION;
206 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
207 return EXIT_NOTINSTALLED;
209 if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
210 sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED))
211 return EXIT_NOTIMPLEMENTED;
213 if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
214 return EXIT_NOTCONFIGURED;
222 static void warn_wall(enum action a) {
223 static const char *table[_ACTION_MAX] = {
224 [ACTION_HALT] = "The system is going down for system halt NOW!",
225 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
226 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
227 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
228 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
229 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
230 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
237 _cleanup_free_ char *p;
239 p = strv_join(arg_wall, " ");
246 utmp_wall(p, NULL, NULL);
254 utmp_wall(table[a], NULL, NULL);
257 static bool avoid_bus(void) {
259 if (running_in_chroot() > 0)
262 if (sd_booted() <= 0)
265 if (!isempty(arg_root))
268 if (arg_scope == UNIT_FILE_GLOBAL)
274 static int compare_unit_info(const void *a, const void *b) {
275 const UnitInfo *u = a, *v = b;
279 /* First, order by machine */
280 if (!u->machine && v->machine)
282 if (u->machine && !v->machine)
284 if (u->machine && v->machine) {
285 r = strcasecmp(u->machine, v->machine);
290 /* Second, order by unit type */
291 d1 = strrchr(u->id, '.');
292 d2 = strrchr(v->id, '.');
294 r = strcasecmp(d1, d2);
299 /* Third, order by name */
300 return strcasecmp(u->id, v->id);
303 static bool output_show_unit(const UnitInfo *u, char **patterns) {
306 if (!strv_isempty(patterns)) {
309 STRV_FOREACH(pattern, patterns)
310 if (fnmatch(*pattern, u->id, FNM_NOESCAPE) == 0)
315 return (!arg_types || ((dot = strrchr(u->id, '.')) &&
316 strv_find(arg_types, dot+1))) &&
317 (arg_all || !(streq(u->active_state, "inactive")
318 || u->following[0]) || u->job_id > 0);
321 static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
322 unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
324 unsigned n_shown = 0;
327 max_id_len = strlen("UNIT");
328 load_len = strlen("LOAD");
329 active_len = strlen("ACTIVE");
330 sub_len = strlen("SUB");
331 job_len = strlen("JOB");
334 for (u = unit_infos; u < unit_infos + c; u++) {
335 max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0));
336 load_len = MAX(load_len, strlen(u->load_state));
337 active_len = MAX(active_len, strlen(u->active_state));
338 sub_len = MAX(sub_len, strlen(u->sub_state));
340 if (u->job_id != 0) {
341 job_len = MAX(job_len, strlen(u->job_type));
345 if (!arg_no_legend &&
346 (streq(u->active_state, "failed") ||
347 STR_IN_SET(u->load_state, "error", "not-found", "masked")))
351 if (!arg_full && original_stdout_is_tty) {
354 id_len = MIN(max_id_len, 25u);
355 basic_len = circle_len + 5 + id_len + 5 + active_len + sub_len;
358 basic_len += job_len + 1;
360 if (basic_len < (unsigned) columns()) {
361 unsigned extra_len, incr;
362 extra_len = columns() - basic_len;
364 /* Either UNIT already got 25, or is fully satisfied.
365 * Grant up to 25 to DESC now. */
366 incr = MIN(extra_len, 25u);
370 /* split the remaining space between UNIT and DESC,
371 * but do not give UNIT more than it needs. */
373 incr = MIN(extra_len / 2, max_id_len - id_len);
375 desc_len += extra_len - incr;
381 for (u = unit_infos; u < unit_infos + c; u++) {
382 _cleanup_free_ char *e = NULL, *j = NULL;
383 const char *on_loaded = "", *off_loaded = "";
384 const char *on_active = "", *off_active = "";
385 const char *on_circle = "", *off_circle = "";
389 if (!n_shown && !arg_no_legend) {
394 printf("%-*s %-*s %-*s %-*s ",
397 active_len, "ACTIVE",
401 printf("%-*s ", job_len, "JOB");
403 if (!arg_full && arg_no_pager)
404 printf("%.*s\n", desc_len, "DESCRIPTION");
406 printf("%s\n", "DESCRIPTION");
411 if (STR_IN_SET(u->load_state, "error", "not-found", "masked")) {
412 on_loaded = ansi_highlight_red();
413 on_circle = ansi_highlight_yellow();
414 off_loaded = off_circle = ansi_highlight_off();
418 if (streq(u->active_state, "failed")) {
419 on_circle = on_active = ansi_highlight_red();
420 off_circle = off_active = ansi_highlight_off();
425 j = strjoin(u->machine, ":", u->id, NULL);
434 e = ellipsize(id, id_len, 33);
442 printf("%s%s%s ", on_circle, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_circle);
444 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
445 on_active, id_len, id, off_active,
446 on_loaded, load_len, u->load_state, off_loaded,
447 on_active, active_len, u->active_state,
448 sub_len, u->sub_state, off_active,
449 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
452 printf("%.*s\n", desc_len, u->description);
454 printf("%s\n", u->description);
457 if (!arg_no_legend) {
458 const char *on, *off;
462 "LOAD = Reflects whether the unit definition was properly loaded.\n"
463 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
464 "SUB = The low-level unit activation state, values depend on unit type.");
465 puts(job_count ? "JOB = Pending job for the unit.\n" : "");
466 on = ansi_highlight();
467 off = ansi_highlight_off();
469 on = ansi_highlight_red();
470 off = ansi_highlight_off();
474 printf("%s%u loaded units listed.%s\n"
475 "To show all installed unit files use 'systemctl list-unit-files'.\n",
478 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
479 "To show all installed unit files use 'systemctl list-unit-files'.\n",
486 static int get_unit_list(
490 UnitInfo **unit_infos,
492 sd_bus_message **_reply) {
494 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
495 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
496 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
505 r = sd_bus_message_new_method_call(
508 "org.freedesktop.systemd1",
509 "/org/freedesktop/systemd1",
510 "org.freedesktop.systemd1.Manager",
511 "ListUnitsFiltered");
514 return bus_log_create_error(r);
516 r = sd_bus_message_append_strv(m, arg_states);
518 return bus_log_create_error(r);
520 r = sd_bus_call(bus, m, 0, &error, &reply);
522 log_error("Failed to list units: %s", bus_error_message(&error, r));
526 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
528 return bus_log_parse_error(r);
530 while ((r = bus_parse_unit_info(reply, &u)) > 0) {
533 if (!output_show_unit(&u, patterns))
536 if (!GREEDY_REALLOC(*unit_infos, size, c+1))
539 (*unit_infos)[c++] = u;
542 return bus_log_parse_error(r);
544 r = sd_bus_message_exit_container(reply);
546 return bus_log_parse_error(r);
554 static void message_set_freep(Set **set) {
557 while ((m = set_steal_first(*set)))
558 sd_bus_message_unref(m);
563 static int get_unit_list_recursive(
566 UnitInfo **_unit_infos,
570 _cleanup_free_ UnitInfo *unit_infos = NULL;
571 _cleanup_(message_set_freep) Set *replies;
572 sd_bus_message *reply;
580 replies = set_new(NULL);
584 c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
588 r = set_put(replies, reply);
590 sd_bus_message_unref(reply);
595 _cleanup_strv_free_ char **machines = NULL;
598 r = sd_get_machine_names(&machines);
602 STRV_FOREACH(i, machines) {
603 _cleanup_bus_close_unref_ sd_bus *container = NULL;
606 r = sd_bus_open_system_container(&container, *i);
608 log_error("Failed to connect to container %s: %s", *i, strerror(-r));
612 k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
618 r = set_put(replies, reply);
620 sd_bus_message_unref(reply);
625 *_machines = machines;
630 *_unit_infos = unit_infos;
639 static int list_units(sd_bus *bus, char **args) {
640 _cleanup_free_ UnitInfo *unit_infos = NULL;
641 _cleanup_(message_set_freep) Set *replies = NULL;
642 _cleanup_strv_free_ char **machines = NULL;
645 pager_open_if_enabled();
647 r = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
651 qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
652 return output_units_list(unit_infos, r);
655 static int get_triggered_units(
660 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
663 r = sd_bus_get_property_strv(
665 "org.freedesktop.systemd1",
667 "org.freedesktop.systemd1.Unit",
673 log_error("Failed to determine triggers: %s", bus_error_message(&error, r));
678 static int get_listening(
680 const char* unit_path,
683 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
684 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
685 const char *type, *path;
688 r = sd_bus_get_property(
690 "org.freedesktop.systemd1",
692 "org.freedesktop.systemd1.Socket",
698 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r));
702 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
704 return bus_log_parse_error(r);
706 while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
708 r = strv_extend(listening, type);
712 r = strv_extend(listening, path);
719 return bus_log_parse_error(r);
721 r = sd_bus_message_exit_container(reply);
723 return bus_log_parse_error(r);
735 /* Note: triggered is a list here, although it almost certainly
736 * will always be one unit. Nevertheless, dbus API allows for multiple
737 * values, so let's follow that.*/
740 /* The strv above is shared. free is set only in the first one. */
744 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
750 if (!a->machine && b->machine)
752 if (a->machine && !b->machine)
754 if (a->machine && b->machine) {
755 o = strcasecmp(a->machine, b->machine);
760 o = strcmp(a->path, b->path);
762 o = strcmp(a->type, b->type);
767 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
768 struct socket_info *s;
769 unsigned pathlen = strlen("LISTEN"),
770 typelen = strlen("TYPE") * arg_show_types,
771 socklen = strlen("UNIT"),
772 servlen = strlen("ACTIVATES");
773 const char *on, *off;
775 for (s = socket_infos; s < socket_infos + cs; s++) {
779 socklen = MAX(socklen, strlen(s->id));
781 typelen = MAX(typelen, strlen(s->type));
782 pathlen = MAX(pathlen, strlen(s->path) + (s->machine ? strlen(s->machine)+1 : 0));
784 STRV_FOREACH(a, s->triggered)
785 tmp += strlen(*a) + 2*(a != s->triggered);
786 servlen = MAX(servlen, tmp);
791 printf("%-*s %-*.*s%-*s %s\n",
793 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
797 for (s = socket_infos; s < socket_infos + cs; s++) {
798 _cleanup_free_ char *j = NULL;
803 j = strjoin(s->machine, ":", s->path, NULL);
811 printf("%-*s %-*s %-*s",
812 pathlen, path, typelen, s->type, socklen, s->id);
815 pathlen, path, socklen, s->id);
816 STRV_FOREACH(a, s->triggered)
818 a == s->triggered ? "" : ",", *a);
822 on = ansi_highlight();
823 off = ansi_highlight_off();
827 on = ansi_highlight_red();
828 off = ansi_highlight_off();
831 if (!arg_no_legend) {
832 printf("%s%u sockets listed.%s\n", on, cs, off);
834 printf("Pass --all to see loaded but inactive sockets, too.\n");
840 static int list_sockets(sd_bus *bus, char **args) {
841 _cleanup_(message_set_freep) Set *replies = NULL;
842 _cleanup_strv_free_ char **machines = NULL;
843 _cleanup_free_ UnitInfo *unit_infos = NULL;
844 _cleanup_free_ struct socket_info *socket_infos = NULL;
846 struct socket_info *s;
851 pager_open_if_enabled();
853 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
857 for (u = unit_infos; u < unit_infos + n; u++) {
858 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
861 if (!endswith(u->id, ".socket"))
864 r = get_triggered_units(bus, u->unit_path, &triggered);
868 c = get_listening(bus, u->unit_path, &listening);
874 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
879 for (i = 0; i < c; i++)
880 socket_infos[cs + i] = (struct socket_info) {
881 .machine = u->machine,
883 .type = listening[i*2],
884 .path = listening[i*2 + 1],
885 .triggered = triggered,
886 .own_triggered = i==0,
889 /* from this point on we will cleanup those socket_infos */
892 listening = triggered = NULL; /* avoid cleanup */
895 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
896 (__compar_fn_t) socket_info_compare);
898 output_sockets_list(socket_infos, cs);
901 assert(cs == 0 || socket_infos);
902 for (s = socket_infos; s < socket_infos + cs; s++) {
905 if (s->own_triggered)
906 strv_free(s->triggered);
912 static int get_next_elapse(
915 dual_timestamp *next) {
917 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
925 r = sd_bus_get_property_trivial(
927 "org.freedesktop.systemd1",
929 "org.freedesktop.systemd1.Timer",
930 "NextElapseUSecMonotonic",
935 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
939 r = sd_bus_get_property_trivial(
941 "org.freedesktop.systemd1",
943 "org.freedesktop.systemd1.Timer",
944 "NextElapseUSecRealtime",
949 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
957 static int get_last_trigger(
962 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
969 r = sd_bus_get_property_trivial(
971 "org.freedesktop.systemd1",
973 "org.freedesktop.systemd1.Timer",
979 log_error("Failed to get last trigger time: %s", bus_error_message(&error, r));
994 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
1000 if (!a->machine && b->machine)
1002 if (a->machine && !b->machine)
1004 if (a->machine && b->machine) {
1005 o = strcasecmp(a->machine, b->machine);
1010 if (a->next_elapse < b->next_elapse)
1012 if (a->next_elapse > b->next_elapse)
1015 return strcmp(a->id, b->id);
1018 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
1019 struct timer_info *t;
1021 nextlen = strlen("NEXT"),
1022 leftlen = strlen("LEFT"),
1023 lastlen = strlen("LAST"),
1024 passedlen = strlen("PASSED"),
1025 unitlen = strlen("UNIT"),
1026 activatelen = strlen("ACTIVATES");
1028 const char *on, *off;
1030 assert(timer_infos || n == 0);
1032 for (t = timer_infos; t < timer_infos + n; t++) {
1036 if (t->next_elapse > 0) {
1037 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1039 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
1040 nextlen = MAX(nextlen, strlen(tstamp) + 1);
1042 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
1043 leftlen = MAX(leftlen, strlen(trel));
1046 if (t->last_trigger > 0) {
1047 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1049 format_timestamp(tstamp, sizeof(tstamp), t->last_trigger);
1050 lastlen = MAX(lastlen, strlen(tstamp) + 1);
1052 format_timestamp_relative(trel, sizeof(trel), t->last_trigger);
1053 passedlen = MAX(passedlen, strlen(trel));
1056 unitlen = MAX(unitlen, strlen(t->id) + (t->machine ? strlen(t->machine)+1 : 0));
1058 STRV_FOREACH(a, t->triggered)
1059 ul += strlen(*a) + 2*(a != t->triggered);
1061 activatelen = MAX(activatelen, ul);
1066 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1070 passedlen, "PASSED",
1074 for (t = timer_infos; t < timer_infos + n; t++) {
1075 _cleanup_free_ char *j = NULL;
1077 char tstamp1[FORMAT_TIMESTAMP_MAX] = "n/a", trel1[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1078 char tstamp2[FORMAT_TIMESTAMP_MAX] = "n/a", trel2[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1081 format_timestamp(tstamp1, sizeof(tstamp1), t->next_elapse);
1082 format_timestamp_relative(trel1, sizeof(trel1), t->next_elapse);
1084 format_timestamp(tstamp2, sizeof(tstamp2), t->last_trigger);
1085 format_timestamp_relative(trel2, sizeof(trel2), t->last_trigger);
1088 j = strjoin(t->machine, ":", t->id, NULL);
1095 printf("%-*s %-*s %-*s %-*s %-*s",
1096 nextlen, tstamp1, leftlen, trel1, lastlen, tstamp2, passedlen, trel2, unitlen, unit);
1098 STRV_FOREACH(a, t->triggered)
1100 a == t->triggered ? "" : ",", *a);
1104 on = ansi_highlight();
1105 off = ansi_highlight_off();
1109 on = ansi_highlight_red();
1110 off = ansi_highlight_off();
1113 if (!arg_no_legend) {
1114 printf("%s%u timers listed.%s\n", on, n, off);
1116 printf("Pass --all to see loaded but inactive timers, too.\n");
1122 static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
1128 if (next->monotonic != USEC_INFINITY && next->monotonic > 0) {
1131 if (next->monotonic > nw->monotonic)
1132 converted = nw->realtime + (next->monotonic - nw->monotonic);
1134 converted = nw->realtime - (nw->monotonic - next->monotonic);
1136 if (next->realtime != USEC_INFINITY && next->realtime > 0)
1137 next_elapse = MIN(converted, next->realtime);
1139 next_elapse = converted;
1142 next_elapse = next->realtime;
1147 static int list_timers(sd_bus *bus, char **args) {
1148 _cleanup_(message_set_freep) Set *replies = NULL;
1149 _cleanup_strv_free_ char **machines = NULL;
1150 _cleanup_free_ struct timer_info *timer_infos = NULL;
1151 _cleanup_free_ UnitInfo *unit_infos = NULL;
1152 struct timer_info *t;
1159 pager_open_if_enabled();
1161 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
1165 dual_timestamp_get(&nw);
1167 for (u = unit_infos; u < unit_infos + n; u++) {
1168 _cleanup_strv_free_ char **triggered = NULL;
1169 dual_timestamp next = {};
1172 if (!endswith(u->id, ".timer"))
1175 r = get_triggered_units(bus, u->unit_path, &triggered);
1179 r = get_next_elapse(bus, u->unit_path, &next);
1183 get_last_trigger(bus, u->unit_path, &last);
1185 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
1190 m = calc_next_elapse(&nw, &next);
1192 timer_infos[c++] = (struct timer_info) {
1193 .machine = u->machine,
1196 .last_trigger = last,
1197 .triggered = triggered,
1200 triggered = NULL; /* avoid cleanup */
1203 qsort_safe(timer_infos, c, sizeof(struct timer_info),
1204 (__compar_fn_t) timer_info_compare);
1206 output_timers_list(timer_infos, c);
1209 for (t = timer_infos; t < timer_infos + c; t++)
1210 strv_free(t->triggered);
1215 static int compare_unit_file_list(const void *a, const void *b) {
1216 const char *d1, *d2;
1217 const UnitFileList *u = a, *v = b;
1219 d1 = strrchr(u->path, '.');
1220 d2 = strrchr(v->path, '.');
1225 r = strcasecmp(d1, d2);
1230 return strcasecmp(basename(u->path), basename(v->path));
1233 static bool output_show_unit_file(const UnitFileList *u, char **patterns) {
1236 if (!strv_isempty(patterns)) {
1239 STRV_FOREACH(pattern, patterns)
1240 if (fnmatch(*pattern, basename(u->path), FNM_NOESCAPE) == 0)
1245 return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
1248 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
1249 unsigned max_id_len, id_cols, state_cols;
1250 const UnitFileList *u;
1252 max_id_len = strlen("UNIT FILE");
1253 state_cols = strlen("STATE");
1255 for (u = units; u < units + c; u++) {
1256 max_id_len = MAX(max_id_len, strlen(basename(u->path)));
1257 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1261 unsigned basic_cols;
1263 id_cols = MIN(max_id_len, 25u);
1264 basic_cols = 1 + id_cols + state_cols;
1265 if (basic_cols < (unsigned) columns())
1266 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1268 id_cols = max_id_len;
1271 printf("%-*s %-*s\n",
1272 id_cols, "UNIT FILE",
1273 state_cols, "STATE");
1275 for (u = units; u < units + c; u++) {
1276 _cleanup_free_ char *e = NULL;
1277 const char *on, *off;
1280 if (u->state == UNIT_FILE_MASKED ||
1281 u->state == UNIT_FILE_MASKED_RUNTIME ||
1282 u->state == UNIT_FILE_DISABLED ||
1283 u->state == UNIT_FILE_INVALID) {
1284 on = ansi_highlight_red();
1285 off = ansi_highlight_off();
1286 } else if (u->state == UNIT_FILE_ENABLED) {
1287 on = ansi_highlight_green();
1288 off = ansi_highlight_off();
1292 id = basename(u->path);
1294 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1296 printf("%-*s %s%-*s%s\n",
1297 id_cols, e ? e : id,
1298 on, state_cols, unit_file_state_to_string(u->state), off);
1302 printf("\n%u unit files listed.\n", c);
1305 static int list_unit_files(sd_bus *bus, char **args) {
1306 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1307 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1308 _cleanup_free_ UnitFileList *units = NULL;
1316 pager_open_if_enabled();
1324 h = hashmap_new(&string_hash_ops);
1328 r = unit_file_get_list(arg_scope, arg_root, h);
1330 unit_file_list_free(h);
1331 log_error("Failed to get unit file list: %s", strerror(-r));
1335 n_units = hashmap_size(h);
1337 units = new(UnitFileList, n_units);
1338 if (!units && n_units > 0) {
1339 unit_file_list_free(h);
1343 HASHMAP_FOREACH(u, h, i) {
1344 if (!output_show_unit_file(u, strv_skip_first(args)))
1351 assert(c <= n_units);
1354 r = sd_bus_call_method(
1356 "org.freedesktop.systemd1",
1357 "/org/freedesktop/systemd1",
1358 "org.freedesktop.systemd1.Manager",
1364 log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1368 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1370 return bus_log_parse_error(r);
1372 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1374 if (!GREEDY_REALLOC(units, size, c + 1))
1377 units[c] = (struct UnitFileList) {
1379 unit_file_state_from_string(state)
1382 if (output_show_unit_file(&units[c], strv_skip_first(args)))
1387 return bus_log_parse_error(r);
1389 r = sd_bus_message_exit_container(reply);
1391 return bus_log_parse_error(r);
1394 qsort_safe(units, c, sizeof(UnitFileList), compare_unit_file_list);
1395 output_unit_file_list(units, c);
1398 for (unit = units; unit < units + c; unit++)
1405 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1406 _cleanup_free_ char *n = NULL;
1407 size_t max_len = MAX(columns(),20u);
1413 for (i = level - 1; i >= 0; i--) {
1415 if (len > max_len - 3 && !arg_full) {
1416 printf("%s...\n",max_len % 2 ? "" : " ");
1419 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERTICAL : DRAW_TREE_SPACE));
1423 if (len > max_len - 3 && !arg_full) {
1424 printf("%s...\n",max_len % 2 ? "" : " ");
1428 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
1432 printf("%s\n", name);
1436 n = ellipsize(name, max_len-len, 100);
1444 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1446 static const char *dependencies[_DEPENDENCY_MAX] = {
1447 [DEPENDENCY_FORWARD] = "Requires\0"
1448 "RequiresOverridable\0"
1450 "RequisiteOverridable\0"
1452 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1453 "RequiredByOverridable\0"
1456 [DEPENDENCY_AFTER] = "After\0",
1457 [DEPENDENCY_BEFORE] = "Before\0",
1460 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1461 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1462 _cleanup_strv_free_ char **ret = NULL;
1463 _cleanup_free_ char *path = NULL;
1469 assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
1471 path = unit_dbus_path_from_name(name);
1475 r = sd_bus_call_method(
1477 "org.freedesktop.systemd1",
1479 "org.freedesktop.DBus.Properties",
1483 "s", "org.freedesktop.systemd1.Unit");
1485 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1489 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1491 return bus_log_parse_error(r);
1493 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1496 r = sd_bus_message_read(reply, "s", &prop);
1498 return bus_log_parse_error(r);
1500 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1501 r = sd_bus_message_skip(reply, "v");
1503 return bus_log_parse_error(r);
1506 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1508 return bus_log_parse_error(r);
1510 r = bus_message_read_strv_extend(reply, &ret);
1512 return bus_log_parse_error(r);
1514 r = sd_bus_message_exit_container(reply);
1516 return bus_log_parse_error(r);
1519 r = sd_bus_message_exit_container(reply);
1521 return bus_log_parse_error(r);
1525 return bus_log_parse_error(r);
1527 r = sd_bus_message_exit_container(reply);
1529 return bus_log_parse_error(r);
1537 static int list_dependencies_compare(const void *_a, const void *_b) {
1538 const char **a = (const char**) _a, **b = (const char**) _b;
1540 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1542 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1545 return strcasecmp(*a, *b);
1548 static int list_dependencies_one(
1553 unsigned int branches) {
1555 _cleanup_strv_free_ char **deps = NULL;
1563 r = strv_extend(units, name);
1567 r = list_dependencies_get_dependencies(bus, name, &deps);
1571 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1573 STRV_FOREACH(c, deps) {
1576 if (strv_contains(*units, *c)) {
1578 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1585 state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true);
1587 printf("%s%s%s ", ansi_highlight_green(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1589 printf("%s%s%s ", ansi_highlight_red(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1591 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1595 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1596 r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1603 strv_remove(*units, name);
1608 static int list_dependencies(sd_bus *bus, char **args) {
1609 _cleanup_strv_free_ char **units = NULL;
1610 _cleanup_free_ char *unit = NULL;
1616 unit = unit_name_mangle(args[1], MANGLE_NOGLOB);
1621 u = SPECIAL_DEFAULT_TARGET;
1623 pager_open_if_enabled();
1627 return list_dependencies_one(bus, u, 0, &units, 0);
1630 struct machine_info {
1634 char *control_group;
1635 uint32_t n_failed_units;
1640 static const struct bus_properties_map machine_info_property_map[] = {
1641 { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
1642 { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
1643 { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
1644 { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
1645 { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
1649 static void free_machines_list(struct machine_info *machine_infos, int n) {
1655 for (i = 0; i < n; i++) {
1656 free(machine_infos[i].name);
1657 free(machine_infos[i].state);
1658 free(machine_infos[i].control_group);
1661 free(machine_infos);
1664 static int compare_machine_info(const void *a, const void *b) {
1665 const struct machine_info *u = a, *v = b;
1667 if (u->is_host != v->is_host)
1668 return u->is_host > v->is_host ? -1 : 1;
1670 return strcasecmp(u->name, v->name);
1673 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1674 _cleanup_bus_close_unref_ sd_bus *container = NULL;
1680 r = sd_bus_open_system_container(&container, mi->name);
1687 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi);
1694 static bool output_show_machine(const char *name, char **patterns) {
1699 if (strv_isempty(patterns))
1702 STRV_FOREACH(i, patterns)
1703 if (fnmatch(*i, name, FNM_NOESCAPE) == 0)
1709 static int get_machine_list(
1711 struct machine_info **_machine_infos,
1714 struct machine_info *machine_infos = NULL;
1715 _cleanup_strv_free_ char **m = NULL;
1716 _cleanup_free_ char *hn = NULL;
1721 hn = gethostname_malloc();
1725 if (output_show_machine(hn, patterns)) {
1726 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1729 machine_infos[c].is_host = true;
1730 machine_infos[c].name = hn;
1733 get_machine_properties(bus, &machine_infos[c]);
1737 sd_get_machine_names(&m);
1738 STRV_FOREACH(i, m) {
1739 _cleanup_free_ char *class = NULL;
1741 if (!output_show_machine(*i, patterns))
1744 sd_machine_get_class(*i, &class);
1745 if (!streq_ptr(class, "container"))
1748 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1749 free_machines_list(machine_infos, c);
1753 machine_infos[c].is_host = false;
1754 machine_infos[c].name = strdup(*i);
1755 if (!machine_infos[c].name) {
1756 free_machines_list(machine_infos, c);
1760 get_machine_properties(NULL, &machine_infos[c]);
1764 *_machine_infos = machine_infos;
1768 static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1769 struct machine_info *m;
1772 namelen = sizeof("NAME") - 1,
1773 statelen = sizeof("STATE") - 1,
1774 failedlen = sizeof("FAILED") - 1,
1775 jobslen = sizeof("JOBS") - 1;
1777 assert(machine_infos || n == 0);
1779 for (m = machine_infos; m < machine_infos + n; m++) {
1780 namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
1781 statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
1782 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
1783 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
1785 if (!arg_no_legend && !streq_ptr(m->state, "running"))
1789 if (!arg_no_legend) {
1793 printf("%-*s %-*s %-*s %-*s\n",
1796 failedlen, "FAILED",
1800 for (m = machine_infos; m < machine_infos + n; m++) {
1801 const char *on_state = "", *off_state = "";
1802 const char *on_failed = "", *off_failed = "";
1803 bool circle = false;
1805 if (streq_ptr(m->state, "degraded")) {
1806 on_state = ansi_highlight_red();
1807 off_state = ansi_highlight_off();
1809 } else if (!streq_ptr(m->state, "running")) {
1810 on_state = ansi_highlight_yellow();
1811 off_state = ansi_highlight_off();
1815 if (m->n_failed_units > 0) {
1816 on_failed = ansi_highlight_red();
1817 off_failed = ansi_highlight_off();
1819 on_failed = off_failed = "";
1822 printf("%s%s%s ", on_state, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_state);
1825 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1826 (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
1827 on_state, statelen, strna(m->state), off_state,
1828 on_failed, failedlen, m->n_failed_units, off_failed,
1829 jobslen, m->n_jobs);
1831 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1832 namelen, strna(m->name),
1833 on_state, statelen, strna(m->state), off_state,
1834 on_failed, failedlen, m->n_failed_units, off_failed,
1835 jobslen, m->n_jobs);
1839 printf("\n%u machines listed.\n", n);
1842 static int list_machines(sd_bus *bus, char **args) {
1843 struct machine_info *machine_infos = NULL;
1848 if (geteuid() != 0) {
1849 log_error("Must be root.");
1853 pager_open_if_enabled();
1855 r = get_machine_list(bus, &machine_infos, strv_skip_first(args));
1859 qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
1860 output_machines_list(machine_infos, r);
1861 free_machines_list(machine_infos, r);
1866 static int get_default(sd_bus *bus, char **args) {
1867 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1868 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1869 _cleanup_free_ char *_path = NULL;
1873 if (!bus || avoid_bus()) {
1874 r = unit_file_get_default(arg_scope, arg_root, &_path);
1876 log_error("Failed to get default target: %s", strerror(-r));
1882 r = sd_bus_call_method(
1884 "org.freedesktop.systemd1",
1885 "/org/freedesktop/systemd1",
1886 "org.freedesktop.systemd1.Manager",
1892 log_error("Failed to get default target: %s", bus_error_message(&error, -r));
1896 r = sd_bus_message_read(reply, "s", &path);
1898 return bus_log_parse_error(r);
1902 printf("%s\n", path);
1907 static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) {
1910 assert(changes || n_changes == 0);
1912 for (i = 0; i < n_changes; i++) {
1913 if (changes[i].type == UNIT_FILE_SYMLINK)
1914 log_info("Created symlink from %s to %s.", changes[i].path, changes[i].source);
1916 log_info("Removed symlink %s.", changes[i].path);
1920 static int deserialize_and_dump_unit_file_changes(sd_bus_message *m) {
1921 const char *type, *path, *source;
1924 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1926 return bus_log_parse_error(r);
1928 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1930 if (streq(type, "symlink"))
1931 log_info("Created symlink from %s to %s.", path, source);
1933 log_info("Removed symlink %s.", path);
1937 return bus_log_parse_error(r);
1939 r = sd_bus_message_exit_container(m);
1941 return bus_log_parse_error(r);
1946 static int set_default(sd_bus *bus, char **args) {
1947 _cleanup_free_ char *unit = NULL;
1948 UnitFileChange *changes = NULL;
1949 unsigned n_changes = 0;
1952 unit = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
1956 if (!bus || avoid_bus()) {
1957 r = unit_file_set_default(arg_scope, arg_root, unit, true, &changes, &n_changes);
1959 log_error("Failed to set default target: %s", strerror(-r));
1964 dump_unit_file_changes(changes, n_changes);
1968 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1969 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1971 r = sd_bus_call_method(
1973 "org.freedesktop.systemd1",
1974 "/org/freedesktop/systemd1",
1975 "org.freedesktop.systemd1.Manager",
1981 log_error("Failed to set default target: %s", bus_error_message(&error, -r));
1985 r = deserialize_and_dump_unit_file_changes(reply);
1989 /* Try to reload if enabled */
1991 r = daemon_reload(bus, args);
1996 unit_file_changes_free(changes, n_changes);
2003 const char *name, *type, *state;
2006 static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
2007 unsigned id_len, unit_len, type_len, state_len;
2008 const struct job_info *j;
2009 const char *on, *off;
2010 bool shorten = false;
2012 assert(n == 0 || jobs);
2015 on = ansi_highlight_green();
2016 off = ansi_highlight_off();
2018 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
2022 pager_open_if_enabled();
2024 id_len = strlen("JOB");
2025 unit_len = strlen("UNIT");
2026 type_len = strlen("TYPE");
2027 state_len = strlen("STATE");
2029 for (j = jobs; j < jobs + n; j++) {
2030 uint32_t id = j->id;
2031 assert(j->name && j->type && j->state);
2033 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
2034 unit_len = MAX(unit_len, strlen(j->name));
2035 type_len = MAX(type_len, strlen(j->type));
2036 state_len = MAX(state_len, strlen(j->state));
2039 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
2040 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
2045 printf("%*s %-*s %-*s %-*s\n",
2049 state_len, "STATE");
2051 for (j = jobs; j < jobs + n; j++) {
2052 _cleanup_free_ char *e = NULL;
2054 if (streq(j->state, "running")) {
2055 on = ansi_highlight();
2056 off = ansi_highlight_off();
2060 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
2061 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2063 on, unit_len, e ? e : j->name, off,
2065 on, state_len, j->state, off);
2068 if (!arg_no_legend) {
2069 on = ansi_highlight();
2070 off = ansi_highlight_off();
2072 printf("\n%s%u jobs listed%s.\n", on, n, off);
2076 static bool output_show_job(struct job_info *job, char **patterns) {
2081 if (strv_isempty(patterns))
2084 STRV_FOREACH(pattern, patterns)
2085 if (fnmatch(*pattern, job->name, FNM_NOESCAPE) == 0)
2090 static int list_jobs(sd_bus *bus, char **args) {
2091 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2092 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2093 const char *name, *type, *state, *job_path, *unit_path;
2094 _cleanup_free_ struct job_info *jobs = NULL;
2099 bool skipped = false;
2101 r = sd_bus_call_method(
2103 "org.freedesktop.systemd1",
2104 "/org/freedesktop/systemd1",
2105 "org.freedesktop.systemd1.Manager",
2111 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
2115 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2117 return bus_log_parse_error(r);
2119 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
2120 struct job_info job = { id, name, type, state };
2122 if (!output_show_job(&job, strv_skip_first(args))) {
2127 if (!GREEDY_REALLOC(jobs, size, c + 1))
2133 return bus_log_parse_error(r);
2135 r = sd_bus_message_exit_container(reply);
2137 return bus_log_parse_error(r);
2139 output_jobs_list(jobs, c, skipped);
2143 static int cancel_job(sd_bus *bus, char **args) {
2144 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2149 if (strv_length(args) <= 1)
2150 return daemon_reload(bus, args);
2152 STRV_FOREACH(name, args+1) {
2156 r = safe_atou32(*name, &id);
2158 log_error("Failed to parse job id \"%s\": %s", *name, strerror(-r));
2162 r = sd_bus_call_method(
2164 "org.freedesktop.systemd1",
2165 "/org/freedesktop/systemd1",
2166 "org.freedesktop.systemd1.Manager",
2172 log_error("Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, r));
2180 static int need_daemon_reload(sd_bus *bus, const char *unit) {
2181 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2185 /* We ignore all errors here, since this is used to show a
2188 /* We don't use unit_dbus_path_from_name() directly since we
2189 * don't want to load the unit if it isn't loaded. */
2191 r = sd_bus_call_method(
2193 "org.freedesktop.systemd1",
2194 "/org/freedesktop/systemd1",
2195 "org.freedesktop.systemd1.Manager",
2203 r = sd_bus_message_read(reply, "o", &path);
2207 r = sd_bus_get_property_trivial(
2209 "org.freedesktop.systemd1",
2211 "org.freedesktop.systemd1.Unit",
2221 typedef struct WaitData {
2228 static int wait_filter(sd_bus *bus, sd_bus_message *m, void *data, sd_bus_error *error) {
2235 log_debug("Got D-Bus request: %s.%s() on %s",
2236 sd_bus_message_get_interface(m),
2237 sd_bus_message_get_member(m),
2238 sd_bus_message_get_path(m));
2240 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
2241 log_error("Warning! D-Bus connection terminated.");
2243 } else if (sd_bus_message_is_signal(m, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
2245 const char *path, *result, *unit;
2249 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
2251 ret = set_remove(d->set, (char*) path);
2257 if (!isempty(result))
2258 d->result = strdup(result);
2261 d->name = strdup(unit);
2266 r = sd_bus_message_read(m, "uos", &id, &path, &result);
2268 ret = set_remove(d->set, (char*) path);
2275 d->result = strdup(result);
2281 bus_log_parse_error(r);
2287 static int enable_wait_for_jobs(sd_bus *bus) {
2292 r = sd_bus_add_match(
2296 "sender='org.freedesktop.systemd1',"
2297 "interface='org.freedesktop.systemd1.Manager',"
2298 "member='JobRemoved',"
2299 "path='/org/freedesktop/systemd1'",
2302 log_error("Failed to add match");
2306 /* This is slightly dirty, since we don't undo the match registrations. */
2310 static int bus_process_wait(sd_bus *bus) {
2314 r = sd_bus_process(bus, NULL);
2319 r = sd_bus_wait(bus, (uint64_t) -1);
2325 static int check_wait_response(WaitData *d) {
2331 if (streq(d->result, "timeout"))
2332 log_error("Job for %s timed out.", strna(d->name));
2333 else if (streq(d->result, "canceled"))
2334 log_error("Job for %s canceled.", strna(d->name));
2335 else if (streq(d->result, "dependency"))
2336 log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
2337 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
2341 quotes = chars_intersect(d->name, SHELL_NEED_QUOTES);
2343 log_error("Job for %s failed. See \"systemctl status %s%s%s\" and \"journalctl -xe\" for details.",
2345 quotes ? "'" : "", d->name, quotes ? "'" : "");
2347 log_error("Job failed. See \"journalctl -xe\" for details.");
2351 if (streq(d->result, "timeout"))
2353 else if (streq(d->result, "canceled"))
2355 else if (streq(d->result, "dependency"))
2357 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2363 static int wait_for_jobs(sd_bus *bus, Set *s) {
2364 _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
2365 WaitData d = { .set = s };
2371 q = sd_bus_add_filter(bus, &slot, wait_filter, &d);
2375 while (!set_isempty(s)) {
2376 q = bus_process_wait(bus);
2378 log_error("Failed to wait for response: %s", strerror(-q));
2383 q = check_wait_response(&d);
2384 /* Return the first error as it is most likely to be
2386 if (q < 0 && r == 0)
2388 log_debug("Got result %s/%s for job %s",
2389 strna(d.result), strerror(-q), strna(d.name));
2402 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2403 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2404 _cleanup_free_ char *n = NULL, *state = NULL;
2410 n = unit_name_mangle(name, MANGLE_NOGLOB);
2414 /* We don't use unit_dbus_path_from_name() directly since we
2415 * don't want to load the unit if it isn't loaded. */
2417 r = sd_bus_call_method(
2419 "org.freedesktop.systemd1",
2420 "/org/freedesktop/systemd1",
2421 "org.freedesktop.systemd1.Manager",
2432 r = sd_bus_message_read(reply, "o", &path);
2434 return bus_log_parse_error(r);
2436 r = sd_bus_get_property_string(
2438 "org.freedesktop.systemd1",
2440 "org.freedesktop.systemd1.Unit",
2453 return nulstr_contains(good_states, state);
2456 static int check_triggering_units(
2460 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2461 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2462 _cleanup_strv_free_ char **triggered_by = NULL;
2463 bool print_warning_label = true;
2467 n = unit_name_mangle(name, MANGLE_NOGLOB);
2471 path = unit_dbus_path_from_name(n);
2475 r = sd_bus_get_property_string(
2477 "org.freedesktop.systemd1",
2479 "org.freedesktop.systemd1.Unit",
2484 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2488 if (streq(state, "masked"))
2491 r = sd_bus_get_property_strv(
2493 "org.freedesktop.systemd1",
2495 "org.freedesktop.systemd1.Unit",
2500 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2504 STRV_FOREACH(i, triggered_by) {
2505 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2507 log_error("Failed to check unit: %s", strerror(-r));
2514 if (print_warning_label) {
2515 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2516 print_warning_label = false;
2519 log_warning(" %s", *i);
2525 static const struct {
2528 } unit_actions[] = {
2529 { "start", "StartUnit" },
2530 { "stop", "StopUnit" },
2531 { "condstop", "StopUnit" },
2532 { "reload", "ReloadUnit" },
2533 { "restart", "RestartUnit" },
2534 { "try-restart", "TryRestartUnit" },
2535 { "condrestart", "TryRestartUnit" },
2536 { "reload-or-restart", "ReloadOrRestartUnit" },
2537 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2538 { "condreload", "ReloadOrTryRestartUnit" },
2539 { "force-reload", "ReloadOrTryRestartUnit" }
2542 static const char *verb_to_method(const char *verb) {
2545 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2546 if (streq_ptr(unit_actions[i].verb, verb))
2547 return unit_actions[i].method;
2552 static const char *method_to_verb(const char *method) {
2555 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2556 if (streq_ptr(unit_actions[i].method, method))
2557 return unit_actions[i].verb;
2562 static int start_unit_one(
2567 sd_bus_error *error,
2570 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2579 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2580 r = sd_bus_call_method(
2582 "org.freedesktop.systemd1",
2583 "/org/freedesktop/systemd1",
2584 "org.freedesktop.systemd1.Manager",
2592 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2593 /* There's always a fallback possible for
2594 * legacy actions. */
2595 return -EADDRNOTAVAIL;
2597 verb = method_to_verb(method);
2599 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2603 r = sd_bus_message_read(reply, "o", &path);
2605 return bus_log_parse_error(r);
2607 if (need_daemon_reload(bus, name) > 0)
2608 log_warning("Warning: Unit file of %s changed on disk, 'systemctl%s daemon-reload' recommended.",
2609 name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2618 log_debug("Adding %s to the set", p);
2619 r = set_consume(s, p);
2627 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2629 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2633 STRV_FOREACH(name, names) {
2637 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2639 t = unit_name_mangle(*name, MANGLE_GLOB);
2643 if (string_is_glob(t))
2644 r = strv_consume(&globs, t);
2646 r = strv_consume(&mangled, t);
2651 /* Query the manager only if any of the names are a glob, since
2652 * this is fairly expensive */
2653 if (!strv_isempty(globs)) {
2654 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2655 _cleanup_free_ UnitInfo *unit_infos = NULL;
2657 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2661 for (i = 0; i < r; i++)
2662 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2667 mangled = NULL; /* do not free */
2672 static const struct {
2676 } action_table[_ACTION_MAX] = {
2677 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2678 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2679 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2680 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2681 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
2682 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
2683 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
2684 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
2685 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2686 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2687 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2688 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2689 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2690 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2691 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2694 static enum action verb_to_action(const char *verb) {
2697 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2698 if (streq_ptr(action_table[i].verb, verb))
2701 return _ACTION_INVALID;
2704 static int start_unit(sd_bus *bus, char **args) {
2705 _cleanup_set_free_free_ Set *s = NULL;
2706 _cleanup_strv_free_ char **names = NULL;
2707 const char *method, *mode, *one_name, *suffix = NULL;
2713 ask_password_agent_open_if_enabled();
2715 if (arg_action == ACTION_SYSTEMCTL) {
2717 method = verb_to_method(args[0]);
2718 action = verb_to_action(args[0]);
2720 if (streq(args[0], "isolate")) {
2724 mode = action_table[action].mode ?: arg_job_mode;
2726 one_name = action_table[action].target;
2728 assert(arg_action < ELEMENTSOF(action_table));
2729 assert(action_table[arg_action].target);
2731 method = "StartUnit";
2733 mode = action_table[arg_action].mode;
2734 one_name = action_table[arg_action].target;
2738 names = strv_new(one_name, NULL);
2740 r = expand_names(bus, args + 1, suffix, &names);
2742 log_error("Failed to expand names: %s", strerror(-r));
2745 if (!arg_no_block) {
2746 r = enable_wait_for_jobs(bus);
2748 log_error("Could not watch jobs: %s", strerror(-r));
2752 s = set_new(&string_hash_ops);
2757 STRV_FOREACH(name, names) {
2758 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2761 q = start_unit_one(bus, method, *name, mode, &error, s);
2762 if (r >= 0 && q < 0)
2763 r = translate_bus_error_to_exit_status(q, &error);
2766 if (!arg_no_block) {
2769 q = wait_for_jobs(bus, s);
2773 /* When stopping units, warn if they can still be triggered by
2774 * another active unit (socket, path, timer) */
2775 if (!arg_quiet && streq(method, "StopUnit"))
2776 STRV_FOREACH(name, names)
2777 check_triggering_units(bus, *name);
2783 /* Ask systemd-logind, which might grant access to unprivileged users
2784 * through PolicyKit */
2785 static int reboot_with_logind(sd_bus *bus, enum action a) {
2787 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2794 polkit_agent_open_if_enabled();
2802 case ACTION_POWEROFF:
2803 method = "PowerOff";
2806 case ACTION_SUSPEND:
2810 case ACTION_HIBERNATE:
2811 method = "Hibernate";
2814 case ACTION_HYBRID_SLEEP:
2815 method = "HybridSleep";
2822 r = sd_bus_call_method(
2824 "org.freedesktop.login1",
2825 "/org/freedesktop/login1",
2826 "org.freedesktop.login1.Manager",
2832 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2840 static int check_inhibitors(sd_bus *bus, enum action a) {
2842 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2843 _cleanup_strv_free_ char **sessions = NULL;
2844 const char *what, *who, *why, *mode;
2853 if (arg_ignore_inhibitors || arg_force > 0)
2865 r = sd_bus_call_method(
2867 "org.freedesktop.login1",
2868 "/org/freedesktop/login1",
2869 "org.freedesktop.login1.Manager",
2875 /* If logind is not around, then there are no inhibitors... */
2878 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2880 return bus_log_parse_error(r);
2882 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2883 _cleanup_free_ char *comm = NULL, *user = NULL;
2884 _cleanup_strv_free_ char **sv = NULL;
2886 if (!streq(mode, "block"))
2889 sv = strv_split(what, ":");
2893 if (!strv_contains(sv,
2895 a == ACTION_POWEROFF ||
2896 a == ACTION_REBOOT ||
2897 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2900 get_process_comm(pid, &comm);
2901 user = uid_to_name(uid);
2903 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
2904 who, pid, strna(comm), strna(user), why);
2909 return bus_log_parse_error(r);
2911 r = sd_bus_message_exit_container(reply);
2913 return bus_log_parse_error(r);
2915 /* Check for current sessions */
2916 sd_get_sessions(&sessions);
2917 STRV_FOREACH(s, sessions) {
2918 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2920 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2923 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2926 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2929 sd_session_get_tty(*s, &tty);
2930 sd_session_get_seat(*s, &seat);
2931 sd_session_get_service(*s, &service);
2932 user = uid_to_name(uid);
2934 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2941 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2942 action_table[a].verb);
2950 static int start_special(sd_bus *bus, char **args) {
2956 a = verb_to_action(args[0]);
2958 r = check_inhibitors(bus, a);
2962 if (arg_force >= 2 && geteuid() != 0) {
2963 log_error("Must be root.");
2967 if (arg_force >= 2 &&
2968 (a == ACTION_HALT ||
2969 a == ACTION_POWEROFF ||
2970 a == ACTION_REBOOT))
2973 if (arg_force >= 1 &&
2974 (a == ACTION_HALT ||
2975 a == ACTION_POWEROFF ||
2976 a == ACTION_REBOOT ||
2977 a == ACTION_KEXEC ||
2979 return daemon_reload(bus, args);
2981 /* first try logind, to allow authentication with polkit */
2982 if (geteuid() != 0 &&
2983 (a == ACTION_POWEROFF ||
2984 a == ACTION_REBOOT ||
2985 a == ACTION_SUSPEND ||
2986 a == ACTION_HIBERNATE ||
2987 a == ACTION_HYBRID_SLEEP)) {
2988 r = reboot_with_logind(bus, a);
2993 r = start_unit(bus, args);
2994 if (r == EXIT_SUCCESS)
3000 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
3001 _cleanup_strv_free_ char **names = NULL;
3008 r = expand_names(bus, args, NULL, &names);
3010 log_error("Failed to expand names: %s", strerror(-r));
3014 STRV_FOREACH(name, names) {
3017 state = check_one_unit(bus, *name, good_states, arg_quiet);
3027 static int check_unit_active(sd_bus *bus, char **args) {
3028 /* According to LSB: 3, "program is not running" */
3029 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
3032 static int check_unit_failed(sd_bus *bus, char **args) {
3033 return check_unit_generic(bus, 1, "failed\0", args + 1);
3036 static int kill_unit(sd_bus *bus, char **args) {
3037 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3038 _cleanup_strv_free_ char **names = NULL;
3046 arg_kill_who = "all";
3048 r = expand_names(bus, args + 1, NULL, &names);
3050 log_error("Failed to expand names: %s", strerror(-r));
3052 STRV_FOREACH(name, names) {
3053 q = sd_bus_call_method(
3055 "org.freedesktop.systemd1",
3056 "/org/freedesktop/systemd1",
3057 "org.freedesktop.systemd1.Manager",
3061 "ssi", *names, arg_kill_who, arg_signal);
3063 log_error("Failed to kill unit %s: %s",
3064 *names, bus_error_message(&error, r));
3073 typedef struct ExecStatusInfo {
3081 usec_t start_timestamp;
3082 usec_t exit_timestamp;
3087 LIST_FIELDS(struct ExecStatusInfo, exec);
3090 static void exec_status_info_free(ExecStatusInfo *i) {
3099 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3100 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3103 int32_t code, status;
3109 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3111 return bus_log_parse_error(r);
3115 r = sd_bus_message_read(m, "s", &path);
3117 return bus_log_parse_error(r);
3119 i->path = strdup(path);
3123 r = sd_bus_message_read_strv(m, &i->argv);
3125 return bus_log_parse_error(r);
3127 r = sd_bus_message_read(m,
3130 &start_timestamp, &start_timestamp_monotonic,
3131 &exit_timestamp, &exit_timestamp_monotonic,
3135 return bus_log_parse_error(r);
3138 i->start_timestamp = (usec_t) start_timestamp;
3139 i->exit_timestamp = (usec_t) exit_timestamp;
3140 i->pid = (pid_t) pid;
3144 r = sd_bus_message_exit_container(m);
3146 return bus_log_parse_error(r);
3151 typedef struct UnitStatusInfo {
3153 const char *load_state;
3154 const char *active_state;
3155 const char *sub_state;
3156 const char *unit_file_state;
3158 const char *description;
3159 const char *following;
3161 char **documentation;
3163 const char *fragment_path;
3164 const char *source_path;
3165 const char *control_group;
3167 char **dropin_paths;
3169 const char *load_error;
3172 usec_t inactive_exit_timestamp;
3173 usec_t inactive_exit_timestamp_monotonic;
3174 usec_t active_enter_timestamp;
3175 usec_t active_exit_timestamp;
3176 usec_t inactive_enter_timestamp;
3178 bool need_daemon_reload;
3183 const char *status_text;
3184 const char *pid_file;
3188 usec_t start_timestamp;
3189 usec_t exit_timestamp;
3191 int exit_code, exit_status;
3193 usec_t condition_timestamp;
3194 bool condition_result;
3195 bool failed_condition_trigger;
3196 bool failed_condition_negate;
3197 const char *failed_condition;
3198 const char *failed_condition_param;
3201 unsigned n_accepted;
3202 unsigned n_connections;
3205 /* Pairs of type, path */
3209 const char *sysfs_path;
3211 /* Mount, Automount */
3217 LIST_HEAD(ExecStatusInfo, exec);
3220 static void print_status_info(
3225 const char *active_on, *active_off, *on, *off, *ss;
3227 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3228 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3231 arg_all * OUTPUT_SHOW_ALL |
3232 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
3233 on_tty() * OUTPUT_COLOR |
3234 !arg_quiet * OUTPUT_WARN_CUTOFF |
3235 arg_full * OUTPUT_FULL_WIDTH;
3240 /* This shows pretty information about a unit. See
3241 * print_property() for a low-level property printer */
3243 if (streq_ptr(i->active_state, "failed")) {
3244 active_on = ansi_highlight_red();
3245 active_off = ansi_highlight_off();
3246 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3247 active_on = ansi_highlight_green();
3248 active_off = ansi_highlight_off();
3250 active_on = active_off = "";
3252 printf("%s%s%s %s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3254 if (i->description && !streq_ptr(i->id, i->description))
3255 printf(" - %s", i->description);
3260 printf(" Follow: unit currently follows state of %s\n", i->following);
3262 if (streq_ptr(i->load_state, "error")) {
3263 on = ansi_highlight_red();
3264 off = ansi_highlight_off();
3268 path = i->source_path ? i->source_path : i->fragment_path;
3271 printf(" Loaded: %s%s%s (Reason: %s)\n",
3272 on, strna(i->load_state), off, i->load_error);
3273 else if (path && i->unit_file_state)
3274 printf(" Loaded: %s%s%s (%s; %s)\n",
3275 on, strna(i->load_state), off, path, i->unit_file_state);
3277 printf(" Loaded: %s%s%s (%s)\n",
3278 on, strna(i->load_state), off, path);
3280 printf(" Loaded: %s%s%s\n",
3281 on, strna(i->load_state), off);
3283 if (!strv_isempty(i->dropin_paths)) {
3284 _cleanup_free_ char *dir = NULL;
3288 STRV_FOREACH(dropin, i->dropin_paths) {
3289 if (! dir || last) {
3290 printf(dir ? " " : " Drop-In: ");
3295 if (path_get_parent(*dropin, &dir) < 0) {
3300 printf("%s\n %s", dir,
3301 draw_special_char(DRAW_TREE_RIGHT));
3304 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3306 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3310 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3312 printf(" Active: %s%s (%s)%s",
3313 active_on, strna(i->active_state), ss, active_off);
3315 printf(" Active: %s%s%s",
3316 active_on, strna(i->active_state), active_off);
3318 if (!isempty(i->result) && !streq(i->result, "success"))
3319 printf(" (Result: %s)", i->result);
3321 timestamp = (streq_ptr(i->active_state, "active") ||
3322 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
3323 (streq_ptr(i->active_state, "inactive") ||
3324 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
3325 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
3326 i->active_exit_timestamp;
3328 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3329 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3332 printf(" since %s; %s\n", s2, s1);
3334 printf(" since %s\n", s2);
3338 if (!i->condition_result && i->condition_timestamp > 0) {
3339 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3340 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3342 printf(" start condition failed at %s%s%s\n",
3343 s2, s1 ? "; " : "", s1 ? s1 : "");
3344 if (i->failed_condition_trigger)
3345 printf(" none of the trigger conditions were met\n");
3346 else if (i->failed_condition)
3347 printf(" %s=%s%s was not met\n",
3348 i->failed_condition,
3349 i->failed_condition_negate ? "!" : "",
3350 i->failed_condition_param);
3354 printf(" Device: %s\n", i->sysfs_path);
3356 printf(" Where: %s\n", i->where);
3358 printf(" What: %s\n", i->what);
3360 STRV_FOREACH(t, i->documentation)
3361 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3363 STRV_FOREACH_PAIR(t, t2, i->listen)
3364 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3367 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3369 LIST_FOREACH(exec, p, i->exec) {
3370 _cleanup_free_ char *argv = NULL;
3373 /* Only show exited processes here */
3377 argv = strv_join(p->argv, " ");
3378 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
3380 good = is_clean_exit_lsb(p->code, p->status, NULL);
3382 on = ansi_highlight_red();
3383 off = ansi_highlight_off();
3387 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3389 if (p->code == CLD_EXITED) {
3392 printf("status=%i", p->status);
3394 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3399 printf("signal=%s", signal_to_string(p->status));
3401 printf(")%s\n", off);
3403 if (i->main_pid == p->pid &&
3404 i->start_timestamp == p->start_timestamp &&
3405 i->exit_timestamp == p->start_timestamp)
3406 /* Let's not show this twice */
3409 if (p->pid == i->control_pid)
3413 if (i->main_pid > 0 || i->control_pid > 0) {
3414 if (i->main_pid > 0) {
3415 printf(" Main PID: "PID_FMT, i->main_pid);
3418 _cleanup_free_ char *comm = NULL;
3419 get_process_comm(i->main_pid, &comm);
3421 printf(" (%s)", comm);
3422 } else if (i->exit_code > 0) {
3423 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3425 if (i->exit_code == CLD_EXITED) {
3428 printf("status=%i", i->exit_status);
3430 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3435 printf("signal=%s", signal_to_string(i->exit_status));
3439 if (i->control_pid > 0)
3443 if (i->control_pid > 0) {
3444 _cleanup_free_ char *c = NULL;
3446 printf(" %8s: "PID_FMT, i->main_pid ? "" : " Control", i->control_pid);
3448 get_process_comm(i->control_pid, &c);
3457 printf(" Status: \"%s\"\n", i->status_text);
3458 if (i->status_errno > 0)
3459 printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
3461 if (i->control_group &&
3462 (i->main_pid > 0 || i->control_pid > 0 ||
3463 ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_CONTAINER) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3466 printf(" CGroup: %s\n", i->control_group);
3468 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
3471 static const char prefix[] = " ";
3474 if (c > sizeof(prefix) - 1)
3475 c -= sizeof(prefix) - 1;
3479 if (i->main_pid > 0)
3480 extra[k++] = i->main_pid;
3482 if (i->control_pid > 0)
3483 extra[k++] = i->control_pid;
3485 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, flags);
3489 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3490 show_journal_by_unit(stdout,
3494 i->inactive_exit_timestamp_monotonic,
3497 flags | OUTPUT_BEGIN_NEWLINE,
3498 arg_scope == UNIT_FILE_SYSTEM,
3502 if (i->need_daemon_reload)
3503 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
3504 ansi_highlight_red(),
3505 ansi_highlight_off(),
3506 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
3509 static void show_unit_help(UnitStatusInfo *i) {
3514 if (!i->documentation) {
3515 log_info("Documentation for %s not known.", i->id);
3519 STRV_FOREACH(p, i->documentation)
3520 if (startswith(*p, "man:"))
3521 show_man_page(*p + 4, false);
3523 log_info("Can't show: %s", *p);
3526 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3533 switch (contents[0]) {
3535 case SD_BUS_TYPE_STRING: {
3538 r = sd_bus_message_read(m, "s", &s);
3540 return bus_log_parse_error(r);
3543 if (streq(name, "Id"))
3545 else if (streq(name, "LoadState"))
3547 else if (streq(name, "ActiveState"))
3548 i->active_state = s;
3549 else if (streq(name, "SubState"))
3551 else if (streq(name, "Description"))
3553 else if (streq(name, "FragmentPath"))
3554 i->fragment_path = s;
3555 else if (streq(name, "SourcePath"))
3558 else if (streq(name, "DefaultControlGroup")) {
3560 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3562 i->control_group = e;
3565 else if (streq(name, "ControlGroup"))
3566 i->control_group = s;
3567 else if (streq(name, "StatusText"))
3569 else if (streq(name, "PIDFile"))
3571 else if (streq(name, "SysFSPath"))
3573 else if (streq(name, "Where"))
3575 else if (streq(name, "What"))
3577 else if (streq(name, "Following"))
3579 else if (streq(name, "UnitFileState"))
3580 i->unit_file_state = s;
3581 else if (streq(name, "Result"))
3588 case SD_BUS_TYPE_BOOLEAN: {
3591 r = sd_bus_message_read(m, "b", &b);
3593 return bus_log_parse_error(r);
3595 if (streq(name, "Accept"))
3597 else if (streq(name, "NeedDaemonReload"))
3598 i->need_daemon_reload = b;
3599 else if (streq(name, "ConditionResult"))
3600 i->condition_result = b;
3605 case SD_BUS_TYPE_UINT32: {
3608 r = sd_bus_message_read(m, "u", &u);
3610 return bus_log_parse_error(r);
3612 if (streq(name, "MainPID")) {
3614 i->main_pid = (pid_t) u;
3617 } else if (streq(name, "ControlPID"))
3618 i->control_pid = (pid_t) u;
3619 else if (streq(name, "ExecMainPID")) {
3621 i->main_pid = (pid_t) u;
3622 } else if (streq(name, "NAccepted"))
3624 else if (streq(name, "NConnections"))
3625 i->n_connections = u;
3630 case SD_BUS_TYPE_INT32: {
3633 r = sd_bus_message_read(m, "i", &j);
3635 return bus_log_parse_error(r);
3637 if (streq(name, "ExecMainCode"))
3638 i->exit_code = (int) j;
3639 else if (streq(name, "ExecMainStatus"))
3640 i->exit_status = (int) j;
3641 else if (streq(name, "StatusErrno"))
3642 i->status_errno = (int) j;
3647 case SD_BUS_TYPE_UINT64: {
3650 r = sd_bus_message_read(m, "t", &u);
3652 return bus_log_parse_error(r);
3654 if (streq(name, "ExecMainStartTimestamp"))
3655 i->start_timestamp = (usec_t) u;
3656 else if (streq(name, "ExecMainExitTimestamp"))
3657 i->exit_timestamp = (usec_t) u;
3658 else if (streq(name, "ActiveEnterTimestamp"))
3659 i->active_enter_timestamp = (usec_t) u;
3660 else if (streq(name, "InactiveEnterTimestamp"))
3661 i->inactive_enter_timestamp = (usec_t) u;
3662 else if (streq(name, "InactiveExitTimestamp"))
3663 i->inactive_exit_timestamp = (usec_t) u;
3664 else if (streq(name, "InactiveExitTimestampMonotonic"))
3665 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3666 else if (streq(name, "ActiveExitTimestamp"))
3667 i->active_exit_timestamp = (usec_t) u;
3668 else if (streq(name, "ConditionTimestamp"))
3669 i->condition_timestamp = (usec_t) u;
3674 case SD_BUS_TYPE_ARRAY:
3676 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3677 _cleanup_free_ ExecStatusInfo *info = NULL;
3679 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3681 return bus_log_parse_error(r);
3683 info = new0(ExecStatusInfo, 1);
3687 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3689 info->name = strdup(name);
3693 LIST_PREPEND(exec, i->exec, info);
3695 info = new0(ExecStatusInfo, 1);
3701 return bus_log_parse_error(r);
3703 r = sd_bus_message_exit_container(m);
3705 return bus_log_parse_error(r);
3709 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3710 const char *type, *path;
3712 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3714 return bus_log_parse_error(r);
3716 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3718 r = strv_extend(&i->listen, type);
3722 r = strv_extend(&i->listen, path);
3727 return bus_log_parse_error(r);
3729 r = sd_bus_message_exit_container(m);
3731 return bus_log_parse_error(r);
3735 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3737 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3739 return bus_log_parse_error(r);
3741 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3743 r = sd_bus_message_read_strv(m, &i->documentation);
3745 return bus_log_parse_error(r);
3747 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3748 const char *cond, *param;
3749 int trigger, negate;
3752 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3754 return bus_log_parse_error(r);
3756 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3757 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3758 if (state < 0 && (!trigger || !i->failed_condition)) {
3759 i->failed_condition = cond;
3760 i->failed_condition_trigger = trigger;
3761 i->failed_condition_negate = negate;
3762 i->failed_condition_param = param;
3766 return bus_log_parse_error(r);
3768 r = sd_bus_message_exit_container(m);
3770 return bus_log_parse_error(r);
3777 case SD_BUS_TYPE_STRUCT_BEGIN:
3779 if (streq(name, "LoadError")) {
3780 const char *n, *message;
3782 r = sd_bus_message_read(m, "(ss)", &n, &message);
3784 return bus_log_parse_error(r);
3786 if (!isempty(message))
3787 i->load_error = message;
3800 r = sd_bus_message_skip(m, contents);
3802 return bus_log_parse_error(r);
3807 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3813 /* This is a low-level property printer, see
3814 * print_status_info() for the nicer output */
3816 if (arg_properties && !strv_find(arg_properties, name)) {
3817 /* skip what we didn't read */
3818 r = sd_bus_message_skip(m, contents);
3822 switch (contents[0]) {
3824 case SD_BUS_TYPE_STRUCT_BEGIN:
3826 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3829 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3831 return bus_log_parse_error(r);
3834 printf("%s=%"PRIu32"\n", name, u);
3836 printf("%s=\n", name);
3840 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3843 r = sd_bus_message_read(m, "(so)", &s, NULL);
3845 return bus_log_parse_error(r);
3847 if (arg_all || !isempty(s))
3848 printf("%s=%s\n", name, s);
3852 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3853 const char *a = NULL, *b = NULL;
3855 r = sd_bus_message_read(m, "(ss)", &a, &b);
3857 return bus_log_parse_error(r);
3859 if (arg_all || !isempty(a) || !isempty(b))
3860 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3863 } else if (streq_ptr(name, "SystemCallFilter")) {
3864 _cleanup_strv_free_ char **l = NULL;
3867 r = sd_bus_message_enter_container(m, 'r', "bas");
3869 return bus_log_parse_error(r);
3871 r = sd_bus_message_read(m, "b", &whitelist);
3873 return bus_log_parse_error(r);
3875 r = sd_bus_message_read_strv(m, &l);
3877 return bus_log_parse_error(r);
3879 r = sd_bus_message_exit_container(m);
3881 return bus_log_parse_error(r);
3883 if (arg_all || whitelist || !strv_isempty(l)) {
3887 fputs(name, stdout);
3893 STRV_FOREACH(i, l) {
3901 fputc('\n', stdout);
3909 case SD_BUS_TYPE_ARRAY:
3911 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
3915 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
3917 return bus_log_parse_error(r);
3919 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
3920 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3923 return bus_log_parse_error(r);
3925 r = sd_bus_message_exit_container(m);
3927 return bus_log_parse_error(r);
3931 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
3932 const char *type, *path;
3934 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3936 return bus_log_parse_error(r);
3938 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3939 printf("%s=%s\n", type, path);
3941 return bus_log_parse_error(r);
3943 r = sd_bus_message_exit_container(m);
3945 return bus_log_parse_error(r);
3949 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3950 const char *type, *path;
3952 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3954 return bus_log_parse_error(r);
3956 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3957 printf("Listen%s=%s\n", type, path);
3959 return bus_log_parse_error(r);
3961 r = sd_bus_message_exit_container(m);
3963 return bus_log_parse_error(r);
3967 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
3969 uint64_t value, next_elapse;
3971 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
3973 return bus_log_parse_error(r);
3975 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
3976 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3978 printf("%s={ value=%s ; next_elapse=%s }\n",
3980 format_timespan(timespan1, sizeof(timespan1), value, 0),
3981 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3984 return bus_log_parse_error(r);
3986 r = sd_bus_message_exit_container(m);
3988 return bus_log_parse_error(r);
3992 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3993 ExecStatusInfo info = {};
3995 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3997 return bus_log_parse_error(r);
3999 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
4000 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
4001 _cleanup_free_ char *tt;
4003 tt = strv_join(info.argv, " ");
4005 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",
4009 yes_no(info.ignore),
4010 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
4011 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
4013 sigchld_code_to_string(info.code),
4015 info.code == CLD_EXITED ? "" : "/",
4016 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
4019 strv_free(info.argv);
4023 r = sd_bus_message_exit_container(m);
4025 return bus_log_parse_error(r);
4029 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
4030 const char *path, *rwm;
4032 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4034 return bus_log_parse_error(r);
4036 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
4037 printf("%s=%s %s\n", name, strna(path), strna(rwm));
4039 return bus_log_parse_error(r);
4041 r = sd_bus_message_exit_container(m);
4043 return bus_log_parse_error(r);
4047 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
4051 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4053 return bus_log_parse_error(r);
4055 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4056 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
4058 return bus_log_parse_error(r);
4060 r = sd_bus_message_exit_container(m);
4062 return bus_log_parse_error(r);
4066 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
4070 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4072 return bus_log_parse_error(r);
4074 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4075 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
4077 return bus_log_parse_error(r);
4079 r = sd_bus_message_exit_container(m);
4081 return bus_log_parse_error(r);
4089 r = bus_print_property(name, m, arg_all);
4091 return bus_log_parse_error(r);
4094 r = sd_bus_message_skip(m, contents);
4096 return bus_log_parse_error(r);
4099 printf("%s=[unprintable]\n", name);
4105 static int show_one(
4109 bool show_properties,
4113 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4114 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4115 UnitStatusInfo info = {};
4122 log_debug("Showing one %s", path);
4124 r = sd_bus_call_method(
4126 "org.freedesktop.systemd1",
4128 "org.freedesktop.DBus.Properties",
4134 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4138 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4140 return bus_log_parse_error(r);
4147 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4148 const char *name, *contents;
4150 r = sd_bus_message_read(reply, "s", &name);
4152 return bus_log_parse_error(r);
4154 r = sd_bus_message_peek_type(reply, NULL, &contents);
4156 return bus_log_parse_error(r);
4158 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4160 return bus_log_parse_error(r);
4162 if (show_properties)
4163 r = print_property(name, reply, contents);
4165 r = status_property(name, reply, &info, contents);
4169 r = sd_bus_message_exit_container(reply);
4171 return bus_log_parse_error(r);
4173 r = sd_bus_message_exit_container(reply);
4175 return bus_log_parse_error(r);
4178 return bus_log_parse_error(r);
4180 r = sd_bus_message_exit_container(reply);
4182 return bus_log_parse_error(r);
4186 if (!show_properties) {
4187 if (streq(verb, "help"))
4188 show_unit_help(&info);
4190 print_status_info(&info, ellipsized);
4193 strv_free(info.documentation);
4194 strv_free(info.dropin_paths);
4195 strv_free(info.listen);
4197 if (!streq_ptr(info.active_state, "active") &&
4198 !streq_ptr(info.active_state, "reloading") &&
4199 streq(verb, "status")) {
4200 /* According to LSB: "program not running" */
4201 /* 0: program is running or service is OK
4202 * 1: program is dead and /run PID file exists
4203 * 2: program is dead and /run/lock lock file exists
4204 * 3: program is not running
4205 * 4: program or service status is unknown
4207 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4213 while ((p = info.exec)) {
4214 LIST_REMOVE(exec, info.exec, p);
4215 exec_status_info_free(p);
4221 static int get_unit_dbus_path_by_pid(
4226 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4227 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4231 r = sd_bus_call_method(
4233 "org.freedesktop.systemd1",
4234 "/org/freedesktop/systemd1",
4235 "org.freedesktop.systemd1.Manager",
4241 log_error("Failed to get unit for PID "PID_FMT": %s", pid, bus_error_message(&error, r));
4245 r = sd_bus_message_read(reply, "o", &u);
4247 return bus_log_parse_error(r);
4257 static int show_all(
4260 bool show_properties,
4264 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4265 _cleanup_free_ UnitInfo *unit_infos = NULL;
4270 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4274 pager_open_if_enabled();
4278 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4280 for (u = unit_infos; u < unit_infos + c; u++) {
4281 _cleanup_free_ char *p = NULL;
4283 p = unit_dbus_path_from_name(u->id);
4287 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4290 else if (r > 0 && ret == 0)
4297 static int show_system_status(sd_bus *bus) {
4298 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4299 _cleanup_free_ char *hn = NULL;
4300 struct machine_info mi = {};
4301 const char *on, *off;
4304 hn = gethostname_malloc();
4308 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4310 log_error("Failed to read server status: %s", strerror(-r));
4314 if (streq_ptr(mi.state, "degraded")) {
4315 on = ansi_highlight_red();
4316 off = ansi_highlight_off();
4317 } else if (!streq_ptr(mi.state, "running")) {
4318 on = ansi_highlight_yellow();
4319 off = ansi_highlight_off();
4323 printf("%s%s%s %s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4325 printf(" State: %s%s%s\n",
4326 on, strna(mi.state), off);
4328 printf(" Jobs: %u queued\n", mi.n_jobs);
4329 printf(" Failed: %u units\n", mi.n_failed_units);
4331 printf(" Since: %s; %s\n",
4332 format_timestamp(since2, sizeof(since2), mi.timestamp),
4333 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4335 printf(" CGroup: %s\n", mi.control_group ?: "/");
4336 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
4338 arg_all * OUTPUT_SHOW_ALL |
4339 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
4340 on_tty() * OUTPUT_COLOR |
4341 !arg_quiet * OUTPUT_WARN_CUTOFF |
4342 arg_full * OUTPUT_FULL_WIDTH;
4344 static const char prefix[] = " ";
4348 if (c > sizeof(prefix) - 1)
4349 c -= sizeof(prefix) - 1;
4353 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
4357 free(mi.control_group);
4362 static int show(sd_bus *bus, char **args) {
4363 bool show_properties, show_status, new_line = false;
4364 bool ellipsized = false;
4370 show_properties = streq(args[0], "show");
4371 show_status = streq(args[0], "status");
4373 if (show_properties)
4374 pager_open_if_enabled();
4376 /* If no argument is specified inspect the manager itself */
4378 if (show_properties && strv_length(args) <= 1)
4379 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4381 if (show_status && strv_length(args) <= 1) {
4383 pager_open_if_enabled();
4384 show_system_status(bus);
4388 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4390 _cleanup_free_ char **patterns = NULL;
4393 STRV_FOREACH(name, args + 1) {
4394 _cleanup_free_ char *unit = NULL;
4397 if (safe_atou32(*name, &id) < 0) {
4398 if (strv_push(&patterns, *name) < 0)
4402 } else if (show_properties) {
4403 /* Interpret as job id */
4404 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4408 /* Interpret as PID */
4409 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4416 r = show_one(args[0], bus, unit, show_properties,
4417 &new_line, &ellipsized);
4420 else if (r > 0 && ret == 0)
4424 if (!strv_isempty(patterns)) {
4425 _cleanup_strv_free_ char **names = NULL;
4427 r = expand_names(bus, patterns, NULL, &names);
4429 log_error("Failed to expand names: %s", strerror(-r));
4431 STRV_FOREACH(name, names) {
4432 _cleanup_free_ char *unit;
4434 unit = unit_dbus_path_from_name(*name);
4438 r = show_one(args[0], bus, unit, show_properties,
4439 &new_line, &ellipsized);
4442 else if (r > 0 && ret == 0)
4448 if (ellipsized && !arg_quiet)
4449 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4454 static int cat(sd_bus *bus, char **args) {
4455 _cleanup_strv_free_ char **names = NULL;
4463 r = expand_names(bus, args + 1, NULL, &names);
4465 log_error("Failed to expand names: %s", strerror(-r));
4467 pager_open_if_enabled();
4469 STRV_FOREACH(name, names) {
4470 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4471 _cleanup_strv_free_ char **dropin_paths = NULL;
4472 _cleanup_free_ char *fragment_path = NULL, *unit = NULL;
4475 unit = unit_dbus_path_from_name(*name);
4479 if (need_daemon_reload(bus, *name) > 0)
4480 log_warning("Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'.",
4481 *name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
4483 r = sd_bus_get_property_string(
4485 "org.freedesktop.systemd1",
4487 "org.freedesktop.systemd1.Unit",
4492 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
4496 r = sd_bus_get_property_strv(
4498 "org.freedesktop.systemd1",
4500 "org.freedesktop.systemd1.Unit",
4505 log_warning("Failed to get DropInPaths: %s", bus_error_message(&error, r));
4514 if (!isempty(fragment_path)) {
4515 printf("%s# %s%s\n",
4516 ansi_highlight_blue(),
4518 ansi_highlight_off());
4521 r = sendfile_full(STDOUT_FILENO, fragment_path);
4523 log_warning("Failed to cat %s: %s", fragment_path, strerror(-r));
4528 STRV_FOREACH(path, dropin_paths) {
4529 printf("%s%s# %s%s\n",
4530 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4531 ansi_highlight_blue(),
4533 ansi_highlight_off());
4536 r = sendfile_full(STDOUT_FILENO, *path);
4538 log_warning("Failed to cat %s: %s", *path, strerror(-r));
4544 return r < 0 ? r : 0;
4547 static int set_property(sd_bus *bus, char **args) {
4548 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4549 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4550 _cleanup_free_ char *n = NULL;
4554 r = sd_bus_message_new_method_call(
4557 "org.freedesktop.systemd1",
4558 "/org/freedesktop/systemd1",
4559 "org.freedesktop.systemd1.Manager",
4560 "SetUnitProperties");
4562 return bus_log_create_error(r);
4564 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4568 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4570 return bus_log_create_error(r);
4572 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4574 return bus_log_create_error(r);
4576 STRV_FOREACH(i, args + 2) {
4577 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4579 return bus_log_create_error(r);
4581 r = bus_append_unit_property_assignment(m, *i);
4585 r = sd_bus_message_close_container(m);
4587 return bus_log_create_error(r);
4590 r = sd_bus_message_close_container(m);
4592 return bus_log_create_error(r);
4594 r = sd_bus_call(bus, m, 0, &error, NULL);
4596 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4603 static int snapshot(sd_bus *bus, char **args) {
4604 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4605 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4606 _cleanup_free_ char *n = NULL, *id = NULL;
4610 if (strv_length(args) > 1)
4611 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4617 r = sd_bus_call_method(
4619 "org.freedesktop.systemd1",
4620 "/org/freedesktop/systemd1",
4621 "org.freedesktop.systemd1.Manager",
4627 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4631 r = sd_bus_message_read(reply, "o", &path);
4633 return bus_log_parse_error(r);
4635 r = sd_bus_get_property_string(
4637 "org.freedesktop.systemd1",
4639 "org.freedesktop.systemd1.Unit",
4644 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4654 static int delete_snapshot(sd_bus *bus, char **args) {
4655 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4656 _cleanup_strv_free_ char **names = NULL;
4662 r = expand_names(bus, args + 1, ".snapshot", &names);
4664 log_error("Failed to expand names: %s", strerror(-r));
4666 STRV_FOREACH(name, names) {
4667 q = sd_bus_call_method(
4669 "org.freedesktop.systemd1",
4670 "/org/freedesktop/systemd1",
4671 "org.freedesktop.systemd1.Manager",
4677 log_error("Failed to remove snapshot %s: %s",
4678 *name, bus_error_message(&error, r));
4687 static int daemon_reload(sd_bus *bus, char **args) {
4688 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4692 if (arg_action == ACTION_RELOAD)
4694 else if (arg_action == ACTION_REEXEC)
4695 method = "Reexecute";
4697 assert(arg_action == ACTION_SYSTEMCTL);
4700 streq(args[0], "clear-jobs") ||
4701 streq(args[0], "cancel") ? "ClearJobs" :
4702 streq(args[0], "daemon-reexec") ? "Reexecute" :
4703 streq(args[0], "reset-failed") ? "ResetFailed" :
4704 streq(args[0], "halt") ? "Halt" :
4705 streq(args[0], "poweroff") ? "PowerOff" :
4706 streq(args[0], "reboot") ? "Reboot" :
4707 streq(args[0], "kexec") ? "KExec" :
4708 streq(args[0], "exit") ? "Exit" :
4709 /* "daemon-reload" */ "Reload";
4712 r = sd_bus_call_method(
4714 "org.freedesktop.systemd1",
4715 "/org/freedesktop/systemd1",
4716 "org.freedesktop.systemd1.Manager",
4722 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4723 /* There's always a fallback possible for
4724 * legacy actions. */
4726 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4727 /* On reexecution, we expect a disconnect, not a
4731 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4733 return r < 0 ? r : 0;
4736 static int reset_failed(sd_bus *bus, char **args) {
4737 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4738 _cleanup_strv_free_ char **names = NULL;
4742 if (strv_length(args) <= 1)
4743 return daemon_reload(bus, args);
4745 r = expand_names(bus, args + 1, NULL, &names);
4747 log_error("Failed to expand names: %s", strerror(-r));
4749 STRV_FOREACH(name, names) {
4750 q = sd_bus_call_method(
4752 "org.freedesktop.systemd1",
4753 "/org/freedesktop/systemd1",
4754 "org.freedesktop.systemd1.Manager",
4760 log_error("Failed to reset failed state of unit %s: %s",
4761 *name, bus_error_message(&error, r));
4770 static int show_environment(sd_bus *bus, char **args) {
4771 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4772 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4776 pager_open_if_enabled();
4778 r = sd_bus_get_property(
4780 "org.freedesktop.systemd1",
4781 "/org/freedesktop/systemd1",
4782 "org.freedesktop.systemd1.Manager",
4788 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4792 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4794 return bus_log_parse_error(r);
4796 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4799 return bus_log_parse_error(r);
4801 r = sd_bus_message_exit_container(reply);
4803 return bus_log_parse_error(r);
4808 static int switch_root(sd_bus *bus, char **args) {
4809 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4810 _cleanup_free_ char *cmdline_init = NULL;
4811 const char *root, *init;
4815 l = strv_length(args);
4816 if (l < 2 || l > 3) {
4817 log_error("Wrong number of arguments.");
4826 r = parse_env_file("/proc/cmdline", WHITESPACE,
4827 "init", &cmdline_init,
4830 log_debug("Failed to parse /proc/cmdline: %s", strerror(-r));
4832 init = cmdline_init;
4839 const char *root_systemd_path = NULL, *root_init_path = NULL;
4841 root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
4842 root_init_path = strappenda(root, "/", init);
4844 /* If the passed init is actually the same as the
4845 * systemd binary, then let's suppress it. */
4846 if (files_same(root_init_path, root_systemd_path) > 0)
4850 log_debug("Switching root - root: %s; init: %s", root, strna(init));
4852 r = sd_bus_call_method(
4854 "org.freedesktop.systemd1",
4855 "/org/freedesktop/systemd1",
4856 "org.freedesktop.systemd1.Manager",
4862 log_error("Failed to switch root: %s", bus_error_message(&error, r));
4869 static int set_environment(sd_bus *bus, char **args) {
4870 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4871 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4878 method = streq(args[0], "set-environment")
4880 : "UnsetEnvironment";
4882 r = sd_bus_message_new_method_call(
4885 "org.freedesktop.systemd1",
4886 "/org/freedesktop/systemd1",
4887 "org.freedesktop.systemd1.Manager",
4890 return bus_log_create_error(r);
4892 r = sd_bus_message_append_strv(m, args + 1);
4894 return bus_log_create_error(r);
4896 r = sd_bus_call(bus, m, 0, &error, NULL);
4898 log_error("Failed to set environment: %s", bus_error_message(&error, r));
4905 static int import_environment(sd_bus *bus, char **args) {
4906 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4907 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4913 r = sd_bus_message_new_method_call(
4916 "org.freedesktop.systemd1",
4917 "/org/freedesktop/systemd1",
4918 "org.freedesktop.systemd1.Manager",
4921 return bus_log_create_error(r);
4923 if (strv_isempty(args + 1))
4924 r = sd_bus_message_append_strv(m, environ);
4928 r = sd_bus_message_open_container(m, 'a', "s");
4930 return bus_log_create_error(r);
4932 STRV_FOREACH(a, args + 1) {
4934 if (!env_name_is_valid(*a)) {
4935 log_error("Not a valid environment variable name: %s", *a);
4939 STRV_FOREACH(b, environ) {
4942 eq = startswith(*b, *a);
4943 if (eq && *eq == '=') {
4945 r = sd_bus_message_append(m, "s", *b);
4947 return bus_log_create_error(r);
4954 r = sd_bus_message_close_container(m);
4957 return bus_log_create_error(r);
4959 r = sd_bus_call(bus, m, 0, &error, NULL);
4961 log_error("Failed to import environment: %s", bus_error_message(&error, r));
4968 static int enable_sysv_units(const char *verb, char **args) {
4971 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4972 unsigned f = 1, t = 1;
4973 _cleanup_lookup_paths_free_ LookupPaths paths = {};
4975 if (arg_scope != UNIT_FILE_SYSTEM)
4978 if (!streq(verb, "enable") &&
4979 !streq(verb, "disable") &&
4980 !streq(verb, "is-enabled"))
4983 /* Processes all SysV units, and reshuffles the array so that
4984 * afterwards only the native units remain */
4986 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, arg_root, NULL, NULL, NULL);
4991 for (f = 0; args[f]; f++) {
4993 _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL;
4994 bool found_native = false, found_sysv;
4996 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
5004 if (!endswith(name, ".service"))
5007 if (path_is_absolute(name))
5010 STRV_FOREACH(k, paths.unit_path) {
5011 _cleanup_free_ char *path = NULL;
5013 path = path_join(arg_root, *k, name);
5017 found_native = access(path, F_OK) >= 0;
5025 p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name);
5029 p[strlen(p) - strlen(".service")] = 0;
5030 found_sysv = access(p, F_OK) >= 0;
5034 /* Mark this entry, so that we don't try enabling it as native unit */
5035 args[f] = (char*) "";
5037 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
5039 if (!isempty(arg_root))
5040 argv[c++] = q = strappend("--root=", arg_root);
5042 argv[c++] = basename(p);
5044 streq(verb, "enable") ? "on" :
5045 streq(verb, "disable") ? "off" : "--level=5";
5048 l = strv_join((char**)argv, " ");
5052 log_info("Executing %s", l);
5056 log_error("Failed to fork: %m");
5058 } else if (pid == 0) {
5061 execv(argv[0], (char**) argv);
5062 _exit(EXIT_FAILURE);
5065 j = wait_for_terminate(pid, &status);
5067 log_error("Failed to wait for child: %s", strerror(-r));
5071 if (status.si_code == CLD_EXITED) {
5072 if (streq(verb, "is-enabled")) {
5073 if (status.si_status == 0) {
5082 } else if (status.si_status != 0)
5088 /* Drop all SysV units */
5089 for (f = 0, t = 0; args[f]; f++) {
5091 if (isempty(args[f]))
5094 args[t++] = args[f];
5103 static int mangle_names(char **original_names, char ***mangled_names) {
5104 char **i, **l, **name;
5106 l = new(char*, strv_length(original_names) + 1);
5111 STRV_FOREACH(name, original_names) {
5113 /* When enabling units qualified path names are OK,
5114 * too, hence allow them explicitly. */
5119 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5135 static int enable_unit(sd_bus *bus, char **args) {
5136 _cleanup_strv_free_ char **names = NULL;
5137 const char *verb = args[0];
5138 UnitFileChange *changes = NULL;
5139 unsigned n_changes = 0;
5140 int carries_install_info = -1;
5146 r = mangle_names(args+1, &names);
5150 r = enable_sysv_units(verb, names);
5154 /* If the operation was fully executed by the SysV compat,
5155 * let's finish early */
5156 if (strv_isempty(names))
5159 if (!bus || avoid_bus()) {
5160 if (streq(verb, "enable")) {
5161 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5162 carries_install_info = r;
5163 } else if (streq(verb, "disable"))
5164 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5165 else if (streq(verb, "reenable")) {
5166 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5167 carries_install_info = r;
5168 } else if (streq(verb, "link"))
5169 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5170 else if (streq(verb, "preset")) {
5171 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_preset_mode, arg_force, &changes, &n_changes);
5172 carries_install_info = r;
5173 } else if (streq(verb, "mask"))
5174 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5175 else if (streq(verb, "unmask"))
5176 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5178 assert_not_reached("Unknown verb");
5181 log_error("Operation failed: %s", strerror(-r));
5186 dump_unit_file_changes(changes, n_changes);
5190 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5191 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5192 int expect_carries_install_info = false;
5193 bool send_force = true, send_preset_mode = false;
5196 if (streq(verb, "enable")) {
5197 method = "EnableUnitFiles";
5198 expect_carries_install_info = true;
5199 } else if (streq(verb, "disable")) {
5200 method = "DisableUnitFiles";
5202 } else if (streq(verb, "reenable")) {
5203 method = "ReenableUnitFiles";
5204 expect_carries_install_info = true;
5205 } else if (streq(verb, "link"))
5206 method = "LinkUnitFiles";
5207 else if (streq(verb, "preset")) {
5209 if (arg_preset_mode != UNIT_FILE_PRESET_FULL) {
5210 method = "PresetUnitFilesWithMode";
5211 send_preset_mode = true;
5213 method = "PresetUnitFiles";
5215 expect_carries_install_info = true;
5216 } else if (streq(verb, "mask"))
5217 method = "MaskUnitFiles";
5218 else if (streq(verb, "unmask")) {
5219 method = "UnmaskUnitFiles";
5222 assert_not_reached("Unknown verb");
5224 r = sd_bus_message_new_method_call(
5227 "org.freedesktop.systemd1",
5228 "/org/freedesktop/systemd1",
5229 "org.freedesktop.systemd1.Manager",
5232 return bus_log_create_error(r);
5234 r = sd_bus_message_append_strv(m, names);
5236 return bus_log_create_error(r);
5238 if (send_preset_mode) {
5239 r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode));
5241 return bus_log_create_error(r);
5244 r = sd_bus_message_append(m, "b", arg_runtime);
5246 return bus_log_create_error(r);
5249 r = sd_bus_message_append(m, "b", arg_force);
5251 return bus_log_create_error(r);
5254 r = sd_bus_call(bus, m, 0, &error, &reply);
5256 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5260 if (expect_carries_install_info) {
5261 r = sd_bus_message_read(reply, "b", &carries_install_info);
5263 return bus_log_parse_error(r);
5266 r = deserialize_and_dump_unit_file_changes(reply);
5270 /* Try to reload if enabled */
5272 r = daemon_reload(bus, args);
5277 if (carries_install_info == 0)
5278 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5279 "using systemctl.\n"
5280 "Possible reasons for having this kind of units are:\n"
5281 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5282 " .wants/ or .requires/ directory.\n"
5283 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5284 " a requirement dependency on it.\n"
5285 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5286 " D-Bus, udev, scripted systemctl call, ...).\n");
5289 unit_file_changes_free(changes, n_changes);
5294 static int add_dependency(sd_bus *bus, char **args) {
5295 _cleanup_strv_free_ char **names = NULL;
5296 _cleanup_free_ char *target = NULL;
5297 const char *verb = args[0];
5304 target = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
5308 r = mangle_names(args+2, &names);
5312 if (streq(verb, "add-wants"))
5314 else if (streq(verb, "add-requires"))
5315 dep = UNIT_REQUIRES;
5317 assert_not_reached("Unknown verb");
5319 if (!bus || avoid_bus()) {
5320 UnitFileChange *changes = NULL;
5321 unsigned n_changes = 0;
5323 r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes);
5326 log_error("Can't add dependency: %s", strerror(-r));
5331 dump_unit_file_changes(changes, n_changes);
5333 unit_file_changes_free(changes, n_changes);
5336 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5337 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5339 r = sd_bus_message_new_method_call(
5342 "org.freedesktop.systemd1",
5343 "/org/freedesktop/systemd1",
5344 "org.freedesktop.systemd1.Manager",
5345 "AddDependencyUnitFiles");
5347 return bus_log_create_error(r);
5349 r = sd_bus_message_append_strv(m, names);
5351 return bus_log_create_error(r);
5353 r = sd_bus_message_append(m, "s", target);
5355 return bus_log_create_error(r);
5357 r = sd_bus_message_append(m, "s", unit_dependency_to_string(dep));
5359 return bus_log_create_error(r);
5361 r = sd_bus_message_append(m, "b", arg_runtime);
5363 return bus_log_create_error(r);
5365 r = sd_bus_message_append(m, "b", arg_force);
5367 return bus_log_create_error(r);
5369 r = sd_bus_call(bus, m, 0, &error, &reply);
5371 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5375 r = deserialize_and_dump_unit_file_changes(reply);
5380 r = daemon_reload(bus, args);
5388 static int preset_all(sd_bus *bus, char **args) {
5389 UnitFileChange *changes = NULL;
5390 unsigned n_changes = 0;
5393 if (!bus || avoid_bus()) {
5395 r = unit_file_preset_all(arg_scope, arg_runtime, arg_root, arg_preset_mode, arg_force, &changes, &n_changes);
5397 log_error("Operation failed: %s", strerror(-r));
5402 dump_unit_file_changes(changes, n_changes);
5407 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5408 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5410 r = sd_bus_call_method(
5412 "org.freedesktop.systemd1",
5413 "/org/freedesktop/systemd1",
5414 "org.freedesktop.systemd1.Manager",
5415 "PresetAllUnitFiles",
5419 unit_file_preset_mode_to_string(arg_preset_mode),
5423 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5427 r = deserialize_and_dump_unit_file_changes(reply);
5432 r = daemon_reload(bus, args);
5438 unit_file_changes_free(changes, n_changes);
5443 static int unit_is_enabled(sd_bus *bus, char **args) {
5445 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5446 _cleanup_strv_free_ char **names = NULL;
5451 r = mangle_names(args+1, &names);
5455 r = enable_sysv_units(args[0], names);
5461 if (!bus || avoid_bus()) {
5463 STRV_FOREACH(name, names) {
5464 UnitFileState state;
5466 state = unit_file_get_state(arg_scope, arg_root, *name);
5468 log_error("Failed to get unit file state for %s: %s", *name, strerror(-state));
5472 if (state == UNIT_FILE_ENABLED ||
5473 state == UNIT_FILE_ENABLED_RUNTIME ||
5474 state == UNIT_FILE_STATIC)
5478 puts(unit_file_state_to_string(state));
5482 STRV_FOREACH(name, names) {
5483 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5486 r = sd_bus_call_method(
5488 "org.freedesktop.systemd1",
5489 "/org/freedesktop/systemd1",
5490 "org.freedesktop.systemd1.Manager",
5496 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5500 r = sd_bus_message_read(reply, "s", &s);
5502 return bus_log_parse_error(r);
5504 if (streq(s, "enabled") ||
5505 streq(s, "enabled-runtime") ||
5517 static int is_system_running(sd_bus *bus, char **args) {
5518 _cleanup_free_ char *state = NULL;
5521 r = sd_bus_get_property_string(
5523 "org.freedesktop.systemd1",
5524 "/org/freedesktop/systemd1",
5525 "org.freedesktop.systemd1.Manager",
5538 return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE;
5541 static void systemctl_help(void) {
5543 pager_open_if_enabled();
5545 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
5546 "Query or send control commands to the systemd manager.\n\n"
5547 " -h --help Show this help\n"
5548 " --version Show package version\n"
5549 " --system Connect to system manager\n"
5550 " --user Connect to user service manager\n"
5551 " -H --host=[USER@]HOST\n"
5552 " Operate on remote host\n"
5553 " -M --machine=CONTAINER\n"
5554 " Operate on local container\n"
5555 " -t --type=TYPE List only units of a particular type\n"
5556 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
5557 " -p --property=NAME Show only properties by this name\n"
5558 " -a --all Show all loaded units/properties, including dead/empty\n"
5559 " ones. To list all units installed on the system, use\n"
5560 " the 'list-unit-files' command instead.\n"
5561 " -l --full Don't ellipsize unit names on output\n"
5562 " -r --recursive Show unit list of host and local containers\n"
5563 " --reverse Show reverse dependencies with 'list-dependencies'\n"
5564 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
5565 " queueing a new job\n"
5566 " --show-types When showing sockets, explicitly show their type\n"
5567 " -i --ignore-inhibitors\n"
5568 " When shutting down or sleeping, ignore inhibitors\n"
5569 " --kill-who=WHO Who to send signal to\n"
5570 " -s --signal=SIGNAL Which signal to send\n"
5571 " -q --quiet Suppress output\n"
5572 " --no-block Do not wait until operation finished\n"
5573 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5574 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
5576 " --no-legend Do not print a legend (column headers and hints)\n"
5577 " --no-pager Do not pipe output into a pager\n"
5578 " --no-ask-password\n"
5579 " Do not ask for system passwords\n"
5580 " --global Enable/disable unit files globally\n"
5581 " --runtime Enable unit files only temporarily until next reboot\n"
5582 " -f --force When enabling unit files, override existing symlinks\n"
5583 " When shutting down, execute action immediately\n"
5584 " --preset-mode= Specifies whether fully apply presets, or only enable,\n"
5585 " or only disable\n"
5586 " --root=PATH Enable unit files in the specified root directory\n"
5587 " -n --lines=INTEGER Number of journal entries to show\n"
5588 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
5589 " verbose, export, json, json-pretty, json-sse, cat)\n"
5590 " --plain Print unit dependencies as a list instead of a tree\n\n"
5592 " list-units [PATTERN...] List loaded units\n"
5593 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
5594 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
5595 " start NAME... Start (activate) one or more units\n"
5596 " stop NAME... Stop (deactivate) one or more units\n"
5597 " reload NAME... Reload one or more units\n"
5598 " restart NAME... Start or restart one or more units\n"
5599 " try-restart NAME... Restart one or more units if active\n"
5600 " reload-or-restart NAME... Reload one or more units if possible,\n"
5601 " otherwise start or restart\n"
5602 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
5603 " otherwise restart if active\n"
5604 " isolate NAME Start one unit and stop all others\n"
5605 " kill NAME... Send signal to processes of a unit\n"
5606 " is-active PATTERN... Check whether units are active\n"
5607 " is-failed PATTERN... Check whether units are failed\n"
5608 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
5609 " show [PATTERN...|JOB...] Show properties of one or more\n"
5610 " units/jobs or the manager\n"
5611 " cat PATTERN... Show files and drop-ins of one or more units\n"
5612 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
5613 " help PATTERN...|PID... Show manual for one or more units\n"
5614 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
5616 " list-dependencies [NAME] Recursively show units which are required\n"
5617 " or wanted by this unit or by which this\n"
5618 " unit is required or wanted\n\n"
5619 "Unit File Commands:\n"
5620 " list-unit-files [PATTERN...] List installed unit files\n"
5621 " enable NAME... Enable one or more unit files\n"
5622 " disable NAME... Disable one or more unit files\n"
5623 " reenable NAME... Reenable one or more unit files\n"
5624 " preset NAME... Enable/disable one or more unit files\n"
5625 " based on preset configuration\n"
5626 " preset-all Enable/disable all unit files based on\n"
5627 " preset configuration\n"
5628 " is-enabled NAME... Check whether unit files are enabled\n\n"
5629 " mask NAME... Mask one or more units\n"
5630 " unmask NAME... Unmask one or more units\n"
5631 " link PATH... Link one or more units files into\n"
5632 " the search path\n"
5633 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
5634 " on specified one or more units\n"
5635 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
5636 " on specified one or more units\n"
5637 " get-default Get the name of the default target\n"
5638 " set-default NAME Set the default target\n\n"
5639 "Machine Commands:\n"
5640 " list-machines [PATTERN...] List local containers and host\n\n"
5642 " list-jobs [PATTERN...] List jobs\n"
5643 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
5644 "Snapshot Commands:\n"
5645 " snapshot [NAME] Create a snapshot\n"
5646 " delete NAME... Remove one or more snapshots\n\n"
5647 "Environment Commands:\n"
5648 " show-environment Dump environment\n"
5649 " set-environment NAME=VALUE... Set one or more environment variables\n"
5650 " unset-environment NAME... Unset one or more environment variables\n"
5651 " import-environment NAME... Import all, one or more environment variables\n\n"
5652 "Manager Lifecycle Commands:\n"
5653 " daemon-reload Reload systemd manager configuration\n"
5654 " daemon-reexec Reexecute systemd manager\n\n"
5655 "System Commands:\n"
5656 " is-system-running Check whether system is fully running\n"
5657 " default Enter system default mode\n"
5658 " rescue Enter system rescue mode\n"
5659 " emergency Enter system emergency mode\n"
5660 " halt Shut down and halt the system\n"
5661 " poweroff Shut down and power-off the system\n"
5662 " reboot [ARG] Shut down and reboot the system\n"
5663 " kexec Shut down and reboot the system with kexec\n"
5664 " exit Request user instance exit\n"
5665 " switch-root ROOT [INIT] Change to a different root file system\n"
5666 " suspend Suspend the system\n"
5667 " hibernate Hibernate the system\n"
5668 " hybrid-sleep Hibernate and suspend the system\n",
5669 program_invocation_short_name);
5672 static void halt_help(void) {
5673 printf("%s [OPTIONS...]%s\n\n"
5674 "%s the system.\n\n"
5675 " --help Show this help\n"
5676 " --halt Halt the machine\n"
5677 " -p --poweroff Switch off the machine\n"
5678 " --reboot Reboot the machine\n"
5679 " -f --force Force immediate halt/power-off/reboot\n"
5680 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
5681 " -d --no-wtmp Don't write wtmp record\n"
5682 " --no-wall Don't send wall message before halt/power-off/reboot\n",
5683 program_invocation_short_name,
5684 arg_action == ACTION_REBOOT ? " [ARG]" : "",
5685 arg_action == ACTION_REBOOT ? "Reboot" :
5686 arg_action == ACTION_POWEROFF ? "Power off" :
5690 static void shutdown_help(void) {
5691 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
5692 "Shut down the system.\n\n"
5693 " --help Show this help\n"
5694 " -H --halt Halt the machine\n"
5695 " -P --poweroff Power-off the machine\n"
5696 " -r --reboot Reboot the machine\n"
5697 " -h Equivalent to --poweroff, overridden by --halt\n"
5698 " -k Don't halt/power-off/reboot, just send warnings\n"
5699 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5700 " -c Cancel a pending shutdown\n",
5701 program_invocation_short_name);
5704 static void telinit_help(void) {
5705 printf("%s [OPTIONS...] {COMMAND}\n\n"
5706 "Send control commands to the init daemon.\n\n"
5707 " --help Show this help\n"
5708 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
5710 " 0 Power-off the machine\n"
5711 " 6 Reboot the machine\n"
5712 " 2, 3, 4, 5 Start runlevelX.target unit\n"
5713 " 1, s, S Enter rescue mode\n"
5714 " q, Q Reload init daemon configuration\n"
5715 " u, U Reexecute init daemon\n",
5716 program_invocation_short_name);
5719 static void runlevel_help(void) {
5720 printf("%s [OPTIONS...]\n\n"
5721 "Prints the previous and current runlevel of the init system.\n\n"
5722 " --help Show this help\n",
5723 program_invocation_short_name);
5726 static void help_types(void) {
5731 puts("Available unit types:");
5732 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
5733 t = unit_type_to_string(i);
5739 static int systemctl_parse_argv(int argc, char *argv[]) {
5748 ARG_IGNORE_DEPENDENCIES,
5760 ARG_NO_ASK_PASSWORD,
5770 static const struct option options[] = {
5771 { "help", no_argument, NULL, 'h' },
5772 { "version", no_argument, NULL, ARG_VERSION },
5773 { "type", required_argument, NULL, 't' },
5774 { "property", required_argument, NULL, 'p' },
5775 { "all", no_argument, NULL, 'a' },
5776 { "reverse", no_argument, NULL, ARG_REVERSE },
5777 { "after", no_argument, NULL, ARG_AFTER },
5778 { "before", no_argument, NULL, ARG_BEFORE },
5779 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
5780 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
5781 { "full", no_argument, NULL, 'l' },
5782 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
5783 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
5784 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
5785 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
5786 { "ignore-inhibitors", no_argument, NULL, 'i' },
5787 { "user", no_argument, NULL, ARG_USER },
5788 { "system", no_argument, NULL, ARG_SYSTEM },
5789 { "global", no_argument, NULL, ARG_GLOBAL },
5790 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
5791 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
5792 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
5793 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5794 { "quiet", no_argument, NULL, 'q' },
5795 { "root", required_argument, NULL, ARG_ROOT },
5796 { "force", no_argument, NULL, ARG_FORCE },
5797 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
5798 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
5799 { "signal", required_argument, NULL, 's' },
5800 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
5801 { "host", required_argument, NULL, 'H' },
5802 { "machine", required_argument, NULL, 'M' },
5803 { "runtime", no_argument, NULL, ARG_RUNTIME },
5804 { "lines", required_argument, NULL, 'n' },
5805 { "output", required_argument, NULL, 'o' },
5806 { "plain", no_argument, NULL, ARG_PLAIN },
5807 { "state", required_argument, NULL, ARG_STATE },
5808 { "recursive", no_argument, NULL, 'r' },
5809 { "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
5818 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
5827 puts(PACKAGE_STRING);
5828 puts(SYSTEMD_FEATURES);
5832 const char *word, *state;
5835 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5836 _cleanup_free_ char *type;
5838 type = strndup(word, size);
5842 if (streq(type, "help")) {
5847 if (unit_type_from_string(type) >= 0) {
5848 if (strv_push(&arg_types, type))
5854 /* It's much nicer to use --state= for
5855 * load states, but let's support this
5856 * in --types= too for compatibility
5857 * with old versions */
5858 if (unit_load_state_from_string(optarg) >= 0) {
5859 if (strv_push(&arg_states, type) < 0)
5865 log_error("Unknown unit type or load state '%s'.", type);
5866 log_info("Use -t help to see a list of allowed values.");
5874 /* Make sure that if the empty property list
5875 was specified, we won't show any properties. */
5876 if (isempty(optarg) && !arg_properties) {
5877 arg_properties = new0(char*, 1);
5878 if (!arg_properties)
5881 const char *word, *state;
5884 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5887 prop = strndup(word, size);
5891 if (strv_consume(&arg_properties, prop) < 0)
5896 /* If the user asked for a particular
5897 * property, show it to him, even if it is
5909 arg_dependency = DEPENDENCY_REVERSE;
5913 arg_dependency = DEPENDENCY_AFTER;
5917 arg_dependency = DEPENDENCY_BEFORE;
5920 case ARG_SHOW_TYPES:
5921 arg_show_types = true;
5925 arg_job_mode = optarg;
5929 arg_job_mode = "fail";
5932 case ARG_IRREVERSIBLE:
5933 arg_job_mode = "replace-irreversibly";
5936 case ARG_IGNORE_DEPENDENCIES:
5937 arg_job_mode = "ignore-dependencies";
5941 arg_scope = UNIT_FILE_USER;
5945 arg_scope = UNIT_FILE_SYSTEM;
5949 arg_scope = UNIT_FILE_GLOBAL;
5953 arg_no_block = true;
5957 arg_no_legend = true;
5961 arg_no_pager = true;
5977 if (strv_extend(&arg_states, "failed") < 0)
5995 arg_no_reload = true;
5999 arg_kill_who = optarg;
6003 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
6004 log_error("Failed to parse signal string %s.", optarg);
6009 case ARG_NO_ASK_PASSWORD:
6010 arg_ask_password = false;
6014 arg_transport = BUS_TRANSPORT_REMOTE;
6019 arg_transport = BUS_TRANSPORT_CONTAINER;
6028 if (safe_atou(optarg, &arg_lines) < 0) {
6029 log_error("Failed to parse lines '%s'", optarg);
6035 arg_output = output_mode_from_string(optarg);
6036 if (arg_output < 0) {
6037 log_error("Unknown output '%s'.", optarg);
6043 arg_ignore_inhibitors = true;
6051 const char *word, *state;
6054 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6057 s = strndup(word, size);
6061 if (strv_consume(&arg_states, s) < 0)
6068 if (geteuid() != 0) {
6069 log_error("--recursive requires root privileges.");
6073 arg_recursive = true;
6076 case ARG_PRESET_MODE:
6078 arg_preset_mode = unit_file_preset_mode_from_string(optarg);
6079 if (arg_preset_mode < 0) {
6080 log_error("Failed to parse preset mode: %s.", optarg);
6090 assert_not_reached("Unhandled option");
6093 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
6094 log_error("Cannot access user instance remotely.");
6101 static int halt_parse_argv(int argc, char *argv[]) {
6110 static const struct option options[] = {
6111 { "help", no_argument, NULL, ARG_HELP },
6112 { "halt", no_argument, NULL, ARG_HALT },
6113 { "poweroff", no_argument, NULL, 'p' },
6114 { "reboot", no_argument, NULL, ARG_REBOOT },
6115 { "force", no_argument, NULL, 'f' },
6116 { "wtmp-only", no_argument, NULL, 'w' },
6117 { "no-wtmp", no_argument, NULL, 'd' },
6118 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6127 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
6128 if (runlevel == '0' || runlevel == '6')
6131 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
6139 arg_action = ACTION_HALT;
6143 if (arg_action != ACTION_REBOOT)
6144 arg_action = ACTION_POWEROFF;
6148 arg_action = ACTION_REBOOT;
6170 /* Compatibility nops */
6177 assert_not_reached("Unhandled option");
6180 if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
6181 r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL);
6184 } else if (optind < argc) {
6185 log_error("Too many arguments.");
6192 static int parse_time_spec(const char *t, usec_t *_u) {
6196 if (streq(t, "now"))
6198 else if (!strchr(t, ':')) {
6201 if (safe_atou64(t, &u) < 0)
6204 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
6213 hour = strtol(t, &e, 10);
6214 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
6217 minute = strtol(e+1, &e, 10);
6218 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
6221 n = now(CLOCK_REALTIME);
6222 s = (time_t) (n / USEC_PER_SEC);
6224 assert_se(localtime_r(&s, &tm));
6226 tm.tm_hour = (int) hour;
6227 tm.tm_min = (int) minute;
6230 assert_se(s = mktime(&tm));
6232 *_u = (usec_t) s * USEC_PER_SEC;
6235 *_u += USEC_PER_DAY;
6241 static int shutdown_parse_argv(int argc, char *argv[]) {
6248 static const struct option options[] = {
6249 { "help", no_argument, NULL, ARG_HELP },
6250 { "halt", no_argument, NULL, 'H' },
6251 { "poweroff", no_argument, NULL, 'P' },
6252 { "reboot", no_argument, NULL, 'r' },
6253 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
6254 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6263 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0)
6271 arg_action = ACTION_HALT;
6275 arg_action = ACTION_POWEROFF;
6280 arg_action = ACTION_KEXEC;
6282 arg_action = ACTION_REBOOT;
6286 arg_action = ACTION_KEXEC;
6290 if (arg_action != ACTION_HALT)
6291 arg_action = ACTION_POWEROFF;
6304 /* Compatibility nops */
6308 arg_action = ACTION_CANCEL_SHUTDOWN;
6315 assert_not_reached("Unhandled option");
6318 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
6319 r = parse_time_spec(argv[optind], &arg_when);
6321 log_error("Failed to parse time specification: %s", argv[optind]);
6325 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
6327 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
6328 /* No time argument for shutdown cancel */
6329 arg_wall = argv + optind;
6330 else if (argc > optind + 1)
6331 /* We skip the time argument */
6332 arg_wall = argv + optind + 1;
6339 static int telinit_parse_argv(int argc, char *argv[]) {
6346 static const struct option options[] = {
6347 { "help", no_argument, NULL, ARG_HELP },
6348 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6352 static const struct {
6356 { '0', ACTION_POWEROFF },
6357 { '6', ACTION_REBOOT },
6358 { '1', ACTION_RESCUE },
6359 { '2', ACTION_RUNLEVEL2 },
6360 { '3', ACTION_RUNLEVEL3 },
6361 { '4', ACTION_RUNLEVEL4 },
6362 { '5', ACTION_RUNLEVEL5 },
6363 { 's', ACTION_RESCUE },
6364 { 'S', ACTION_RESCUE },
6365 { 'q', ACTION_RELOAD },
6366 { 'Q', ACTION_RELOAD },
6367 { 'u', ACTION_REEXEC },
6368 { 'U', ACTION_REEXEC }
6377 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6392 assert_not_reached("Unhandled option");
6395 if (optind >= argc) {
6396 log_error("%s: required argument missing.",
6397 program_invocation_short_name);
6401 if (optind + 1 < argc) {
6402 log_error("Too many arguments.");
6406 if (strlen(argv[optind]) != 1) {
6407 log_error("Expected single character argument.");
6411 for (i = 0; i < ELEMENTSOF(table); i++)
6412 if (table[i].from == argv[optind][0])
6415 if (i >= ELEMENTSOF(table)) {
6416 log_error("Unknown command '%s'.", argv[optind]);
6420 arg_action = table[i].to;
6427 static int runlevel_parse_argv(int argc, char *argv[]) {
6433 static const struct option options[] = {
6434 { "help", no_argument, NULL, ARG_HELP },
6443 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6454 assert_not_reached("Unhandled option");
6457 if (optind < argc) {
6458 log_error("Too many arguments.");
6465 static int parse_argv(int argc, char *argv[]) {
6469 if (program_invocation_short_name) {
6471 if (strstr(program_invocation_short_name, "halt")) {
6472 arg_action = ACTION_HALT;
6473 return halt_parse_argv(argc, argv);
6474 } else if (strstr(program_invocation_short_name, "poweroff")) {
6475 arg_action = ACTION_POWEROFF;
6476 return halt_parse_argv(argc, argv);
6477 } else if (strstr(program_invocation_short_name, "reboot")) {
6479 arg_action = ACTION_KEXEC;
6481 arg_action = ACTION_REBOOT;
6482 return halt_parse_argv(argc, argv);
6483 } else if (strstr(program_invocation_short_name, "shutdown")) {
6484 arg_action = ACTION_POWEROFF;
6485 return shutdown_parse_argv(argc, argv);
6486 } else if (strstr(program_invocation_short_name, "init")) {
6488 if (sd_booted() > 0) {
6489 arg_action = _ACTION_INVALID;
6490 return telinit_parse_argv(argc, argv);
6492 /* Hmm, so some other init system is
6493 * running, we need to forward this
6494 * request to it. For now we simply
6495 * guess that it is Upstart. */
6497 execv(TELINIT, argv);
6499 log_error("Couldn't find an alternative telinit implementation to spawn.");
6503 } else if (strstr(program_invocation_short_name, "runlevel")) {
6504 arg_action = ACTION_RUNLEVEL;
6505 return runlevel_parse_argv(argc, argv);
6509 arg_action = ACTION_SYSTEMCTL;
6510 return systemctl_parse_argv(argc, argv);
6513 _pure_ static int action_to_runlevel(void) {
6515 static const char table[_ACTION_MAX] = {
6516 [ACTION_HALT] = '0',
6517 [ACTION_POWEROFF] = '0',
6518 [ACTION_REBOOT] = '6',
6519 [ACTION_RUNLEVEL2] = '2',
6520 [ACTION_RUNLEVEL3] = '3',
6521 [ACTION_RUNLEVEL4] = '4',
6522 [ACTION_RUNLEVEL5] = '5',
6523 [ACTION_RESCUE] = '1'
6526 assert(arg_action < _ACTION_MAX);
6528 return table[arg_action];
6531 static int talk_initctl(void) {
6533 struct init_request request = {
6534 .magic = INIT_MAGIC,
6536 .cmd = INIT_CMD_RUNLVL
6539 _cleanup_close_ int fd = -1;
6543 rl = action_to_runlevel();
6547 request.runlevel = rl;
6549 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
6551 if (errno == ENOENT)
6554 log_error("Failed to open "INIT_FIFO": %m");
6559 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
6561 log_error("Failed to write to "INIT_FIFO": %m");
6562 return errno > 0 ? -errno : -EIO;
6568 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
6570 static const struct {
6578 int (* const dispatch)(sd_bus *bus, char **args);
6584 { "list-units", MORE, 0, list_units },
6585 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
6586 { "list-sockets", MORE, 1, list_sockets },
6587 { "list-timers", MORE, 1, list_timers },
6588 { "list-jobs", MORE, 1, list_jobs },
6589 { "list-machines", MORE, 1, list_machines },
6590 { "clear-jobs", EQUAL, 1, daemon_reload },
6591 { "cancel", MORE, 2, cancel_job },
6592 { "start", MORE, 2, start_unit },
6593 { "stop", MORE, 2, start_unit },
6594 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6595 { "reload", MORE, 2, start_unit },
6596 { "restart", MORE, 2, start_unit },
6597 { "try-restart", MORE, 2, start_unit },
6598 { "reload-or-restart", MORE, 2, start_unit },
6599 { "reload-or-try-restart", MORE, 2, start_unit },
6600 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
6601 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6602 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
6603 { "isolate", EQUAL, 2, start_unit },
6604 { "kill", MORE, 2, kill_unit },
6605 { "is-active", MORE, 2, check_unit_active },
6606 { "check", MORE, 2, check_unit_active },
6607 { "is-failed", MORE, 2, check_unit_failed },
6608 { "show", MORE, 1, show },
6609 { "cat", MORE, 2, cat },
6610 { "status", MORE, 1, show },
6611 { "help", MORE, 2, show },
6612 { "snapshot", LESS, 2, snapshot },
6613 { "delete", MORE, 2, delete_snapshot },
6614 { "daemon-reload", EQUAL, 1, daemon_reload },
6615 { "daemon-reexec", EQUAL, 1, daemon_reload },
6616 { "show-environment", EQUAL, 1, show_environment },
6617 { "set-environment", MORE, 2, set_environment },
6618 { "unset-environment", MORE, 2, set_environment },
6619 { "import-environment", MORE, 1, import_environment},
6620 { "halt", EQUAL, 1, start_special, FORCE },
6621 { "poweroff", EQUAL, 1, start_special, FORCE },
6622 { "reboot", EQUAL, 1, start_special, FORCE },
6623 { "kexec", EQUAL, 1, start_special },
6624 { "suspend", EQUAL, 1, start_special },
6625 { "hibernate", EQUAL, 1, start_special },
6626 { "hybrid-sleep", EQUAL, 1, start_special },
6627 { "default", EQUAL, 1, start_special },
6628 { "rescue", EQUAL, 1, start_special },
6629 { "emergency", EQUAL, 1, start_special },
6630 { "exit", EQUAL, 1, start_special },
6631 { "reset-failed", MORE, 1, reset_failed },
6632 { "enable", MORE, 2, enable_unit, NOBUS },
6633 { "disable", MORE, 2, enable_unit, NOBUS },
6634 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
6635 { "reenable", MORE, 2, enable_unit, NOBUS },
6636 { "preset", MORE, 2, enable_unit, NOBUS },
6637 { "preset-all", EQUAL, 1, preset_all, NOBUS },
6638 { "mask", MORE, 2, enable_unit, NOBUS },
6639 { "unmask", MORE, 2, enable_unit, NOBUS },
6640 { "link", MORE, 2, enable_unit, NOBUS },
6641 { "switch-root", MORE, 2, switch_root },
6642 { "list-dependencies", LESS, 2, list_dependencies },
6643 { "set-default", EQUAL, 2, set_default, NOBUS },
6644 { "get-default", EQUAL, 1, get_default, NOBUS },
6645 { "set-property", MORE, 3, set_property },
6646 { "is-system-running", EQUAL, 1, is_system_running },
6647 { "add-wants", MORE, 3, add_dependency, NOBUS },
6648 { "add-requires", MORE, 3, add_dependency, NOBUS },
6657 left = argc - optind;
6659 /* Special rule: no arguments (left == 0) means "list-units" */
6661 if (streq(argv[optind], "help") && !argv[optind+1]) {
6662 log_error("This command expects one or more "
6663 "unit names. Did you mean --help?");
6667 for (; verb->verb; verb++)
6668 if (streq(argv[optind], verb->verb))
6671 log_error("Unknown operation '%s'.", argv[optind]);
6676 switch (verb->argc_cmp) {
6679 if (left != verb->argc) {
6680 log_error("Invalid number of arguments.");
6687 if (left < verb->argc) {
6688 log_error("Too few arguments.");
6695 if (left > verb->argc) {
6696 log_error("Too many arguments.");
6703 assert_not_reached("Unknown comparison operator.");
6706 /* Require a bus connection for all operations but
6708 if (verb->bus == NOBUS) {
6709 if (!bus && !avoid_bus()) {
6710 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6715 if (running_in_chroot() > 0) {
6716 log_info("Running in chroot, ignoring request.");
6720 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
6721 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6726 return verb->dispatch(bus, argv + optind);
6729 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
6731 struct sd_shutdown_command c = {
6738 union sockaddr_union sockaddr = {
6739 .un.sun_family = AF_UNIX,
6740 .un.sun_path = "/run/systemd/shutdownd",
6743 struct iovec iovec[2] = {{
6744 .iov_base = (char*) &c,
6745 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
6748 struct msghdr msghdr = {
6749 .msg_name = &sockaddr,
6750 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
6751 + strlen("/run/systemd/shutdownd"),
6756 _cleanup_close_ int fd;
6758 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
6762 if (!isempty(message)) {
6763 iovec[1].iov_base = (char*) message;
6764 iovec[1].iov_len = strlen(message);
6765 msghdr.msg_iovlen++;
6768 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
6774 static int reload_with_fallback(sd_bus *bus) {
6777 /* First, try systemd via D-Bus. */
6778 if (daemon_reload(bus, NULL) >= 0)
6782 /* Nothing else worked, so let's try signals */
6783 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
6785 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
6786 log_error("kill() failed: %m");
6793 static int start_with_fallback(sd_bus *bus) {
6796 /* First, try systemd via D-Bus. */
6797 if (start_unit(bus, NULL) >= 0)
6801 /* Nothing else worked, so let's try
6803 if (talk_initctl() > 0)
6806 log_error("Failed to talk to init daemon.");
6810 warn_wall(arg_action);
6814 static int halt_now(enum action a) {
6816 /* Make sure C-A-D is handled by the kernel from this
6818 reboot(RB_ENABLE_CAD);
6823 log_info("Halting.");
6824 reboot(RB_HALT_SYSTEM);
6827 case ACTION_POWEROFF:
6828 log_info("Powering off.");
6829 reboot(RB_POWER_OFF);
6832 case ACTION_REBOOT: {
6833 _cleanup_free_ char *param = NULL;
6835 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
6836 log_info("Rebooting with argument '%s'.", param);
6837 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
6838 LINUX_REBOOT_CMD_RESTART2, param);
6841 log_info("Rebooting.");
6842 reboot(RB_AUTOBOOT);
6847 assert_not_reached("Unknown action.");
6851 static int halt_main(sd_bus *bus) {
6854 r = check_inhibitors(bus, arg_action);
6858 if (geteuid() != 0) {
6859 /* Try logind if we are a normal user and no special
6860 * mode applies. Maybe PolicyKit allows us to shutdown
6863 if (arg_when <= 0 &&
6866 (arg_action == ACTION_POWEROFF ||
6867 arg_action == ACTION_REBOOT)) {
6868 r = reboot_with_logind(bus, arg_action);
6873 log_error("Must be root.");
6878 _cleanup_free_ char *m;
6880 m = strv_join(arg_wall, " ");
6884 r = send_shutdownd(arg_when,
6885 arg_action == ACTION_HALT ? 'H' :
6886 arg_action == ACTION_POWEROFF ? 'P' :
6887 arg_action == ACTION_KEXEC ? 'K' :
6894 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6896 char date[FORMAT_TIMESTAMP_MAX];
6898 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6899 format_timestamp(date, sizeof(date), arg_when));
6904 if (!arg_dry && !arg_force)
6905 return start_with_fallback(bus);
6908 if (sd_booted() > 0)
6909 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6911 r = utmp_put_shutdown();
6913 log_warning("Failed to write utmp record: %s", strerror(-r));
6920 r = halt_now(arg_action);
6921 log_error("Failed to reboot: %s", strerror(-r));
6926 static int runlevel_main(void) {
6927 int r, runlevel, previous;
6929 r = utmp_get_runlevel(&runlevel, &previous);
6936 previous <= 0 ? 'N' : previous,
6937 runlevel <= 0 ? 'N' : runlevel);
6942 int main(int argc, char*argv[]) {
6943 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
6946 setlocale(LC_ALL, "");
6947 log_parse_environment();
6950 /* Explicitly not on_tty() to avoid setting cached value.
6951 * This becomes relevant for piping output which might be
6953 original_stdout_is_tty = isatty(STDOUT_FILENO);
6955 r = parse_argv(argc, argv);
6959 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6960 * let's shortcut this */
6961 if (arg_action == ACTION_RUNLEVEL) {
6962 r = runlevel_main();
6966 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6967 log_info("Running in chroot, ignoring request.");
6973 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
6975 /* systemctl_main() will print an error message for the bus
6976 * connection, but only if it needs to */
6978 switch (arg_action) {
6980 case ACTION_SYSTEMCTL:
6981 r = systemctl_main(bus, argc, argv, r);
6985 case ACTION_POWEROFF:
6991 case ACTION_RUNLEVEL2:
6992 case ACTION_RUNLEVEL3:
6993 case ACTION_RUNLEVEL4:
6994 case ACTION_RUNLEVEL5:
6996 case ACTION_EMERGENCY:
6997 case ACTION_DEFAULT:
6998 r = start_with_fallback(bus);
7003 r = reload_with_fallback(bus);
7006 case ACTION_CANCEL_SHUTDOWN: {
7007 _cleanup_free_ char *m = NULL;
7010 m = strv_join(arg_wall, " ");
7017 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
7019 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
7023 case ACTION_RUNLEVEL:
7024 case _ACTION_INVALID:
7026 assert_not_reached("Unknown action");
7031 ask_password_agent_close();
7032 polkit_agent_close();
7034 strv_free(arg_types);
7035 strv_free(arg_states);
7036 strv_free(arg_properties);
7038 return r < 0 ? EXIT_FAILURE : r;