1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Marc-Antoine Perennou
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/reboot.h>
24 #include <linux/reboot.h>
25 #include <sys/syscall.h>
32 #include <sys/ioctl.h>
36 #include <sys/socket.h>
39 #include <sys/prctl.h>
42 #include "sd-daemon.h"
43 #include "sd-shutdown.h"
50 #include "utmp-wtmp.h"
53 #include "path-util.h"
55 #include "cgroup-show.h"
56 #include "cgroup-util.h"
58 #include "path-lookup.h"
59 #include "conf-parser.h"
60 #include "exit-status.h"
62 #include "unit-name.h"
64 #include "spawn-ask-password-agent.h"
65 #include "spawn-polkit-agent.h"
67 #include "logs-show.h"
68 #include "socket-util.h"
73 #include "bus-message.h"
74 #include "bus-error.h"
75 #include "bus-common-errors.h"
79 static char **arg_types = NULL;
80 static char **arg_states = NULL;
81 static char **arg_properties = NULL;
82 static bool arg_all = false;
83 static enum dependency {
89 } arg_dependency = DEPENDENCY_FORWARD;
90 static const char *arg_job_mode = "replace";
91 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
92 static bool arg_no_block = false;
93 static bool arg_no_legend = false;
94 static bool arg_no_pager = false;
95 static bool arg_no_wtmp = false;
96 static bool arg_no_wall = false;
97 static bool arg_no_reload = false;
98 static bool arg_show_types = false;
99 static bool arg_ignore_inhibitors = false;
100 static bool arg_dry = false;
101 static bool arg_quiet = false;
102 static bool arg_full = false;
103 static bool arg_recursive = false;
104 static int arg_force = 0;
105 static bool arg_ask_password = true;
106 static bool arg_runtime = false;
107 static UnitFilePresetMode arg_preset_mode = UNIT_FILE_PRESET_FULL;
108 static char **arg_wall = NULL;
109 static const char *arg_kill_who = NULL;
110 static int arg_signal = SIGTERM;
111 static const char *arg_root = NULL;
112 static usec_t arg_when = 0;
134 ACTION_CANCEL_SHUTDOWN,
136 } arg_action = ACTION_SYSTEMCTL;
137 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
138 static char *arg_host = NULL;
139 static unsigned arg_lines = 10;
140 static OutputMode arg_output = OUTPUT_SHORT;
141 static bool arg_plain = false;
143 static bool original_stdout_is_tty;
145 static int daemon_reload(sd_bus *bus, char **args);
146 static int halt_now(enum action a);
147 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet);
149 static char** strv_skip_first(char **strv) {
150 if (strv_length(strv) > 0)
155 static void pager_open_if_enabled(void) {
163 static void ask_password_agent_open_if_enabled(void) {
165 /* Open the password agent as a child process if necessary */
167 if (!arg_ask_password)
170 if (arg_scope != UNIT_FILE_SYSTEM)
173 if (arg_transport != BUS_TRANSPORT_LOCAL)
176 ask_password_agent_open();
180 static void polkit_agent_open_if_enabled(void) {
182 /* Open the polkit agent as a child process if necessary */
184 if (!arg_ask_password)
187 if (arg_scope != UNIT_FILE_SYSTEM)
190 if (arg_transport != BUS_TRANSPORT_LOCAL)
197 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
200 if (!sd_bus_error_is_set(error))
203 if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) ||
204 sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
205 sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
206 sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
207 return EXIT_NOPERMISSION;
209 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
210 return EXIT_NOTINSTALLED;
212 if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
213 sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED))
214 return EXIT_NOTIMPLEMENTED;
216 if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
217 return EXIT_NOTCONFIGURED;
225 static void warn_wall(enum action a) {
226 static const char *table[_ACTION_MAX] = {
227 [ACTION_HALT] = "The system is going down for system halt NOW!",
228 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
229 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
230 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
231 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
232 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
233 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
240 _cleanup_free_ char *p;
242 p = strv_join(arg_wall, " ");
249 utmp_wall(p, NULL, NULL);
257 utmp_wall(table[a], NULL, NULL);
260 static bool avoid_bus(void) {
262 if (running_in_chroot() > 0)
265 if (sd_booted() <= 0)
268 if (!isempty(arg_root))
271 if (arg_scope == UNIT_FILE_GLOBAL)
277 static int compare_unit_info(const void *a, const void *b) {
278 const UnitInfo *u = a, *v = b;
282 /* First, order by machine */
283 if (!u->machine && v->machine)
285 if (u->machine && !v->machine)
287 if (u->machine && v->machine) {
288 r = strcasecmp(u->machine, v->machine);
293 /* Second, order by unit type */
294 d1 = strrchr(u->id, '.');
295 d2 = strrchr(v->id, '.');
297 r = strcasecmp(d1, d2);
302 /* Third, order by name */
303 return strcasecmp(u->id, v->id);
306 static bool output_show_unit(const UnitInfo *u, char **patterns) {
307 if (!strv_isempty(patterns)) {
310 STRV_FOREACH(pattern, patterns)
311 if (fnmatch(*pattern, u->id, FNM_NOESCAPE) == 0)
320 dot = strrchr(u->id, '.');
324 if (!strv_find(arg_types, dot+1))
334 if (streq(u->active_state, "inactive") || u->following[0])
340 static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
341 unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
343 unsigned n_shown = 0;
346 max_id_len = strlen("UNIT");
347 load_len = strlen("LOAD");
348 active_len = strlen("ACTIVE");
349 sub_len = strlen("SUB");
350 job_len = strlen("JOB");
353 for (u = unit_infos; u < unit_infos + c; u++) {
354 max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0));
355 load_len = MAX(load_len, strlen(u->load_state));
356 active_len = MAX(active_len, strlen(u->active_state));
357 sub_len = MAX(sub_len, strlen(u->sub_state));
359 if (u->job_id != 0) {
360 job_len = MAX(job_len, strlen(u->job_type));
364 if (!arg_no_legend &&
365 (streq(u->active_state, "failed") ||
366 STR_IN_SET(u->load_state, "error", "not-found", "masked")))
370 if (!arg_full && original_stdout_is_tty) {
373 id_len = MIN(max_id_len, 25u);
374 basic_len = circle_len + 5 + id_len + 5 + active_len + sub_len;
377 basic_len += job_len + 1;
379 if (basic_len < (unsigned) columns()) {
380 unsigned extra_len, incr;
381 extra_len = columns() - basic_len;
383 /* Either UNIT already got 25, or is fully satisfied.
384 * Grant up to 25 to DESC now. */
385 incr = MIN(extra_len, 25u);
389 /* split the remaining space between UNIT and DESC,
390 * but do not give UNIT more than it needs. */
392 incr = MIN(extra_len / 2, max_id_len - id_len);
394 desc_len += extra_len - incr;
400 for (u = unit_infos; u < unit_infos + c; u++) {
401 _cleanup_free_ char *e = NULL, *j = NULL;
402 const char *on_loaded = "", *off_loaded = "";
403 const char *on_active = "", *off_active = "";
404 const char *on_circle = "", *off_circle = "";
408 if (!n_shown && !arg_no_legend) {
413 printf("%-*s %-*s %-*s %-*s ",
416 active_len, "ACTIVE",
420 printf("%-*s ", job_len, "JOB");
422 if (!arg_full && arg_no_pager)
423 printf("%.*s\n", desc_len, "DESCRIPTION");
425 printf("%s\n", "DESCRIPTION");
430 if (STR_IN_SET(u->load_state, "error", "not-found", "masked")) {
431 on_loaded = ansi_highlight_red();
432 on_circle = ansi_highlight_yellow();
433 off_loaded = off_circle = ansi_highlight_off();
437 if (streq(u->active_state, "failed")) {
438 on_circle = on_active = ansi_highlight_red();
439 off_circle = off_active = ansi_highlight_off();
444 j = strjoin(u->machine, ":", u->id, NULL);
453 e = ellipsize(id, id_len, 33);
461 printf("%s%s%s ", on_circle, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_circle);
463 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
464 on_active, id_len, id, off_active,
465 on_loaded, load_len, u->load_state, off_loaded,
466 on_active, active_len, u->active_state,
467 sub_len, u->sub_state, off_active,
468 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
471 printf("%.*s\n", desc_len, u->description);
473 printf("%s\n", u->description);
476 if (!arg_no_legend) {
477 const char *on, *off;
481 "LOAD = Reflects whether the unit definition was properly loaded.\n"
482 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
483 "SUB = The low-level unit activation state, values depend on unit type.");
484 puts(job_count ? "JOB = Pending job for the unit.\n" : "");
485 on = ansi_highlight();
486 off = ansi_highlight_off();
488 on = ansi_highlight_red();
489 off = ansi_highlight_off();
493 printf("%s%u loaded units listed.%s\n"
494 "To show all installed unit files use 'systemctl list-unit-files'.\n",
497 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
498 "To show all installed unit files use 'systemctl list-unit-files'.\n",
505 static int get_unit_list(
509 UnitInfo **unit_infos,
511 sd_bus_message **_reply) {
513 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
514 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
515 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
524 r = sd_bus_message_new_method_call(
527 "org.freedesktop.systemd1",
528 "/org/freedesktop/systemd1",
529 "org.freedesktop.systemd1.Manager",
530 "ListUnitsFiltered");
533 return bus_log_create_error(r);
535 r = sd_bus_message_append_strv(m, arg_states);
537 return bus_log_create_error(r);
539 r = sd_bus_call(bus, m, 0, &error, &reply);
541 log_error("Failed to list units: %s", bus_error_message(&error, r));
545 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
547 return bus_log_parse_error(r);
549 while ((r = bus_parse_unit_info(reply, &u)) > 0) {
552 if (!output_show_unit(&u, patterns))
555 if (!GREEDY_REALLOC(*unit_infos, size, c+1))
558 (*unit_infos)[c++] = u;
561 return bus_log_parse_error(r);
563 r = sd_bus_message_exit_container(reply);
565 return bus_log_parse_error(r);
573 static void message_set_freep(Set **set) {
576 while ((m = set_steal_first(*set)))
577 sd_bus_message_unref(m);
582 static int get_unit_list_recursive(
585 UnitInfo **_unit_infos,
589 _cleanup_free_ UnitInfo *unit_infos = NULL;
590 _cleanup_(message_set_freep) Set *replies;
591 sd_bus_message *reply;
599 replies = set_new(NULL);
603 c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
607 r = set_put(replies, reply);
609 sd_bus_message_unref(reply);
614 _cleanup_strv_free_ char **machines = NULL;
617 r = sd_get_machine_names(&machines);
621 STRV_FOREACH(i, machines) {
622 _cleanup_bus_close_unref_ sd_bus *container = NULL;
625 r = sd_bus_open_system_machine(&container, *i);
627 log_error_errno(r, "Failed to connect to container %s: %m", *i);
631 k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
637 r = set_put(replies, reply);
639 sd_bus_message_unref(reply);
644 *_machines = machines;
649 *_unit_infos = unit_infos;
658 static int list_units(sd_bus *bus, char **args) {
659 _cleanup_free_ UnitInfo *unit_infos = NULL;
660 _cleanup_(message_set_freep) Set *replies = NULL;
661 _cleanup_strv_free_ char **machines = NULL;
664 pager_open_if_enabled();
666 r = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
670 qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
671 return output_units_list(unit_infos, r);
674 static int get_triggered_units(
679 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
682 r = sd_bus_get_property_strv(
684 "org.freedesktop.systemd1",
686 "org.freedesktop.systemd1.Unit",
692 log_error("Failed to determine triggers: %s", bus_error_message(&error, r));
697 static int get_listening(
699 const char* unit_path,
702 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
703 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
704 const char *type, *path;
707 r = sd_bus_get_property(
709 "org.freedesktop.systemd1",
711 "org.freedesktop.systemd1.Socket",
717 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r));
721 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
723 return bus_log_parse_error(r);
725 while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
727 r = strv_extend(listening, type);
731 r = strv_extend(listening, path);
738 return bus_log_parse_error(r);
740 r = sd_bus_message_exit_container(reply);
742 return bus_log_parse_error(r);
754 /* Note: triggered is a list here, although it almost certainly
755 * will always be one unit. Nevertheless, dbus API allows for multiple
756 * values, so let's follow that. */
759 /* The strv above is shared. free is set only in the first one. */
763 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
769 if (!a->machine && b->machine)
771 if (a->machine && !b->machine)
773 if (a->machine && b->machine) {
774 o = strcasecmp(a->machine, b->machine);
779 o = strcmp(a->path, b->path);
781 o = strcmp(a->type, b->type);
786 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
787 struct socket_info *s;
788 unsigned pathlen = strlen("LISTEN"),
789 typelen = strlen("TYPE") * arg_show_types,
790 socklen = strlen("UNIT"),
791 servlen = strlen("ACTIVATES");
792 const char *on, *off;
794 for (s = socket_infos; s < socket_infos + cs; s++) {
798 socklen = MAX(socklen, strlen(s->id));
800 typelen = MAX(typelen, strlen(s->type));
801 pathlen = MAX(pathlen, strlen(s->path) + (s->machine ? strlen(s->machine)+1 : 0));
803 STRV_FOREACH(a, s->triggered)
804 tmp += strlen(*a) + 2*(a != s->triggered);
805 servlen = MAX(servlen, tmp);
810 printf("%-*s %-*.*s%-*s %s\n",
812 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
816 for (s = socket_infos; s < socket_infos + cs; s++) {
817 _cleanup_free_ char *j = NULL;
822 j = strjoin(s->machine, ":", s->path, NULL);
830 printf("%-*s %-*s %-*s",
831 pathlen, path, typelen, s->type, socklen, s->id);
834 pathlen, path, socklen, s->id);
835 STRV_FOREACH(a, s->triggered)
837 a == s->triggered ? "" : ",", *a);
841 on = ansi_highlight();
842 off = ansi_highlight_off();
846 on = ansi_highlight_red();
847 off = ansi_highlight_off();
850 if (!arg_no_legend) {
851 printf("%s%u sockets listed.%s\n", on, cs, off);
853 printf("Pass --all to see loaded but inactive sockets, too.\n");
859 static int list_sockets(sd_bus *bus, char **args) {
860 _cleanup_(message_set_freep) Set *replies = NULL;
861 _cleanup_strv_free_ char **machines = NULL;
862 _cleanup_free_ UnitInfo *unit_infos = NULL;
863 _cleanup_free_ struct socket_info *socket_infos = NULL;
865 struct socket_info *s;
870 pager_open_if_enabled();
872 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
876 for (u = unit_infos; u < unit_infos + n; u++) {
877 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
880 if (!endswith(u->id, ".socket"))
883 r = get_triggered_units(bus, u->unit_path, &triggered);
887 c = get_listening(bus, u->unit_path, &listening);
893 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
898 for (i = 0; i < c; i++)
899 socket_infos[cs + i] = (struct socket_info) {
900 .machine = u->machine,
902 .type = listening[i*2],
903 .path = listening[i*2 + 1],
904 .triggered = triggered,
905 .own_triggered = i==0,
908 /* from this point on we will cleanup those socket_infos */
911 listening = triggered = NULL; /* avoid cleanup */
914 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
915 (__compar_fn_t) socket_info_compare);
917 output_sockets_list(socket_infos, cs);
920 assert(cs == 0 || socket_infos);
921 for (s = socket_infos; s < socket_infos + cs; s++) {
924 if (s->own_triggered)
925 strv_free(s->triggered);
931 static int get_next_elapse(
934 dual_timestamp *next) {
936 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
944 r = sd_bus_get_property_trivial(
946 "org.freedesktop.systemd1",
948 "org.freedesktop.systemd1.Timer",
949 "NextElapseUSecMonotonic",
954 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
958 r = sd_bus_get_property_trivial(
960 "org.freedesktop.systemd1",
962 "org.freedesktop.systemd1.Timer",
963 "NextElapseUSecRealtime",
968 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
976 static int get_last_trigger(
981 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
988 r = sd_bus_get_property_trivial(
990 "org.freedesktop.systemd1",
992 "org.freedesktop.systemd1.Timer",
998 log_error("Failed to get last trigger time: %s", bus_error_message(&error, r));
1006 const char* machine;
1009 usec_t last_trigger;
1013 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
1019 if (!a->machine && b->machine)
1021 if (a->machine && !b->machine)
1023 if (a->machine && b->machine) {
1024 o = strcasecmp(a->machine, b->machine);
1029 if (a->next_elapse < b->next_elapse)
1031 if (a->next_elapse > b->next_elapse)
1034 return strcmp(a->id, b->id);
1037 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
1038 struct timer_info *t;
1040 nextlen = strlen("NEXT"),
1041 leftlen = strlen("LEFT"),
1042 lastlen = strlen("LAST"),
1043 passedlen = strlen("PASSED"),
1044 unitlen = strlen("UNIT"),
1045 activatelen = strlen("ACTIVATES");
1047 const char *on, *off;
1049 assert(timer_infos || n == 0);
1051 for (t = timer_infos; t < timer_infos + n; t++) {
1055 if (t->next_elapse > 0) {
1056 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1058 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
1059 nextlen = MAX(nextlen, strlen(tstamp) + 1);
1061 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
1062 leftlen = MAX(leftlen, strlen(trel));
1065 if (t->last_trigger > 0) {
1066 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1068 format_timestamp(tstamp, sizeof(tstamp), t->last_trigger);
1069 lastlen = MAX(lastlen, strlen(tstamp) + 1);
1071 format_timestamp_relative(trel, sizeof(trel), t->last_trigger);
1072 passedlen = MAX(passedlen, strlen(trel));
1075 unitlen = MAX(unitlen, strlen(t->id) + (t->machine ? strlen(t->machine)+1 : 0));
1077 STRV_FOREACH(a, t->triggered)
1078 ul += strlen(*a) + 2*(a != t->triggered);
1080 activatelen = MAX(activatelen, ul);
1085 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1089 passedlen, "PASSED",
1093 for (t = timer_infos; t < timer_infos + n; t++) {
1094 _cleanup_free_ char *j = NULL;
1096 char tstamp1[FORMAT_TIMESTAMP_MAX] = "n/a", trel1[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1097 char tstamp2[FORMAT_TIMESTAMP_MAX] = "n/a", trel2[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1100 format_timestamp(tstamp1, sizeof(tstamp1), t->next_elapse);
1101 format_timestamp_relative(trel1, sizeof(trel1), t->next_elapse);
1103 format_timestamp(tstamp2, sizeof(tstamp2), t->last_trigger);
1104 format_timestamp_relative(trel2, sizeof(trel2), t->last_trigger);
1107 j = strjoin(t->machine, ":", t->id, NULL);
1114 printf("%-*s %-*s %-*s %-*s %-*s",
1115 nextlen, tstamp1, leftlen, trel1, lastlen, tstamp2, passedlen, trel2, unitlen, unit);
1117 STRV_FOREACH(a, t->triggered)
1119 a == t->triggered ? "" : ",", *a);
1123 on = ansi_highlight();
1124 off = ansi_highlight_off();
1128 on = ansi_highlight_red();
1129 off = ansi_highlight_off();
1132 if (!arg_no_legend) {
1133 printf("%s%u timers listed.%s\n", on, n, off);
1135 printf("Pass --all to see loaded but inactive timers, too.\n");
1141 static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
1147 if (next->monotonic != USEC_INFINITY && next->monotonic > 0) {
1150 if (next->monotonic > nw->monotonic)
1151 converted = nw->realtime + (next->monotonic - nw->monotonic);
1153 converted = nw->realtime - (nw->monotonic - next->monotonic);
1155 if (next->realtime != USEC_INFINITY && next->realtime > 0)
1156 next_elapse = MIN(converted, next->realtime);
1158 next_elapse = converted;
1161 next_elapse = next->realtime;
1166 static int list_timers(sd_bus *bus, char **args) {
1167 _cleanup_(message_set_freep) Set *replies = NULL;
1168 _cleanup_strv_free_ char **machines = NULL;
1169 _cleanup_free_ struct timer_info *timer_infos = NULL;
1170 _cleanup_free_ UnitInfo *unit_infos = NULL;
1171 struct timer_info *t;
1178 pager_open_if_enabled();
1180 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
1184 dual_timestamp_get(&nw);
1186 for (u = unit_infos; u < unit_infos + n; u++) {
1187 _cleanup_strv_free_ char **triggered = NULL;
1188 dual_timestamp next = {};
1191 if (!endswith(u->id, ".timer"))
1194 r = get_triggered_units(bus, u->unit_path, &triggered);
1198 r = get_next_elapse(bus, u->unit_path, &next);
1202 get_last_trigger(bus, u->unit_path, &last);
1204 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
1209 m = calc_next_elapse(&nw, &next);
1211 timer_infos[c++] = (struct timer_info) {
1212 .machine = u->machine,
1215 .last_trigger = last,
1216 .triggered = triggered,
1219 triggered = NULL; /* avoid cleanup */
1222 qsort_safe(timer_infos, c, sizeof(struct timer_info),
1223 (__compar_fn_t) timer_info_compare);
1225 output_timers_list(timer_infos, c);
1228 for (t = timer_infos; t < timer_infos + c; t++)
1229 strv_free(t->triggered);
1234 static int compare_unit_file_list(const void *a, const void *b) {
1235 const char *d1, *d2;
1236 const UnitFileList *u = a, *v = b;
1238 d1 = strrchr(u->path, '.');
1239 d2 = strrchr(v->path, '.');
1244 r = strcasecmp(d1, d2);
1249 return strcasecmp(basename(u->path), basename(v->path));
1252 static bool output_show_unit_file(const UnitFileList *u, char **patterns) {
1253 if (!strv_isempty(patterns)) {
1256 STRV_FOREACH(pattern, patterns)
1257 if (fnmatch(*pattern, basename(u->path), FNM_NOESCAPE) == 0)
1263 if (!strv_isempty(arg_types)) {
1266 dot = strrchr(u->path, '.');
1270 if (!strv_find(arg_types, dot+1))
1274 if (!strv_isempty(arg_states)) {
1275 if (!strv_find(arg_states, unit_file_state_to_string(u->state)))
1282 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
1283 unsigned max_id_len, id_cols, state_cols;
1284 const UnitFileList *u;
1286 max_id_len = strlen("UNIT FILE");
1287 state_cols = strlen("STATE");
1289 for (u = units; u < units + c; u++) {
1290 max_id_len = MAX(max_id_len, strlen(basename(u->path)));
1291 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1295 unsigned basic_cols;
1297 id_cols = MIN(max_id_len, 25u);
1298 basic_cols = 1 + id_cols + state_cols;
1299 if (basic_cols < (unsigned) columns())
1300 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1302 id_cols = max_id_len;
1305 printf("%-*s %-*s\n",
1306 id_cols, "UNIT FILE",
1307 state_cols, "STATE");
1309 for (u = units; u < units + c; u++) {
1310 _cleanup_free_ char *e = NULL;
1311 const char *on, *off;
1314 if (u->state == UNIT_FILE_MASKED ||
1315 u->state == UNIT_FILE_MASKED_RUNTIME ||
1316 u->state == UNIT_FILE_DISABLED ||
1317 u->state == UNIT_FILE_INVALID) {
1318 on = ansi_highlight_red();
1319 off = ansi_highlight_off();
1320 } else if (u->state == UNIT_FILE_ENABLED) {
1321 on = ansi_highlight_green();
1322 off = ansi_highlight_off();
1326 id = basename(u->path);
1328 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1330 printf("%-*s %s%-*s%s\n",
1331 id_cols, e ? e : id,
1332 on, state_cols, unit_file_state_to_string(u->state), off);
1336 printf("\n%u unit files listed.\n", c);
1339 static int list_unit_files(sd_bus *bus, char **args) {
1340 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1341 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1342 _cleanup_free_ UnitFileList *units = NULL;
1350 pager_open_if_enabled();
1358 h = hashmap_new(&string_hash_ops);
1362 r = unit_file_get_list(arg_scope, arg_root, h);
1364 unit_file_list_free(h);
1365 log_error_errno(r, "Failed to get unit file list: %m");
1369 n_units = hashmap_size(h);
1371 units = new(UnitFileList, n_units);
1372 if (!units && n_units > 0) {
1373 unit_file_list_free(h);
1377 HASHMAP_FOREACH(u, h, i) {
1378 if (!output_show_unit_file(u, strv_skip_first(args)))
1385 assert(c <= n_units);
1388 r = sd_bus_call_method(
1390 "org.freedesktop.systemd1",
1391 "/org/freedesktop/systemd1",
1392 "org.freedesktop.systemd1.Manager",
1398 log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1402 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1404 return bus_log_parse_error(r);
1406 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1408 if (!GREEDY_REALLOC(units, size, c + 1))
1411 units[c] = (struct UnitFileList) {
1413 unit_file_state_from_string(state)
1416 if (output_show_unit_file(&units[c], strv_skip_first(args)))
1421 return bus_log_parse_error(r);
1423 r = sd_bus_message_exit_container(reply);
1425 return bus_log_parse_error(r);
1428 qsort_safe(units, c, sizeof(UnitFileList), compare_unit_file_list);
1429 output_unit_file_list(units, c);
1432 for (unit = units; unit < units + c; unit++)
1439 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1440 _cleanup_free_ char *n = NULL;
1441 size_t max_len = MAX(columns(),20u);
1447 for (i = level - 1; i >= 0; i--) {
1449 if (len > max_len - 3 && !arg_full) {
1450 printf("%s...\n",max_len % 2 ? "" : " ");
1453 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERTICAL : DRAW_TREE_SPACE));
1457 if (len > max_len - 3 && !arg_full) {
1458 printf("%s...\n",max_len % 2 ? "" : " ");
1462 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
1466 printf("%s\n", name);
1470 n = ellipsize(name, max_len-len, 100);
1478 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1480 static const char *dependencies[_DEPENDENCY_MAX] = {
1481 [DEPENDENCY_FORWARD] = "Requires\0"
1482 "RequiresOverridable\0"
1484 "RequisiteOverridable\0"
1487 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1488 "RequiredByOverridable\0"
1492 [DEPENDENCY_AFTER] = "After\0",
1493 [DEPENDENCY_BEFORE] = "Before\0",
1496 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1497 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1498 _cleanup_strv_free_ char **ret = NULL;
1499 _cleanup_free_ char *path = NULL;
1505 assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
1507 path = unit_dbus_path_from_name(name);
1511 r = sd_bus_call_method(
1513 "org.freedesktop.systemd1",
1515 "org.freedesktop.DBus.Properties",
1519 "s", "org.freedesktop.systemd1.Unit");
1521 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1525 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1527 return bus_log_parse_error(r);
1529 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1532 r = sd_bus_message_read(reply, "s", &prop);
1534 return bus_log_parse_error(r);
1536 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1537 r = sd_bus_message_skip(reply, "v");
1539 return bus_log_parse_error(r);
1542 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1544 return bus_log_parse_error(r);
1546 r = bus_message_read_strv_extend(reply, &ret);
1548 return bus_log_parse_error(r);
1550 r = sd_bus_message_exit_container(reply);
1552 return bus_log_parse_error(r);
1555 r = sd_bus_message_exit_container(reply);
1557 return bus_log_parse_error(r);
1561 return bus_log_parse_error(r);
1563 r = sd_bus_message_exit_container(reply);
1565 return bus_log_parse_error(r);
1573 static int list_dependencies_compare(const void *_a, const void *_b) {
1574 const char **a = (const char**) _a, **b = (const char**) _b;
1576 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1578 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1581 return strcasecmp(*a, *b);
1584 static int list_dependencies_one(
1589 unsigned int branches) {
1591 _cleanup_strv_free_ char **deps = NULL;
1599 r = strv_extend(units, name);
1603 r = list_dependencies_get_dependencies(bus, name, &deps);
1607 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1609 STRV_FOREACH(c, deps) {
1612 if (strv_contains(*units, *c)) {
1614 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1621 state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true);
1623 printf("%s%s%s ", ansi_highlight_green(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1625 printf("%s%s%s ", ansi_highlight_red(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1627 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1631 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1632 r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1639 strv_remove(*units, name);
1644 static int list_dependencies(sd_bus *bus, char **args) {
1645 _cleanup_strv_free_ char **units = NULL;
1646 _cleanup_free_ char *unit = NULL;
1652 unit = unit_name_mangle(args[1], MANGLE_NOGLOB);
1657 u = SPECIAL_DEFAULT_TARGET;
1659 pager_open_if_enabled();
1663 return list_dependencies_one(bus, u, 0, &units, 0);
1666 struct machine_info {
1670 char *control_group;
1671 uint32_t n_failed_units;
1676 static const struct bus_properties_map machine_info_property_map[] = {
1677 { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
1678 { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
1679 { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
1680 { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
1681 { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
1685 static void free_machines_list(struct machine_info *machine_infos, int n) {
1691 for (i = 0; i < n; i++) {
1692 free(machine_infos[i].name);
1693 free(machine_infos[i].state);
1694 free(machine_infos[i].control_group);
1697 free(machine_infos);
1700 static int compare_machine_info(const void *a, const void *b) {
1701 const struct machine_info *u = a, *v = b;
1703 if (u->is_host != v->is_host)
1704 return u->is_host > v->is_host ? -1 : 1;
1706 return strcasecmp(u->name, v->name);
1709 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1710 _cleanup_bus_close_unref_ sd_bus *container = NULL;
1716 r = sd_bus_open_system_machine(&container, mi->name);
1723 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi);
1730 static bool output_show_machine(const char *name, char **patterns) {
1735 if (strv_isempty(patterns))
1738 STRV_FOREACH(i, patterns)
1739 if (fnmatch(*i, name, FNM_NOESCAPE) == 0)
1745 static int get_machine_list(
1747 struct machine_info **_machine_infos,
1750 struct machine_info *machine_infos = NULL;
1751 _cleanup_strv_free_ char **m = NULL;
1752 _cleanup_free_ char *hn = NULL;
1757 hn = gethostname_malloc();
1761 if (output_show_machine(hn, patterns)) {
1762 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1765 machine_infos[c].is_host = true;
1766 machine_infos[c].name = hn;
1769 get_machine_properties(bus, &machine_infos[c]);
1773 sd_get_machine_names(&m);
1774 STRV_FOREACH(i, m) {
1775 _cleanup_free_ char *class = NULL;
1777 if (!output_show_machine(*i, patterns))
1780 sd_machine_get_class(*i, &class);
1781 if (!streq_ptr(class, "container"))
1784 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1785 free_machines_list(machine_infos, c);
1789 machine_infos[c].is_host = false;
1790 machine_infos[c].name = strdup(*i);
1791 if (!machine_infos[c].name) {
1792 free_machines_list(machine_infos, c);
1796 get_machine_properties(NULL, &machine_infos[c]);
1800 *_machine_infos = machine_infos;
1804 static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1805 struct machine_info *m;
1808 namelen = sizeof("NAME") - 1,
1809 statelen = sizeof("STATE") - 1,
1810 failedlen = sizeof("FAILED") - 1,
1811 jobslen = sizeof("JOBS") - 1;
1813 assert(machine_infos || n == 0);
1815 for (m = machine_infos; m < machine_infos + n; m++) {
1816 namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
1817 statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
1818 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
1819 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
1821 if (!arg_no_legend && !streq_ptr(m->state, "running"))
1825 if (!arg_no_legend) {
1829 printf("%-*s %-*s %-*s %-*s\n",
1832 failedlen, "FAILED",
1836 for (m = machine_infos; m < machine_infos + n; m++) {
1837 const char *on_state = "", *off_state = "";
1838 const char *on_failed = "", *off_failed = "";
1839 bool circle = false;
1841 if (streq_ptr(m->state, "degraded")) {
1842 on_state = ansi_highlight_red();
1843 off_state = ansi_highlight_off();
1845 } else if (!streq_ptr(m->state, "running")) {
1846 on_state = ansi_highlight_yellow();
1847 off_state = ansi_highlight_off();
1851 if (m->n_failed_units > 0) {
1852 on_failed = ansi_highlight_red();
1853 off_failed = ansi_highlight_off();
1855 on_failed = off_failed = "";
1858 printf("%s%s%s ", on_state, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_state);
1861 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1862 (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
1863 on_state, statelen, strna(m->state), off_state,
1864 on_failed, failedlen, m->n_failed_units, off_failed,
1865 jobslen, m->n_jobs);
1867 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1868 namelen, strna(m->name),
1869 on_state, statelen, strna(m->state), off_state,
1870 on_failed, failedlen, m->n_failed_units, off_failed,
1871 jobslen, m->n_jobs);
1875 printf("\n%u machines listed.\n", n);
1878 static int list_machines(sd_bus *bus, char **args) {
1879 struct machine_info *machine_infos = NULL;
1884 if (geteuid() != 0) {
1885 log_error("Must be root.");
1889 pager_open_if_enabled();
1891 r = get_machine_list(bus, &machine_infos, strv_skip_first(args));
1895 qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
1896 output_machines_list(machine_infos, r);
1897 free_machines_list(machine_infos, r);
1902 static int get_default(sd_bus *bus, char **args) {
1903 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1904 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1905 _cleanup_free_ char *_path = NULL;
1909 if (!bus || avoid_bus()) {
1910 r = unit_file_get_default(arg_scope, arg_root, &_path);
1912 return log_error_errno(r, "Failed to get default target: %m");
1916 r = sd_bus_call_method(
1918 "org.freedesktop.systemd1",
1919 "/org/freedesktop/systemd1",
1920 "org.freedesktop.systemd1.Manager",
1926 log_error("Failed to get default target: %s", bus_error_message(&error, -r));
1930 r = sd_bus_message_read(reply, "s", &path);
1932 return bus_log_parse_error(r);
1936 printf("%s\n", path);
1941 static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) {
1944 assert(changes || n_changes == 0);
1946 for (i = 0; i < n_changes; i++) {
1947 if (changes[i].type == UNIT_FILE_SYMLINK)
1948 log_info("Created symlink from %s to %s.", changes[i].path, changes[i].source);
1950 log_info("Removed symlink %s.", changes[i].path);
1954 static int set_default(sd_bus *bus, char **args) {
1955 _cleanup_free_ char *unit = NULL;
1956 UnitFileChange *changes = NULL;
1957 unsigned n_changes = 0;
1960 unit = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
1964 if (!bus || avoid_bus()) {
1965 r = unit_file_set_default(arg_scope, arg_root, unit, true, &changes, &n_changes);
1967 return log_error_errno(r, "Failed to set default target: %m");
1970 dump_unit_file_changes(changes, n_changes);
1974 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1975 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1977 r = sd_bus_message_new_method_call(
1980 "org.freedesktop.systemd1",
1981 "/org/freedesktop/systemd1",
1982 "org.freedesktop.systemd1.Manager",
1983 "SetDefaultTarget");
1985 return bus_log_create_error(r);
1987 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
1989 return bus_log_create_error(r);
1991 r = sd_bus_message_append(m, "sb", unit, 1);
1993 return bus_log_create_error(r);
1995 r = sd_bus_call(bus, m, 0, &error, &reply);
1997 log_error("Failed to set default target: %s", bus_error_message(&error, -r));
2001 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
2005 /* Try to reload if enabled */
2007 r = daemon_reload(bus, args);
2012 unit_file_changes_free(changes, n_changes);
2019 const char *name, *type, *state;
2022 static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
2023 unsigned id_len, unit_len, type_len, state_len;
2024 const struct job_info *j;
2025 const char *on, *off;
2026 bool shorten = false;
2028 assert(n == 0 || jobs);
2031 on = ansi_highlight_green();
2032 off = ansi_highlight_off();
2034 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
2038 pager_open_if_enabled();
2040 id_len = strlen("JOB");
2041 unit_len = strlen("UNIT");
2042 type_len = strlen("TYPE");
2043 state_len = strlen("STATE");
2045 for (j = jobs; j < jobs + n; j++) {
2046 uint32_t id = j->id;
2047 assert(j->name && j->type && j->state);
2049 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
2050 unit_len = MAX(unit_len, strlen(j->name));
2051 type_len = MAX(type_len, strlen(j->type));
2052 state_len = MAX(state_len, strlen(j->state));
2055 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
2056 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
2061 printf("%*s %-*s %-*s %-*s\n",
2065 state_len, "STATE");
2067 for (j = jobs; j < jobs + n; j++) {
2068 _cleanup_free_ char *e = NULL;
2070 if (streq(j->state, "running")) {
2071 on = ansi_highlight();
2072 off = ansi_highlight_off();
2076 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
2077 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2079 on, unit_len, e ? e : j->name, off,
2081 on, state_len, j->state, off);
2084 if (!arg_no_legend) {
2085 on = ansi_highlight();
2086 off = ansi_highlight_off();
2088 printf("\n%s%u jobs listed%s.\n", on, n, off);
2092 static bool output_show_job(struct job_info *job, char **patterns) {
2097 if (strv_isempty(patterns))
2100 STRV_FOREACH(pattern, patterns)
2101 if (fnmatch(*pattern, job->name, FNM_NOESCAPE) == 0)
2106 static int list_jobs(sd_bus *bus, char **args) {
2107 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2108 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2109 const char *name, *type, *state, *job_path, *unit_path;
2110 _cleanup_free_ struct job_info *jobs = NULL;
2115 bool skipped = false;
2117 r = sd_bus_call_method(
2119 "org.freedesktop.systemd1",
2120 "/org/freedesktop/systemd1",
2121 "org.freedesktop.systemd1.Manager",
2127 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
2131 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2133 return bus_log_parse_error(r);
2135 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
2136 struct job_info job = { id, name, type, state };
2138 if (!output_show_job(&job, strv_skip_first(args))) {
2143 if (!GREEDY_REALLOC(jobs, size, c + 1))
2149 return bus_log_parse_error(r);
2151 r = sd_bus_message_exit_container(reply);
2153 return bus_log_parse_error(r);
2155 output_jobs_list(jobs, c, skipped);
2159 static int cancel_job(sd_bus *bus, char **args) {
2160 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2166 if (strv_length(args) <= 1)
2167 return daemon_reload(bus, args);
2169 STRV_FOREACH(name, args+1) {
2170 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2174 q = safe_atou32(*name, &id);
2176 return log_error_errno(q, "Failed to parse job id \"%s\": %m", *name);
2178 q = sd_bus_message_new_method_call(
2181 "org.freedesktop.systemd1",
2182 "/org/freedesktop/systemd1",
2183 "org.freedesktop.systemd1.Manager",
2186 return bus_log_create_error(q);
2188 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2190 return bus_log_create_error(1);
2192 q = sd_bus_message_append(m, "u", id);
2194 return bus_log_create_error(q);
2196 q = sd_bus_call(bus, m, 0, &error, NULL);
2198 log_error("Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, q));
2207 static int need_daemon_reload(sd_bus *bus, const char *unit) {
2208 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2212 /* We ignore all errors here, since this is used to show a
2215 /* We don't use unit_dbus_path_from_name() directly since we
2216 * don't want to load the unit if it isn't loaded. */
2218 r = sd_bus_call_method(
2220 "org.freedesktop.systemd1",
2221 "/org/freedesktop/systemd1",
2222 "org.freedesktop.systemd1.Manager",
2230 r = sd_bus_message_read(reply, "o", &path);
2234 r = sd_bus_get_property_trivial(
2236 "org.freedesktop.systemd1",
2238 "org.freedesktop.systemd1.Unit",
2248 static void warn_unit_file_changed(const char *name) {
2249 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2250 ansi_highlight_red(),
2251 ansi_highlight_off(),
2253 arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2256 static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **unit_path) {
2263 STRV_FOREACH(p, lp->unit_path) {
2264 _cleanup_free_ char *path;
2266 path = path_join(arg_root, *p, unit_name);
2270 if (access(path, F_OK) == 0) {
2280 static int unit_find_paths(sd_bus *bus,
2281 const char *unit_name,
2282 bool avoid_bus_cache,
2284 char **fragment_path,
2285 char ***dropin_paths) {
2289 * Finds where the unit is defined on disk. Returns 0 if the unit
2290 * is not found. Returns 1 if it is found, and sets
2291 * - the path to the unit in *path, if it exists on disk,
2292 * - and a strv of existing drop-ins in *dropins,
2293 * if the arg is not NULL and any dropins were found.
2297 assert(fragment_path);
2300 if (!avoid_bus_cache && !unit_name_is_template(unit_name)) {
2301 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2302 _cleanup_free_ char *unit = NULL;
2303 _cleanup_free_ char *path = NULL;
2304 _cleanup_strv_free_ char **dropins = NULL;
2306 unit = unit_dbus_path_from_name(unit_name);
2310 if (need_daemon_reload(bus, unit_name) > 0)
2311 warn_unit_file_changed(unit_name);
2313 r = sd_bus_get_property_string(
2315 "org.freedesktop.systemd1",
2317 "org.freedesktop.systemd1.Unit",
2322 return log_error_errno(r, "Failed to get FragmentPath: %s", bus_error_message(&error, r));
2324 r = sd_bus_get_property_strv(
2326 "org.freedesktop.systemd1",
2328 "org.freedesktop.systemd1.Unit",
2333 return log_error_errno(r, "Failed to get DropInPaths: %s", bus_error_message(&error, r));
2336 if (!isempty(path)) {
2337 *fragment_path = path;
2342 if (dropin_paths && !strv_isempty(dropins)) {
2343 *dropin_paths = dropins;
2348 _cleanup_set_free_ Set *names;
2350 names = set_new(NULL);
2354 r = set_put(names, unit_name);
2358 r = unit_file_find_path(lp, unit_name, fragment_path);
2363 _cleanup_free_ char *template;
2365 template = unit_name_template(unit_name);
2369 if (!streq(template, unit_name)) {
2370 r = unit_file_find_path(lp, template, fragment_path);
2377 r = unit_file_find_dropin_paths(lp->unit_path, NULL, names, dropin_paths);
2383 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2384 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2385 _cleanup_free_ char *n = NULL, *state = NULL;
2391 n = unit_name_mangle(name, MANGLE_NOGLOB);
2395 /* We don't use unit_dbus_path_from_name() directly since we
2396 * don't want to load the unit if it isn't loaded. */
2398 r = sd_bus_call_method(
2400 "org.freedesktop.systemd1",
2401 "/org/freedesktop/systemd1",
2402 "org.freedesktop.systemd1.Manager",
2413 r = sd_bus_message_read(reply, "o", &path);
2415 return bus_log_parse_error(r);
2417 r = sd_bus_get_property_string(
2419 "org.freedesktop.systemd1",
2421 "org.freedesktop.systemd1.Unit",
2434 return nulstr_contains(good_states, state);
2437 static int check_triggering_units(
2441 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2442 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2443 _cleanup_strv_free_ char **triggered_by = NULL;
2444 bool print_warning_label = true;
2448 n = unit_name_mangle(name, MANGLE_NOGLOB);
2452 path = unit_dbus_path_from_name(n);
2456 r = sd_bus_get_property_string(
2458 "org.freedesktop.systemd1",
2460 "org.freedesktop.systemd1.Unit",
2465 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2469 if (streq(state, "masked"))
2472 r = sd_bus_get_property_strv(
2474 "org.freedesktop.systemd1",
2476 "org.freedesktop.systemd1.Unit",
2481 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2485 STRV_FOREACH(i, triggered_by) {
2486 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2488 return log_error_errno(r, "Failed to check unit: %m");
2493 if (print_warning_label) {
2494 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2495 print_warning_label = false;
2498 log_warning(" %s", *i);
2504 static const struct {
2507 } unit_actions[] = {
2508 { "start", "StartUnit" },
2509 { "stop", "StopUnit" },
2510 { "condstop", "StopUnit" },
2511 { "reload", "ReloadUnit" },
2512 { "restart", "RestartUnit" },
2513 { "try-restart", "TryRestartUnit" },
2514 { "condrestart", "TryRestartUnit" },
2515 { "reload-or-restart", "ReloadOrRestartUnit" },
2516 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2517 { "condreload", "ReloadOrTryRestartUnit" },
2518 { "force-reload", "ReloadOrTryRestartUnit" }
2521 static const char *verb_to_method(const char *verb) {
2524 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2525 if (streq_ptr(unit_actions[i].verb, verb))
2526 return unit_actions[i].method;
2531 static const char *method_to_verb(const char *method) {
2534 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2535 if (streq_ptr(unit_actions[i].method, method))
2536 return unit_actions[i].verb;
2541 static int start_unit_one(
2546 sd_bus_error *error,
2547 BusWaitForJobs *w) {
2549 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2558 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2560 r = sd_bus_message_new_method_call(
2563 "org.freedesktop.systemd1",
2564 "/org/freedesktop/systemd1",
2565 "org.freedesktop.systemd1.Manager",
2568 return bus_log_create_error(r);
2570 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2572 return bus_log_create_error(r);
2574 r = sd_bus_message_append(m, "ss", name, mode);
2576 return bus_log_create_error(r);
2578 r = sd_bus_call(bus, m, 0, error, &reply);
2582 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2583 /* There's always a fallback possible for
2584 * legacy actions. */
2585 return -EADDRNOTAVAIL;
2587 verb = method_to_verb(method);
2589 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2593 r = sd_bus_message_read(reply, "o", &path);
2595 return bus_log_parse_error(r);
2597 if (need_daemon_reload(bus, name) > 0)
2598 warn_unit_file_changed(name);
2601 log_debug("Adding %s to the set", path);
2602 r = bus_wait_for_jobs_add(w, path);
2610 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2612 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2616 STRV_FOREACH(name, names) {
2620 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2622 t = unit_name_mangle(*name, MANGLE_GLOB);
2626 if (string_is_glob(t))
2627 r = strv_consume(&globs, t);
2629 r = strv_consume(&mangled, t);
2634 /* Query the manager only if any of the names are a glob, since
2635 * this is fairly expensive */
2636 if (!strv_isempty(globs)) {
2637 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2638 _cleanup_free_ UnitInfo *unit_infos = NULL;
2641 return log_error_errno(ENOTSUP, "Unit name globbing without bus is not implemented.");
2643 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2647 for (i = 0; i < r; i++)
2648 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2653 mangled = NULL; /* do not free */
2658 static const struct {
2662 } action_table[_ACTION_MAX] = {
2663 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2664 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2665 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2666 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2667 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
2668 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
2669 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
2670 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
2671 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2672 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2673 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2674 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2675 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2676 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2677 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2680 static enum action verb_to_action(const char *verb) {
2683 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2684 if (streq_ptr(action_table[i].verb, verb))
2687 return _ACTION_INVALID;
2690 static int start_unit(sd_bus *bus, char **args) {
2691 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
2692 const char *method, *mode, *one_name, *suffix = NULL;
2693 _cleanup_strv_free_ char **names = NULL;
2699 ask_password_agent_open_if_enabled();
2701 if (arg_action == ACTION_SYSTEMCTL) {
2703 method = verb_to_method(args[0]);
2704 action = verb_to_action(args[0]);
2706 if (streq(args[0], "isolate")) {
2710 mode = action_table[action].mode ?: arg_job_mode;
2712 one_name = action_table[action].target;
2714 assert(arg_action < ELEMENTSOF(action_table));
2715 assert(action_table[arg_action].target);
2717 method = "StartUnit";
2719 mode = action_table[arg_action].mode;
2720 one_name = action_table[arg_action].target;
2724 names = strv_new(one_name, NULL);
2726 r = expand_names(bus, args + 1, suffix, &names);
2728 log_error_errno(r, "Failed to expand names: %m");
2731 if (!arg_no_block) {
2732 r = bus_wait_for_jobs_new(bus, &w);
2734 return log_error_errno(r, "Could not watch jobs: %m");
2737 STRV_FOREACH(name, names) {
2738 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2741 q = start_unit_one(bus, method, *name, mode, &error, w);
2742 if (r >= 0 && q < 0)
2743 r = translate_bus_error_to_exit_status(q, &error);
2746 if (!arg_no_block) {
2749 q = bus_wait_for_jobs(w, arg_quiet);
2753 /* When stopping units, warn if they can still be triggered by
2754 * another active unit (socket, path, timer) */
2755 if (!arg_quiet && streq(method, "StopUnit"))
2756 STRV_FOREACH(name, names)
2757 check_triggering_units(bus, *name);
2763 /* Ask systemd-logind, which might grant access to unprivileged users
2764 * through PolicyKit */
2765 static int reboot_with_logind(sd_bus *bus, enum action a) {
2767 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2774 polkit_agent_open_if_enabled();
2782 case ACTION_POWEROFF:
2783 method = "PowerOff";
2786 case ACTION_SUSPEND:
2790 case ACTION_HIBERNATE:
2791 method = "Hibernate";
2794 case ACTION_HYBRID_SLEEP:
2795 method = "HybridSleep";
2802 r = sd_bus_call_method(
2804 "org.freedesktop.login1",
2805 "/org/freedesktop/login1",
2806 "org.freedesktop.login1.Manager",
2810 "b", arg_ask_password);
2812 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2820 static int check_inhibitors(sd_bus *bus, enum action a) {
2822 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2823 _cleanup_strv_free_ char **sessions = NULL;
2824 const char *what, *who, *why, *mode;
2833 if (arg_ignore_inhibitors || arg_force > 0)
2845 r = sd_bus_call_method(
2847 "org.freedesktop.login1",
2848 "/org/freedesktop/login1",
2849 "org.freedesktop.login1.Manager",
2855 /* If logind is not around, then there are no inhibitors... */
2858 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2860 return bus_log_parse_error(r);
2862 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2863 _cleanup_free_ char *comm = NULL, *user = NULL;
2864 _cleanup_strv_free_ char **sv = NULL;
2866 if (!streq(mode, "block"))
2869 sv = strv_split(what, ":");
2873 if (!strv_contains(sv,
2875 a == ACTION_POWEROFF ||
2876 a == ACTION_REBOOT ||
2877 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2880 get_process_comm(pid, &comm);
2881 user = uid_to_name(uid);
2883 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
2884 who, pid, strna(comm), strna(user), why);
2889 return bus_log_parse_error(r);
2891 r = sd_bus_message_exit_container(reply);
2893 return bus_log_parse_error(r);
2895 /* Check for current sessions */
2896 sd_get_sessions(&sessions);
2897 STRV_FOREACH(s, sessions) {
2898 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2900 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2903 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2906 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2909 sd_session_get_tty(*s, &tty);
2910 sd_session_get_seat(*s, &seat);
2911 sd_session_get_service(*s, &service);
2912 user = uid_to_name(uid);
2914 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2921 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2922 action_table[a].verb);
2930 static int start_special(sd_bus *bus, char **args) {
2936 a = verb_to_action(args[0]);
2938 r = check_inhibitors(bus, a);
2942 if (arg_force >= 2 && geteuid() != 0) {
2943 log_error("Must be root.");
2947 if (arg_force >= 2 &&
2948 (a == ACTION_HALT ||
2949 a == ACTION_POWEROFF ||
2950 a == ACTION_REBOOT))
2953 if (arg_force >= 1 &&
2954 (a == ACTION_HALT ||
2955 a == ACTION_POWEROFF ||
2956 a == ACTION_REBOOT ||
2957 a == ACTION_KEXEC ||
2959 return daemon_reload(bus, args);
2961 /* first try logind, to allow authentication with polkit */
2962 if (geteuid() != 0 &&
2963 (a == ACTION_POWEROFF ||
2964 a == ACTION_REBOOT ||
2965 a == ACTION_SUSPEND ||
2966 a == ACTION_HIBERNATE ||
2967 a == ACTION_HYBRID_SLEEP)) {
2968 r = reboot_with_logind(bus, a);
2969 if (r >= 0 || IN_SET(r, -ENOTSUP, -EINPROGRESS))
2973 r = start_unit(bus, args);
2974 if (r == EXIT_SUCCESS)
2980 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
2981 _cleanup_strv_free_ char **names = NULL;
2988 r = expand_names(bus, args, NULL, &names);
2990 return log_error_errno(r, "Failed to expand names: %m");
2992 STRV_FOREACH(name, names) {
2995 state = check_one_unit(bus, *name, good_states, arg_quiet);
3005 static int check_unit_active(sd_bus *bus, char **args) {
3006 /* According to LSB: 3, "program is not running" */
3007 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
3010 static int check_unit_failed(sd_bus *bus, char **args) {
3011 return check_unit_generic(bus, 1, "failed\0", args + 1);
3014 static int kill_unit(sd_bus *bus, char **args) {
3015 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3016 _cleanup_strv_free_ char **names = NULL;
3024 arg_kill_who = "all";
3026 r = expand_names(bus, args + 1, NULL, &names);
3028 log_error_errno(r, "Failed to expand names: %m");
3030 STRV_FOREACH(name, names) {
3031 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3033 q = sd_bus_message_new_method_call(
3036 "org.freedesktop.systemd1",
3037 "/org/freedesktop/systemd1",
3038 "org.freedesktop.systemd1.Manager",
3041 return bus_log_create_error(q);
3043 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
3045 return bus_log_create_error(q);
3047 q = sd_bus_message_append(m, "ssi", *names, arg_kill_who, arg_signal);
3049 return bus_log_create_error(q);
3051 q = sd_bus_call(bus, m, 0, &error, NULL);
3053 log_error("Failed to kill unit %s: %s", *names, bus_error_message(&error, q));
3062 typedef struct ExecStatusInfo {
3070 usec_t start_timestamp;
3071 usec_t exit_timestamp;
3076 LIST_FIELDS(struct ExecStatusInfo, exec);
3079 static void exec_status_info_free(ExecStatusInfo *i) {
3088 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3089 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3092 int32_t code, status;
3098 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3100 return bus_log_parse_error(r);
3104 r = sd_bus_message_read(m, "s", &path);
3106 return bus_log_parse_error(r);
3108 i->path = strdup(path);
3112 r = sd_bus_message_read_strv(m, &i->argv);
3114 return bus_log_parse_error(r);
3116 r = sd_bus_message_read(m,
3119 &start_timestamp, &start_timestamp_monotonic,
3120 &exit_timestamp, &exit_timestamp_monotonic,
3124 return bus_log_parse_error(r);
3127 i->start_timestamp = (usec_t) start_timestamp;
3128 i->exit_timestamp = (usec_t) exit_timestamp;
3129 i->pid = (pid_t) pid;
3133 r = sd_bus_message_exit_container(m);
3135 return bus_log_parse_error(r);
3140 typedef struct UnitStatusInfo {
3142 const char *load_state;
3143 const char *active_state;
3144 const char *sub_state;
3145 const char *unit_file_state;
3146 const char *unit_file_preset;
3148 const char *description;
3149 const char *following;
3151 char **documentation;
3153 const char *fragment_path;
3154 const char *source_path;
3155 const char *control_group;
3157 char **dropin_paths;
3159 const char *load_error;
3162 usec_t inactive_exit_timestamp;
3163 usec_t inactive_exit_timestamp_monotonic;
3164 usec_t active_enter_timestamp;
3165 usec_t active_exit_timestamp;
3166 usec_t inactive_enter_timestamp;
3168 bool need_daemon_reload;
3173 const char *status_text;
3174 const char *pid_file;
3178 usec_t start_timestamp;
3179 usec_t exit_timestamp;
3181 int exit_code, exit_status;
3183 usec_t condition_timestamp;
3184 bool condition_result;
3185 bool failed_condition_trigger;
3186 bool failed_condition_negate;
3187 const char *failed_condition;
3188 const char *failed_condition_parameter;
3190 usec_t assert_timestamp;
3192 bool failed_assert_trigger;
3193 bool failed_assert_negate;
3194 const char *failed_assert;
3195 const char *failed_assert_parameter;
3198 unsigned n_accepted;
3199 unsigned n_connections;
3202 /* Pairs of type, path */
3206 const char *sysfs_path;
3208 /* Mount, Automount */
3214 LIST_HEAD(ExecStatusInfo, exec);
3217 static void print_status_info(
3222 const char *active_on, *active_off, *on, *off, *ss;
3224 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3225 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3228 arg_all * OUTPUT_SHOW_ALL |
3229 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
3230 on_tty() * OUTPUT_COLOR |
3231 !arg_quiet * OUTPUT_WARN_CUTOFF |
3232 arg_full * OUTPUT_FULL_WIDTH;
3237 /* This shows pretty information about a unit. See
3238 * print_property() for a low-level property printer */
3240 if (streq_ptr(i->active_state, "failed")) {
3241 active_on = ansi_highlight_red();
3242 active_off = ansi_highlight_off();
3243 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3244 active_on = ansi_highlight_green();
3245 active_off = ansi_highlight_off();
3247 active_on = active_off = "";
3249 printf("%s%s%s %s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3251 if (i->description && !streq_ptr(i->id, i->description))
3252 printf(" - %s", i->description);
3257 printf(" Follow: unit currently follows state of %s\n", i->following);
3259 if (streq_ptr(i->load_state, "error")) {
3260 on = ansi_highlight_red();
3261 off = ansi_highlight_off();
3265 path = i->source_path ? i->source_path : i->fragment_path;
3268 printf(" Loaded: %s%s%s (Reason: %s)\n",
3269 on, strna(i->load_state), off, i->load_error);
3270 else if (path && !isempty(i->unit_file_state) && !isempty(i->unit_file_preset))
3271 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3272 on, strna(i->load_state), off, path, i->unit_file_state, i->unit_file_preset);
3273 else if (path && !isempty(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("Condition: start %scondition failed%s at %s%s%s\n",
3343 ansi_highlight_yellow(), ansi_highlight_off(),
3344 s2, s1 ? "; " : "", s1 ? s1 : "");
3345 if (i->failed_condition_trigger)
3346 printf(" none of the trigger conditions were met\n");
3347 else if (i->failed_condition)
3348 printf(" %s=%s%s was not met\n",
3349 i->failed_condition,
3350 i->failed_condition_negate ? "!" : "",
3351 i->failed_condition_parameter);
3354 if (!i->assert_result && i->assert_timestamp > 0) {
3355 s1 = format_timestamp_relative(since1, sizeof(since1), i->assert_timestamp);
3356 s2 = format_timestamp(since2, sizeof(since2), i->assert_timestamp);
3358 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3359 ansi_highlight_red(), ansi_highlight_off(),
3360 s2, s1 ? "; " : "", s1 ? s1 : "");
3361 if (i->failed_assert_trigger)
3362 printf(" none of the trigger assertions were met\n");
3363 else if (i->failed_assert)
3364 printf(" %s=%s%s was not met\n",
3366 i->failed_assert_negate ? "!" : "",
3367 i->failed_assert_parameter);
3371 printf(" Device: %s\n", i->sysfs_path);
3373 printf(" Where: %s\n", i->where);
3375 printf(" What: %s\n", i->what);
3377 STRV_FOREACH(t, i->documentation)
3378 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3380 STRV_FOREACH_PAIR(t, t2, i->listen)
3381 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3384 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3386 LIST_FOREACH(exec, p, i->exec) {
3387 _cleanup_free_ char *argv = NULL;
3390 /* Only show exited processes here */
3394 argv = strv_join(p->argv, " ");
3395 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
3397 good = is_clean_exit_lsb(p->code, p->status, NULL);
3399 on = ansi_highlight_red();
3400 off = ansi_highlight_off();
3404 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3406 if (p->code == CLD_EXITED) {
3409 printf("status=%i", p->status);
3411 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3416 printf("signal=%s", signal_to_string(p->status));
3418 printf(")%s\n", off);
3420 if (i->main_pid == p->pid &&
3421 i->start_timestamp == p->start_timestamp &&
3422 i->exit_timestamp == p->start_timestamp)
3423 /* Let's not show this twice */
3426 if (p->pid == i->control_pid)
3430 if (i->main_pid > 0 || i->control_pid > 0) {
3431 if (i->main_pid > 0) {
3432 printf(" Main PID: "PID_FMT, i->main_pid);
3435 _cleanup_free_ char *comm = NULL;
3436 get_process_comm(i->main_pid, &comm);
3438 printf(" (%s)", comm);
3439 } else if (i->exit_code > 0) {
3440 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3442 if (i->exit_code == CLD_EXITED) {
3445 printf("status=%i", i->exit_status);
3447 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3452 printf("signal=%s", signal_to_string(i->exit_status));
3456 if (i->control_pid > 0)
3460 if (i->control_pid > 0) {
3461 _cleanup_free_ char *c = NULL;
3463 printf(" %8s: "PID_FMT, i->main_pid ? "" : " Control", i->control_pid);
3465 get_process_comm(i->control_pid, &c);
3474 printf(" Status: \"%s\"\n", i->status_text);
3475 if (i->status_errno > 0)
3476 printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
3478 if (i->control_group &&
3479 (i->main_pid > 0 || i->control_pid > 0 ||
3480 ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_MACHINE) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3483 printf(" CGroup: %s\n", i->control_group);
3485 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_MACHINE) {
3488 static const char prefix[] = " ";
3491 if (c > sizeof(prefix) - 1)
3492 c -= sizeof(prefix) - 1;
3496 if (i->main_pid > 0)
3497 extra[k++] = i->main_pid;
3499 if (i->control_pid > 0)
3500 extra[k++] = i->control_pid;
3502 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, flags);
3506 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3507 show_journal_by_unit(stdout,
3511 i->inactive_exit_timestamp_monotonic,
3514 flags | OUTPUT_BEGIN_NEWLINE,
3515 arg_scope == UNIT_FILE_SYSTEM,
3519 if (i->need_daemon_reload)
3520 warn_unit_file_changed(i->id);
3523 static void show_unit_help(UnitStatusInfo *i) {
3528 if (!i->documentation) {
3529 log_info("Documentation for %s not known.", i->id);
3533 STRV_FOREACH(p, i->documentation)
3534 if (startswith(*p, "man:"))
3535 show_man_page(*p + 4, false);
3537 log_info("Can't show: %s", *p);
3540 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3547 switch (contents[0]) {
3549 case SD_BUS_TYPE_STRING: {
3552 r = sd_bus_message_read(m, "s", &s);
3554 return bus_log_parse_error(r);
3557 if (streq(name, "Id"))
3559 else if (streq(name, "LoadState"))
3561 else if (streq(name, "ActiveState"))
3562 i->active_state = s;
3563 else if (streq(name, "SubState"))
3565 else if (streq(name, "Description"))
3567 else if (streq(name, "FragmentPath"))
3568 i->fragment_path = s;
3569 else if (streq(name, "SourcePath"))
3572 else if (streq(name, "DefaultControlGroup")) {
3574 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3576 i->control_group = e;
3579 else if (streq(name, "ControlGroup"))
3580 i->control_group = s;
3581 else if (streq(name, "StatusText"))
3583 else if (streq(name, "PIDFile"))
3585 else if (streq(name, "SysFSPath"))
3587 else if (streq(name, "Where"))
3589 else if (streq(name, "What"))
3591 else if (streq(name, "Following"))
3593 else if (streq(name, "UnitFileState"))
3594 i->unit_file_state = s;
3595 else if (streq(name, "UnitFilePreset"))
3596 i->unit_file_preset = s;
3597 else if (streq(name, "Result"))
3604 case SD_BUS_TYPE_BOOLEAN: {
3607 r = sd_bus_message_read(m, "b", &b);
3609 return bus_log_parse_error(r);
3611 if (streq(name, "Accept"))
3613 else if (streq(name, "NeedDaemonReload"))
3614 i->need_daemon_reload = b;
3615 else if (streq(name, "ConditionResult"))
3616 i->condition_result = b;
3617 else if (streq(name, "AssertResult"))
3618 i->assert_result = b;
3623 case SD_BUS_TYPE_UINT32: {
3626 r = sd_bus_message_read(m, "u", &u);
3628 return bus_log_parse_error(r);
3630 if (streq(name, "MainPID")) {
3632 i->main_pid = (pid_t) u;
3635 } else if (streq(name, "ControlPID"))
3636 i->control_pid = (pid_t) u;
3637 else if (streq(name, "ExecMainPID")) {
3639 i->main_pid = (pid_t) u;
3640 } else if (streq(name, "NAccepted"))
3642 else if (streq(name, "NConnections"))
3643 i->n_connections = u;
3648 case SD_BUS_TYPE_INT32: {
3651 r = sd_bus_message_read(m, "i", &j);
3653 return bus_log_parse_error(r);
3655 if (streq(name, "ExecMainCode"))
3656 i->exit_code = (int) j;
3657 else if (streq(name, "ExecMainStatus"))
3658 i->exit_status = (int) j;
3659 else if (streq(name, "StatusErrno"))
3660 i->status_errno = (int) j;
3665 case SD_BUS_TYPE_UINT64: {
3668 r = sd_bus_message_read(m, "t", &u);
3670 return bus_log_parse_error(r);
3672 if (streq(name, "ExecMainStartTimestamp"))
3673 i->start_timestamp = (usec_t) u;
3674 else if (streq(name, "ExecMainExitTimestamp"))
3675 i->exit_timestamp = (usec_t) u;
3676 else if (streq(name, "ActiveEnterTimestamp"))
3677 i->active_enter_timestamp = (usec_t) u;
3678 else if (streq(name, "InactiveEnterTimestamp"))
3679 i->inactive_enter_timestamp = (usec_t) u;
3680 else if (streq(name, "InactiveExitTimestamp"))
3681 i->inactive_exit_timestamp = (usec_t) u;
3682 else if (streq(name, "InactiveExitTimestampMonotonic"))
3683 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3684 else if (streq(name, "ActiveExitTimestamp"))
3685 i->active_exit_timestamp = (usec_t) u;
3686 else if (streq(name, "ConditionTimestamp"))
3687 i->condition_timestamp = (usec_t) u;
3688 else if (streq(name, "AssertTimestamp"))
3689 i->assert_timestamp = (usec_t) u;
3694 case SD_BUS_TYPE_ARRAY:
3696 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3697 _cleanup_free_ ExecStatusInfo *info = NULL;
3699 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3701 return bus_log_parse_error(r);
3703 info = new0(ExecStatusInfo, 1);
3707 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3709 info->name = strdup(name);
3713 LIST_PREPEND(exec, i->exec, info);
3715 info = new0(ExecStatusInfo, 1);
3721 return bus_log_parse_error(r);
3723 r = sd_bus_message_exit_container(m);
3725 return bus_log_parse_error(r);
3729 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3730 const char *type, *path;
3732 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3734 return bus_log_parse_error(r);
3736 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3738 r = strv_extend(&i->listen, type);
3742 r = strv_extend(&i->listen, path);
3747 return bus_log_parse_error(r);
3749 r = sd_bus_message_exit_container(m);
3751 return bus_log_parse_error(r);
3755 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3757 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3759 return bus_log_parse_error(r);
3761 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3763 r = sd_bus_message_read_strv(m, &i->documentation);
3765 return bus_log_parse_error(r);
3767 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3768 const char *cond, *param;
3769 int trigger, negate;
3772 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3774 return bus_log_parse_error(r);
3776 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3777 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3778 if (state < 0 && (!trigger || !i->failed_condition)) {
3779 i->failed_condition = cond;
3780 i->failed_condition_trigger = trigger;
3781 i->failed_condition_negate = negate;
3782 i->failed_condition_parameter = param;
3786 return bus_log_parse_error(r);
3788 r = sd_bus_message_exit_container(m);
3790 return bus_log_parse_error(r);
3792 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Asserts")) {
3793 const char *cond, *param;
3794 int trigger, negate;
3797 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3799 return bus_log_parse_error(r);
3801 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3802 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3803 if (state < 0 && (!trigger || !i->failed_assert)) {
3804 i->failed_assert = cond;
3805 i->failed_assert_trigger = trigger;
3806 i->failed_assert_negate = negate;
3807 i->failed_assert_parameter = param;
3811 return bus_log_parse_error(r);
3813 r = sd_bus_message_exit_container(m);
3815 return bus_log_parse_error(r);
3822 case SD_BUS_TYPE_STRUCT_BEGIN:
3824 if (streq(name, "LoadError")) {
3825 const char *n, *message;
3827 r = sd_bus_message_read(m, "(ss)", &n, &message);
3829 return bus_log_parse_error(r);
3831 if (!isempty(message))
3832 i->load_error = message;
3845 r = sd_bus_message_skip(m, contents);
3847 return bus_log_parse_error(r);
3852 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3858 /* This is a low-level property printer, see
3859 * print_status_info() for the nicer output */
3861 if (arg_properties && !strv_find(arg_properties, name)) {
3862 /* skip what we didn't read */
3863 r = sd_bus_message_skip(m, contents);
3867 switch (contents[0]) {
3869 case SD_BUS_TYPE_STRUCT_BEGIN:
3871 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3874 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3876 return bus_log_parse_error(r);
3879 printf("%s=%"PRIu32"\n", name, u);
3881 printf("%s=\n", name);
3885 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3888 r = sd_bus_message_read(m, "(so)", &s, NULL);
3890 return bus_log_parse_error(r);
3892 if (arg_all || !isempty(s))
3893 printf("%s=%s\n", name, s);
3897 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3898 const char *a = NULL, *b = NULL;
3900 r = sd_bus_message_read(m, "(ss)", &a, &b);
3902 return bus_log_parse_error(r);
3904 if (arg_all || !isempty(a) || !isempty(b))
3905 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3908 } else if (streq_ptr(name, "SystemCallFilter")) {
3909 _cleanup_strv_free_ char **l = NULL;
3912 r = sd_bus_message_enter_container(m, 'r', "bas");
3914 return bus_log_parse_error(r);
3916 r = sd_bus_message_read(m, "b", &whitelist);
3918 return bus_log_parse_error(r);
3920 r = sd_bus_message_read_strv(m, &l);
3922 return bus_log_parse_error(r);
3924 r = sd_bus_message_exit_container(m);
3926 return bus_log_parse_error(r);
3928 if (arg_all || whitelist || !strv_isempty(l)) {
3932 fputs(name, stdout);
3938 STRV_FOREACH(i, l) {
3946 fputc('\n', stdout);
3954 case SD_BUS_TYPE_ARRAY:
3956 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
3960 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
3962 return bus_log_parse_error(r);
3964 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
3965 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3968 return bus_log_parse_error(r);
3970 r = sd_bus_message_exit_container(m);
3972 return bus_log_parse_error(r);
3976 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
3977 const char *type, *path;
3979 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3981 return bus_log_parse_error(r);
3983 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3984 printf("%s=%s\n", type, path);
3986 return bus_log_parse_error(r);
3988 r = sd_bus_message_exit_container(m);
3990 return bus_log_parse_error(r);
3994 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3995 const char *type, *path;
3997 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3999 return bus_log_parse_error(r);
4001 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4002 printf("Listen%s=%s\n", type, path);
4004 return bus_log_parse_error(r);
4006 r = sd_bus_message_exit_container(m);
4008 return bus_log_parse_error(r);
4012 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
4014 uint64_t value, next_elapse;
4016 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
4018 return bus_log_parse_error(r);
4020 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
4021 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
4023 printf("%s={ value=%s ; next_elapse=%s }\n",
4025 format_timespan(timespan1, sizeof(timespan1), value, 0),
4026 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
4029 return bus_log_parse_error(r);
4031 r = sd_bus_message_exit_container(m);
4033 return bus_log_parse_error(r);
4037 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
4038 ExecStatusInfo info = {};
4040 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
4042 return bus_log_parse_error(r);
4044 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
4045 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
4046 _cleanup_free_ char *tt;
4048 tt = strv_join(info.argv, " ");
4050 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }\n",
4054 yes_no(info.ignore),
4055 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
4056 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
4058 sigchld_code_to_string(info.code),
4060 info.code == CLD_EXITED ? "" : "/",
4061 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
4064 strv_free(info.argv);
4068 r = sd_bus_message_exit_container(m);
4070 return bus_log_parse_error(r);
4074 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
4075 const char *path, *rwm;
4077 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4079 return bus_log_parse_error(r);
4081 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
4082 printf("%s=%s %s\n", name, strna(path), strna(rwm));
4084 return bus_log_parse_error(r);
4086 r = sd_bus_message_exit_container(m);
4088 return bus_log_parse_error(r);
4092 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
4096 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4098 return bus_log_parse_error(r);
4100 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4101 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
4103 return bus_log_parse_error(r);
4105 r = sd_bus_message_exit_container(m);
4107 return bus_log_parse_error(r);
4111 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
4115 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4117 return bus_log_parse_error(r);
4119 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4120 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
4122 return bus_log_parse_error(r);
4124 r = sd_bus_message_exit_container(m);
4126 return bus_log_parse_error(r);
4134 r = bus_print_property(name, m, arg_all);
4136 return bus_log_parse_error(r);
4139 r = sd_bus_message_skip(m, contents);
4141 return bus_log_parse_error(r);
4144 printf("%s=[unprintable]\n", name);
4150 static int show_one(
4154 bool show_properties,
4158 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4159 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4160 UnitStatusInfo info = {};
4167 log_debug("Showing one %s", path);
4169 r = sd_bus_call_method(
4171 "org.freedesktop.systemd1",
4173 "org.freedesktop.DBus.Properties",
4179 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4183 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4185 return bus_log_parse_error(r);
4192 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4193 const char *name, *contents;
4195 r = sd_bus_message_read(reply, "s", &name);
4197 return bus_log_parse_error(r);
4199 r = sd_bus_message_peek_type(reply, NULL, &contents);
4201 return bus_log_parse_error(r);
4203 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4205 return bus_log_parse_error(r);
4207 if (show_properties)
4208 r = print_property(name, reply, contents);
4210 r = status_property(name, reply, &info, contents);
4214 r = sd_bus_message_exit_container(reply);
4216 return bus_log_parse_error(r);
4218 r = sd_bus_message_exit_container(reply);
4220 return bus_log_parse_error(r);
4223 return bus_log_parse_error(r);
4225 r = sd_bus_message_exit_container(reply);
4227 return bus_log_parse_error(r);
4231 if (!show_properties) {
4232 if (streq(verb, "help"))
4233 show_unit_help(&info);
4235 print_status_info(&info, ellipsized);
4238 strv_free(info.documentation);
4239 strv_free(info.dropin_paths);
4240 strv_free(info.listen);
4242 if (!streq_ptr(info.active_state, "active") &&
4243 !streq_ptr(info.active_state, "reloading") &&
4244 streq(verb, "status")) {
4245 /* According to LSB: "program not running" */
4246 /* 0: program is running or service is OK
4247 * 1: program is dead and /run PID file exists
4248 * 2: program is dead and /run/lock lock file exists
4249 * 3: program is not running
4250 * 4: program or service status is unknown
4252 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4258 while ((p = info.exec)) {
4259 LIST_REMOVE(exec, info.exec, p);
4260 exec_status_info_free(p);
4266 static int get_unit_dbus_path_by_pid(
4271 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4272 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4276 r = sd_bus_call_method(
4278 "org.freedesktop.systemd1",
4279 "/org/freedesktop/systemd1",
4280 "org.freedesktop.systemd1.Manager",
4286 log_error("Failed to get unit for PID "PID_FMT": %s", pid, bus_error_message(&error, r));
4290 r = sd_bus_message_read(reply, "o", &u);
4292 return bus_log_parse_error(r);
4302 static int show_all(
4305 bool show_properties,
4309 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4310 _cleanup_free_ UnitInfo *unit_infos = NULL;
4315 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4319 pager_open_if_enabled();
4323 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4325 for (u = unit_infos; u < unit_infos + c; u++) {
4326 _cleanup_free_ char *p = NULL;
4328 p = unit_dbus_path_from_name(u->id);
4332 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4335 else if (r > 0 && ret == 0)
4342 static int show_system_status(sd_bus *bus) {
4343 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4344 _cleanup_free_ char *hn = NULL;
4345 struct machine_info mi = {};
4346 const char *on, *off;
4349 hn = gethostname_malloc();
4353 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4355 return log_error_errno(r, "Failed to read server status: %m");
4357 if (streq_ptr(mi.state, "degraded")) {
4358 on = ansi_highlight_red();
4359 off = ansi_highlight_off();
4360 } else if (!streq_ptr(mi.state, "running")) {
4361 on = ansi_highlight_yellow();
4362 off = ansi_highlight_off();
4366 printf("%s%s%s %s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4368 printf(" State: %s%s%s\n",
4369 on, strna(mi.state), off);
4371 printf(" Jobs: %u queued\n", mi.n_jobs);
4372 printf(" Failed: %u units\n", mi.n_failed_units);
4374 printf(" Since: %s; %s\n",
4375 format_timestamp(since2, sizeof(since2), mi.timestamp),
4376 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4378 printf(" CGroup: %s\n", mi.control_group ?: "/");
4379 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_MACHINE) {
4381 arg_all * OUTPUT_SHOW_ALL |
4382 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
4383 on_tty() * OUTPUT_COLOR |
4384 !arg_quiet * OUTPUT_WARN_CUTOFF |
4385 arg_full * OUTPUT_FULL_WIDTH;
4387 static const char prefix[] = " ";
4391 if (c > sizeof(prefix) - 1)
4392 c -= sizeof(prefix) - 1;
4396 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
4400 free(mi.control_group);
4405 static int show(sd_bus *bus, char **args) {
4406 bool show_properties, show_status, new_line = false;
4407 bool ellipsized = false;
4413 show_properties = streq(args[0], "show");
4414 show_status = streq(args[0], "status");
4416 if (show_properties)
4417 pager_open_if_enabled();
4419 /* If no argument is specified inspect the manager itself */
4421 if (show_properties && strv_length(args) <= 1)
4422 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4424 if (show_status && strv_length(args) <= 1) {
4426 pager_open_if_enabled();
4427 show_system_status(bus);
4431 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4433 _cleanup_free_ char **patterns = NULL;
4436 STRV_FOREACH(name, args + 1) {
4437 _cleanup_free_ char *unit = NULL;
4440 if (safe_atou32(*name, &id) < 0) {
4441 if (strv_push(&patterns, *name) < 0)
4445 } else if (show_properties) {
4446 /* Interpret as job id */
4447 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4451 /* Interpret as PID */
4452 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4459 r = show_one(args[0], bus, unit, show_properties,
4460 &new_line, &ellipsized);
4463 else if (r > 0 && ret == 0)
4467 if (!strv_isempty(patterns)) {
4468 _cleanup_strv_free_ char **names = NULL;
4470 r = expand_names(bus, patterns, NULL, &names);
4472 log_error_errno(r, "Failed to expand names: %m");
4474 STRV_FOREACH(name, names) {
4475 _cleanup_free_ char *unit;
4477 unit = unit_dbus_path_from_name(*name);
4481 r = show_one(args[0], bus, unit, show_properties,
4482 &new_line, &ellipsized);
4485 else if (r > 0 && ret == 0)
4491 if (ellipsized && !arg_quiet)
4492 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4497 static int init_home_and_lookup_paths(char **user_home, char **user_runtime, LookupPaths *lp) {
4501 assert(user_runtime);
4504 if (arg_scope == UNIT_FILE_USER) {
4505 r = user_config_home(user_home);
4507 return log_error_errno(r, "Failed to query XDG_CONFIG_HOME: %m");
4509 return log_error_errno(ENOTDIR, "Cannot find units: $XDG_CONFIG_HOME and $HOME are not set.");
4511 r = user_runtime_dir(user_runtime);
4513 return log_error_errno(r, "Failed to query XDG_CONFIG_HOME: %m");
4515 return log_error_errno(ENOTDIR, "Cannot find units: $XDG_RUNTIME_DIR is not set.");
4518 r = lookup_paths_init(lp,
4519 arg_scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
4520 arg_scope == UNIT_FILE_USER,
4524 return log_error_errno(r, "Failed to lookup unit lookup paths: %m");
4529 static int cat(sd_bus *bus, char **args) {
4530 _cleanup_free_ char *user_home = NULL;
4531 _cleanup_free_ char *user_runtime = NULL;
4532 _cleanup_lookup_paths_free_ LookupPaths lp = {};
4533 _cleanup_strv_free_ char **names = NULL;
4535 bool first = true, avoid_bus_cache;
4540 r = init_home_and_lookup_paths(&user_home, &user_runtime, &lp);
4544 r = expand_names(bus, args + 1, NULL, &names);
4546 log_error_errno(r, "Failed to expand names: %m");
4548 avoid_bus_cache = !bus || avoid_bus();
4550 pager_open_if_enabled();
4552 STRV_FOREACH(name, names) {
4553 _cleanup_free_ char *fragment_path = NULL;
4554 _cleanup_strv_free_ char **dropin_paths = NULL;
4557 r = unit_find_paths(bus, *name, avoid_bus_cache, &lp, &fragment_path, &dropin_paths);
4561 log_warning("Unit %s does not have any files on disk", *name);
4570 if (fragment_path) {
4571 printf("%s# %s%s\n",
4572 ansi_highlight_blue(),
4574 ansi_highlight_off());
4577 r = copy_file_fd(fragment_path, STDOUT_FILENO, false);
4579 log_warning_errno(r, "Failed to cat %s: %m", fragment_path);
4584 STRV_FOREACH(path, dropin_paths) {
4585 printf("%s%s# %s%s\n",
4586 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4587 ansi_highlight_blue(),
4589 ansi_highlight_off());
4592 r = copy_file_fd(*path, STDOUT_FILENO, false);
4594 log_warning_errno(r, "Failed to cat %s: %m", *path);
4600 return r < 0 ? r : 0;
4603 static int set_property(sd_bus *bus, char **args) {
4604 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4605 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4606 _cleanup_free_ char *n = NULL;
4610 r = sd_bus_message_new_method_call(
4613 "org.freedesktop.systemd1",
4614 "/org/freedesktop/systemd1",
4615 "org.freedesktop.systemd1.Manager",
4616 "SetUnitProperties");
4618 return bus_log_create_error(r);
4620 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4622 return bus_log_create_error(r);
4624 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4628 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4630 return bus_log_create_error(r);
4632 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4634 return bus_log_create_error(r);
4636 STRV_FOREACH(i, args + 2) {
4637 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4639 return bus_log_create_error(r);
4641 r = bus_append_unit_property_assignment(m, *i);
4645 r = sd_bus_message_close_container(m);
4647 return bus_log_create_error(r);
4650 r = sd_bus_message_close_container(m);
4652 return bus_log_create_error(r);
4654 r = sd_bus_call(bus, m, 0, &error, NULL);
4656 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4663 static int snapshot(sd_bus *bus, char **args) {
4664 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4665 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
4666 _cleanup_free_ char *n = NULL, *id = NULL;
4670 if (strv_length(args) > 1)
4671 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4677 r = sd_bus_message_new_method_call(
4680 "org.freedesktop.systemd1",
4681 "/org/freedesktop/systemd1",
4682 "org.freedesktop.systemd1.Manager",
4685 return bus_log_create_error(r);
4687 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4689 return bus_log_create_error(r);
4691 r = sd_bus_message_append(m, "sb", n, false);
4693 return bus_log_create_error(r);
4695 r = sd_bus_call(bus, m, 0, &error, &reply);
4697 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4701 r = sd_bus_message_read(reply, "o", &path);
4703 return bus_log_parse_error(r);
4705 r = sd_bus_get_property_string(
4707 "org.freedesktop.systemd1",
4709 "org.freedesktop.systemd1.Unit",
4714 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4724 static int delete_snapshot(sd_bus *bus, char **args) {
4725 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4726 _cleanup_strv_free_ char **names = NULL;
4732 r = expand_names(bus, args + 1, ".snapshot", &names);
4734 log_error_errno(r, "Failed to expand names: %m");
4736 STRV_FOREACH(name, names) {
4737 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4740 q = sd_bus_message_new_method_call(
4743 "org.freedesktop.systemd1",
4744 "/org/freedesktop/systemd1",
4745 "org.freedesktop.systemd1.Manager",
4748 return bus_log_create_error(q);
4750 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4752 return bus_log_create_error(q);
4754 q = sd_bus_message_append(m, "s", *name);
4756 return bus_log_create_error(q);
4758 q = sd_bus_call(bus, m, 0, &error, NULL);
4760 log_error("Failed to remove snapshot %s: %s", *name, bus_error_message(&error, q));
4769 static int daemon_reload(sd_bus *bus, char **args) {
4770 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4771 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4775 if (arg_action == ACTION_RELOAD)
4777 else if (arg_action == ACTION_REEXEC)
4778 method = "Reexecute";
4780 assert(arg_action == ACTION_SYSTEMCTL);
4783 streq(args[0], "clear-jobs") ||
4784 streq(args[0], "cancel") ? "ClearJobs" :
4785 streq(args[0], "daemon-reexec") ? "Reexecute" :
4786 streq(args[0], "reset-failed") ? "ResetFailed" :
4787 streq(args[0], "halt") ? "Halt" :
4788 streq(args[0], "poweroff") ? "PowerOff" :
4789 streq(args[0], "reboot") ? "Reboot" :
4790 streq(args[0], "kexec") ? "KExec" :
4791 streq(args[0], "exit") ? "Exit" :
4792 /* "daemon-reload" */ "Reload";
4795 r = sd_bus_message_new_method_call(
4798 "org.freedesktop.systemd1",
4799 "/org/freedesktop/systemd1",
4800 "org.freedesktop.systemd1.Manager",
4803 return bus_log_create_error(r);
4805 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4807 return bus_log_create_error(r);
4809 r = sd_bus_call(bus, m, 0, &error, NULL);
4810 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4811 /* There's always a fallback possible for
4812 * legacy actions. */
4814 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4815 /* On reexecution, we expect a disconnect, not a
4819 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4821 return r < 0 ? r : 0;
4824 static int reset_failed(sd_bus *bus, char **args) {
4825 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4826 _cleanup_strv_free_ char **names = NULL;
4830 if (strv_length(args) <= 1)
4831 return daemon_reload(bus, args);
4833 r = expand_names(bus, args + 1, NULL, &names);
4835 log_error_errno(r, "Failed to expand names: %m");
4837 STRV_FOREACH(name, names) {
4838 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4840 q = sd_bus_message_new_method_call(
4843 "org.freedesktop.systemd1",
4844 "/org/freedesktop/systemd1",
4845 "org.freedesktop.systemd1.Manager",
4848 return bus_log_create_error(q);
4850 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4852 return bus_log_create_error(q);
4854 q = sd_bus_message_append(m, "s", *name);
4856 return bus_log_create_error(q);
4858 q = sd_bus_call(bus, m, 0, &error, NULL);
4860 log_error("Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q));
4869 static int show_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 *reply = NULL;
4875 pager_open_if_enabled();
4877 r = sd_bus_get_property(
4879 "org.freedesktop.systemd1",
4880 "/org/freedesktop/systemd1",
4881 "org.freedesktop.systemd1.Manager",
4887 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4891 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4893 return bus_log_parse_error(r);
4895 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4898 return bus_log_parse_error(r);
4900 r = sd_bus_message_exit_container(reply);
4902 return bus_log_parse_error(r);
4907 static int switch_root(sd_bus *bus, char **args) {
4908 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4909 _cleanup_free_ char *cmdline_init = NULL;
4910 const char *root, *init;
4914 l = strv_length(args);
4915 if (l < 2 || l > 3) {
4916 log_error("Wrong number of arguments.");
4925 r = parse_env_file("/proc/cmdline", WHITESPACE,
4926 "init", &cmdline_init,
4929 log_debug_errno(r, "Failed to parse /proc/cmdline: %m");
4931 init = cmdline_init;
4938 const char *root_systemd_path = NULL, *root_init_path = NULL;
4940 root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
4941 root_init_path = strappenda(root, "/", init);
4943 /* If the passed init is actually the same as the
4944 * systemd binary, then let's suppress it. */
4945 if (files_same(root_init_path, root_systemd_path) > 0)
4949 log_debug("Switching root - root: %s; init: %s", root, strna(init));
4951 r = sd_bus_call_method(
4953 "org.freedesktop.systemd1",
4954 "/org/freedesktop/systemd1",
4955 "org.freedesktop.systemd1.Manager",
4961 log_error("Failed to switch root: %s", bus_error_message(&error, r));
4968 static int set_environment(sd_bus *bus, char **args) {
4969 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4970 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4977 method = streq(args[0], "set-environment")
4979 : "UnsetEnvironment";
4981 r = sd_bus_message_new_method_call(
4984 "org.freedesktop.systemd1",
4985 "/org/freedesktop/systemd1",
4986 "org.freedesktop.systemd1.Manager",
4989 return bus_log_create_error(r);
4991 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4993 return bus_log_create_error(r);
4995 r = sd_bus_message_append_strv(m, args + 1);
4997 return bus_log_create_error(r);
4999 r = sd_bus_call(bus, m, 0, &error, NULL);
5001 log_error("Failed to set environment: %s", bus_error_message(&error, r));
5008 static int import_environment(sd_bus *bus, char **args) {
5009 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5010 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
5016 r = sd_bus_message_new_method_call(
5019 "org.freedesktop.systemd1",
5020 "/org/freedesktop/systemd1",
5021 "org.freedesktop.systemd1.Manager",
5024 return bus_log_create_error(r);
5026 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5028 return bus_log_create_error(r);
5030 if (strv_isempty(args + 1))
5031 r = sd_bus_message_append_strv(m, environ);
5035 r = sd_bus_message_open_container(m, 'a', "s");
5037 return bus_log_create_error(r);
5039 STRV_FOREACH(a, args + 1) {
5041 if (!env_name_is_valid(*a)) {
5042 log_error("Not a valid environment variable name: %s", *a);
5046 STRV_FOREACH(b, environ) {
5049 eq = startswith(*b, *a);
5050 if (eq && *eq == '=') {
5052 r = sd_bus_message_append(m, "s", *b);
5054 return bus_log_create_error(r);
5061 r = sd_bus_message_close_container(m);
5064 return bus_log_create_error(r);
5066 r = sd_bus_call(bus, m, 0, &error, NULL);
5068 log_error("Failed to import environment: %s", bus_error_message(&error, r));
5075 static int enable_sysv_units(const char *verb, char **args) {
5078 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
5080 _cleanup_lookup_paths_free_ LookupPaths paths = {};
5082 if (arg_scope != UNIT_FILE_SYSTEM)
5085 if (!streq(verb, "enable") &&
5086 !streq(verb, "disable") &&
5087 !streq(verb, "is-enabled"))
5090 /* Processes all SysV units, and reshuffles the array so that
5091 * afterwards only the native units remain */
5093 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, arg_root, NULL, NULL, NULL);
5100 _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL;
5101 bool found_native = false, found_sysv;
5103 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
5111 if (!endswith(name, ".service"))
5114 if (path_is_absolute(name))
5117 STRV_FOREACH(k, paths.unit_path) {
5118 _cleanup_free_ char *path = NULL;
5120 path = path_join(arg_root, *k, name);
5124 found_native = access(path, F_OK) >= 0;
5132 p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name);
5136 p[strlen(p) - strlen(".service")] = 0;
5137 found_sysv = access(p, F_OK) >= 0;
5141 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
5143 if (!isempty(arg_root))
5144 argv[c++] = q = strappend("--root=", arg_root);
5146 argv[c++] = basename(p);
5148 streq(verb, "enable") ? "on" :
5149 streq(verb, "disable") ? "off" : "--level=5";
5152 l = strv_join((char**)argv, " ");
5156 log_info("Executing %s", l);
5160 return log_error_errno(errno, "Failed to fork: %m");
5161 else if (pid == 0) {
5164 execv(argv[0], (char**) argv);
5165 _exit(EXIT_FAILURE);
5168 j = wait_for_terminate(pid, &status);
5170 log_error_errno(r, "Failed to wait for child: %m");
5174 if (status.si_code == CLD_EXITED) {
5175 if (streq(verb, "is-enabled")) {
5176 if (status.si_status == 0) {
5185 } else if (status.si_status != 0)
5190 /* Remove this entry, so that we don't try enabling it as native unit */
5191 assert(f > 0 && streq(args[f-1], name));
5192 assert_se(strv_remove(args + f - 1, name));
5199 static int mangle_names(char **original_names, char ***mangled_names) {
5200 char **i, **l, **name;
5202 l = new(char*, strv_length(original_names) + 1);
5207 STRV_FOREACH(name, original_names) {
5209 /* When enabling units qualified path names are OK,
5210 * too, hence allow them explicitly. */
5215 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5231 static int enable_unit(sd_bus *bus, char **args) {
5232 _cleanup_strv_free_ char **names = NULL;
5233 const char *verb = args[0];
5234 UnitFileChange *changes = NULL;
5235 unsigned n_changes = 0;
5236 int carries_install_info = -1;
5242 r = mangle_names(args+1, &names);
5246 r = enable_sysv_units(verb, names);
5250 /* If the operation was fully executed by the SysV compat,
5251 * let's finish early */
5252 if (strv_isempty(names))
5255 if (!bus || avoid_bus()) {
5256 if (streq(verb, "enable")) {
5257 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5258 carries_install_info = r;
5259 } else if (streq(verb, "disable"))
5260 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5261 else if (streq(verb, "reenable")) {
5262 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5263 carries_install_info = r;
5264 } else if (streq(verb, "link"))
5265 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5266 else if (streq(verb, "preset")) {
5267 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_preset_mode, arg_force, &changes, &n_changes);
5268 carries_install_info = r;
5269 } else if (streq(verb, "mask"))
5270 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5271 else if (streq(verb, "unmask"))
5272 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5274 assert_not_reached("Unknown verb");
5277 log_error_errno(r, "Operation failed: %m");
5282 dump_unit_file_changes(changes, n_changes);
5286 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5287 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5288 int expect_carries_install_info = false;
5289 bool send_force = true, send_preset_mode = false;
5292 if (streq(verb, "enable")) {
5293 method = "EnableUnitFiles";
5294 expect_carries_install_info = true;
5295 } else if (streq(verb, "disable")) {
5296 method = "DisableUnitFiles";
5298 } else if (streq(verb, "reenable")) {
5299 method = "ReenableUnitFiles";
5300 expect_carries_install_info = true;
5301 } else if (streq(verb, "link"))
5302 method = "LinkUnitFiles";
5303 else if (streq(verb, "preset")) {
5305 if (arg_preset_mode != UNIT_FILE_PRESET_FULL) {
5306 method = "PresetUnitFilesWithMode";
5307 send_preset_mode = true;
5309 method = "PresetUnitFiles";
5311 expect_carries_install_info = true;
5312 } else if (streq(verb, "mask"))
5313 method = "MaskUnitFiles";
5314 else if (streq(verb, "unmask")) {
5315 method = "UnmaskUnitFiles";
5318 assert_not_reached("Unknown verb");
5320 r = sd_bus_message_new_method_call(
5323 "org.freedesktop.systemd1",
5324 "/org/freedesktop/systemd1",
5325 "org.freedesktop.systemd1.Manager",
5328 return bus_log_create_error(r);
5330 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5332 return bus_log_create_error(r);
5334 r = sd_bus_message_append_strv(m, names);
5336 return bus_log_create_error(r);
5338 if (send_preset_mode) {
5339 r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode));
5341 return bus_log_create_error(r);
5344 r = sd_bus_message_append(m, "b", arg_runtime);
5346 return bus_log_create_error(r);
5349 r = sd_bus_message_append(m, "b", arg_force);
5351 return bus_log_create_error(r);
5354 r = sd_bus_call(bus, m, 0, &error, &reply);
5356 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5360 if (expect_carries_install_info) {
5361 r = sd_bus_message_read(reply, "b", &carries_install_info);
5363 return bus_log_parse_error(r);
5366 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
5370 /* Try to reload if enabled */
5372 r = daemon_reload(bus, args);
5377 if (carries_install_info == 0)
5378 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5379 "using systemctl.\n"
5380 "Possible reasons for having this kind of units are:\n"
5381 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5382 " .wants/ or .requires/ directory.\n"
5383 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5384 " a requirement dependency on it.\n"
5385 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5386 " D-Bus, udev, scripted systemctl call, ...).\n");
5389 unit_file_changes_free(changes, n_changes);
5394 static int add_dependency(sd_bus *bus, char **args) {
5395 _cleanup_strv_free_ char **names = NULL;
5396 _cleanup_free_ char *target = NULL;
5397 const char *verb = args[0];
5404 target = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
5408 r = mangle_names(args+2, &names);
5412 if (streq(verb, "add-wants"))
5414 else if (streq(verb, "add-requires"))
5415 dep = UNIT_REQUIRES;
5417 assert_not_reached("Unknown verb");
5419 if (!bus || avoid_bus()) {
5420 UnitFileChange *changes = NULL;
5421 unsigned n_changes = 0;
5423 r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes);
5426 return log_error_errno(r, "Can't add dependency: %m");
5429 dump_unit_file_changes(changes, n_changes);
5431 unit_file_changes_free(changes, n_changes);
5434 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5435 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5437 r = sd_bus_message_new_method_call(
5440 "org.freedesktop.systemd1",
5441 "/org/freedesktop/systemd1",
5442 "org.freedesktop.systemd1.Manager",
5443 "AddDependencyUnitFiles");
5445 return bus_log_create_error(r);
5447 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5449 return bus_log_create_error(r);
5451 r = sd_bus_message_append_strv(m, names);
5453 return bus_log_create_error(r);
5455 r = sd_bus_message_append(m, "ssbb", target, unit_dependency_to_string(dep), arg_runtime, arg_force);
5457 return bus_log_create_error(r);
5459 r = sd_bus_call(bus, m, 0, &error, &reply);
5461 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5465 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
5470 r = daemon_reload(bus, args);
5478 static int preset_all(sd_bus *bus, char **args) {
5479 UnitFileChange *changes = NULL;
5480 unsigned n_changes = 0;
5483 if (!bus || avoid_bus()) {
5485 r = unit_file_preset_all(arg_scope, arg_runtime, arg_root, arg_preset_mode, arg_force, &changes, &n_changes);
5487 log_error_errno(r, "Operation failed: %m");
5492 dump_unit_file_changes(changes, n_changes);
5497 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
5498 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5500 r = sd_bus_message_new_method_call(
5503 "org.freedesktop.systemd1",
5504 "/org/freedesktop/systemd1",
5505 "org.freedesktop.systemd1.Manager",
5506 "PresetAllUnitFiles");
5508 return bus_log_create_error(r);
5510 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5512 return bus_log_create_error(r);
5514 r = sd_bus_message_append(
5517 unit_file_preset_mode_to_string(arg_preset_mode),
5521 return bus_log_create_error(r);
5523 r = sd_bus_call(bus, m, 0, &error, &reply);
5525 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5529 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
5534 r = daemon_reload(bus, args);
5540 unit_file_changes_free(changes, n_changes);
5545 static int unit_is_enabled(sd_bus *bus, char **args) {
5547 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5548 _cleanup_strv_free_ char **names = NULL;
5553 r = mangle_names(args+1, &names);
5557 r = enable_sysv_units(args[0], names);
5563 if (!bus || avoid_bus()) {
5565 STRV_FOREACH(name, names) {
5566 UnitFileState state;
5568 state = unit_file_get_state(arg_scope, arg_root, *name);
5570 return log_error_errno(state, "Failed to get unit file state for %s: %m", *name);
5572 if (state == UNIT_FILE_ENABLED ||
5573 state == UNIT_FILE_ENABLED_RUNTIME ||
5574 state == UNIT_FILE_STATIC ||
5575 state == UNIT_FILE_INDIRECT)
5579 puts(unit_file_state_to_string(state));
5583 STRV_FOREACH(name, names) {
5584 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5587 r = sd_bus_call_method(
5589 "org.freedesktop.systemd1",
5590 "/org/freedesktop/systemd1",
5591 "org.freedesktop.systemd1.Manager",
5597 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5601 r = sd_bus_message_read(reply, "s", &s);
5603 return bus_log_parse_error(r);
5605 if (STR_IN_SET(s, "enabled", "enabled-runtime", "static", "indirect"))
5616 static int is_system_running(sd_bus *bus, char **args) {
5617 _cleanup_free_ char *state = NULL;
5620 r = sd_bus_get_property_string(
5622 "org.freedesktop.systemd1",
5623 "/org/freedesktop/systemd1",
5624 "org.freedesktop.systemd1.Manager",
5637 return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE;
5640 static int create_edit_temp_file(const char *new_path, const char *original_path, char **ret_tmp_fn) {
5645 assert(original_path);
5648 r = tempfn_random(new_path, &t);
5650 return log_error_errno(r, "Failed to determine temporary filename for %s: %m", new_path);
5652 r = mkdir_parents(new_path, 0755);
5654 log_error_errno(r, "Failed to create directories for %s: %m", new_path);
5659 r = copy_file(original_path, t, 0, 0644);
5663 log_error_errno(r, "Failed to create temporary file %s: %m", t);
5668 log_error_errno(r, "Failed to copy %s to %s: %m", original_path, t);
5678 static int get_file_to_edit(const char *name, const char *user_home, const char *user_runtime, char **ret_path) {
5679 _cleanup_free_ char *path = NULL, *path2 = NULL, *run = NULL;
5681 switch (arg_scope) {
5682 case UNIT_FILE_SYSTEM:
5683 path = path_join(arg_root, SYSTEM_CONFIG_UNIT_PATH, name);
5685 run = path_join(arg_root, "/run/systemd/system/", name);
5687 case UNIT_FILE_GLOBAL:
5688 path = path_join(arg_root, USER_CONFIG_UNIT_PATH, name);
5690 run = path_join(arg_root, "/run/systemd/user/", name);
5692 case UNIT_FILE_USER:
5694 assert(user_runtime);
5696 path = path_join(arg_root, user_home, name);
5698 path2 = path_join(arg_root, USER_CONFIG_UNIT_PATH, name);
5701 run = path_join(arg_root, user_runtime, name);
5705 assert_not_reached("Invalid scope");
5707 if (!path || (arg_runtime && !run))
5711 if (access(path, F_OK) >= 0)
5712 return log_error_errno(EEXIST, "Refusing to create \"%s\" because it would be overriden by \"%s\" anyway.",
5714 if (path2 && access(path2, F_OK) >= 0)
5715 return log_error_errno(EEXIST, "Refusing to create \"%s\" because it would be overriden by \"%s\" anyway.",
5728 static int unit_file_create_dropin(const char *unit_name, const char *user_home, const char *user_runtime, char **ret_new_path, char **ret_tmp_path) {
5729 char *tmp_new_path, *ending;
5734 assert(ret_new_path);
5735 assert(ret_tmp_path);
5737 ending = strappenda(unit_name, ".d/override.conf");
5738 r = get_file_to_edit(ending, user_home, user_runtime, &tmp_new_path);
5742 r = create_edit_temp_file(tmp_new_path, tmp_new_path, &tmp_tmp_path);
5748 *ret_new_path = tmp_new_path;
5749 *ret_tmp_path = tmp_tmp_path;
5754 static int unit_file_create_copy(const char *unit_name,
5755 const char *fragment_path,
5756 const char *user_home,
5757 const char *user_runtime,
5758 char **ret_new_path,
5759 char **ret_tmp_path) {
5764 assert(fragment_path);
5766 assert(ret_new_path);
5767 assert(ret_tmp_path);
5769 r = get_file_to_edit(unit_name, user_home, user_runtime, &tmp_new_path);
5773 if (!path_equal(fragment_path, tmp_new_path) && access(tmp_new_path, F_OK) == 0) {
5776 r = ask_char(&response, "yn", "%s already exists, are you sure to overwrite it with %s? [(y)es, (n)o] ", tmp_new_path, fragment_path);
5781 if (response != 'y') {
5782 log_warning("%s ignored", unit_name);
5788 r = create_edit_temp_file(tmp_new_path, fragment_path, &tmp_tmp_path);
5790 log_error_errno(r, "Failed to create temporary file for %s: %m", tmp_new_path);
5795 *ret_new_path = tmp_new_path;
5796 *ret_tmp_path = tmp_tmp_path;
5801 static int run_editor(char **paths) {
5809 log_error_errno(errno, "Failed to fork: %m");
5815 char **backup_editors = STRV_MAKE("nano", "vim", "vi");
5817 char **tmp_path, **original_path, **p;
5821 argc = strv_length(paths)/2 + 1;
5822 args = newa(const char*, argc + 1);
5825 STRV_FOREACH_PAIR(original_path, tmp_path, paths) {
5826 args[i] = *tmp_path;
5831 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
5832 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
5833 * we try to execute well known editors
5835 editor = getenv("SYSTEMD_EDITOR");
5837 editor = getenv("EDITOR");
5839 editor = getenv("VISUAL");
5841 if (!isempty(editor)) {
5843 execvp(editor, (char* const*) args);
5846 STRV_FOREACH(p, backup_editors) {
5848 execvp(*p, (char* const*) args);
5849 /* We do not fail if the editor doesn't exist
5850 * because we want to try each one of them before
5853 if (errno != ENOENT) {
5854 log_error("Failed to execute %s: %m", editor);
5855 _exit(EXIT_FAILURE);
5859 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR or $EDITOR or $VISUAL.");
5860 _exit(EXIT_FAILURE);
5863 r = wait_for_terminate_and_warn("editor", pid, true);
5865 return log_error_errno(r, "Failed to wait for child: %m");
5870 static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
5871 _cleanup_free_ char *user_home = NULL;
5872 _cleanup_free_ char *user_runtime = NULL;
5873 _cleanup_lookup_paths_free_ LookupPaths lp = {};
5874 bool avoid_bus_cache;
5881 r = init_home_and_lookup_paths(&user_home, &user_runtime, &lp);
5885 avoid_bus_cache = !bus || avoid_bus();
5887 STRV_FOREACH(name, names) {
5888 _cleanup_free_ char *path = NULL;
5889 char *new_path, *tmp_path;
5891 r = unit_find_paths(bus, *name, avoid_bus_cache, &lp, &path, NULL);
5894 else if (r == 0 || !path)
5895 // FIXME: support units with path==NULL (no FragmentPath)
5896 return log_error_errno(ENOENT, "Unit %s not found, cannot edit.", *name);
5899 r = unit_file_create_copy(*name, path, user_home, user_runtime, &new_path, &tmp_path);
5901 r = unit_file_create_dropin(*name, user_home, user_runtime, &new_path, &tmp_path);
5905 r = strv_push_pair(paths, new_path, tmp_path);
5913 static int edit(sd_bus *bus, char **args) {
5914 _cleanup_strv_free_ char **names = NULL;
5915 _cleanup_strv_free_ char **paths = NULL;
5916 char **original, **tmp;
5922 log_error("Cannot edit units if we are not on a tty");
5926 if (arg_transport != BUS_TRANSPORT_LOCAL) {
5927 log_error("Cannot remotely edit units");
5931 r = expand_names(bus, args + 1, NULL, &names);
5933 return log_error_errno(r, "Failed to expand names: %m");
5936 log_error("No unit name found by expanding names");
5940 r = find_paths_to_edit(bus, names, &paths);
5944 if (strv_isempty(paths)) {
5945 log_error("Cannot find any units to edit");
5949 r = run_editor(paths);
5953 STRV_FOREACH_PAIR(original, tmp, paths) {
5954 /* If the temporary file is empty we ignore it.
5955 * It's useful if the user wants to cancel its modification
5957 if (null_or_empty_path(*tmp)) {
5958 log_warning("Edition of %s canceled: temporary file empty", *original);
5961 r = rename(*tmp, *original);
5963 r = log_error_errno(errno, "Failed to rename %s to %s: %m", *tmp, *original);
5968 if (!arg_no_reload && bus && !avoid_bus())
5969 r = daemon_reload(bus, args);
5972 STRV_FOREACH_PAIR(original, tmp, paths)
5973 unlink_noerrno(*tmp);
5978 static void systemctl_help(void) {
5980 pager_open_if_enabled();
5982 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
5983 "Query or send control commands to the systemd manager.\n\n"
5984 " -h --help Show this help\n"
5985 " --version Show package version\n"
5986 " --system Connect to system manager\n"
5987 " --user Connect to user service manager\n"
5988 " -H --host=[USER@]HOST\n"
5989 " Operate on remote host\n"
5990 " -M --machine=CONTAINER\n"
5991 " Operate on local container\n"
5992 " -t --type=TYPE List only units of a particular type\n"
5993 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
5994 " -p --property=NAME Show only properties by this name\n"
5995 " -a --all Show all loaded units/properties, including dead/empty\n"
5996 " ones. To list all units installed on the system, use\n"
5997 " the 'list-unit-files' command instead.\n"
5998 " -l --full Don't ellipsize unit names on output\n"
5999 " -r --recursive Show unit list of host and local containers\n"
6000 " --reverse Show reverse dependencies with 'list-dependencies'\n"
6001 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
6002 " queueing a new job\n"
6003 " --show-types When showing sockets, explicitly show their type\n"
6004 " -i --ignore-inhibitors\n"
6005 " When shutting down or sleeping, ignore inhibitors\n"
6006 " --kill-who=WHO Who to send signal to\n"
6007 " -s --signal=SIGNAL Which signal to send\n"
6008 " -q --quiet Suppress output\n"
6009 " --no-block Do not wait until operation finished\n"
6010 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6011 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
6013 " --no-legend Do not print a legend (column headers and hints)\n"
6014 " --no-pager Do not pipe output into a pager\n"
6015 " --no-ask-password\n"
6016 " Do not ask for system passwords\n"
6017 " --global Enable/disable unit files globally\n"
6018 " --runtime Enable unit files only temporarily until next reboot\n"
6019 " -f --force When enabling unit files, override existing symlinks\n"
6020 " When shutting down, execute action immediately\n"
6021 " --preset-mode= Specifies whether fully apply presets, or only enable,\n"
6022 " or only disable\n"
6023 " --root=PATH Enable unit files in the specified root directory\n"
6024 " -n --lines=INTEGER Number of journal entries to show\n"
6025 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
6026 " verbose, export, json, json-pretty, json-sse, cat)\n"
6027 " --plain Print unit dependencies as a list instead of a tree\n\n"
6029 " list-units [PATTERN...] List loaded units\n"
6030 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
6031 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
6032 " start NAME... Start (activate) one or more units\n"
6033 " stop NAME... Stop (deactivate) one or more units\n"
6034 " reload NAME... Reload one or more units\n"
6035 " restart NAME... Start or restart one or more units\n"
6036 " try-restart NAME... Restart one or more units if active\n"
6037 " reload-or-restart NAME... Reload one or more units if possible,\n"
6038 " otherwise start or restart\n"
6039 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
6040 " otherwise restart if active\n"
6041 " isolate NAME Start one unit and stop all others\n"
6042 " kill NAME... Send signal to processes of a unit\n"
6043 " is-active PATTERN... Check whether units are active\n"
6044 " is-failed PATTERN... Check whether units are failed\n"
6045 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
6046 " show [PATTERN...|JOB...] Show properties of one or more\n"
6047 " units/jobs or the manager\n"
6048 " cat PATTERN... Show files and drop-ins of one or more units\n"
6049 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
6050 " help PATTERN...|PID... Show manual for one or more units\n"
6051 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
6053 " list-dependencies [NAME] Recursively show units which are required\n"
6054 " or wanted by this unit or by which this\n"
6055 " unit is required or wanted\n\n"
6056 "Unit File Commands:\n"
6057 " list-unit-files [PATTERN...] List installed unit files\n"
6058 " enable NAME... Enable one or more unit files\n"
6059 " disable NAME... Disable one or more unit files\n"
6060 " reenable NAME... Reenable one or more unit files\n"
6061 " preset NAME... Enable/disable one or more unit files\n"
6062 " based on preset configuration\n"
6063 " preset-all Enable/disable all unit files based on\n"
6064 " preset configuration\n"
6065 " is-enabled NAME... Check whether unit files are enabled\n\n"
6066 " mask NAME... Mask one or more units\n"
6067 " unmask NAME... Unmask one or more units\n"
6068 " link PATH... Link one or more units files into\n"
6069 " the search path\n"
6070 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6071 " on specified one or more units\n"
6072 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6073 " on specified one or more units\n"
6074 " get-default Get the name of the default target\n"
6075 " set-default NAME Set the default target\n"
6076 " edit NAME... Edit one or more unit files\n"
6078 "Machine Commands:\n"
6079 " list-machines [PATTERN...] List local containers and host\n\n"
6081 " list-jobs [PATTERN...] List jobs\n"
6082 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
6083 "Snapshot Commands:\n"
6084 " snapshot [NAME] Create a snapshot\n"
6085 " delete NAME... Remove one or more snapshots\n\n"
6086 "Environment Commands:\n"
6087 " show-environment Dump environment\n"
6088 " set-environment NAME=VALUE... Set one or more environment variables\n"
6089 " unset-environment NAME... Unset one or more environment variables\n"
6090 " import-environment NAME... Import all, one or more environment variables\n\n"
6091 "Manager Lifecycle Commands:\n"
6092 " daemon-reload Reload systemd manager configuration\n"
6093 " daemon-reexec Reexecute systemd manager\n\n"
6094 "System Commands:\n"
6095 " is-system-running Check whether system is fully running\n"
6096 " default Enter system default mode\n"
6097 " rescue Enter system rescue mode\n"
6098 " emergency Enter system emergency mode\n"
6099 " halt Shut down and halt the system\n"
6100 " poweroff Shut down and power-off the system\n"
6101 " reboot [ARG] Shut down and reboot the system\n"
6102 " kexec Shut down and reboot the system with kexec\n"
6103 " exit Request user instance exit\n"
6104 " switch-root ROOT [INIT] Change to a different root file system\n"
6105 " suspend Suspend the system\n"
6106 " hibernate Hibernate the system\n"
6107 " hybrid-sleep Hibernate and suspend the system\n",
6108 program_invocation_short_name);
6111 static void halt_help(void) {
6112 printf("%s [OPTIONS...]%s\n\n"
6113 "%s the system.\n\n"
6114 " --help Show this help\n"
6115 " --halt Halt the machine\n"
6116 " -p --poweroff Switch off the machine\n"
6117 " --reboot Reboot the machine\n"
6118 " -f --force Force immediate halt/power-off/reboot\n"
6119 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
6120 " -d --no-wtmp Don't write wtmp record\n"
6121 " --no-wall Don't send wall message before halt/power-off/reboot\n",
6122 program_invocation_short_name,
6123 arg_action == ACTION_REBOOT ? " [ARG]" : "",
6124 arg_action == ACTION_REBOOT ? "Reboot" :
6125 arg_action == ACTION_POWEROFF ? "Power off" :
6129 static void shutdown_help(void) {
6130 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
6131 "Shut down the system.\n\n"
6132 " --help Show this help\n"
6133 " -H --halt Halt the machine\n"
6134 " -P --poweroff Power-off the machine\n"
6135 " -r --reboot Reboot the machine\n"
6136 " -h Equivalent to --poweroff, overridden by --halt\n"
6137 " -k Don't halt/power-off/reboot, just send warnings\n"
6138 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6139 " -c Cancel a pending shutdown\n",
6140 program_invocation_short_name);
6143 static void telinit_help(void) {
6144 printf("%s [OPTIONS...] {COMMAND}\n\n"
6145 "Send control commands to the init daemon.\n\n"
6146 " --help Show this help\n"
6147 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
6149 " 0 Power-off the machine\n"
6150 " 6 Reboot the machine\n"
6151 " 2, 3, 4, 5 Start runlevelX.target unit\n"
6152 " 1, s, S Enter rescue mode\n"
6153 " q, Q Reload init daemon configuration\n"
6154 " u, U Reexecute init daemon\n",
6155 program_invocation_short_name);
6158 static void runlevel_help(void) {
6159 printf("%s [OPTIONS...]\n\n"
6160 "Prints the previous and current runlevel of the init system.\n\n"
6161 " --help Show this help\n",
6162 program_invocation_short_name);
6165 static void help_types(void) {
6170 puts("Available unit types:");
6171 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
6172 t = unit_type_to_string(i);
6178 static int systemctl_parse_argv(int argc, char *argv[]) {
6187 ARG_IGNORE_DEPENDENCIES,
6199 ARG_NO_ASK_PASSWORD,
6209 static const struct option options[] = {
6210 { "help", no_argument, NULL, 'h' },
6211 { "version", no_argument, NULL, ARG_VERSION },
6212 { "type", required_argument, NULL, 't' },
6213 { "property", required_argument, NULL, 'p' },
6214 { "all", no_argument, NULL, 'a' },
6215 { "reverse", no_argument, NULL, ARG_REVERSE },
6216 { "after", no_argument, NULL, ARG_AFTER },
6217 { "before", no_argument, NULL, ARG_BEFORE },
6218 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
6219 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
6220 { "full", no_argument, NULL, 'l' },
6221 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
6222 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
6223 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
6224 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
6225 { "ignore-inhibitors", no_argument, NULL, 'i' },
6226 { "user", no_argument, NULL, ARG_USER },
6227 { "system", no_argument, NULL, ARG_SYSTEM },
6228 { "global", no_argument, NULL, ARG_GLOBAL },
6229 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
6230 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
6231 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
6232 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6233 { "quiet", no_argument, NULL, 'q' },
6234 { "root", required_argument, NULL, ARG_ROOT },
6235 { "force", no_argument, NULL, ARG_FORCE },
6236 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
6237 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
6238 { "signal", required_argument, NULL, 's' },
6239 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
6240 { "host", required_argument, NULL, 'H' },
6241 { "machine", required_argument, NULL, 'M' },
6242 { "runtime", no_argument, NULL, ARG_RUNTIME },
6243 { "lines", required_argument, NULL, 'n' },
6244 { "output", required_argument, NULL, 'o' },
6245 { "plain", no_argument, NULL, ARG_PLAIN },
6246 { "state", required_argument, NULL, ARG_STATE },
6247 { "recursive", no_argument, NULL, 'r' },
6248 { "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
6257 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
6266 puts(PACKAGE_STRING);
6267 puts(SYSTEMD_FEATURES);
6271 const char *word, *state;
6274 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6275 _cleanup_free_ char *type;
6277 type = strndup(word, size);
6281 if (streq(type, "help")) {
6286 if (unit_type_from_string(type) >= 0) {
6287 if (strv_push(&arg_types, type))
6293 /* It's much nicer to use --state= for
6294 * load states, but let's support this
6295 * in --types= too for compatibility
6296 * with old versions */
6297 if (unit_load_state_from_string(optarg) >= 0) {
6298 if (strv_push(&arg_states, type) < 0)
6304 log_error("Unknown unit type or load state '%s'.", type);
6305 log_info("Use -t help to see a list of allowed values.");
6313 /* Make sure that if the empty property list
6314 was specified, we won't show any properties. */
6315 if (isempty(optarg) && !arg_properties) {
6316 arg_properties = new0(char*, 1);
6317 if (!arg_properties)
6320 const char *word, *state;
6323 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6326 prop = strndup(word, size);
6330 if (strv_consume(&arg_properties, prop) < 0)
6335 /* If the user asked for a particular
6336 * property, show it to him, even if it is
6348 arg_dependency = DEPENDENCY_REVERSE;
6352 arg_dependency = DEPENDENCY_AFTER;
6356 arg_dependency = DEPENDENCY_BEFORE;
6359 case ARG_SHOW_TYPES:
6360 arg_show_types = true;
6364 arg_job_mode = optarg;
6368 arg_job_mode = "fail";
6371 case ARG_IRREVERSIBLE:
6372 arg_job_mode = "replace-irreversibly";
6375 case ARG_IGNORE_DEPENDENCIES:
6376 arg_job_mode = "ignore-dependencies";
6380 arg_scope = UNIT_FILE_USER;
6384 arg_scope = UNIT_FILE_SYSTEM;
6388 arg_scope = UNIT_FILE_GLOBAL;
6392 arg_no_block = true;
6396 arg_no_legend = true;
6400 arg_no_pager = true;
6416 if (strv_extend(&arg_states, "failed") < 0)
6434 arg_no_reload = true;
6438 arg_kill_who = optarg;
6442 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
6443 log_error("Failed to parse signal string %s.", optarg);
6448 case ARG_NO_ASK_PASSWORD:
6449 arg_ask_password = false;
6453 arg_transport = BUS_TRANSPORT_REMOTE;
6458 arg_transport = BUS_TRANSPORT_MACHINE;
6467 if (safe_atou(optarg, &arg_lines) < 0) {
6468 log_error("Failed to parse lines '%s'", optarg);
6474 arg_output = output_mode_from_string(optarg);
6475 if (arg_output < 0) {
6476 log_error("Unknown output '%s'.", optarg);
6482 arg_ignore_inhibitors = true;
6490 const char *word, *state;
6493 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6496 s = strndup(word, size);
6500 if (strv_consume(&arg_states, s) < 0)
6507 if (geteuid() != 0) {
6508 log_error("--recursive requires root privileges.");
6512 arg_recursive = true;
6515 case ARG_PRESET_MODE:
6517 arg_preset_mode = unit_file_preset_mode_from_string(optarg);
6518 if (arg_preset_mode < 0) {
6519 log_error("Failed to parse preset mode: %s.", optarg);
6529 assert_not_reached("Unhandled option");
6532 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
6533 log_error("Cannot access user instance remotely.");
6540 static int halt_parse_argv(int argc, char *argv[]) {
6549 static const struct option options[] = {
6550 { "help", no_argument, NULL, ARG_HELP },
6551 { "halt", no_argument, NULL, ARG_HALT },
6552 { "poweroff", no_argument, NULL, 'p' },
6553 { "reboot", no_argument, NULL, ARG_REBOOT },
6554 { "force", no_argument, NULL, 'f' },
6555 { "wtmp-only", no_argument, NULL, 'w' },
6556 { "no-wtmp", no_argument, NULL, 'd' },
6557 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6566 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
6567 if (runlevel == '0' || runlevel == '6')
6570 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
6578 arg_action = ACTION_HALT;
6582 if (arg_action != ACTION_REBOOT)
6583 arg_action = ACTION_POWEROFF;
6587 arg_action = ACTION_REBOOT;
6609 /* Compatibility nops */
6616 assert_not_reached("Unhandled option");
6619 if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
6620 r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL);
6623 } else if (optind < argc) {
6624 log_error("Too many arguments.");
6631 static int parse_time_spec(const char *t, usec_t *_u) {
6635 if (streq(t, "now"))
6637 else if (!strchr(t, ':')) {
6640 if (safe_atou64(t, &u) < 0)
6643 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
6652 hour = strtol(t, &e, 10);
6653 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
6656 minute = strtol(e+1, &e, 10);
6657 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
6660 n = now(CLOCK_REALTIME);
6661 s = (time_t) (n / USEC_PER_SEC);
6663 assert_se(localtime_r(&s, &tm));
6665 tm.tm_hour = (int) hour;
6666 tm.tm_min = (int) minute;
6669 assert_se(s = mktime(&tm));
6671 *_u = (usec_t) s * USEC_PER_SEC;
6674 *_u += USEC_PER_DAY;
6680 static int shutdown_parse_argv(int argc, char *argv[]) {
6687 static const struct option options[] = {
6688 { "help", no_argument, NULL, ARG_HELP },
6689 { "halt", no_argument, NULL, 'H' },
6690 { "poweroff", no_argument, NULL, 'P' },
6691 { "reboot", no_argument, NULL, 'r' },
6692 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
6693 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6702 while ((c = getopt_long(argc, argv, "HPrhkKt:afFc", options, NULL)) >= 0)
6710 arg_action = ACTION_HALT;
6714 arg_action = ACTION_POWEROFF;
6719 arg_action = ACTION_KEXEC;
6721 arg_action = ACTION_REBOOT;
6725 arg_action = ACTION_KEXEC;
6729 if (arg_action != ACTION_HALT)
6730 arg_action = ACTION_POWEROFF;
6745 /* Compatibility nops */
6749 arg_action = ACTION_CANCEL_SHUTDOWN;
6756 assert_not_reached("Unhandled option");
6759 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
6760 r = parse_time_spec(argv[optind], &arg_when);
6762 log_error("Failed to parse time specification: %s", argv[optind]);
6766 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
6768 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
6769 /* No time argument for shutdown cancel */
6770 arg_wall = argv + optind;
6771 else if (argc > optind + 1)
6772 /* We skip the time argument */
6773 arg_wall = argv + optind + 1;
6780 static int telinit_parse_argv(int argc, char *argv[]) {
6787 static const struct option options[] = {
6788 { "help", no_argument, NULL, ARG_HELP },
6789 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6793 static const struct {
6797 { '0', ACTION_POWEROFF },
6798 { '6', ACTION_REBOOT },
6799 { '1', ACTION_RESCUE },
6800 { '2', ACTION_RUNLEVEL2 },
6801 { '3', ACTION_RUNLEVEL3 },
6802 { '4', ACTION_RUNLEVEL4 },
6803 { '5', ACTION_RUNLEVEL5 },
6804 { 's', ACTION_RESCUE },
6805 { 'S', ACTION_RESCUE },
6806 { 'q', ACTION_RELOAD },
6807 { 'Q', ACTION_RELOAD },
6808 { 'u', ACTION_REEXEC },
6809 { 'U', ACTION_REEXEC }
6818 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6833 assert_not_reached("Unhandled option");
6836 if (optind >= argc) {
6837 log_error("%s: required argument missing.",
6838 program_invocation_short_name);
6842 if (optind + 1 < argc) {
6843 log_error("Too many arguments.");
6847 if (strlen(argv[optind]) != 1) {
6848 log_error("Expected single character argument.");
6852 for (i = 0; i < ELEMENTSOF(table); i++)
6853 if (table[i].from == argv[optind][0])
6856 if (i >= ELEMENTSOF(table)) {
6857 log_error("Unknown command '%s'.", argv[optind]);
6861 arg_action = table[i].to;
6868 static int runlevel_parse_argv(int argc, char *argv[]) {
6874 static const struct option options[] = {
6875 { "help", no_argument, NULL, ARG_HELP },
6884 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6895 assert_not_reached("Unhandled option");
6898 if (optind < argc) {
6899 log_error("Too many arguments.");
6906 static int parse_argv(int argc, char *argv[]) {
6910 if (program_invocation_short_name) {
6912 if (strstr(program_invocation_short_name, "halt")) {
6913 arg_action = ACTION_HALT;
6914 return halt_parse_argv(argc, argv);
6915 } else if (strstr(program_invocation_short_name, "poweroff")) {
6916 arg_action = ACTION_POWEROFF;
6917 return halt_parse_argv(argc, argv);
6918 } else if (strstr(program_invocation_short_name, "reboot")) {
6920 arg_action = ACTION_KEXEC;
6922 arg_action = ACTION_REBOOT;
6923 return halt_parse_argv(argc, argv);
6924 } else if (strstr(program_invocation_short_name, "shutdown")) {
6925 arg_action = ACTION_POWEROFF;
6926 return shutdown_parse_argv(argc, argv);
6927 } else if (strstr(program_invocation_short_name, "init")) {
6929 if (sd_booted() > 0) {
6930 arg_action = _ACTION_INVALID;
6931 return telinit_parse_argv(argc, argv);
6933 /* Hmm, so some other init system is
6934 * running, we need to forward this
6935 * request to it. For now we simply
6936 * guess that it is Upstart. */
6938 execv(TELINIT, argv);
6940 log_error("Couldn't find an alternative telinit implementation to spawn.");
6944 } else if (strstr(program_invocation_short_name, "runlevel")) {
6945 arg_action = ACTION_RUNLEVEL;
6946 return runlevel_parse_argv(argc, argv);
6950 arg_action = ACTION_SYSTEMCTL;
6951 return systemctl_parse_argv(argc, argv);
6954 _pure_ static int action_to_runlevel(void) {
6956 static const char table[_ACTION_MAX] = {
6957 [ACTION_HALT] = '0',
6958 [ACTION_POWEROFF] = '0',
6959 [ACTION_REBOOT] = '6',
6960 [ACTION_RUNLEVEL2] = '2',
6961 [ACTION_RUNLEVEL3] = '3',
6962 [ACTION_RUNLEVEL4] = '4',
6963 [ACTION_RUNLEVEL5] = '5',
6964 [ACTION_RESCUE] = '1'
6967 assert(arg_action < _ACTION_MAX);
6969 return table[arg_action];
6972 static int talk_initctl(void) {
6974 struct init_request request = {
6975 .magic = INIT_MAGIC,
6977 .cmd = INIT_CMD_RUNLVL
6980 _cleanup_close_ int fd = -1;
6984 rl = action_to_runlevel();
6988 request.runlevel = rl;
6990 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
6992 if (errno == ENOENT)
6995 log_error_errno(errno, "Failed to open "INIT_FIFO": %m");
6999 r = loop_write(fd, &request, sizeof(request), false);
7001 return log_error_errno(r, "Failed to write to "INIT_FIFO": %m");
7006 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
7008 static const struct {
7016 int (* const dispatch)(sd_bus *bus, char **args);
7022 { "list-units", MORE, 0, list_units },
7023 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
7024 { "list-sockets", MORE, 1, list_sockets },
7025 { "list-timers", MORE, 1, list_timers },
7026 { "list-jobs", MORE, 1, list_jobs },
7027 { "list-machines", MORE, 1, list_machines },
7028 { "clear-jobs", EQUAL, 1, daemon_reload },
7029 { "cancel", MORE, 2, cancel_job },
7030 { "start", MORE, 2, start_unit },
7031 { "stop", MORE, 2, start_unit },
7032 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
7033 { "reload", MORE, 2, start_unit },
7034 { "restart", MORE, 2, start_unit },
7035 { "try-restart", MORE, 2, start_unit },
7036 { "reload-or-restart", MORE, 2, start_unit },
7037 { "reload-or-try-restart", MORE, 2, start_unit },
7038 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
7039 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
7040 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
7041 { "isolate", EQUAL, 2, start_unit },
7042 { "kill", MORE, 2, kill_unit },
7043 { "is-active", MORE, 2, check_unit_active },
7044 { "check", MORE, 2, check_unit_active },
7045 { "is-failed", MORE, 2, check_unit_failed },
7046 { "show", MORE, 1, show },
7047 { "cat", MORE, 2, cat, NOBUS },
7048 { "status", MORE, 1, show },
7049 { "help", MORE, 2, show },
7050 { "snapshot", LESS, 2, snapshot },
7051 { "delete", MORE, 2, delete_snapshot },
7052 { "daemon-reload", EQUAL, 1, daemon_reload },
7053 { "daemon-reexec", EQUAL, 1, daemon_reload },
7054 { "show-environment", EQUAL, 1, show_environment },
7055 { "set-environment", MORE, 2, set_environment },
7056 { "unset-environment", MORE, 2, set_environment },
7057 { "import-environment", MORE, 1, import_environment},
7058 { "halt", EQUAL, 1, start_special, FORCE },
7059 { "poweroff", EQUAL, 1, start_special, FORCE },
7060 { "reboot", EQUAL, 1, start_special, FORCE },
7061 { "kexec", EQUAL, 1, start_special },
7062 { "suspend", EQUAL, 1, start_special },
7063 { "hibernate", EQUAL, 1, start_special },
7064 { "hybrid-sleep", EQUAL, 1, start_special },
7065 { "default", EQUAL, 1, start_special },
7066 { "rescue", EQUAL, 1, start_special },
7067 { "emergency", EQUAL, 1, start_special },
7068 { "exit", EQUAL, 1, start_special },
7069 { "reset-failed", MORE, 1, reset_failed },
7070 { "enable", MORE, 2, enable_unit, NOBUS },
7071 { "disable", MORE, 2, enable_unit, NOBUS },
7072 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
7073 { "reenable", MORE, 2, enable_unit, NOBUS },
7074 { "preset", MORE, 2, enable_unit, NOBUS },
7075 { "preset-all", EQUAL, 1, preset_all, NOBUS },
7076 { "mask", MORE, 2, enable_unit, NOBUS },
7077 { "unmask", MORE, 2, enable_unit, NOBUS },
7078 { "link", MORE, 2, enable_unit, NOBUS },
7079 { "switch-root", MORE, 2, switch_root },
7080 { "list-dependencies", LESS, 2, list_dependencies },
7081 { "set-default", EQUAL, 2, set_default, NOBUS },
7082 { "get-default", EQUAL, 1, get_default, NOBUS },
7083 { "set-property", MORE, 3, set_property },
7084 { "is-system-running", EQUAL, 1, is_system_running },
7085 { "add-wants", MORE, 3, add_dependency, NOBUS },
7086 { "add-requires", MORE, 3, add_dependency, NOBUS },
7087 { "edit", MORE, 2, edit, NOBUS },
7096 left = argc - optind;
7098 /* Special rule: no arguments (left == 0) means "list-units" */
7100 if (streq(argv[optind], "help") && !argv[optind+1]) {
7101 log_error("This command expects one or more "
7102 "unit names. Did you mean --help?");
7106 for (; verb->verb; verb++)
7107 if (streq(argv[optind], verb->verb))
7110 log_error("Unknown operation '%s'.", argv[optind]);
7115 switch (verb->argc_cmp) {
7118 if (left != verb->argc) {
7119 log_error("Invalid number of arguments.");
7126 if (left < verb->argc) {
7127 log_error("Too few arguments.");
7134 if (left > verb->argc) {
7135 log_error("Too many arguments.");
7142 assert_not_reached("Unknown comparison operator.");
7145 /* Require a bus connection for all operations but
7147 if (verb->bus == NOBUS) {
7148 if (!bus && !avoid_bus()) {
7149 log_error_errno(bus_error, "Failed to get D-Bus connection: %m");
7154 if (running_in_chroot() > 0) {
7155 log_info("Running in chroot, ignoring request.");
7159 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
7160 log_error_errno(bus_error, "Failed to get D-Bus connection: %m");
7165 return verb->dispatch(bus, argv + optind);
7168 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
7170 struct sd_shutdown_command c = {
7177 union sockaddr_union sockaddr = {
7178 .un.sun_family = AF_UNIX,
7179 .un.sun_path = "/run/systemd/shutdownd",
7182 struct iovec iovec[2] = {{
7183 .iov_base = (char*) &c,
7184 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
7187 struct msghdr msghdr = {
7188 .msg_name = &sockaddr,
7189 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
7190 + strlen("/run/systemd/shutdownd"),
7195 _cleanup_close_ int fd;
7197 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
7201 if (!isempty(message)) {
7202 iovec[1].iov_base = (char*) message;
7203 iovec[1].iov_len = strlen(message);
7204 msghdr.msg_iovlen++;
7207 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
7213 static int reload_with_fallback(sd_bus *bus) {
7216 /* First, try systemd via D-Bus. */
7217 if (daemon_reload(bus, NULL) >= 0)
7221 /* Nothing else worked, so let's try signals */
7222 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
7224 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0)
7225 return log_error_errno(errno, "kill() failed: %m");
7230 static int start_with_fallback(sd_bus *bus) {
7233 /* First, try systemd via D-Bus. */
7234 if (start_unit(bus, NULL) >= 0)
7238 /* Nothing else worked, so let's try
7240 if (talk_initctl() > 0)
7243 log_error("Failed to talk to init daemon.");
7247 warn_wall(arg_action);
7251 static int halt_now(enum action a) {
7253 /* The kernel will automaticall flush ATA disks and suchlike
7254 * on reboot(), but the file systems need to be synce'd
7255 * explicitly in advance. */
7258 /* Make sure C-A-D is handled by the kernel from this point
7260 reboot(RB_ENABLE_CAD);
7265 log_info("Halting.");
7266 reboot(RB_HALT_SYSTEM);
7269 case ACTION_POWEROFF:
7270 log_info("Powering off.");
7271 reboot(RB_POWER_OFF);
7274 case ACTION_REBOOT: {
7275 _cleanup_free_ char *param = NULL;
7277 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
7278 log_info("Rebooting with argument '%s'.", param);
7279 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
7280 LINUX_REBOOT_CMD_RESTART2, param);
7283 log_info("Rebooting.");
7284 reboot(RB_AUTOBOOT);
7289 assert_not_reached("Unknown action.");
7293 static int halt_main(sd_bus *bus) {
7296 r = check_inhibitors(bus, arg_action);
7300 if (geteuid() != 0) {
7301 /* Try logind if we are a normal user and no special
7302 * mode applies. Maybe PolicyKit allows us to shutdown
7305 if (arg_when <= 0 &&
7308 (arg_action == ACTION_POWEROFF ||
7309 arg_action == ACTION_REBOOT)) {
7310 r = reboot_with_logind(bus, arg_action);
7315 log_error("Must be root.");
7320 _cleanup_free_ char *m;
7322 m = strv_join(arg_wall, " ");
7326 r = send_shutdownd(arg_when,
7327 arg_action == ACTION_HALT ? 'H' :
7328 arg_action == ACTION_POWEROFF ? 'P' :
7329 arg_action == ACTION_KEXEC ? 'K' :
7336 log_warning_errno(r, "Failed to talk to shutdownd, proceeding with immediate shutdown: %m");
7338 char date[FORMAT_TIMESTAMP_MAX];
7340 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
7341 format_timestamp(date, sizeof(date), arg_when));
7346 if (!arg_dry && !arg_force)
7347 return start_with_fallback(bus);
7350 if (sd_booted() > 0)
7351 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7353 r = utmp_put_shutdown();
7355 log_warning_errno(r, "Failed to write utmp record: %m");
7362 r = halt_now(arg_action);
7363 log_error_errno(r, "Failed to reboot: %m");
7368 static int runlevel_main(void) {
7369 int r, runlevel, previous;
7371 r = utmp_get_runlevel(&runlevel, &previous);
7378 previous <= 0 ? 'N' : previous,
7379 runlevel <= 0 ? 'N' : runlevel);
7384 int main(int argc, char*argv[]) {
7385 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
7388 setlocale(LC_ALL, "");
7389 log_parse_environment();
7392 /* Explicitly not on_tty() to avoid setting cached value.
7393 * This becomes relevant for piping output which might be
7395 original_stdout_is_tty = isatty(STDOUT_FILENO);
7397 r = parse_argv(argc, argv);
7401 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
7402 * let's shortcut this */
7403 if (arg_action == ACTION_RUNLEVEL) {
7404 r = runlevel_main();
7408 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
7409 log_info("Running in chroot, ignoring request.");
7415 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
7417 /* systemctl_main() will print an error message for the bus
7418 * connection, but only if it needs to */
7420 switch (arg_action) {
7422 case ACTION_SYSTEMCTL:
7423 r = systemctl_main(bus, argc, argv, r);
7427 case ACTION_POWEROFF:
7433 case ACTION_RUNLEVEL2:
7434 case ACTION_RUNLEVEL3:
7435 case ACTION_RUNLEVEL4:
7436 case ACTION_RUNLEVEL5:
7438 case ACTION_EMERGENCY:
7439 case ACTION_DEFAULT:
7440 r = start_with_fallback(bus);
7445 r = reload_with_fallback(bus);
7448 case ACTION_CANCEL_SHUTDOWN: {
7449 _cleanup_free_ char *m = NULL;
7452 m = strv_join(arg_wall, " ");
7459 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
7461 log_warning_errno(r, "Failed to talk to shutdownd, shutdown hasn't been cancelled: %m");
7465 case ACTION_RUNLEVEL:
7466 case _ACTION_INVALID:
7468 assert_not_reached("Unknown action");
7473 ask_password_agent_close();
7474 polkit_agent_close();
7476 strv_free(arg_types);
7477 strv_free(arg_states);
7478 strv_free(arg_properties);
7480 return r < 0 ? EXIT_FAILURE : r;