1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Marc-Antoine Perennou
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/reboot.h>
24 #include <linux/reboot.h>
25 #include <sys/syscall.h>
32 #include <sys/ioctl.h>
36 #include <sys/socket.h>
39 #include <sys/prctl.h>
42 #include "sd-daemon.h"
43 #include "sd-shutdown.h"
50 #include "utmp-wtmp.h"
53 #include "path-util.h"
55 #include "cgroup-show.h"
56 #include "cgroup-util.h"
58 #include "path-lookup.h"
59 #include "conf-parser.h"
60 #include "exit-status.h"
62 #include "unit-name.h"
64 #include "spawn-ask-password-agent.h"
65 #include "spawn-polkit-agent.h"
67 #include "logs-show.h"
68 #include "socket-util.h"
72 #include "bus-message.h"
73 #include "bus-error.h"
74 #include "bus-errors.h"
76 static char **arg_types = NULL;
77 static char **arg_states = NULL;
78 static char **arg_properties = NULL;
79 static bool arg_all = false;
80 static bool original_stdout_is_tty;
81 static enum dependency {
87 } arg_dependency = DEPENDENCY_FORWARD;
88 static const char *arg_job_mode = "replace";
89 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
90 static bool arg_no_block = false;
91 static bool arg_no_legend = false;
92 static bool arg_no_pager = false;
93 static bool arg_no_wtmp = false;
94 static bool arg_no_wall = false;
95 static bool arg_no_reload = false;
96 static bool arg_show_types = false;
97 static bool arg_ignore_inhibitors = false;
98 static bool arg_dry = false;
99 static bool arg_quiet = false;
100 static bool arg_full = false;
101 static int arg_force = 0;
102 static bool arg_ask_password = true;
103 static bool arg_runtime = false;
104 static char **arg_wall = NULL;
105 static const char *arg_kill_who = NULL;
106 static int arg_signal = SIGTERM;
107 static const char *arg_root = NULL;
108 static usec_t arg_when = 0;
130 ACTION_CANCEL_SHUTDOWN,
132 } arg_action = ACTION_SYSTEMCTL;
133 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
134 static char *arg_host = NULL;
135 static unsigned arg_lines = 10;
136 static OutputMode arg_output = OUTPUT_SHORT;
137 static bool arg_plain = false;
138 static const struct {
142 { "start", "StartUnit" },
143 { "stop", "StopUnit" },
144 { "condstop", "StopUnit" },
145 { "reload", "ReloadUnit" },
146 { "restart", "RestartUnit" },
147 { "try-restart", "TryRestartUnit" },
148 { "condrestart", "TryRestartUnit" },
149 { "reload-or-restart", "ReloadOrRestartUnit" },
150 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
151 { "condreload", "ReloadOrTryRestartUnit" },
152 { "force-reload", "ReloadOrTryRestartUnit" }
155 static int daemon_reload(sd_bus *bus, char **args);
156 static int halt_now(enum action a);
158 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet);
160 static char** strv_skip_first(char **strv) {
161 if (strv_length(strv) > 0)
166 static void pager_open_if_enabled(void) {
174 static void ask_password_agent_open_if_enabled(void) {
176 /* Open the password agent as a child process if necessary */
178 if (!arg_ask_password)
181 if (arg_scope != UNIT_FILE_SYSTEM)
184 if (arg_transport != BUS_TRANSPORT_LOCAL)
187 ask_password_agent_open();
191 static void polkit_agent_open_if_enabled(void) {
193 /* Open the polkit agent as a child process if necessary */
195 if (!arg_ask_password)
198 if (arg_scope != UNIT_FILE_SYSTEM)
201 if (arg_transport != BUS_TRANSPORT_LOCAL)
208 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
211 if (!sd_bus_error_is_set(error))
214 if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) ||
215 sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
216 sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
217 sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
218 return EXIT_NOPERMISSION;
220 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
221 return EXIT_NOTINSTALLED;
223 if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
224 sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED))
225 return EXIT_NOTIMPLEMENTED;
227 if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
228 return EXIT_NOTCONFIGURED;
236 static void warn_wall(enum action a) {
237 static const char *table[_ACTION_MAX] = {
238 [ACTION_HALT] = "The system is going down for system halt NOW!",
239 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
240 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
241 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
242 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
243 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
244 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
251 _cleanup_free_ char *p;
253 p = strv_join(arg_wall, " ");
268 utmp_wall(table[a], NULL);
271 static bool avoid_bus(void) {
273 if (running_in_chroot() > 0)
276 if (sd_booted() <= 0)
279 if (!isempty(arg_root))
282 if (arg_scope == UNIT_FILE_GLOBAL)
288 static int compare_unit_info(const void *a, const void *b) {
289 const UnitInfo *u = a, *v = b;
292 d1 = strrchr(u->id, '.');
293 d2 = strrchr(v->id, '.');
298 r = strcasecmp(d1, d2);
303 return strcasecmp(u->id, v->id);
306 static bool output_show_unit(const UnitInfo *u, char **patterns) {
309 if (!strv_isempty(arg_states))
311 strv_contains(arg_states, u->load_state) ||
312 strv_contains(arg_states, u->sub_state) ||
313 strv_contains(arg_states, u->active_state);
315 if (!strv_isempty(patterns)) {
318 STRV_FOREACH(pattern, patterns)
319 if (fnmatch(*pattern, u->id, FNM_NOESCAPE) == 0)
324 return (!arg_types || ((dot = strrchr(u->id, '.')) &&
325 strv_find(arg_types, dot+1))) &&
326 (arg_all || !(streq(u->active_state, "inactive")
327 || u->following[0]) || u->job_id > 0);
330 static void output_units_list(const UnitInfo *unit_infos, unsigned c) {
331 unsigned id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
333 unsigned n_shown = 0;
336 max_id_len = sizeof("UNIT")-1;
337 load_len = sizeof("LOAD")-1;
338 active_len = sizeof("ACTIVE")-1;
339 sub_len = sizeof("SUB")-1;
340 job_len = sizeof("JOB")-1;
343 for (u = unit_infos; u < unit_infos + c; u++) {
344 max_id_len = MAX(max_id_len, strlen(u->id));
345 load_len = MAX(load_len, strlen(u->load_state));
346 active_len = MAX(active_len, strlen(u->active_state));
347 sub_len = MAX(sub_len, strlen(u->sub_state));
349 if (u->job_id != 0) {
350 job_len = MAX(job_len, strlen(u->job_type));
355 if (!arg_full && original_stdout_is_tty) {
358 id_len = MIN(max_id_len, 25u);
359 basic_len = 5 + id_len + 5 + active_len + sub_len;
362 basic_len += job_len + 1;
364 if (basic_len < (unsigned) columns()) {
365 unsigned extra_len, incr;
366 extra_len = columns() - basic_len;
368 /* Either UNIT already got 25, or is fully satisfied.
369 * Grant up to 25 to DESC now. */
370 incr = MIN(extra_len, 25u);
374 /* split the remaining space between UNIT and DESC,
375 * but do not give UNIT more than it needs. */
377 incr = MIN(extra_len / 2, max_id_len - id_len);
379 desc_len += extra_len - incr;
385 for (u = unit_infos; u < unit_infos + c; u++) {
386 _cleanup_free_ char *e = NULL;
387 const char *on_loaded, *off_loaded, *on = "";
388 const char *on_active, *off_active, *off = "";
390 if (!n_shown && !arg_no_legend) {
391 printf("%-*s %-*s %-*s %-*s ",
394 active_len, "ACTIVE",
398 printf("%-*s ", job_len, "JOB");
400 if (!arg_full && arg_no_pager)
401 printf("%.*s\n", desc_len, "DESCRIPTION");
403 printf("%s\n", "DESCRIPTION");
408 if (streq(u->load_state, "error") ||
409 streq(u->load_state, "not-found")) {
410 on_loaded = on = ansi_highlight_red();
411 off_loaded = off = ansi_highlight_off();
413 on_loaded = off_loaded = "";
415 if (streq(u->active_state, "failed")) {
416 on_active = on = ansi_highlight_red();
417 off_active = off = ansi_highlight_off();
419 on_active = off_active = "";
421 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
423 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
424 on, id_len, e ? e : u->id, off,
425 on_loaded, load_len, u->load_state, off_loaded,
426 on_active, active_len, u->active_state,
427 sub_len, u->sub_state, off_active,
428 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
431 printf("%.*s\n", desc_len, u->description);
433 printf("%s\n", u->description);
436 if (!arg_no_legend) {
437 const char *on, *off;
440 puts("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
441 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
442 "SUB = The low-level unit activation state, values depend on unit type.");
443 puts(job_count ? "JOB = Pending job for the unit.\n" : "");
444 on = ansi_highlight();
445 off = ansi_highlight_off();
447 on = ansi_highlight_red();
448 off = ansi_highlight_off();
452 printf("%s%u loaded units listed.%s\n"
453 "To show all installed unit files use 'systemctl list-unit-files'.\n",
456 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
457 "To show all installed unit files use 'systemctl list-unit-files'.\n",
462 static int get_unit_list(
464 sd_bus_message **_reply,
465 UnitInfo **_unit_infos,
468 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
469 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
470 _cleanup_free_ UnitInfo *unit_infos = NULL;
479 r = sd_bus_call_method(
481 "org.freedesktop.systemd1",
482 "/org/freedesktop/systemd1",
483 "org.freedesktop.systemd1.Manager",
489 log_error("Failed to list units: %s", bus_error_message(&error, r));
493 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
495 return bus_log_parse_error(r);
497 while ((r = bus_parse_unit_info(reply, &u)) > 0) {
498 if (!output_show_unit(&u, patterns))
501 if (!GREEDY_REALLOC(unit_infos, size, c+1))
507 return bus_log_parse_error(r);
509 r = sd_bus_message_exit_container(reply);
511 return bus_log_parse_error(r);
516 *_unit_infos = unit_infos;
522 static int list_units(sd_bus *bus, char **args) {
523 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
524 _cleanup_free_ UnitInfo *unit_infos = NULL;
527 pager_open_if_enabled();
529 r = get_unit_list(bus, &reply, &unit_infos, strv_skip_first(args));
533 qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
534 output_units_list(unit_infos, r);
539 static int get_triggered_units(
544 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
547 r = sd_bus_get_property_strv(
549 "org.freedesktop.systemd1",
551 "org.freedesktop.systemd1.Unit",
557 log_error("Failed to determine triggers: %s", bus_error_message(&error, r));
562 static int get_listening(
564 const char* unit_path,
567 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
568 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
569 const char *type, *path;
572 r = sd_bus_get_property(
574 "org.freedesktop.systemd1",
576 "org.freedesktop.systemd1.Socket",
582 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r));
586 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
588 return bus_log_parse_error(r);
590 while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
592 r = strv_extend(listening, type);
596 r = strv_extend(listening, path);
603 return bus_log_parse_error(r);
605 r = sd_bus_message_exit_container(reply);
607 return bus_log_parse_error(r);
618 /* Note: triggered is a list here, although it almost certainly
619 * will always be one unit. Nevertheless, dbus API allows for multiple
620 * values, so let's follow that.*/
623 /* The strv above is shared. free is set only in the first one. */
627 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
633 o = strcmp(a->path, b->path);
635 o = strcmp(a->type, b->type);
640 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
641 struct socket_info *s;
642 unsigned pathlen = sizeof("LISTEN") - 1,
643 typelen = (sizeof("TYPE") - 1) * arg_show_types,
644 socklen = sizeof("UNIT") - 1,
645 servlen = sizeof("ACTIVATES") - 1;
646 const char *on, *off;
648 for (s = socket_infos; s < socket_infos + cs; s++) {
652 socklen = MAX(socklen, strlen(s->id));
654 typelen = MAX(typelen, strlen(s->type));
655 pathlen = MAX(pathlen, strlen(s->path));
657 STRV_FOREACH(a, s->triggered)
658 tmp += strlen(*a) + 2*(a != s->triggered);
659 servlen = MAX(servlen, tmp);
664 printf("%-*s %-*.*s%-*s %s\n",
666 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
670 for (s = socket_infos; s < socket_infos + cs; s++) {
674 printf("%-*s %-*s %-*s",
675 pathlen, s->path, typelen, s->type, socklen, s->id);
678 pathlen, s->path, socklen, s->id);
679 STRV_FOREACH(a, s->triggered)
681 a == s->triggered ? "" : ",", *a);
685 on = ansi_highlight();
686 off = ansi_highlight_off();
690 on = ansi_highlight_red();
691 off = ansi_highlight_off();
694 if (!arg_no_legend) {
695 printf("%s%u sockets listed.%s\n", on, cs, off);
697 printf("Pass --all to see loaded but inactive sockets, too.\n");
703 static int list_sockets(sd_bus *bus, char **args) {
704 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
705 _cleanup_free_ UnitInfo *unit_infos = NULL;
706 _cleanup_free_ struct socket_info *socket_infos = NULL;
708 struct socket_info *s;
713 pager_open_if_enabled();
715 n = get_unit_list(bus, &reply, &unit_infos, strv_skip_first(args));
719 for (u = unit_infos; u < unit_infos + n; u++) {
720 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
723 if (!endswith(u->id, ".socket"))
726 r = get_triggered_units(bus, u->unit_path, &triggered);
730 c = get_listening(bus, u->unit_path, &listening);
736 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
741 for (i = 0; i < c; i++)
742 socket_infos[cs + i] = (struct socket_info) {
744 .type = listening[i*2],
745 .path = listening[i*2 + 1],
746 .triggered = triggered,
747 .own_triggered = i==0,
750 /* from this point on we will cleanup those socket_infos */
753 listening = triggered = NULL; /* avoid cleanup */
756 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
757 (__compar_fn_t) socket_info_compare);
759 output_sockets_list(socket_infos, cs);
762 assert(cs == 0 || socket_infos);
763 for (s = socket_infos; s < socket_infos + cs; s++) {
766 if (s->own_triggered)
767 strv_free(s->triggered);
773 static int get_next_elapse(
776 dual_timestamp *next) {
778 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
786 r = sd_bus_get_property_trivial(
788 "org.freedesktop.systemd1",
790 "org.freedesktop.systemd1.Timer",
791 "NextElapseUSecMonotonic",
796 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
800 r = sd_bus_get_property_trivial(
802 "org.freedesktop.systemd1",
804 "org.freedesktop.systemd1.Timer",
805 "NextElapseUSecRealtime",
810 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
824 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
828 if (a->next_elapse < b->next_elapse)
830 if (a->next_elapse > b->next_elapse)
833 return strcmp(a->id, b->id);
836 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
837 struct timer_info *t;
839 nextlen = sizeof("NEXT") - 1,
840 leftlen = sizeof("LEFT") - 1,
841 unitlen = sizeof("UNIT") - 1,
842 activatelen = sizeof("ACTIVATES") - 1;
844 const char *on, *off;
846 assert(timer_infos || n == 0);
848 for (t = timer_infos; t < timer_infos + n; t++) {
852 if (t->next_elapse > 0) {
853 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
855 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
856 nextlen = MAX(nextlen, strlen(tstamp) + 1);
858 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
859 leftlen = MAX(leftlen, strlen(trel));
862 unitlen = MAX(unitlen, strlen(t->id));
864 STRV_FOREACH(a, t->triggered)
865 ul += strlen(*a) + 2*(a != t->triggered);
866 activatelen = MAX(activatelen, ul);
871 printf("%-*s %-*s %-*s %s\n",
877 for (t = timer_infos; t < timer_infos + n; t++) {
878 char tstamp[FORMAT_TIMESTAMP_MAX] = "n/a", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
881 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
882 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
884 printf("%-*s %-*s %-*s",
885 nextlen, tstamp, leftlen, trel, unitlen, t->id);
887 STRV_FOREACH(a, t->triggered)
889 a == t->triggered ? "" : ",", *a);
893 on = ansi_highlight();
894 off = ansi_highlight_off();
898 on = ansi_highlight_red();
899 off = ansi_highlight_off();
902 if (!arg_no_legend) {
903 printf("%s%u timers listed.%s\n", on, n, off);
905 printf("Pass --all to see loaded but inactive timers, too.\n");
911 static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
917 if (next->monotonic != (usec_t) -1 && next->monotonic > 0) {
920 if (next->monotonic > nw->monotonic)
921 converted = nw->realtime + (next->monotonic - nw->monotonic);
923 converted = nw->realtime - (nw->monotonic - next->monotonic);
925 if (next->realtime != (usec_t) -1 && next->realtime > 0)
926 next_elapse = MIN(converted, next->realtime);
928 next_elapse = converted;
931 next_elapse = next->realtime;
936 static int list_timers(sd_bus *bus, char **args) {
938 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
939 _cleanup_free_ struct timer_info *timer_infos = NULL;
940 _cleanup_free_ UnitInfo *unit_infos = NULL;
941 struct timer_info *t;
948 pager_open_if_enabled();
950 n = get_unit_list(bus, &reply, &unit_infos, strv_skip_first(args));
954 dual_timestamp_get(&nw);
956 for (u = unit_infos; u < unit_infos + n; u++) {
957 _cleanup_strv_free_ char **triggered = NULL;
958 dual_timestamp next = {};
961 if (!endswith(u->id, ".timer"))
964 r = get_triggered_units(bus, u->unit_path, &triggered);
968 r = get_next_elapse(bus, u->unit_path, &next);
972 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
977 m = calc_next_elapse(&nw, &next);
979 timer_infos[c++] = (struct timer_info) {
982 .triggered = triggered,
985 triggered = NULL; /* avoid cleanup */
988 qsort_safe(timer_infos, c, sizeof(struct timer_info),
989 (__compar_fn_t) timer_info_compare);
991 output_timers_list(timer_infos, c);
994 for (t = timer_infos; t < timer_infos + c; t++)
995 strv_free(t->triggered);
1000 static int compare_unit_file_list(const void *a, const void *b) {
1001 const char *d1, *d2;
1002 const UnitFileList *u = a, *v = b;
1004 d1 = strrchr(u->path, '.');
1005 d2 = strrchr(v->path, '.');
1010 r = strcasecmp(d1, d2);
1015 return strcasecmp(basename(u->path), basename(v->path));
1018 static bool output_show_unit_file(const UnitFileList *u, char **patterns) {
1021 if (!strv_isempty(patterns)) {
1024 STRV_FOREACH(pattern, patterns)
1025 if (fnmatch(*pattern, basename(u->path), FNM_NOESCAPE) == 0)
1030 return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
1033 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
1034 unsigned max_id_len, id_cols, state_cols;
1035 const UnitFileList *u;
1037 max_id_len = sizeof("UNIT FILE")-1;
1038 state_cols = sizeof("STATE")-1;
1040 for (u = units; u < units + c; u++) {
1041 max_id_len = MAX(max_id_len, strlen(basename(u->path)));
1042 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1046 unsigned basic_cols;
1048 id_cols = MIN(max_id_len, 25u);
1049 basic_cols = 1 + id_cols + state_cols;
1050 if (basic_cols < (unsigned) columns())
1051 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1053 id_cols = max_id_len;
1056 printf("%-*s %-*s\n",
1057 id_cols, "UNIT FILE",
1058 state_cols, "STATE");
1060 for (u = units; u < units + c; u++) {
1061 _cleanup_free_ char *e = NULL;
1062 const char *on, *off;
1065 if (u->state == UNIT_FILE_MASKED ||
1066 u->state == UNIT_FILE_MASKED_RUNTIME ||
1067 u->state == UNIT_FILE_DISABLED ||
1068 u->state == UNIT_FILE_INVALID) {
1069 on = ansi_highlight_red();
1070 off = ansi_highlight_off();
1071 } else if (u->state == UNIT_FILE_ENABLED) {
1072 on = ansi_highlight_green();
1073 off = ansi_highlight_off();
1077 id = basename(u->path);
1079 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1081 printf("%-*s %s%-*s%s\n",
1082 id_cols, e ? e : id,
1083 on, state_cols, unit_file_state_to_string(u->state), off);
1087 printf("\n%u unit files listed.\n", c);
1090 static int list_unit_files(sd_bus *bus, char **args) {
1091 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1092 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1093 _cleanup_free_ UnitFileList *units = NULL;
1101 pager_open_if_enabled();
1109 h = hashmap_new(string_hash_func, string_compare_func);
1113 r = unit_file_get_list(arg_scope, arg_root, h);
1115 unit_file_list_free(h);
1116 log_error("Failed to get unit file list: %s", strerror(-r));
1120 n_units = hashmap_size(h);
1121 units = new(UnitFileList, n_units);
1123 unit_file_list_free(h);
1127 HASHMAP_FOREACH(u, h, i) {
1128 if (!output_show_unit_file(u, strv_skip_first(args)))
1135 assert(c <= n_units);
1138 r = sd_bus_call_method(
1140 "org.freedesktop.systemd1",
1141 "/org/freedesktop/systemd1",
1142 "org.freedesktop.systemd1.Manager",
1148 log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1152 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1154 return bus_log_parse_error(r);
1156 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1158 if (!GREEDY_REALLOC(units, size, c + 1))
1161 units[c] = (struct UnitFileList) {
1163 unit_file_state_from_string(state)
1166 if (output_show_unit_file(&units[c], strv_skip_first(args)))
1171 return bus_log_parse_error(r);
1173 r = sd_bus_message_exit_container(reply);
1175 return bus_log_parse_error(r);
1179 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
1180 output_unit_file_list(units, c);
1184 for (unit = units; unit < units + c; unit++)
1190 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1191 _cleanup_free_ char *n = NULL;
1192 size_t max_len = MAX(columns(),20u);
1198 for (i = level - 1; i >= 0; i--) {
1200 if (len > max_len - 3 && !arg_full) {
1201 printf("%s...\n",max_len % 2 ? "" : " ");
1204 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
1208 if (len > max_len - 3 && !arg_full) {
1209 printf("%s...\n",max_len % 2 ? "" : " ");
1213 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
1217 printf("%s\n", name);
1221 n = ellipsize(name, max_len-len, 100);
1229 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1231 static const char *dependencies[_DEPENDENCY_MAX] = {
1232 [DEPENDENCY_FORWARD] = "Requires\0"
1233 "RequiresOverridable\0"
1235 "RequisiteOverridable\0"
1237 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1238 "RequiredByOverridable\0"
1241 [DEPENDENCY_AFTER] = "After\0",
1242 [DEPENDENCY_BEFORE] = "Before\0",
1245 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1246 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1247 _cleanup_strv_free_ char **ret = NULL;
1248 _cleanup_free_ char *path = NULL;
1254 assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
1256 path = unit_dbus_path_from_name(name);
1260 r = sd_bus_call_method(
1262 "org.freedesktop.systemd1",
1264 "org.freedesktop.DBus.Properties",
1268 "s", "org.freedesktop.systemd1.Unit");
1270 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1274 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1276 return bus_log_parse_error(r);
1278 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1281 r = sd_bus_message_read(reply, "s", &prop);
1283 return bus_log_parse_error(r);
1285 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1286 r = sd_bus_message_skip(reply, "v");
1288 return bus_log_parse_error(r);
1291 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1293 return bus_log_parse_error(r);
1295 r = bus_message_read_strv_extend(reply, &ret);
1297 return bus_log_parse_error(r);
1299 r = sd_bus_message_exit_container(reply);
1301 return bus_log_parse_error(r);
1304 r = sd_bus_message_exit_container(reply);
1306 return bus_log_parse_error(r);
1310 return bus_log_parse_error(r);
1312 r = sd_bus_message_exit_container(reply);
1314 return bus_log_parse_error(r);
1322 static int list_dependencies_compare(const void *_a, const void *_b) {
1323 const char **a = (const char**) _a, **b = (const char**) _b;
1325 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1327 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1330 return strcasecmp(*a, *b);
1333 static int list_dependencies_one(
1338 unsigned int branches) {
1340 _cleanup_strv_free_ char **deps = NULL;
1348 r = strv_extend(units, name);
1352 r = list_dependencies_get_dependencies(bus, name, &deps);
1356 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1358 STRV_FOREACH(c, deps) {
1361 if (strv_contains(*units, *c)) {
1363 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1370 state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true);
1372 printf("%s%s%s", ansi_highlight_green(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1374 printf("%s%s%s", ansi_highlight_red(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1376 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1380 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1381 r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1388 strv_remove(*units, name);
1393 static int list_dependencies(sd_bus *bus, char **args) {
1394 _cleanup_strv_free_ char **units = NULL;
1395 _cleanup_free_ char *unit = NULL;
1401 unit = unit_name_mangle(args[1], MANGLE_NOGLOB);
1406 u = SPECIAL_DEFAULT_TARGET;
1408 pager_open_if_enabled();
1412 return list_dependencies_one(bus, u, 0, &units, 0);
1415 struct machine_info {
1419 char *control_group;
1420 uint32_t n_failed_units;
1425 static const struct bus_properties_map machine_info_property_map[] = {
1426 { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
1427 { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
1428 { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
1429 { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
1430 { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
1434 static void free_machines_list(struct machine_info *machine_infos, int n) {
1440 for (i = 0; i < n; i++) {
1441 free(machine_infos[i].name);
1442 free(machine_infos[i].state);
1443 free(machine_infos[i].control_group);
1446 free(machine_infos);
1449 static int compare_machine_info(const void *a, const void *b) {
1450 const struct machine_info *u = a, *v = b;
1452 if (u->is_host != v->is_host)
1453 return u->is_host > v->is_host ? 1 : -1;
1455 return strcasecmp(u->name, v->name);
1458 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1459 _cleanup_bus_unref_ sd_bus *container = NULL;
1465 r = sd_bus_open_system_container(&container, mi->name);
1472 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi);
1479 static bool output_show_machine(const char *name, char **patterns) {
1484 if (strv_isempty(patterns))
1487 STRV_FOREACH(i, patterns)
1488 if (fnmatch(*i, name, FNM_NOESCAPE) == 0)
1494 static int get_machine_list(
1496 struct machine_info **_machine_infos,
1499 struct machine_info *machine_infos = NULL;
1500 _cleanup_strv_free_ char **m = NULL;
1501 _cleanup_free_ char *hn = NULL;
1506 hn = gethostname_malloc();
1510 if (output_show_machine(hn, patterns)) {
1511 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1514 machine_infos[c].is_host = true;
1515 machine_infos[c].name = hn;
1518 get_machine_properties(bus, &machine_infos[c]);
1522 sd_get_machine_names(&m);
1523 STRV_FOREACH(i, m) {
1524 _cleanup_free_ char *class = NULL;
1526 if (!output_show_machine(*i, patterns))
1529 sd_machine_get_class(*i, &class);
1530 if (!streq_ptr(class, "container"))
1533 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1534 free_machines_list(machine_infos, c);
1538 machine_infos[c].is_host = false;
1539 machine_infos[c].name = strdup(*i);
1540 if (!machine_infos[c].name) {
1541 free_machines_list(machine_infos, c);
1545 get_machine_properties(NULL, &machine_infos[c]);
1549 *_machine_infos = machine_infos;
1553 static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1554 struct machine_info *m;
1556 namelen = sizeof("NAME") - 1,
1557 statelen = sizeof("STATE") - 1,
1558 failedlen = sizeof("FAILED") - 1,
1559 jobslen = sizeof("JOBS") - 1;
1561 assert(machine_infos || n == 0);
1563 for (m = machine_infos; m < machine_infos + n; m++) {
1564 namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
1565 statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
1566 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
1567 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
1571 printf("%-*s %-*s %-*s %-*s\n",
1574 failedlen, "FAILED",
1577 for (m = machine_infos; m < machine_infos + n; m++) {
1578 const char *on_state, *off_state, *on_failed, *off_failed;
1580 if (streq_ptr(m->state, "degraded")) {
1581 on_state = ansi_highlight_red();
1582 off_state = ansi_highlight_off();
1583 } else if (!streq_ptr(m->state, "running")) {
1584 on_state = ansi_highlight_yellow();
1585 off_state = ansi_highlight_off();
1587 on_state = off_state = "";
1589 if (m->n_failed_units > 0) {
1590 on_failed = ansi_highlight_red();
1591 off_failed = ansi_highlight_off();
1593 on_failed = off_failed = "";
1596 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1597 (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
1598 on_state, statelen, strna(m->state), off_state,
1599 on_failed, failedlen, m->n_failed_units, off_failed,
1600 jobslen, m->n_jobs);
1602 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1603 namelen, strna(m->name),
1604 on_state, statelen, strna(m->state), off_state,
1605 on_failed, failedlen, m->n_failed_units, off_failed,
1606 jobslen, m->n_jobs);
1610 printf("\n%u machines listed.\n", n);
1613 static int list_machines(sd_bus *bus, char **args) {
1614 struct machine_info *machine_infos = NULL;
1619 if (geteuid() != 0) {
1620 log_error("Must be root.");
1624 pager_open_if_enabled();
1626 r = get_machine_list(bus, &machine_infos, strv_skip_first(args));
1630 qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
1631 output_machines_list(machine_infos, r);
1632 free_machines_list(machine_infos, r);
1637 static int get_default(sd_bus *bus, char **args) {
1638 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1639 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1640 _cleanup_free_ char *_path = NULL;
1644 if (!bus || avoid_bus()) {
1645 r = unit_file_get_default(arg_scope, arg_root, &_path);
1647 log_error("Failed to get default target: %s", strerror(-r));
1653 r = sd_bus_call_method(
1655 "org.freedesktop.systemd1",
1656 "/org/freedesktop/systemd1",
1657 "org.freedesktop.systemd1.Manager",
1663 log_error("Failed to get default target: %s", bus_error_message(&error, -r));
1667 r = sd_bus_message_read(reply, "s", &path);
1669 return bus_log_parse_error(r);
1673 printf("%s\n", path);
1678 static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) {
1681 assert(changes || n_changes == 0);
1683 for (i = 0; i < n_changes; i++) {
1684 if (changes[i].type == UNIT_FILE_SYMLINK)
1685 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
1687 log_info("rm '%s'", changes[i].path);
1691 static int deserialize_and_dump_unit_file_changes(sd_bus_message *m) {
1692 const char *type, *path, *source;
1695 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1697 return bus_log_parse_error(r);
1699 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1701 if (streq(type, "symlink"))
1702 log_info("ln -s '%s' '%s'", source, path);
1704 log_info("rm '%s'", path);
1708 return bus_log_parse_error(r);
1710 r = sd_bus_message_exit_container(m);
1712 return bus_log_parse_error(r);
1717 static int set_default(sd_bus *bus, char **args) {
1718 _cleanup_free_ char *unit = NULL;
1719 UnitFileChange *changes = NULL;
1720 unsigned n_changes = 0;
1723 unit = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
1727 if (!bus || avoid_bus()) {
1728 r = unit_file_set_default(arg_scope, arg_root, unit, arg_force, &changes, &n_changes);
1730 log_error("Failed to set default target: %s", strerror(-r));
1735 dump_unit_file_changes(changes, n_changes);
1739 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1740 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1742 r = sd_bus_call_method(
1744 "org.freedesktop.systemd1",
1745 "/org/freedesktop/systemd1",
1746 "org.freedesktop.systemd1.Manager",
1750 "sb", unit, arg_force);
1752 log_error("Failed to set default target: %s", bus_error_message(&error, -r));
1756 r = deserialize_and_dump_unit_file_changes(reply);
1760 /* Try to reload if enabeld */
1762 r = daemon_reload(bus, args);
1767 unit_file_changes_free(changes, n_changes);
1774 const char *name, *type, *state;
1777 static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
1778 unsigned id_len, unit_len, type_len, state_len;
1779 const struct job_info *j;
1780 const char *on, *off;
1781 bool shorten = false;
1783 assert(n == 0 || jobs);
1786 on = ansi_highlight_green();
1787 off = ansi_highlight_off();
1789 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
1793 pager_open_if_enabled();
1795 id_len = sizeof("JOB")-1;
1796 unit_len = sizeof("UNIT")-1;
1797 type_len = sizeof("TYPE")-1;
1798 state_len = sizeof("STATE")-1;
1800 for (j = jobs; j < jobs + n; j++) {
1801 uint32_t id = j->id;
1802 assert(j->name && j->type && j->state);
1804 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
1805 unit_len = MAX(unit_len, strlen(j->name));
1806 type_len = MAX(type_len, strlen(j->type));
1807 state_len = MAX(state_len, strlen(j->state));
1810 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
1811 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
1816 printf("%*s %-*s %-*s %-*s\n",
1820 state_len, "STATE");
1822 for (j = jobs; j < jobs + n; j++) {
1823 _cleanup_free_ char *e = NULL;
1825 if (streq(j->state, "running")) {
1826 on = ansi_highlight();
1827 off = ansi_highlight_off();
1831 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
1832 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
1834 on, unit_len, e ? e : j->name, off,
1836 on, state_len, j->state, off);
1839 if (!arg_no_legend) {
1840 on = ansi_highlight();
1841 off = ansi_highlight_off();
1843 printf("\n%s%u jobs listed%s.\n", on, n, off);
1847 static bool output_show_job(struct job_info *job, char **patterns) {
1852 if (strv_isempty(patterns))
1855 STRV_FOREACH(pattern, patterns)
1856 if (fnmatch(*pattern, job->name, FNM_NOESCAPE) == 0)
1861 static int list_jobs(sd_bus *bus, char **args) {
1862 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1863 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1864 const char *name, *type, *state, *job_path, *unit_path;
1865 _cleanup_free_ struct job_info *jobs = NULL;
1870 bool skipped = false;
1872 r = sd_bus_call_method(
1874 "org.freedesktop.systemd1",
1875 "/org/freedesktop/systemd1",
1876 "org.freedesktop.systemd1.Manager",
1882 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
1886 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
1888 return bus_log_parse_error(r);
1890 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
1891 struct job_info job = { id, name, type, state };
1893 if (!output_show_job(&job, strv_skip_first(args))) {
1898 if (!GREEDY_REALLOC(jobs, size, c + 1))
1904 return bus_log_parse_error(r);
1906 r = sd_bus_message_exit_container(reply);
1908 return bus_log_parse_error(r);
1910 output_jobs_list(jobs, c, skipped);
1914 static int cancel_job(sd_bus *bus, char **args) {
1915 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1920 if (strv_length(args) <= 1)
1921 return daemon_reload(bus, args);
1923 STRV_FOREACH(name, args+1) {
1927 r = safe_atou32(*name, &id);
1929 log_error("Failed to parse job id \"%s\": %s", *name, strerror(-r));
1933 r = sd_bus_call_method(
1935 "org.freedesktop.systemd1",
1936 "/org/freedesktop/systemd1",
1937 "org.freedesktop.systemd1.Manager",
1943 log_error("Failed to cancel job %u: %s", (unsigned) id, bus_error_message(&error, r));
1951 static int need_daemon_reload(sd_bus *bus, const char *unit) {
1952 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1956 /* We ignore all errors here, since this is used to show a
1959 /* We don't use unit_dbus_path_from_name() directly since we
1960 * don't want to load the unit if it isn't loaded. */
1962 r = sd_bus_call_method(
1964 "org.freedesktop.systemd1",
1965 "/org/freedesktop/systemd1",
1966 "org.freedesktop.systemd1.Manager",
1974 r = sd_bus_message_read(reply, "o", &path);
1978 r = sd_bus_get_property_trivial(
1980 "org.freedesktop.systemd1",
1982 "org.freedesktop.systemd1.Unit",
1992 typedef struct WaitData {
1999 static int wait_filter(sd_bus *bus, sd_bus_message *m, void *data, sd_bus_error *error) {
2006 log_debug("Got D-Bus request: %s.%s() on %s",
2007 sd_bus_message_get_interface(m),
2008 sd_bus_message_get_member(m),
2009 sd_bus_message_get_path(m));
2011 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
2012 log_error("Warning! D-Bus connection terminated.");
2014 } else if (sd_bus_message_is_signal(m, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
2016 const char *path, *result, *unit;
2020 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
2022 ret = set_remove(d->set, (char*) path);
2028 if (!isempty(result))
2029 d->result = strdup(result);
2032 d->name = strdup(unit);
2037 r = sd_bus_message_read(m, "uos", &id, &path, &result);
2039 ret = set_remove(d->set, (char*) path);
2046 d->result = strdup(result);
2052 bus_log_parse_error(r);
2058 static int enable_wait_for_jobs(sd_bus *bus) {
2063 r = sd_bus_add_match(
2066 "sender='org.freedesktop.systemd1',"
2067 "interface='org.freedesktop.systemd1.Manager',"
2068 "member='JobRemoved',"
2069 "path='/org/freedesktop/systemd1'",
2072 log_error("Failed to add match");
2076 /* This is slightly dirty, since we don't undo the match registrations. */
2080 static int bus_process_wait(sd_bus *bus) {
2084 r = sd_bus_process(bus, NULL);
2089 r = sd_bus_wait(bus, (uint64_t) -1);
2095 static int check_wait_response(WaitData *d) {
2101 if (streq(d->result, "timeout"))
2102 log_error("Job for %s timed out.", strna(d->name));
2103 else if (streq(d->result, "canceled"))
2104 log_error("Job for %s canceled.", strna(d->name));
2105 else if (streq(d->result, "dependency"))
2106 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d->name));
2107 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2108 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d->name), strna(d->name));
2111 if (streq(d->result, "timeout"))
2113 else if (streq(d->result, "canceled"))
2115 else if (streq(d->result, "dependency"))
2117 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2123 static int wait_for_jobs(sd_bus *bus, Set *s) {
2124 WaitData d = { .set = s };
2130 q = sd_bus_add_filter(bus, wait_filter, &d);
2134 while (!set_isempty(s)) {
2135 q = bus_process_wait(bus);
2137 log_error("Failed to wait for response: %s", strerror(-r));
2142 q = check_wait_response(&d);
2143 /* Return the first error as it is most likely to be
2145 if (q < 0 && r == 0)
2147 log_debug("Got result %s/%s for job %s",
2148 strna(d.result), strerror(-q), strna(d.name));
2158 q = sd_bus_remove_filter(bus, wait_filter, &d);
2159 if (q < 0 && r == 0)
2165 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2166 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2167 _cleanup_free_ char *n = NULL, *state = NULL;
2173 n = unit_name_mangle(name, MANGLE_NOGLOB);
2177 /* We don't use unit_dbus_path_from_name() directly since we
2178 * don't want to load the unit if it isn't loaded. */
2180 r = sd_bus_call_method(
2182 "org.freedesktop.systemd1",
2183 "/org/freedesktop/systemd1",
2184 "org.freedesktop.systemd1.Manager",
2195 r = sd_bus_message_read(reply, "o", &path);
2197 return bus_log_parse_error(r);
2199 r = sd_bus_get_property_string(
2201 "org.freedesktop.systemd1",
2203 "org.freedesktop.systemd1.Unit",
2216 return nulstr_contains(good_states, state);
2219 static int check_triggering_units(
2223 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2224 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2225 _cleanup_strv_free_ char **triggered_by = NULL;
2226 bool print_warning_label = true;
2230 n = unit_name_mangle(name, MANGLE_NOGLOB);
2234 path = unit_dbus_path_from_name(n);
2238 r = sd_bus_get_property_string(
2240 "org.freedesktop.systemd1",
2242 "org.freedesktop.systemd1.Unit",
2247 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2251 if (streq(state, "masked"))
2254 r = sd_bus_get_property_strv(
2256 "org.freedesktop.systemd1",
2258 "org.freedesktop.systemd1.Unit",
2263 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2267 STRV_FOREACH(i, triggered_by) {
2268 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2270 log_error("Failed to check unit: %s", strerror(-r));
2277 if (print_warning_label) {
2278 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2279 print_warning_label = false;
2282 log_warning(" %s", *i);
2288 static const char *verb_to_method(const char *verb) {
2291 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2292 if (streq_ptr(unit_actions[i].verb, verb))
2293 return unit_actions[i].method;
2298 static const char *method_to_verb(const char *method) {
2301 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2302 if (streq_ptr(unit_actions[i].method, method))
2303 return unit_actions[i].verb;
2308 static int start_unit_one(
2313 sd_bus_error *error,
2316 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2325 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2326 r = sd_bus_call_method(
2328 "org.freedesktop.systemd1",
2329 "/org/freedesktop/systemd1",
2330 "org.freedesktop.systemd1.Manager",
2338 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2339 /* There's always a fallback possible for
2340 * legacy actions. */
2341 return -EADDRNOTAVAIL;
2343 verb = method_to_verb(method);
2345 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2349 r = sd_bus_message_read(reply, "o", &path);
2351 return bus_log_parse_error(r);
2353 if (need_daemon_reload(bus, name) > 0)
2354 log_warning("Warning: Unit file of %s changed on disk, 'systemctl%s daemon-reload' recommended.",
2355 name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2364 log_debug("Adding %s to the set", p);
2365 r = set_consume(s, p);
2373 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2375 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2376 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2380 STRV_FOREACH(name, names) {
2384 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2386 t = unit_name_mangle(*name, MANGLE_GLOB);
2390 if (string_is_glob(t))
2391 r = strv_consume(&globs, t);
2393 r = strv_consume(&mangled, t);
2398 /* Query the manager only if any of the names are a glob, since
2399 * this is fairly expensive */
2400 if (!strv_isempty(globs)) {
2401 _cleanup_free_ UnitInfo *unit_infos = NULL;
2403 r = get_unit_list(bus, &reply, &unit_infos, globs);
2407 for (i = 0; i < r; i++)
2408 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2413 mangled = NULL; /* do not free */
2417 static const struct {
2421 } action_table[_ACTION_MAX] = {
2422 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2423 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2424 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2425 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2426 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
2427 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
2428 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
2429 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
2430 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2431 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2432 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2433 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2434 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2435 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2436 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2439 static enum action verb_to_action(const char *verb) {
2442 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2443 if (streq_ptr(action_table[i].verb, verb))
2446 return _ACTION_INVALID;
2449 static int start_unit(sd_bus *bus, char **args) {
2450 _cleanup_set_free_free_ Set *s = NULL;
2451 _cleanup_strv_free_ char **names = NULL;
2452 const char *method, *mode, *one_name;
2458 ask_password_agent_open_if_enabled();
2460 if (arg_action == ACTION_SYSTEMCTL) {
2462 method = verb_to_method(args[0]);
2463 action = verb_to_action(args[0]);
2465 mode = streq(args[0], "isolate") ? "isolate" :
2466 action_table[action].mode ?: arg_job_mode;
2468 one_name = action_table[action].target;
2470 assert(arg_action < ELEMENTSOF(action_table));
2471 assert(action_table[arg_action].target);
2473 method = "StartUnit";
2475 mode = action_table[arg_action].mode;
2476 one_name = action_table[arg_action].target;
2480 names = strv_new(one_name, NULL);
2482 r = expand_names(bus, args + 1, NULL, &names);
2484 log_error("Failed to expand names: %s", strerror(-r));
2487 if (!arg_no_block) {
2488 r = enable_wait_for_jobs(bus);
2490 log_error("Could not watch jobs: %s", strerror(-r));
2494 s = set_new(string_hash_func, string_compare_func);
2499 STRV_FOREACH(name, names) {
2500 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2503 q = start_unit_one(bus, method, *name, mode, &error, s);
2504 if (r >= 0 && q < 0)
2505 r = translate_bus_error_to_exit_status(q, &error);
2508 if (!arg_no_block) {
2511 q = wait_for_jobs(bus, s);
2515 /* When stopping units, warn if they can still be triggered by
2516 * another active unit (socket, path, timer) */
2517 if (!arg_quiet && streq(method, "StopUnit"))
2518 STRV_FOREACH(name, names)
2519 check_triggering_units(bus, *name);
2525 /* Ask systemd-logind, which might grant access to unprivileged users
2526 * through PolicyKit */
2527 static int reboot_with_logind(sd_bus *bus, enum action a) {
2529 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2536 polkit_agent_open_if_enabled();
2544 case ACTION_POWEROFF:
2545 method = "PowerOff";
2548 case ACTION_SUSPEND:
2552 case ACTION_HIBERNATE:
2553 method = "Hibernate";
2556 case ACTION_HYBRID_SLEEP:
2557 method = "HybridSleep";
2564 r = sd_bus_call_method(
2566 "org.freedesktop.login1",
2567 "/org/freedesktop/login1",
2568 "org.freedesktop.login1.Manager",
2574 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2582 static int check_inhibitors(sd_bus *bus, enum action a) {
2584 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2585 _cleanup_strv_free_ char **sessions = NULL;
2586 const char *what, *who, *why, *mode;
2595 if (arg_ignore_inhibitors || arg_force > 0)
2607 r = sd_bus_call_method(
2609 "org.freedesktop.login1",
2610 "/org/freedesktop/login1",
2611 "org.freedesktop.login1.Manager",
2617 /* If logind is not around, then there are no inhibitors... */
2620 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2622 return bus_log_parse_error(r);
2624 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2625 _cleanup_free_ char *comm = NULL, *user = NULL;
2626 _cleanup_strv_free_ char **sv = NULL;
2628 if (!streq(mode, "block"))
2631 sv = strv_split(what, ":");
2635 if (!strv_contains(sv,
2637 a == ACTION_POWEROFF ||
2638 a == ACTION_REBOOT ||
2639 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2642 get_process_comm(pid, &comm);
2643 user = uid_to_name(uid);
2645 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2646 who, (unsigned long) pid, strna(comm), strna(user), why);
2651 return bus_log_parse_error(r);
2653 r = sd_bus_message_exit_container(reply);
2655 return bus_log_parse_error(r);
2657 /* Check for current sessions */
2658 sd_get_sessions(&sessions);
2659 STRV_FOREACH(s, sessions) {
2660 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2662 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2665 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2668 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2671 sd_session_get_tty(*s, &tty);
2672 sd_session_get_seat(*s, &seat);
2673 sd_session_get_service(*s, &service);
2674 user = uid_to_name(uid);
2676 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2683 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2684 action_table[a].verb);
2692 static int start_special(sd_bus *bus, char **args) {
2698 a = verb_to_action(args[0]);
2700 r = check_inhibitors(bus, a);
2704 if (arg_force >= 2 && geteuid() != 0) {
2705 log_error("Must be root.");
2709 if (arg_force >= 2 &&
2710 (a == ACTION_HALT ||
2711 a == ACTION_POWEROFF ||
2712 a == ACTION_REBOOT))
2715 if (arg_force >= 1 &&
2716 (a == ACTION_HALT ||
2717 a == ACTION_POWEROFF ||
2718 a == ACTION_REBOOT ||
2719 a == ACTION_KEXEC ||
2721 return daemon_reload(bus, args);
2723 /* first try logind, to allow authentication with polkit */
2724 if (geteuid() != 0 &&
2725 (a == ACTION_POWEROFF ||
2726 a == ACTION_REBOOT ||
2727 a == ACTION_SUSPEND ||
2728 a == ACTION_HIBERNATE ||
2729 a == ACTION_HYBRID_SLEEP)) {
2730 r = reboot_with_logind(bus, a);
2735 r = start_unit(bus, args);
2736 if (r == EXIT_SUCCESS)
2742 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
2743 _cleanup_strv_free_ char **names = NULL;
2750 r = expand_names(bus, args, NULL, &names);
2752 log_error("Failed to expand names: %s", strerror(-r));
2756 STRV_FOREACH(name, names) {
2759 state = check_one_unit(bus, *name, good_states, arg_quiet);
2769 static int check_unit_active(sd_bus *bus, char **args) {
2770 /* According to LSB: 3, "program is not running" */
2771 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
2774 static int check_unit_failed(sd_bus *bus, char **args) {
2775 return check_unit_generic(bus, 1, "failed\0", args + 1);
2778 static int kill_unit(sd_bus *bus, char **args) {
2779 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2780 _cleanup_strv_free_ char **names = NULL;
2788 arg_kill_who = "all";
2790 r = expand_names(bus, args + 1, NULL, &names);
2792 log_error("Failed to expand names: %s", strerror(-r));
2794 STRV_FOREACH(name, names) {
2795 q = sd_bus_call_method(
2797 "org.freedesktop.systemd1",
2798 "/org/freedesktop/systemd1",
2799 "org.freedesktop.systemd1.Manager",
2803 "ssi", *names, arg_kill_who, arg_signal);
2805 log_error("Failed to kill unit %s: %s",
2806 *names, bus_error_message(&error, r));
2815 typedef struct ExecStatusInfo {
2823 usec_t start_timestamp;
2824 usec_t exit_timestamp;
2829 LIST_FIELDS(struct ExecStatusInfo, exec);
2832 static void exec_status_info_free(ExecStatusInfo *i) {
2841 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
2842 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2845 int32_t code, status;
2851 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
2853 return bus_log_parse_error(r);
2857 r = sd_bus_message_read(m, "s", &path);
2859 return bus_log_parse_error(r);
2861 i->path = strdup(path);
2865 r = sd_bus_message_read_strv(m, &i->argv);
2867 return bus_log_parse_error(r);
2869 r = sd_bus_message_read(m,
2872 &start_timestamp, &start_timestamp_monotonic,
2873 &exit_timestamp, &exit_timestamp_monotonic,
2877 return bus_log_parse_error(r);
2880 i->start_timestamp = (usec_t) start_timestamp;
2881 i->exit_timestamp = (usec_t) exit_timestamp;
2882 i->pid = (pid_t) pid;
2886 r = sd_bus_message_exit_container(m);
2888 return bus_log_parse_error(r);
2893 typedef struct UnitStatusInfo {
2895 const char *load_state;
2896 const char *active_state;
2897 const char *sub_state;
2898 const char *unit_file_state;
2900 const char *description;
2901 const char *following;
2903 char **documentation;
2905 const char *fragment_path;
2906 const char *source_path;
2907 const char *control_group;
2909 char **dropin_paths;
2911 const char *load_error;
2914 usec_t inactive_exit_timestamp;
2915 usec_t inactive_exit_timestamp_monotonic;
2916 usec_t active_enter_timestamp;
2917 usec_t active_exit_timestamp;
2918 usec_t inactive_enter_timestamp;
2920 bool need_daemon_reload;
2925 const char *status_text;
2926 const char *pid_file;
2929 usec_t start_timestamp;
2930 usec_t exit_timestamp;
2932 int exit_code, exit_status;
2934 usec_t condition_timestamp;
2935 bool condition_result;
2936 bool failed_condition_trigger;
2937 bool failed_condition_negate;
2938 const char *failed_condition;
2939 const char *failed_condition_param;
2942 unsigned n_accepted;
2943 unsigned n_connections;
2946 /* Pairs of type, path */
2950 const char *sysfs_path;
2952 /* Mount, Automount */
2958 LIST_HEAD(ExecStatusInfo, exec);
2961 static void print_status_info(
2966 const char *on, *off, *ss;
2968 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2969 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2972 arg_all * OUTPUT_SHOW_ALL |
2973 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2974 on_tty() * OUTPUT_COLOR |
2975 !arg_quiet * OUTPUT_WARN_CUTOFF |
2976 arg_full * OUTPUT_FULL_WIDTH;
2981 /* This shows pretty information about a unit. See
2982 * print_property() for a low-level property printer */
2984 printf("%s", strna(i->id));
2986 if (i->description && !streq_ptr(i->id, i->description))
2987 printf(" - %s", i->description);
2992 printf(" Follow: unit currently follows state of %s\n", i->following);
2994 if (streq_ptr(i->load_state, "error")) {
2995 on = ansi_highlight_red();
2996 off = ansi_highlight_off();
3000 path = i->source_path ? i->source_path : i->fragment_path;
3003 printf(" Loaded: %s%s%s (Reason: %s)\n",
3004 on, strna(i->load_state), off, i->load_error);
3005 else if (path && i->unit_file_state)
3006 printf(" Loaded: %s%s%s (%s; %s)\n",
3007 on, strna(i->load_state), off, path, i->unit_file_state);
3009 printf(" Loaded: %s%s%s (%s)\n",
3010 on, strna(i->load_state), off, path);
3012 printf(" Loaded: %s%s%s\n",
3013 on, strna(i->load_state), off);
3015 if (!strv_isempty(i->dropin_paths)) {
3016 _cleanup_free_ char *dir = NULL;
3020 STRV_FOREACH(dropin, i->dropin_paths) {
3021 if (! dir || last) {
3022 printf(dir ? " " : " Drop-In: ");
3027 if (path_get_parent(*dropin, &dir) < 0) {
3032 printf("%s\n %s", dir,
3033 draw_special_char(DRAW_TREE_RIGHT));
3036 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3038 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3042 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3044 if (streq_ptr(i->active_state, "failed")) {
3045 on = ansi_highlight_red();
3046 off = ansi_highlight_off();
3047 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3048 on = ansi_highlight_green();
3049 off = ansi_highlight_off();
3054 printf(" Active: %s%s (%s)%s",
3055 on, strna(i->active_state), ss, off);
3057 printf(" Active: %s%s%s",
3058 on, strna(i->active_state), off);
3060 if (!isempty(i->result) && !streq(i->result, "success"))
3061 printf(" (Result: %s)", i->result);
3063 timestamp = (streq_ptr(i->active_state, "active") ||
3064 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
3065 (streq_ptr(i->active_state, "inactive") ||
3066 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
3067 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
3068 i->active_exit_timestamp;
3070 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3071 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3074 printf(" since %s; %s\n", s2, s1);
3076 printf(" since %s\n", s2);
3080 if (!i->condition_result && i->condition_timestamp > 0) {
3081 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3082 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3084 printf(" start condition failed at %s%s%s\n",
3085 s2, s1 ? "; " : "", s1 ? s1 : "");
3086 if (i->failed_condition_trigger)
3087 printf(" none of the trigger conditions were met\n");
3088 else if (i->failed_condition)
3089 printf(" %s=%s%s was not met\n",
3090 i->failed_condition,
3091 i->failed_condition_negate ? "!" : "",
3092 i->failed_condition_param);
3096 printf(" Device: %s\n", i->sysfs_path);
3098 printf(" Where: %s\n", i->where);
3100 printf(" What: %s\n", i->what);
3102 STRV_FOREACH(t, i->documentation)
3103 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3105 STRV_FOREACH_PAIR(t, t2, i->listen)
3106 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3109 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3111 LIST_FOREACH(exec, p, i->exec) {
3112 _cleanup_free_ char *argv = NULL;
3115 /* Only show exited processes here */
3119 argv = strv_join(p->argv, " ");
3120 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
3122 good = is_clean_exit_lsb(p->code, p->status, NULL);
3124 on = ansi_highlight_red();
3125 off = ansi_highlight_off();
3129 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3131 if (p->code == CLD_EXITED) {
3134 printf("status=%i", p->status);
3136 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3141 printf("signal=%s", signal_to_string(p->status));
3143 printf(")%s\n", off);
3145 if (i->main_pid == p->pid &&
3146 i->start_timestamp == p->start_timestamp &&
3147 i->exit_timestamp == p->start_timestamp)
3148 /* Let's not show this twice */
3151 if (p->pid == i->control_pid)
3155 if (i->main_pid > 0 || i->control_pid > 0) {
3156 if (i->main_pid > 0) {
3157 printf(" Main PID: %u", (unsigned) i->main_pid);
3160 _cleanup_free_ char *comm = NULL;
3161 get_process_comm(i->main_pid, &comm);
3163 printf(" (%s)", comm);
3164 } else if (i->exit_code > 0) {
3165 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3167 if (i->exit_code == CLD_EXITED) {
3170 printf("status=%i", i->exit_status);
3172 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3177 printf("signal=%s", signal_to_string(i->exit_status));
3181 if (i->control_pid > 0)
3185 if (i->control_pid > 0) {
3186 _cleanup_free_ char *c = NULL;
3188 printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
3190 get_process_comm(i->control_pid, &c);
3199 printf(" Status: \"%s\"\n", i->status_text);
3201 if (i->control_group &&
3202 (i->main_pid > 0 || i->control_pid > 0 ||
3203 ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_CONTAINER) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3206 printf(" CGroup: %s\n", i->control_group);
3208 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
3211 static const char prefix[] = " ";
3214 if (c > sizeof(prefix) - 1)
3215 c -= sizeof(prefix) - 1;
3219 if (i->main_pid > 0)
3220 extra[k++] = i->main_pid;
3222 if (i->control_pid > 0)
3223 extra[k++] = i->control_pid;
3225 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, flags);
3229 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3231 show_journal_by_unit(stdout,
3235 i->inactive_exit_timestamp_monotonic,
3239 arg_scope == UNIT_FILE_SYSTEM,
3243 if (i->need_daemon_reload)
3244 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
3245 ansi_highlight_red(),
3246 ansi_highlight_off(),
3247 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
3250 static void show_unit_help(UnitStatusInfo *i) {
3255 if (!i->documentation) {
3256 log_info("Documentation for %s not known.", i->id);
3260 STRV_FOREACH(p, i->documentation) {
3262 if (startswith(*p, "man:")) {
3263 const char *args[4] = { "man", NULL, NULL, NULL };
3264 _cleanup_free_ char *page = NULL, *section = NULL;
3271 if ((*p)[k-1] == ')')
3272 e = strrchr(*p, '(');
3275 page = strndup((*p) + 4, e - *p - 4);
3276 section = strndup(e + 1, *p + k - e - 2);
3277 if (!page || !section) {
3289 log_error("Failed to fork: %m");
3295 execvp(args[0], (char**) args);
3296 log_error("Failed to execute man: %m");
3297 _exit(EXIT_FAILURE);
3300 wait_for_terminate(pid, NULL);
3302 log_info("Can't show: %s", *p);
3306 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3313 switch (contents[0]) {
3315 case SD_BUS_TYPE_STRING: {
3318 r = sd_bus_message_read(m, "s", &s);
3320 return bus_log_parse_error(r);
3323 if (streq(name, "Id"))
3325 else if (streq(name, "LoadState"))
3327 else if (streq(name, "ActiveState"))
3328 i->active_state = s;
3329 else if (streq(name, "SubState"))
3331 else if (streq(name, "Description"))
3333 else if (streq(name, "FragmentPath"))
3334 i->fragment_path = s;
3335 else if (streq(name, "SourcePath"))
3338 else if (streq(name, "DefaultControlGroup")) {
3340 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3342 i->control_group = e;
3345 else if (streq(name, "ControlGroup"))
3346 i->control_group = s;
3347 else if (streq(name, "StatusText"))
3349 else if (streq(name, "PIDFile"))
3351 else if (streq(name, "SysFSPath"))
3353 else if (streq(name, "Where"))
3355 else if (streq(name, "What"))
3357 else if (streq(name, "Following"))
3359 else if (streq(name, "UnitFileState"))
3360 i->unit_file_state = s;
3361 else if (streq(name, "Result"))
3368 case SD_BUS_TYPE_BOOLEAN: {
3371 r = sd_bus_message_read(m, "b", &b);
3373 return bus_log_parse_error(r);
3375 if (streq(name, "Accept"))
3377 else if (streq(name, "NeedDaemonReload"))
3378 i->need_daemon_reload = b;
3379 else if (streq(name, "ConditionResult"))
3380 i->condition_result = b;
3385 case SD_BUS_TYPE_UINT32: {
3388 r = sd_bus_message_read(m, "u", &u);
3390 return bus_log_parse_error(r);
3392 if (streq(name, "MainPID")) {
3394 i->main_pid = (pid_t) u;
3397 } else if (streq(name, "ControlPID"))
3398 i->control_pid = (pid_t) u;
3399 else if (streq(name, "ExecMainPID")) {
3401 i->main_pid = (pid_t) u;
3402 } else if (streq(name, "NAccepted"))
3404 else if (streq(name, "NConnections"))
3405 i->n_connections = u;
3410 case SD_BUS_TYPE_INT32: {
3413 r = sd_bus_message_read(m, "i", &j);
3415 return bus_log_parse_error(r);
3417 if (streq(name, "ExecMainCode"))
3418 i->exit_code = (int) j;
3419 else if (streq(name, "ExecMainStatus"))
3420 i->exit_status = (int) j;
3425 case SD_BUS_TYPE_UINT64: {
3428 r = sd_bus_message_read(m, "t", &u);
3430 return bus_log_parse_error(r);
3432 if (streq(name, "ExecMainStartTimestamp"))
3433 i->start_timestamp = (usec_t) u;
3434 else if (streq(name, "ExecMainExitTimestamp"))
3435 i->exit_timestamp = (usec_t) u;
3436 else if (streq(name, "ActiveEnterTimestamp"))
3437 i->active_enter_timestamp = (usec_t) u;
3438 else if (streq(name, "InactiveEnterTimestamp"))
3439 i->inactive_enter_timestamp = (usec_t) u;
3440 else if (streq(name, "InactiveExitTimestamp"))
3441 i->inactive_exit_timestamp = (usec_t) u;
3442 else if (streq(name, "InactiveExitTimestampMonotonic"))
3443 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3444 else if (streq(name, "ActiveExitTimestamp"))
3445 i->active_exit_timestamp = (usec_t) u;
3446 else if (streq(name, "ConditionTimestamp"))
3447 i->condition_timestamp = (usec_t) u;
3452 case SD_BUS_TYPE_ARRAY:
3454 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3455 _cleanup_free_ ExecStatusInfo *info = NULL;
3457 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3459 return bus_log_parse_error(r);
3461 info = new0(ExecStatusInfo, 1);
3465 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3467 info->name = strdup(name);
3471 LIST_PREPEND(exec, i->exec, info);
3473 info = new0(ExecStatusInfo, 1);
3479 return bus_log_parse_error(r);
3481 r = sd_bus_message_exit_container(m);
3483 return bus_log_parse_error(r);
3487 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3488 const char *type, *path;
3490 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3492 return bus_log_parse_error(r);
3494 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3496 r = strv_extend(&i->listen, type);
3500 r = strv_extend(&i->listen, path);
3505 return bus_log_parse_error(r);
3507 r = sd_bus_message_exit_container(m);
3509 return bus_log_parse_error(r);
3513 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3515 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3517 return bus_log_parse_error(r);
3519 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3521 r = sd_bus_message_read_strv(m, &i->documentation);
3523 return bus_log_parse_error(r);
3525 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3526 const char *cond, *param;
3527 int trigger, negate;
3530 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3532 return bus_log_parse_error(r);
3534 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3535 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3536 if (state < 0 && (!trigger || !i->failed_condition)) {
3537 i->failed_condition = cond;
3538 i->failed_condition_trigger = trigger;
3539 i->failed_condition_negate = negate;
3540 i->failed_condition_param = param;
3544 return bus_log_parse_error(r);
3546 r = sd_bus_message_exit_container(m);
3548 return bus_log_parse_error(r);
3555 case SD_BUS_TYPE_STRUCT_BEGIN:
3557 if (streq(name, "LoadError")) {
3558 const char *n, *message;
3560 r = sd_bus_message_read(m, "(ss)", &n, &message);
3562 return bus_log_parse_error(r);
3564 if (!isempty(message))
3565 i->load_error = message;
3578 r = sd_bus_message_skip(m, contents);
3580 return bus_log_parse_error(r);
3585 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3591 /* This is a low-level property printer, see
3592 * print_status_info() for the nicer output */
3594 if (arg_properties && !strv_find(arg_properties, name)) {
3595 /* skip what we didn't read */
3596 r = sd_bus_message_skip(m, contents);
3600 switch (contents[0]) {
3602 case SD_BUS_TYPE_STRUCT_BEGIN:
3604 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3607 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3609 return bus_log_parse_error(r);
3612 printf("%s=%u\n", name, (unsigned) u);
3614 printf("%s=\n", name);
3618 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3621 r = sd_bus_message_read(m, "(so)", &s, NULL);
3623 return bus_log_parse_error(r);
3625 if (arg_all || !isempty(s))
3626 printf("%s=%s\n", name, s);
3630 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3631 const char *a = NULL, *b = NULL;
3633 r = sd_bus_message_read(m, "(ss)", &a, &b);
3635 return bus_log_parse_error(r);
3637 if (arg_all || !isempty(a) || !isempty(b))
3638 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3641 } else if (streq_ptr(name, "SystemCallFilter")) {
3642 _cleanup_strv_free_ char **l = NULL;
3645 r = sd_bus_message_enter_container(m, 'r', "bas");
3647 return bus_log_parse_error(r);
3649 r = sd_bus_message_read(m, "b", &whitelist);
3651 return bus_log_parse_error(r);
3653 r = sd_bus_message_read_strv(m, &l);
3655 return bus_log_parse_error(r);
3657 r = sd_bus_message_exit_container(m);
3659 return bus_log_parse_error(r);
3661 if (arg_all || whitelist || !strv_isempty(l)) {
3665 fputs(name, stdout);
3671 STRV_FOREACH(i, l) {
3679 fputc('\n', stdout);
3687 case SD_BUS_TYPE_ARRAY:
3689 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
3693 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
3695 return bus_log_parse_error(r);
3697 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
3698 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3701 return bus_log_parse_error(r);
3703 r = sd_bus_message_exit_container(m);
3705 return bus_log_parse_error(r);
3709 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
3710 const char *type, *path;
3712 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3714 return bus_log_parse_error(r);
3716 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3717 printf("%s=%s\n", type, path);
3719 return bus_log_parse_error(r);
3721 r = sd_bus_message_exit_container(m);
3723 return bus_log_parse_error(r);
3727 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3728 const char *type, *path;
3730 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3732 return bus_log_parse_error(r);
3734 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3735 printf("Listen%s=%s\n", type, path);
3737 return bus_log_parse_error(r);
3739 r = sd_bus_message_exit_container(m);
3741 return bus_log_parse_error(r);
3745 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
3747 uint64_t value, next_elapse;
3749 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
3751 return bus_log_parse_error(r);
3753 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
3754 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3756 printf("%s={ value=%s ; next_elapse=%s }\n",
3758 format_timespan(timespan1, sizeof(timespan1), value, 0),
3759 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3762 return bus_log_parse_error(r);
3764 r = sd_bus_message_exit_container(m);
3766 return bus_log_parse_error(r);
3770 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3771 ExecStatusInfo info = {};
3773 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3775 return bus_log_parse_error(r);
3777 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
3778 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3779 _cleanup_free_ char *tt;
3781 tt = strv_join(info.argv, " ");
3783 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3787 yes_no(info.ignore),
3788 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3789 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3790 (unsigned) info. pid,
3791 sigchld_code_to_string(info.code),
3793 info.code == CLD_EXITED ? "" : "/",
3794 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3797 strv_free(info.argv);
3801 r = sd_bus_message_exit_container(m);
3803 return bus_log_parse_error(r);
3807 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
3808 const char *path, *rwm;
3810 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3812 return bus_log_parse_error(r);
3814 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
3815 printf("%s=%s %s\n", name, strna(path), strna(rwm));
3817 return bus_log_parse_error(r);
3819 r = sd_bus_message_exit_container(m);
3821 return bus_log_parse_error(r);
3825 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
3829 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
3831 return bus_log_parse_error(r);
3833 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
3834 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
3836 return bus_log_parse_error(r);
3838 r = sd_bus_message_exit_container(m);
3840 return bus_log_parse_error(r);
3844 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
3848 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
3850 return bus_log_parse_error(r);
3852 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
3853 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
3855 return bus_log_parse_error(r);
3857 r = sd_bus_message_exit_container(m);
3859 return bus_log_parse_error(r);
3867 r = bus_print_property(name, m, arg_all);
3869 return bus_log_parse_error(r);
3872 r = sd_bus_message_skip(m, contents);
3874 return bus_log_parse_error(r);
3877 printf("%s=[unprintable]\n", name);
3883 static int show_one(
3887 bool show_properties,
3891 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
3892 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3893 UnitStatusInfo info = {};
3900 log_debug("Showing one %s", path);
3902 r = sd_bus_call_method(
3904 "org.freedesktop.systemd1",
3906 "org.freedesktop.DBus.Properties",
3912 log_error("Failed to get properties: %s", bus_error_message(&error, r));
3916 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
3918 return bus_log_parse_error(r);
3925 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
3926 const char *name, *contents;
3928 r = sd_bus_message_read(reply, "s", &name);
3930 return bus_log_parse_error(r);
3932 r = sd_bus_message_peek_type(reply, NULL, &contents);
3934 return bus_log_parse_error(r);
3936 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
3938 return bus_log_parse_error(r);
3940 if (show_properties)
3941 r = print_property(name, reply, contents);
3943 r = status_property(name, reply, &info, contents);
3947 r = sd_bus_message_exit_container(reply);
3949 return bus_log_parse_error(r);
3951 r = sd_bus_message_exit_container(reply);
3953 return bus_log_parse_error(r);
3956 return bus_log_parse_error(r);
3958 r = sd_bus_message_exit_container(reply);
3960 return bus_log_parse_error(r);
3964 if (!show_properties) {
3965 if (streq(verb, "help"))
3966 show_unit_help(&info);
3968 print_status_info(&info, ellipsized);
3971 strv_free(info.documentation);
3972 strv_free(info.dropin_paths);
3973 strv_free(info.listen);
3975 if (!streq_ptr(info.active_state, "active") &&
3976 !streq_ptr(info.active_state, "reloading") &&
3977 streq(verb, "status")) {
3978 /* According to LSB: "program not running" */
3979 /* 0: program is running or service is OK
3980 * 1: program is dead and /run PID file exists
3981 * 2: program is dead and /run/lock lock file exists
3982 * 3: program is not running
3983 * 4: program or service status is unknown
3985 if (info.pid_file && access(info.pid_file, F_OK) == 0)
3991 while ((p = info.exec)) {
3992 LIST_REMOVE(exec, info.exec, p);
3993 exec_status_info_free(p);
3999 static int get_unit_dbus_path_by_pid(
4004 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4005 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4009 r = sd_bus_call_method(
4011 "org.freedesktop.systemd1",
4012 "/org/freedesktop/systemd1",
4013 "org.freedesktop.systemd1.Manager",
4019 log_error("Failed to get unit for PID %lu: %s", (unsigned long) pid, bus_error_message(&error, r));
4023 r = sd_bus_message_read(reply, "o", &u);
4025 return bus_log_parse_error(r);
4035 static int show_all(
4038 bool show_properties,
4042 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4043 _cleanup_free_ UnitInfo *unit_infos = NULL;
4048 r = get_unit_list(bus, &reply, &unit_infos, NULL);
4052 pager_open_if_enabled();
4056 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4058 for (u = unit_infos; u < unit_infos + c; u++) {
4059 _cleanup_free_ char *p = NULL;
4061 p = unit_dbus_path_from_name(u->id);
4065 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4073 static int cat(sd_bus *bus, char **args) {
4074 _cleanup_free_ char *unit = NULL;
4075 _cleanup_strv_free_ char **names = NULL;
4083 r = expand_names(bus, args + 1, NULL, &names);
4085 log_error("Failed to expand names: %s", strerror(-r));
4087 pager_open_if_enabled();
4089 STRV_FOREACH(name, names) {
4090 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4091 _cleanup_strv_free_ char **dropin_paths = NULL;
4092 _cleanup_free_ char *fragment_path = NULL;
4095 unit = unit_dbus_path_from_name(*name);
4099 if (need_daemon_reload(bus, *name) > 0)
4100 log_warning("Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'.",
4101 *name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
4103 r = sd_bus_get_property_string(
4105 "org.freedesktop.systemd1",
4107 "org.freedesktop.systemd1.Unit",
4112 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
4116 r = sd_bus_get_property_strv(
4118 "org.freedesktop.systemd1",
4120 "org.freedesktop.systemd1.Unit",
4125 log_warning("Failed to get DropInPaths: %s", bus_error_message(&error, r));
4134 if (!isempty(fragment_path)) {
4135 printf("%s# %s%s\n",
4136 ansi_highlight_blue(),
4138 ansi_highlight_off());
4141 r = sendfile_full(STDOUT_FILENO, fragment_path);
4143 log_warning("Failed to cat %s: %s", fragment_path, strerror(-r));
4148 STRV_FOREACH(path, dropin_paths) {
4149 printf("%s%s# %s%s\n",
4150 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4151 ansi_highlight_blue(),
4153 ansi_highlight_off());
4156 r = sendfile_full(STDOUT_FILENO, *path);
4158 log_warning("Failed to cat %s: %s", *path, strerror(-r));
4164 return r < 0 ? r : 0;
4167 static int show_system_status(sd_bus *bus) {
4168 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4169 _cleanup_free_ char *hn = NULL;
4170 struct machine_info mi = {};
4171 const char *on, *off;
4174 hn = gethostname_malloc();
4178 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4180 log_error("Failed to read server status: %s", strerror(-r));
4184 printf("%s\n", arg_host ? arg_host : hn);
4186 if (streq_ptr(mi.state, "degraded")) {
4187 on = ansi_highlight_red();
4188 off = ansi_highlight_off();
4189 } else if (!streq_ptr(mi.state, "running")) {
4190 on = ansi_highlight_yellow();
4191 off = ansi_highlight_off();
4195 printf(" State: %s%s%s\n",
4196 on, strna(mi.state), off);
4198 printf(" Jobs: %u queued\n", mi.n_jobs);
4199 printf(" Failed: %u units\n", mi.n_failed_units);
4201 printf(" Since: %s; %s\n",
4202 format_timestamp(since2, sizeof(since2), mi.timestamp),
4203 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4205 printf(" CGroup: %s\n", mi.control_group ?: "/");
4206 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
4208 arg_all * OUTPUT_SHOW_ALL |
4209 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
4210 on_tty() * OUTPUT_COLOR |
4211 !arg_quiet * OUTPUT_WARN_CUTOFF |
4212 arg_full * OUTPUT_FULL_WIDTH;
4214 static const char prefix[] = " ";
4218 if (c > sizeof(prefix) - 1)
4219 c -= sizeof(prefix) - 1;
4223 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
4227 free(mi.control_group);
4232 static int show(sd_bus *bus, char **args) {
4233 bool show_properties, show_status, new_line = false;
4234 bool ellipsized = false;
4240 show_properties = streq(args[0], "show");
4241 show_status = streq(args[0], "status");
4243 if (show_properties)
4244 pager_open_if_enabled();
4246 /* If no argument is specified inspect the manager itself */
4248 if (show_properties && strv_length(args) <= 1)
4249 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4251 if (show_status && strv_length(args) <= 1) {
4254 pager_open_if_enabled();
4256 show_system_status(bus);
4260 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4262 _cleanup_free_ char **patterns = NULL;
4265 STRV_FOREACH(name, args + 1) {
4266 _cleanup_free_ char *unit = NULL;
4269 if (safe_atou32(*name, &id) < 0) {
4270 if (strv_push(&patterns, *name) < 0)
4274 } else if (show_properties) {
4275 /* Interpret as job id */
4276 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4280 /* Interpret as PID */
4281 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4288 show_one(args[0], bus, unit, show_properties, &new_line, &ellipsized);
4291 if (!strv_isempty(patterns)) {
4292 _cleanup_strv_free_ char **names = NULL;
4294 r = expand_names(bus, patterns, NULL, &names);
4296 log_error("Failed to expand names: %s", strerror(-r));
4298 STRV_FOREACH(name, names) {
4299 _cleanup_free_ char *unit;
4301 unit = unit_dbus_path_from_name(*name);
4305 show_one(args[0], bus, unit, show_properties, &new_line, &ellipsized);
4310 if (ellipsized && !arg_quiet)
4311 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4316 static int set_property(sd_bus *bus, char **args) {
4317 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4318 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4319 _cleanup_free_ char *n = NULL;
4323 r = sd_bus_message_new_method_call(
4326 "org.freedesktop.systemd1",
4327 "/org/freedesktop/systemd1",
4328 "org.freedesktop.systemd1.Manager",
4329 "SetUnitProperties");
4331 return bus_log_create_error(r);
4333 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4337 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4339 return bus_log_create_error(r);
4341 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4343 return bus_log_create_error(r);
4345 STRV_FOREACH(i, args + 2) {
4346 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4348 return bus_log_create_error(r);
4350 r = bus_append_unit_property_assignment(m, *i);
4354 r = sd_bus_message_close_container(m);
4356 return bus_log_create_error(r);
4359 r = sd_bus_message_close_container(m);
4361 return bus_log_create_error(r);
4363 r = sd_bus_call(bus, m, 0, &error, NULL);
4365 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4372 static int snapshot(sd_bus *bus, char **args) {
4373 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4374 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4375 _cleanup_free_ char *n = NULL, *id = NULL;
4379 if (strv_length(args) > 1)
4380 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4386 r = sd_bus_call_method(
4388 "org.freedesktop.systemd1",
4389 "/org/freedesktop/systemd1",
4390 "org.freedesktop.systemd1.Manager",
4396 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4400 r = sd_bus_message_read(reply, "o", &path);
4402 return bus_log_parse_error(r);
4404 r = sd_bus_get_property_string(
4406 "org.freedesktop.systemd1",
4408 "org.freedesktop.systemd1.Unit",
4413 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4423 static int delete_snapshot(sd_bus *bus, char **args) {
4424 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4425 _cleanup_strv_free_ char **names = NULL;
4431 r = expand_names(bus, args + 1, ".snapshot", &names);
4433 log_error("Failed to expand names: %s", strerror(-r));
4435 STRV_FOREACH(name, names) {
4436 q = sd_bus_call_method(
4438 "org.freedesktop.systemd1",
4439 "/org/freedesktop/systemd1",
4440 "org.freedesktop.systemd1.Manager",
4446 log_error("Failed to remove snapshot %s: %s",
4447 *name, bus_error_message(&error, r));
4456 static int daemon_reload(sd_bus *bus, char **args) {
4457 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4461 if (arg_action == ACTION_RELOAD)
4463 else if (arg_action == ACTION_REEXEC)
4464 method = "Reexecute";
4466 assert(arg_action == ACTION_SYSTEMCTL);
4469 streq(args[0], "clear-jobs") ||
4470 streq(args[0], "cancel") ? "ClearJobs" :
4471 streq(args[0], "daemon-reexec") ? "Reexecute" :
4472 streq(args[0], "reset-failed") ? "ResetFailed" :
4473 streq(args[0], "halt") ? "Halt" :
4474 streq(args[0], "poweroff") ? "PowerOff" :
4475 streq(args[0], "reboot") ? "Reboot" :
4476 streq(args[0], "kexec") ? "KExec" :
4477 streq(args[0], "exit") ? "Exit" :
4478 /* "daemon-reload" */ "Reload";
4481 r = sd_bus_call_method(
4483 "org.freedesktop.systemd1",
4484 "/org/freedesktop/systemd1",
4485 "org.freedesktop.systemd1.Manager",
4491 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4492 /* There's always a fallback possible for
4493 * legacy actions. */
4495 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4496 /* On reexecution, we expect a disconnect, not a
4500 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4502 return r < 0 ? r : 0;
4505 static int reset_failed(sd_bus *bus, char **args) {
4506 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4507 _cleanup_strv_free_ char **names = NULL;
4511 if (strv_length(args) <= 1)
4512 return daemon_reload(bus, args);
4514 r = expand_names(bus, args + 1, NULL, &names);
4516 log_error("Failed to expand names: %s", strerror(-r));
4518 STRV_FOREACH(name, names) {
4519 q = sd_bus_call_method(
4521 "org.freedesktop.systemd1",
4522 "/org/freedesktop/systemd1",
4523 "org.freedesktop.systemd1.Manager",
4529 log_error("Failed to reset failed state of unit %s: %s",
4530 *name, bus_error_message(&error, r));
4539 static int show_environment(sd_bus *bus, char **args) {
4540 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4541 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4545 pager_open_if_enabled();
4547 r = sd_bus_get_property(
4549 "org.freedesktop.systemd1",
4550 "/org/freedesktop/systemd1",
4551 "org.freedesktop.systemd1.Manager",
4557 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4561 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4563 return bus_log_parse_error(r);
4565 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4568 return bus_log_parse_error(r);
4570 r = sd_bus_message_exit_container(reply);
4572 return bus_log_parse_error(r);
4577 static int switch_root(sd_bus *bus, char **args) {
4578 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4579 _cleanup_free_ char *cmdline_init = NULL;
4580 const char *root, *init;
4584 l = strv_length(args);
4585 if (l < 2 || l > 3) {
4586 log_error("Wrong number of arguments.");
4595 r = parse_env_file("/proc/cmdline", WHITESPACE,
4596 "init", &cmdline_init,
4599 log_debug("Failed to parse /proc/cmdline: %s", strerror(-r));
4601 init = cmdline_init;
4608 const char *root_systemd_path = NULL, *root_init_path = NULL;
4610 root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
4611 root_init_path = strappenda3(root, "/", init);
4613 /* If the passed init is actually the same as the
4614 * systemd binary, then let's suppress it. */
4615 if (files_same(root_init_path, root_systemd_path) > 0)
4619 log_debug("Switching root - root: %s; init: %s", root, strna(init));
4621 r = sd_bus_call_method(
4623 "org.freedesktop.systemd1",
4624 "/org/freedesktop/systemd1",
4625 "org.freedesktop.systemd1.Manager",
4631 log_error("Failed to switch root: %s", bus_error_message(&error, r));
4638 static int set_environment(sd_bus *bus, char **args) {
4639 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4640 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4647 method = streq(args[0], "set-environment")
4649 : "UnsetEnvironment";
4651 r = sd_bus_message_new_method_call(
4654 "org.freedesktop.systemd1",
4655 "/org/freedesktop/systemd1",
4656 "org.freedesktop.systemd1.Manager",
4659 return bus_log_create_error(r);
4661 r = sd_bus_message_append_strv(m, args + 1);
4663 return bus_log_create_error(r);
4665 r = sd_bus_call(bus, m, 0, &error, NULL);
4667 log_error("Failed to set environment: %s", bus_error_message(&error, r));
4674 static int import_environment(sd_bus *bus, char **args) {
4675 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4676 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4682 r = sd_bus_message_new_method_call(
4685 "org.freedesktop.systemd1",
4686 "/org/freedesktop/systemd1",
4687 "org.freedesktop.systemd1.Manager",
4690 return bus_log_create_error(r);
4692 if (strv_isempty(args + 1))
4693 r = sd_bus_message_append_strv(m, environ);
4697 r = sd_bus_message_open_container(m, 'a', "s");
4699 return bus_log_create_error(r);
4701 STRV_FOREACH(a, args + 1) {
4703 if (!env_name_is_valid(*a)) {
4704 log_error("Not a valid environment variable name: %s", *a);
4708 STRV_FOREACH(b, environ) {
4711 eq = startswith(*b, *a);
4712 if (eq && *eq == '=') {
4714 r = sd_bus_message_append(m, "s", *b);
4716 return bus_log_create_error(r);
4723 r = sd_bus_message_close_container(m);
4726 return bus_log_create_error(r);
4728 r = sd_bus_call(bus, m, 0, &error, NULL);
4730 log_error("Failed to import environment: %s", bus_error_message(&error, r));
4737 static int enable_sysv_units(const char *verb, char **args) {
4740 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4741 unsigned f = 1, t = 1;
4742 _cleanup_lookup_paths_free_ LookupPaths paths = {};
4744 if (arg_scope != UNIT_FILE_SYSTEM)
4747 if (!streq(verb, "enable") &&
4748 !streq(verb, "disable") &&
4749 !streq(verb, "is-enabled"))
4752 /* Processes all SysV units, and reshuffles the array so that
4753 * afterwards only the native units remain */
4755 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4760 for (f = 0; args[f]; f++) {
4762 _cleanup_free_ char *p = NULL, *q = NULL;
4763 bool found_native = false, found_sysv;
4765 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4773 if (!endswith(name, ".service"))
4776 if (path_is_absolute(name))
4779 STRV_FOREACH(k, paths.unit_path) {
4780 if (!isempty(arg_root))
4781 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4783 asprintf(&p, "%s/%s", *k, name);
4790 found_native = access(p, F_OK) >= 0;
4801 if (!isempty(arg_root))
4802 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4804 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4810 p[strlen(p) - sizeof(".service") + 1] = 0;
4811 found_sysv = access(p, F_OK) >= 0;
4816 /* Mark this entry, so that we don't try enabling it as native unit */
4817 args[f] = (char*) "";
4819 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4821 if (!isempty(arg_root))
4822 argv[c++] = q = strappend("--root=", arg_root);
4824 argv[c++] = basename(p);
4826 streq(verb, "enable") ? "on" :
4827 streq(verb, "disable") ? "off" : "--level=5";
4830 l = strv_join((char**)argv, " ");
4836 log_info("Executing %s", l);
4841 log_error("Failed to fork: %m");
4844 } else if (pid == 0) {
4847 execv(argv[0], (char**) argv);
4848 _exit(EXIT_FAILURE);
4851 j = wait_for_terminate(pid, &status);
4853 log_error("Failed to wait for child: %s", strerror(-r));
4858 if (status.si_code == CLD_EXITED) {
4859 if (streq(verb, "is-enabled")) {
4860 if (status.si_status == 0) {
4869 } else if (status.si_status != 0) {
4880 /* Drop all SysV units */
4881 for (f = 0, t = 0; args[f]; f++) {
4883 if (isempty(args[f]))
4886 args[t++] = args[f];
4895 static int mangle_names(char **original_names, char ***mangled_names) {
4896 char **i, **l, **name;
4898 l = new(char*, strv_length(original_names) + 1);
4903 STRV_FOREACH(name, original_names) {
4905 /* When enabling units qualified path names are OK,
4906 * too, hence allow them explicitly. */
4911 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
4927 static int enable_unit(sd_bus *bus, char **args) {
4928 _cleanup_strv_free_ char **names = NULL;
4929 const char *verb = args[0];
4930 UnitFileChange *changes = NULL;
4931 unsigned n_changes = 0;
4932 int carries_install_info = -1;
4938 r = mangle_names(args+1, &names);
4942 r = enable_sysv_units(verb, names);
4946 /* If the operation was fully executed by the SysV compat,
4947 * let's finish early */
4948 if (strv_isempty(names))
4951 if (!bus || avoid_bus()) {
4952 if (streq(verb, "enable")) {
4953 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
4954 carries_install_info = r;
4955 } else if (streq(verb, "disable"))
4956 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
4957 else if (streq(verb, "reenable")) {
4958 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
4959 carries_install_info = r;
4960 } else if (streq(verb, "link"))
4961 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
4962 else if (streq(verb, "preset")) {
4963 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
4964 carries_install_info = r;
4965 } else if (streq(verb, "mask"))
4966 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
4967 else if (streq(verb, "unmask"))
4968 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
4970 assert_not_reached("Unknown verb");
4973 log_error("Operation failed: %s", strerror(-r));
4978 dump_unit_file_changes(changes, n_changes);
4982 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
4983 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4984 int expect_carries_install_info = false;
4985 bool send_force = true;
4988 if (streq(verb, "enable")) {
4989 method = "EnableUnitFiles";
4990 expect_carries_install_info = true;
4991 } else if (streq(verb, "disable")) {
4992 method = "DisableUnitFiles";
4994 } else if (streq(verb, "reenable")) {
4995 method = "ReenableUnitFiles";
4996 expect_carries_install_info = true;
4997 } else if (streq(verb, "link"))
4998 method = "LinkUnitFiles";
4999 else if (streq(verb, "preset")) {
5000 method = "PresetUnitFiles";
5001 expect_carries_install_info = true;
5002 } else if (streq(verb, "mask"))
5003 method = "MaskUnitFiles";
5004 else if (streq(verb, "unmask")) {
5005 method = "UnmaskUnitFiles";
5008 assert_not_reached("Unknown verb");
5010 r = sd_bus_message_new_method_call(
5013 "org.freedesktop.systemd1",
5014 "/org/freedesktop/systemd1",
5015 "org.freedesktop.systemd1.Manager",
5018 return bus_log_create_error(r);
5020 r = sd_bus_message_append_strv(m, names);
5022 return bus_log_create_error(r);
5024 r = sd_bus_message_append(m, "b", arg_runtime);
5026 return bus_log_create_error(r);
5029 r = sd_bus_message_append(m, "b", arg_force);
5031 return bus_log_create_error(r);
5034 r = sd_bus_call(bus, m, 0, &error, &reply);
5036 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5040 if (expect_carries_install_info) {
5041 r = sd_bus_message_read(reply, "b", &carries_install_info);
5043 return bus_log_parse_error(r);
5046 r = deserialize_and_dump_unit_file_changes(reply);
5050 /* Try to reload if enabeld */
5052 r = daemon_reload(bus, args);
5057 if (carries_install_info == 0)
5058 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5059 "using systemctl.\n"
5060 "Possible reasons for having this kind of units are:\n"
5061 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5062 " .wants/ or .requires/ directory.\n"
5063 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5064 " a requirement dependency on it.\n"
5065 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5066 " D-Bus, udev, scripted systemctl call, ...).\n");
5069 unit_file_changes_free(changes, n_changes);
5074 static int unit_is_enabled(sd_bus *bus, char **args) {
5076 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5077 _cleanup_strv_free_ char **names = NULL;
5082 r = mangle_names(args+1, &names);
5086 r = enable_sysv_units(args[0], names);
5092 if (!bus || avoid_bus()) {
5094 STRV_FOREACH(name, names) {
5095 UnitFileState state;
5097 state = unit_file_get_state(arg_scope, arg_root, *name);
5099 log_error("Failed to get unit file state for %s: %s", *name, strerror(-state));
5103 if (state == UNIT_FILE_ENABLED ||
5104 state == UNIT_FILE_ENABLED_RUNTIME ||
5105 state == UNIT_FILE_STATIC)
5109 puts(unit_file_state_to_string(state));
5113 STRV_FOREACH(name, names) {
5114 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5117 r = sd_bus_call_method(
5119 "org.freedesktop.systemd1",
5120 "/org/freedesktop/systemd1",
5121 "org.freedesktop.systemd1.Manager",
5127 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5131 r = sd_bus_message_read(reply, "s", &s);
5133 return bus_log_parse_error(r);
5135 if (streq(s, "enabled") ||
5136 streq(s, "enabled-runtime") ||
5148 static int systemctl_help(void) {
5150 pager_open_if_enabled();
5152 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
5153 "Query or send control commands to the systemd manager.\n\n"
5154 " -h --help Show this help\n"
5155 " --version Show package version\n"
5156 " --system Connect to system manager\n"
5157 " --user Connect to user service manager\n"
5158 " -H --host=[USER@]HOST\n"
5159 " Operate on remote host\n"
5160 " -M --machine=CONTAINER\n"
5161 " Operate on local container\n"
5162 " -t --type=TYPE List only units of a particular type\n"
5163 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
5164 " -p --property=NAME Show only properties by this name\n"
5165 " -a --all Show all loaded units/properties, including dead/empty\n"
5166 " ones. To list all units installed on the system, use\n"
5167 " the 'list-unit-files' command instead.\n"
5168 " -l --full Don't ellipsize unit names on output\n"
5169 " --reverse Show reverse dependencies with 'list-dependencies'\n"
5170 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
5171 " queueing a new job\n"
5172 " --show-types When showing sockets, explicitly show their type\n"
5173 " -i --ignore-inhibitors\n"
5174 " When shutting down or sleeping, ignore inhibitors\n"
5175 " --kill-who=WHO Who to send signal to\n"
5176 " -s --signal=SIGNAL Which signal to send\n"
5177 " -q --quiet Suppress output\n"
5178 " --no-block Do not wait until operation finished\n"
5179 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5180 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
5182 " --no-legend Do not print a legend (column headers and hints)\n"
5183 " --no-pager Do not pipe output into a pager\n"
5184 " --no-ask-password\n"
5185 " Do not ask for system passwords\n"
5186 " --global Enable/disable unit files globally\n"
5187 " --runtime Enable unit files only temporarily until next reboot\n"
5188 " -f --force When enabling unit files, override existing symlinks\n"
5189 " When shutting down, execute action immediately\n"
5190 " --root=PATH Enable unit files in the specified root directory\n"
5191 " -n --lines=INTEGER Number of journal entries to show\n"
5192 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
5193 " verbose, export, json, json-pretty, json-sse, cat)\n"
5194 " --plain Print unit dependencies as a list instead of a tree\n\n"
5196 " list-units [PATTERN...] List loaded units\n"
5197 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
5198 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
5199 " start NAME... Start (activate) one or more units\n"
5200 " stop NAME... Stop (deactivate) one or more units\n"
5201 " reload NAME... Reload one or more units\n"
5202 " restart NAME... Start or restart one or more units\n"
5203 " try-restart NAME... Restart one or more units if active\n"
5204 " reload-or-restart NAME... Reload one or more units if possible,\n"
5205 " otherwise start or restart\n"
5206 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
5207 " otherwise restart if active\n"
5208 " isolate NAME Start one unit and stop all others\n"
5209 " kill NAME... Send signal to processes of a unit\n"
5210 " is-active NAME... Check whether units are active\n"
5211 " is-failed NAME... Check whether units are failed\n"
5212 " status [NAME...|PID...] Show runtime status of one or more units\n"
5213 " show [NAME...|JOB...] Show properties of one or more\n"
5214 " units/jobs or the manager\n"
5215 " cat NAME... Show files and drop-ins of one or more units\n"
5216 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
5217 " help NAME...|PID... Show manual for one or more units\n"
5218 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
5220 " list-dependencies [NAME] Recursively show units which are required\n"
5221 " or wanted by this unit or by which this\n"
5222 " unit is required or wanted\n\n"
5223 "Unit File Commands:\n"
5224 " list-unit-files [PATTERN...] List installed unit files\n"
5225 " enable NAME... Enable one or more unit files\n"
5226 " disable NAME... Disable one or more unit files\n"
5227 " reenable NAME... Reenable one or more unit files\n"
5228 " preset NAME... Enable/disable one or more unit files\n"
5229 " based on preset configuration\n"
5230 " is-enabled NAME... Check whether unit files are enabled\n\n"
5231 " mask NAME... Mask one or more units\n"
5232 " unmask NAME... Unmask one or more units\n"
5233 " link PATH... Link one or more units files into\n"
5234 " the search path\n"
5235 " get-default Get the name of the default target\n"
5236 " set-default NAME Set the default target\n\n"
5237 "Machine Commands:\n"
5238 " list-machines [PATTERN...] List local containers and host\n\n"
5240 " list-jobs [PATTERN...] List jobs\n"
5241 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
5242 "Snapshot Commands:\n"
5243 " snapshot [NAME] Create a snapshot\n"
5244 " delete NAME... Remove one or more snapshots\n\n"
5245 "Environment Commands:\n"
5246 " show-environment Dump environment\n"
5247 " set-environment NAME=VALUE... Set one or more environment variables\n"
5248 " unset-environment NAME... Unset one or more environment variables\n"
5249 " import-environment NAME... Import all, one or more environment variables\n\n"
5250 "Manager Lifecycle Commands:\n"
5251 " daemon-reload Reload systemd manager configuration\n"
5252 " daemon-reexec Reexecute systemd manager\n\n"
5253 "System Commands:\n"
5254 " default Enter system default mode\n"
5255 " rescue Enter system rescue mode\n"
5256 " emergency Enter system emergency mode\n"
5257 " halt Shut down and halt the system\n"
5258 " poweroff Shut down and power-off the system\n"
5259 " reboot [ARG] Shut down and reboot the system\n"
5260 " kexec Shut down and reboot the system with kexec\n"
5261 " exit Request user instance exit\n"
5262 " switch-root ROOT [INIT] Change to a different root file system\n"
5263 " suspend Suspend the system\n"
5264 " hibernate Hibernate the system\n"
5265 " hybrid-sleep Hibernate and suspend the system\n",
5266 program_invocation_short_name);
5271 static int halt_help(void) {
5273 printf("%s [OPTIONS...]%s\n\n"
5274 "%s the system.\n\n"
5275 " --help Show this help\n"
5276 " --halt Halt the machine\n"
5277 " -p --poweroff Switch off the machine\n"
5278 " --reboot Reboot the machine\n"
5279 " -f --force Force immediate halt/power-off/reboot\n"
5280 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
5281 " -d --no-wtmp Don't write wtmp record\n"
5282 " --no-wall Don't send wall message before halt/power-off/reboot\n",
5283 program_invocation_short_name,
5284 arg_action == ACTION_REBOOT ? " [ARG]" : "",
5285 arg_action == ACTION_REBOOT ? "Reboot" :
5286 arg_action == ACTION_POWEROFF ? "Power off" :
5292 static int shutdown_help(void) {
5294 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
5295 "Shut down the system.\n\n"
5296 " --help Show this help\n"
5297 " -H --halt Halt the machine\n"
5298 " -P --poweroff Power-off the machine\n"
5299 " -r --reboot Reboot the machine\n"
5300 " -h Equivalent to --poweroff, overridden by --halt\n"
5301 " -k Don't halt/power-off/reboot, just send warnings\n"
5302 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5303 " -c Cancel a pending shutdown\n",
5304 program_invocation_short_name);
5309 static int telinit_help(void) {
5311 printf("%s [OPTIONS...] {COMMAND}\n\n"
5312 "Send control commands to the init daemon.\n\n"
5313 " --help Show this help\n"
5314 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
5316 " 0 Power-off the machine\n"
5317 " 6 Reboot the machine\n"
5318 " 2, 3, 4, 5 Start runlevelX.target unit\n"
5319 " 1, s, S Enter rescue mode\n"
5320 " q, Q Reload init daemon configuration\n"
5321 " u, U Reexecute init daemon\n",
5322 program_invocation_short_name);
5327 static int runlevel_help(void) {
5329 printf("%s [OPTIONS...]\n\n"
5330 "Prints the previous and current runlevel of the init system.\n\n"
5331 " --help Show this help\n",
5332 program_invocation_short_name);
5337 static int help_types(void) {
5341 puts("Available unit types:");
5342 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
5343 t = unit_type_to_string(i);
5351 static int systemctl_parse_argv(int argc, char *argv[]) {
5360 ARG_IGNORE_DEPENDENCIES,
5372 ARG_NO_ASK_PASSWORD,
5381 static const struct option options[] = {
5382 { "help", no_argument, NULL, 'h' },
5383 { "version", no_argument, NULL, ARG_VERSION },
5384 { "type", required_argument, NULL, 't' },
5385 { "property", required_argument, NULL, 'p' },
5386 { "all", no_argument, NULL, 'a' },
5387 { "reverse", no_argument, NULL, ARG_REVERSE },
5388 { "after", no_argument, NULL, ARG_AFTER },
5389 { "before", no_argument, NULL, ARG_BEFORE },
5390 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
5391 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
5392 { "full", no_argument, NULL, 'l' },
5393 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
5394 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
5395 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
5396 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
5397 { "ignore-inhibitors", no_argument, NULL, 'i' },
5398 { "user", no_argument, NULL, ARG_USER },
5399 { "system", no_argument, NULL, ARG_SYSTEM },
5400 { "global", no_argument, NULL, ARG_GLOBAL },
5401 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
5402 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
5403 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
5404 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5405 { "quiet", no_argument, NULL, 'q' },
5406 { "root", required_argument, NULL, ARG_ROOT },
5407 { "force", no_argument, NULL, ARG_FORCE },
5408 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
5409 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
5410 { "signal", required_argument, NULL, 's' },
5411 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
5412 { "host", required_argument, NULL, 'H' },
5413 { "machine", required_argument, NULL, 'M' },
5414 { "runtime", no_argument, NULL, ARG_RUNTIME },
5415 { "lines", required_argument, NULL, 'n' },
5416 { "output", required_argument, NULL, 'o' },
5417 { "plain", no_argument, NULL, ARG_PLAIN },
5418 { "state", required_argument, NULL, ARG_STATE },
5427 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:i", options, NULL)) >= 0) {
5432 return systemctl_help();
5435 puts(PACKAGE_STRING);
5436 puts(SYSTEMD_FEATURES);
5443 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5444 _cleanup_free_ char *type;
5446 type = strndup(word, size);
5450 if (streq(type, "help")) {
5455 if (unit_type_from_string(type) >= 0) {
5456 if (strv_push(&arg_types, type))
5462 /* It's much nicer to use --state= for
5463 * load states, but let's support this
5464 * in --types= too for compatibility
5465 * with old versions */
5466 if (unit_load_state_from_string(optarg) >= 0) {
5467 if (strv_push(&arg_states, type) < 0)
5473 log_error("Unknown unit type or load state '%s'.", type);
5474 log_info("Use -t help to see a list of allowed values.");
5482 /* Make sure that if the empty property list
5483 was specified, we won't show any properties. */
5484 if (isempty(optarg) && !arg_properties) {
5485 arg_properties = new0(char*, 1);
5486 if (!arg_properties)
5492 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5495 prop = strndup(word, size);
5499 if (strv_consume(&arg_properties, prop) < 0)
5504 /* If the user asked for a particular
5505 * property, show it to him, even if it is
5517 arg_dependency = DEPENDENCY_REVERSE;
5521 arg_dependency = DEPENDENCY_AFTER;
5525 arg_dependency = DEPENDENCY_BEFORE;
5528 case ARG_SHOW_TYPES:
5529 arg_show_types = true;
5533 arg_job_mode = optarg;
5537 arg_job_mode = "fail";
5540 case ARG_IRREVERSIBLE:
5541 arg_job_mode = "replace-irreversibly";
5544 case ARG_IGNORE_DEPENDENCIES:
5545 arg_job_mode = "ignore-dependencies";
5549 arg_scope = UNIT_FILE_USER;
5553 arg_scope = UNIT_FILE_SYSTEM;
5557 arg_scope = UNIT_FILE_GLOBAL;
5561 arg_no_block = true;
5565 arg_no_legend = true;
5569 arg_no_pager = true;
5585 if (strv_extend(&arg_states, "failed") < 0)
5603 arg_no_reload = true;
5607 arg_kill_who = optarg;
5611 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5612 log_error("Failed to parse signal string %s.", optarg);
5617 case ARG_NO_ASK_PASSWORD:
5618 arg_ask_password = false;
5622 arg_transport = BUS_TRANSPORT_REMOTE;
5627 arg_transport = BUS_TRANSPORT_CONTAINER;
5636 if (safe_atou(optarg, &arg_lines) < 0) {
5637 log_error("Failed to parse lines '%s'", optarg);
5643 arg_output = output_mode_from_string(optarg);
5644 if (arg_output < 0) {
5645 log_error("Unknown output '%s'.", optarg);
5651 arg_ignore_inhibitors = true;
5662 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5665 s = strndup(word, size);
5669 if (strv_consume(&arg_states, s) < 0)
5679 assert_not_reached("Unhandled option");
5683 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
5684 log_error("Cannot access user instance remotely.");
5691 static int halt_parse_argv(int argc, char *argv[]) {
5700 static const struct option options[] = {
5701 { "help", no_argument, NULL, ARG_HELP },
5702 { "halt", no_argument, NULL, ARG_HALT },
5703 { "poweroff", no_argument, NULL, 'p' },
5704 { "reboot", no_argument, NULL, ARG_REBOOT },
5705 { "force", no_argument, NULL, 'f' },
5706 { "wtmp-only", no_argument, NULL, 'w' },
5707 { "no-wtmp", no_argument, NULL, 'd' },
5708 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5717 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5718 if (runlevel == '0' || runlevel == '6')
5721 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5728 arg_action = ACTION_HALT;
5732 if (arg_action != ACTION_REBOOT)
5733 arg_action = ACTION_POWEROFF;
5737 arg_action = ACTION_REBOOT;
5759 /* Compatibility nops */
5766 assert_not_reached("Unhandled option");
5770 if (arg_action == ACTION_REBOOT && argc == optind + 1) {
5771 r = write_string_file(REBOOT_PARAM_FILE, argv[optind]);
5773 log_error("Failed to write reboot param to "
5774 REBOOT_PARAM_FILE": %s", strerror(-r));
5777 } else if (optind < argc) {
5778 log_error("Too many arguments.");
5785 static int parse_time_spec(const char *t, usec_t *_u) {
5789 if (streq(t, "now"))
5791 else if (!strchr(t, ':')) {
5794 if (safe_atou64(t, &u) < 0)
5797 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5806 hour = strtol(t, &e, 10);
5807 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5810 minute = strtol(e+1, &e, 10);
5811 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5814 n = now(CLOCK_REALTIME);
5815 s = (time_t) (n / USEC_PER_SEC);
5817 assert_se(localtime_r(&s, &tm));
5819 tm.tm_hour = (int) hour;
5820 tm.tm_min = (int) minute;
5823 assert_se(s = mktime(&tm));
5825 *_u = (usec_t) s * USEC_PER_SEC;
5828 *_u += USEC_PER_DAY;
5834 static int shutdown_parse_argv(int argc, char *argv[]) {
5841 static const struct option options[] = {
5842 { "help", no_argument, NULL, ARG_HELP },
5843 { "halt", no_argument, NULL, 'H' },
5844 { "poweroff", no_argument, NULL, 'P' },
5845 { "reboot", no_argument, NULL, 'r' },
5846 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5847 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5856 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5860 return shutdown_help();
5863 arg_action = ACTION_HALT;
5867 arg_action = ACTION_POWEROFF;
5872 arg_action = ACTION_KEXEC;
5874 arg_action = ACTION_REBOOT;
5878 arg_action = ACTION_KEXEC;
5882 if (arg_action != ACTION_HALT)
5883 arg_action = ACTION_POWEROFF;
5896 /* Compatibility nops */
5900 arg_action = ACTION_CANCEL_SHUTDOWN;
5907 assert_not_reached("Unhandled option");
5911 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5912 r = parse_time_spec(argv[optind], &arg_when);
5914 log_error("Failed to parse time specification: %s", argv[optind]);
5918 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5920 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5921 /* No time argument for shutdown cancel */
5922 arg_wall = argv + optind;
5923 else if (argc > optind + 1)
5924 /* We skip the time argument */
5925 arg_wall = argv + optind + 1;
5932 static int telinit_parse_argv(int argc, char *argv[]) {
5939 static const struct option options[] = {
5940 { "help", no_argument, NULL, ARG_HELP },
5941 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5945 static const struct {
5949 { '0', ACTION_POWEROFF },
5950 { '6', ACTION_REBOOT },
5951 { '1', ACTION_RESCUE },
5952 { '2', ACTION_RUNLEVEL2 },
5953 { '3', ACTION_RUNLEVEL3 },
5954 { '4', ACTION_RUNLEVEL4 },
5955 { '5', ACTION_RUNLEVEL5 },
5956 { 's', ACTION_RESCUE },
5957 { 'S', ACTION_RESCUE },
5958 { 'q', ACTION_RELOAD },
5959 { 'Q', ACTION_RELOAD },
5960 { 'u', ACTION_REEXEC },
5961 { 'U', ACTION_REEXEC }
5970 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5974 return telinit_help();
5984 assert_not_reached("Unhandled option");
5988 if (optind >= argc) {
5993 if (optind + 1 < argc) {
5994 log_error("Too many arguments.");
5998 if (strlen(argv[optind]) != 1) {
5999 log_error("Expected single character argument.");
6003 for (i = 0; i < ELEMENTSOF(table); i++)
6004 if (table[i].from == argv[optind][0])
6007 if (i >= ELEMENTSOF(table)) {
6008 log_error("Unknown command '%s'.", argv[optind]);
6012 arg_action = table[i].to;
6019 static int runlevel_parse_argv(int argc, char *argv[]) {
6025 static const struct option options[] = {
6026 { "help", no_argument, NULL, ARG_HELP },
6035 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
6039 return runlevel_help();
6045 assert_not_reached("Unhandled option");
6049 if (optind < argc) {
6050 log_error("Too many arguments.");
6057 static int parse_argv(int argc, char *argv[]) {
6061 if (program_invocation_short_name) {
6063 if (strstr(program_invocation_short_name, "halt")) {
6064 arg_action = ACTION_HALT;
6065 return halt_parse_argv(argc, argv);
6066 } else if (strstr(program_invocation_short_name, "poweroff")) {
6067 arg_action = ACTION_POWEROFF;
6068 return halt_parse_argv(argc, argv);
6069 } else if (strstr(program_invocation_short_name, "reboot")) {
6071 arg_action = ACTION_KEXEC;
6073 arg_action = ACTION_REBOOT;
6074 return halt_parse_argv(argc, argv);
6075 } else if (strstr(program_invocation_short_name, "shutdown")) {
6076 arg_action = ACTION_POWEROFF;
6077 return shutdown_parse_argv(argc, argv);
6078 } else if (strstr(program_invocation_short_name, "init")) {
6080 if (sd_booted() > 0) {
6081 arg_action = _ACTION_INVALID;
6082 return telinit_parse_argv(argc, argv);
6084 /* Hmm, so some other init system is
6085 * running, we need to forward this
6086 * request to it. For now we simply
6087 * guess that it is Upstart. */
6089 execv(TELINIT, argv);
6091 log_error("Couldn't find an alternative telinit implementation to spawn.");
6095 } else if (strstr(program_invocation_short_name, "runlevel")) {
6096 arg_action = ACTION_RUNLEVEL;
6097 return runlevel_parse_argv(argc, argv);
6101 arg_action = ACTION_SYSTEMCTL;
6102 return systemctl_parse_argv(argc, argv);
6105 _pure_ static int action_to_runlevel(void) {
6107 static const char table[_ACTION_MAX] = {
6108 [ACTION_HALT] = '0',
6109 [ACTION_POWEROFF] = '0',
6110 [ACTION_REBOOT] = '6',
6111 [ACTION_RUNLEVEL2] = '2',
6112 [ACTION_RUNLEVEL3] = '3',
6113 [ACTION_RUNLEVEL4] = '4',
6114 [ACTION_RUNLEVEL5] = '5',
6115 [ACTION_RESCUE] = '1'
6118 assert(arg_action < _ACTION_MAX);
6120 return table[arg_action];
6123 static int talk_initctl(void) {
6125 struct init_request request = {
6126 .magic = INIT_MAGIC,
6128 .cmd = INIT_CMD_RUNLVL
6131 _cleanup_close_ int fd = -1;
6135 rl = action_to_runlevel();
6139 request.runlevel = rl;
6141 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
6143 if (errno == ENOENT)
6146 log_error("Failed to open "INIT_FIFO": %m");
6151 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
6153 log_error("Failed to write to "INIT_FIFO": %m");
6154 return errno > 0 ? -errno : -EIO;
6160 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
6162 static const struct {
6170 int (* const dispatch)(sd_bus *bus, char **args);
6176 { "list-units", MORE, 0, list_units },
6177 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
6178 { "list-sockets", MORE, 1, list_sockets },
6179 { "list-timers", MORE, 1, list_timers },
6180 { "list-jobs", MORE, 1, list_jobs },
6181 { "list-machines", MORE, 1, list_machines },
6182 { "clear-jobs", EQUAL, 1, daemon_reload },
6183 { "cancel", MORE, 2, cancel_job },
6184 { "start", MORE, 2, start_unit },
6185 { "stop", MORE, 2, start_unit },
6186 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6187 { "reload", MORE, 2, start_unit },
6188 { "restart", MORE, 2, start_unit },
6189 { "try-restart", MORE, 2, start_unit },
6190 { "reload-or-restart", MORE, 2, start_unit },
6191 { "reload-or-try-restart", MORE, 2, start_unit },
6192 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
6193 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6194 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
6195 { "isolate", EQUAL, 2, start_unit },
6196 { "kill", MORE, 2, kill_unit },
6197 { "is-active", MORE, 2, check_unit_active },
6198 { "check", MORE, 2, check_unit_active },
6199 { "is-failed", MORE, 2, check_unit_failed },
6200 { "show", MORE, 1, show },
6201 { "cat", MORE, 2, cat },
6202 { "status", MORE, 1, show },
6203 { "help", MORE, 2, show },
6204 { "snapshot", LESS, 2, snapshot },
6205 { "delete", MORE, 2, delete_snapshot },
6206 { "daemon-reload", EQUAL, 1, daemon_reload },
6207 { "daemon-reexec", EQUAL, 1, daemon_reload },
6208 { "show-environment", EQUAL, 1, show_environment },
6209 { "set-environment", MORE, 2, set_environment },
6210 { "unset-environment", MORE, 2, set_environment },
6211 { "import-environment", MORE, 1, import_environment},
6212 { "halt", EQUAL, 1, start_special, FORCE },
6213 { "poweroff", EQUAL, 1, start_special, FORCE },
6214 { "reboot", EQUAL, 1, start_special, FORCE },
6215 { "kexec", EQUAL, 1, start_special },
6216 { "suspend", EQUAL, 1, start_special },
6217 { "hibernate", EQUAL, 1, start_special },
6218 { "hybrid-sleep", EQUAL, 1, start_special },
6219 { "default", EQUAL, 1, start_special },
6220 { "rescue", EQUAL, 1, start_special },
6221 { "emergency", EQUAL, 1, start_special },
6222 { "exit", EQUAL, 1, start_special },
6223 { "reset-failed", MORE, 1, reset_failed },
6224 { "enable", MORE, 2, enable_unit, NOBUS },
6225 { "disable", MORE, 2, enable_unit, NOBUS },
6226 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
6227 { "reenable", MORE, 2, enable_unit, NOBUS },
6228 { "preset", MORE, 2, enable_unit, NOBUS },
6229 { "mask", MORE, 2, enable_unit, NOBUS },
6230 { "unmask", MORE, 2, enable_unit, NOBUS },
6231 { "link", MORE, 2, enable_unit, NOBUS },
6232 { "switch-root", MORE, 2, switch_root },
6233 { "list-dependencies", LESS, 2, list_dependencies },
6234 { "set-default", EQUAL, 2, set_default, NOBUS },
6235 { "get-default", EQUAL, 1, get_default, NOBUS },
6236 { "set-property", MORE, 3, set_property },
6245 left = argc - optind;
6247 /* Special rule: no arguments (left == 0) means "list-units" */
6249 if (streq(argv[optind], "help") && !argv[optind+1]) {
6250 log_error("This command expects one or more "
6251 "unit names. Did you mean --help?");
6255 for (; verb->verb; verb++)
6256 if (streq(argv[optind], verb->verb))
6259 log_error("Unknown operation '%s'.", argv[optind]);
6264 switch (verb->argc_cmp) {
6267 if (left != verb->argc) {
6268 log_error("Invalid number of arguments.");
6275 if (left < verb->argc) {
6276 log_error("Too few arguments.");
6283 if (left > verb->argc) {
6284 log_error("Too many arguments.");
6291 assert_not_reached("Unknown comparison operator.");
6294 /* Require a bus connection for all operations but
6296 if (verb->bus == NOBUS) {
6297 if (!bus && !avoid_bus()) {
6298 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6303 if (running_in_chroot() > 0) {
6304 log_info("Running in chroot, ignoring request.");
6308 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
6309 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6314 return verb->dispatch(bus, argv + optind);
6317 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
6319 struct sd_shutdown_command c = {
6326 union sockaddr_union sockaddr = {
6327 .un.sun_family = AF_UNIX,
6328 .un.sun_path = "/run/systemd/shutdownd",
6331 struct iovec iovec[2] = {{
6332 .iov_base = (char*) &c,
6333 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
6336 struct msghdr msghdr = {
6337 .msg_name = &sockaddr,
6338 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
6339 + sizeof("/run/systemd/shutdownd") - 1,
6344 _cleanup_close_ int fd;
6346 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
6350 if (!isempty(message)) {
6351 iovec[1].iov_base = (char*) message;
6352 iovec[1].iov_len = strlen(message);
6353 msghdr.msg_iovlen++;
6356 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
6362 static int reload_with_fallback(sd_bus *bus) {
6365 /* First, try systemd via D-Bus. */
6366 if (daemon_reload(bus, NULL) >= 0)
6370 /* Nothing else worked, so let's try signals */
6371 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
6373 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
6374 log_error("kill() failed: %m");
6381 static int start_with_fallback(sd_bus *bus) {
6384 /* First, try systemd via D-Bus. */
6385 if (start_unit(bus, NULL) >= 0)
6389 /* Nothing else worked, so let's try
6391 if (talk_initctl() > 0)
6394 log_error("Failed to talk to init daemon.");
6398 warn_wall(arg_action);
6402 static int halt_now(enum action a) {
6404 /* Make sure C-A-D is handled by the kernel from this
6406 reboot(RB_ENABLE_CAD);
6411 log_info("Halting.");
6412 reboot(RB_HALT_SYSTEM);
6415 case ACTION_POWEROFF:
6416 log_info("Powering off.");
6417 reboot(RB_POWER_OFF);
6420 case ACTION_REBOOT: {
6421 _cleanup_free_ char *param = NULL;
6423 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
6424 log_info("Rebooting with argument '%s'.", param);
6425 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
6426 LINUX_REBOOT_CMD_RESTART2, param);
6429 log_info("Rebooting.");
6430 reboot(RB_AUTOBOOT);
6435 assert_not_reached("Unknown action.");
6439 static int halt_main(sd_bus *bus) {
6442 r = check_inhibitors(bus, arg_action);
6446 if (geteuid() != 0) {
6447 /* Try logind if we are a normal user and no special
6448 * mode applies. Maybe PolicyKit allows us to shutdown
6451 if (arg_when <= 0 &&
6454 (arg_action == ACTION_POWEROFF ||
6455 arg_action == ACTION_REBOOT)) {
6456 r = reboot_with_logind(bus, arg_action);
6461 log_error("Must be root.");
6466 _cleanup_free_ char *m;
6468 m = strv_join(arg_wall, " ");
6472 r = send_shutdownd(arg_when,
6473 arg_action == ACTION_HALT ? 'H' :
6474 arg_action == ACTION_POWEROFF ? 'P' :
6475 arg_action == ACTION_KEXEC ? 'K' :
6482 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6484 char date[FORMAT_TIMESTAMP_MAX];
6486 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6487 format_timestamp(date, sizeof(date), arg_when));
6492 if (!arg_dry && !arg_force)
6493 return start_with_fallback(bus);
6496 if (sd_booted() > 0)
6497 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6499 r = utmp_put_shutdown();
6501 log_warning("Failed to write utmp record: %s", strerror(-r));
6508 r = halt_now(arg_action);
6509 log_error("Failed to reboot: %s", strerror(-r));
6514 static int runlevel_main(void) {
6515 int r, runlevel, previous;
6517 r = utmp_get_runlevel(&runlevel, &previous);
6524 previous <= 0 ? 'N' : previous,
6525 runlevel <= 0 ? 'N' : runlevel);
6530 int main(int argc, char*argv[]) {
6531 _cleanup_bus_unref_ sd_bus *bus = NULL;
6534 setlocale(LC_ALL, "");
6535 log_parse_environment();
6538 /* Explicitly not on_tty() to avoid setting cached value.
6539 * This becomes relevant for piping output which might be
6541 original_stdout_is_tty = isatty(STDOUT_FILENO);
6543 r = parse_argv(argc, argv);
6547 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6548 * let's shortcut this */
6549 if (arg_action == ACTION_RUNLEVEL) {
6550 r = runlevel_main();
6554 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6555 log_info("Running in chroot, ignoring request.");
6561 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
6563 /* systemctl_main() will print an error message for the bus
6564 * connection, but only if it needs to */
6566 switch (arg_action) {
6568 case ACTION_SYSTEMCTL:
6569 r = systemctl_main(bus, argc, argv, r);
6573 case ACTION_POWEROFF:
6579 case ACTION_RUNLEVEL2:
6580 case ACTION_RUNLEVEL3:
6581 case ACTION_RUNLEVEL4:
6582 case ACTION_RUNLEVEL5:
6584 case ACTION_EMERGENCY:
6585 case ACTION_DEFAULT:
6586 r = start_with_fallback(bus);
6591 r = reload_with_fallback(bus);
6594 case ACTION_CANCEL_SHUTDOWN: {
6595 _cleanup_free_ char *m = NULL;
6598 m = strv_join(arg_wall, " ");
6605 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6607 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6611 case ACTION_RUNLEVEL:
6612 case _ACTION_INVALID:
6614 assert_not_reached("Unknown action");
6619 ask_password_agent_close();
6620 polkit_agent_close();
6622 strv_free(arg_types);
6623 strv_free(arg_states);
6624 strv_free(arg_properties);
6626 return r < 0 ? EXIT_FAILURE : r;