1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Marc-Antoine Perennou
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/reboot.h>
24 #include <linux/reboot.h>
25 #include <sys/syscall.h>
32 #include <sys/ioctl.h>
36 #include <sys/socket.h>
39 #include <sys/prctl.h>
42 #include "sd-daemon.h"
43 #include "sd-shutdown.h"
50 #include "utmp-wtmp.h"
53 #include "path-util.h"
55 #include "cgroup-show.h"
56 #include "cgroup-util.h"
58 #include "path-lookup.h"
59 #include "conf-parser.h"
60 #include "exit-status.h"
62 #include "unit-name.h"
64 #include "spawn-ask-password-agent.h"
65 #include "spawn-polkit-agent.h"
67 #include "logs-show.h"
68 #include "socket-util.h"
72 #include "bus-message.h"
73 #include "bus-error.h"
74 #include "bus-errors.h"
76 static char **arg_types = NULL;
77 static char **arg_states = NULL;
78 static char **arg_properties = NULL;
79 static bool arg_all = false;
80 static enum dependency {
86 } arg_dependency = DEPENDENCY_FORWARD;
87 static const char *arg_job_mode = "replace";
88 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
89 static bool arg_no_block = false;
90 static bool arg_no_legend = false;
91 static bool arg_no_pager = false;
92 static bool arg_no_wtmp = false;
93 static bool arg_no_wall = false;
94 static bool arg_no_reload = false;
95 static bool arg_show_types = false;
96 static bool arg_ignore_inhibitors = false;
97 static bool arg_dry = false;
98 static bool arg_quiet = false;
99 static bool arg_full = false;
100 static bool arg_recursive = false;
101 static int arg_force = 0;
102 static bool arg_ask_password = true;
103 static bool arg_runtime = false;
104 static 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;
139 static const struct {
143 { "start", "StartUnit" },
144 { "stop", "StopUnit" },
145 { "condstop", "StopUnit" },
146 { "reload", "ReloadUnit" },
147 { "restart", "RestartUnit" },
148 { "try-restart", "TryRestartUnit" },
149 { "condrestart", "TryRestartUnit" },
150 { "reload-or-restart", "ReloadOrRestartUnit" },
151 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
152 { "condreload", "ReloadOrTryRestartUnit" },
153 { "force-reload", "ReloadOrTryRestartUnit" }
156 static bool original_stdout_is_tty;
158 static int daemon_reload(sd_bus *bus, char **args);
159 static int halt_now(enum action a);
160 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet);
162 static char** strv_skip_first(char **strv) {
163 if (strv_length(strv) > 0)
168 static void pager_open_if_enabled(void) {
176 static void ask_password_agent_open_if_enabled(void) {
178 /* Open the password agent as a child process if necessary */
180 if (!arg_ask_password)
183 if (arg_scope != UNIT_FILE_SYSTEM)
186 if (arg_transport != BUS_TRANSPORT_LOCAL)
189 ask_password_agent_open();
193 static void polkit_agent_open_if_enabled(void) {
195 /* Open the polkit agent as a child process if necessary */
197 if (!arg_ask_password)
200 if (arg_scope != UNIT_FILE_SYSTEM)
203 if (arg_transport != BUS_TRANSPORT_LOCAL)
210 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
213 if (!sd_bus_error_is_set(error))
216 if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) ||
217 sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
218 sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
219 sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
220 return EXIT_NOPERMISSION;
222 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
223 return EXIT_NOTINSTALLED;
225 if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
226 sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED))
227 return EXIT_NOTIMPLEMENTED;
229 if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
230 return EXIT_NOTCONFIGURED;
238 static void warn_wall(enum action a) {
239 static const char *table[_ACTION_MAX] = {
240 [ACTION_HALT] = "The system is going down for system halt NOW!",
241 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
242 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
243 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
244 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
245 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
246 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
253 _cleanup_free_ char *p;
255 p = strv_join(arg_wall, " ");
262 utmp_wall(p, NULL, NULL);
270 utmp_wall(table[a], NULL, NULL);
273 static bool avoid_bus(void) {
275 if (running_in_chroot() > 0)
278 if (sd_booted() <= 0)
281 if (!isempty(arg_root))
284 if (arg_scope == UNIT_FILE_GLOBAL)
290 static int compare_unit_info(const void *a, const void *b) {
291 const UnitInfo *u = a, *v = b;
295 /* First, order by machine */
296 if (!u->machine && v->machine)
298 if (u->machine && !v->machine)
300 if (u->machine && v->machine) {
301 r = strcasecmp(u->machine, v->machine);
306 /* Second, order by unit type */
307 d1 = strrchr(u->id, '.');
308 d2 = strrchr(v->id, '.');
310 r = strcasecmp(d1, d2);
315 /* Third, order by name */
316 return strcasecmp(u->id, v->id);
319 static bool output_show_unit(const UnitInfo *u, char **patterns) {
322 if (!strv_isempty(arg_states))
324 strv_contains(arg_states, u->load_state) ||
325 strv_contains(arg_states, u->sub_state) ||
326 strv_contains(arg_states, u->active_state);
328 if (!strv_isempty(patterns)) {
331 STRV_FOREACH(pattern, patterns)
332 if (fnmatch(*pattern, u->id, FNM_NOESCAPE) == 0)
337 return (!arg_types || ((dot = strrchr(u->id, '.')) &&
338 strv_find(arg_types, dot+1))) &&
339 (arg_all || !(streq(u->active_state, "inactive")
340 || u->following[0]) || u->job_id > 0);
343 static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
344 unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
346 unsigned n_shown = 0;
349 max_id_len = strlen("UNIT");
350 load_len = strlen("LOAD");
351 active_len = strlen("ACTIVE");
352 sub_len = strlen("SUB");
353 job_len = strlen("JOB");
356 for (u = unit_infos; u < unit_infos + c; u++) {
357 max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0));
358 load_len = MAX(load_len, strlen(u->load_state));
359 active_len = MAX(active_len, strlen(u->active_state));
360 sub_len = MAX(sub_len, strlen(u->sub_state));
362 if (u->job_id != 0) {
363 job_len = MAX(job_len, strlen(u->job_type));
367 if (!arg_no_legend &&
368 (streq(u->active_state, "failed") ||
369 STR_IN_SET(u->load_state, "error", "not-found", "masked")))
373 if (!arg_full && original_stdout_is_tty) {
376 id_len = MIN(max_id_len, 25u);
377 basic_len = circle_len + 5 + id_len + 5 + active_len + sub_len;
380 basic_len += job_len + 1;
382 if (basic_len < (unsigned) columns()) {
383 unsigned extra_len, incr;
384 extra_len = columns() - basic_len;
386 /* Either UNIT already got 25, or is fully satisfied.
387 * Grant up to 25 to DESC now. */
388 incr = MIN(extra_len, 25u);
392 /* split the remaining space between UNIT and DESC,
393 * but do not give UNIT more than it needs. */
395 incr = MIN(extra_len / 2, max_id_len - id_len);
397 desc_len += extra_len - incr;
403 for (u = unit_infos; u < unit_infos + c; u++) {
404 _cleanup_free_ char *e = NULL, *j = NULL;
405 const char *on_loaded = "", *off_loaded = "";
406 const char *on_active = "", *off_active = "";
407 const char *on_circle = "", *off_circle = "";
411 if (!n_shown && !arg_no_legend) {
416 printf("%-*s %-*s %-*s %-*s ",
419 active_len, "ACTIVE",
423 printf("%-*s ", job_len, "JOB");
425 if (!arg_full && arg_no_pager)
426 printf("%.*s\n", desc_len, "DESCRIPTION");
428 printf("%s\n", "DESCRIPTION");
433 if (STR_IN_SET(u->load_state, "error", "not-found", "masked")) {
434 on_loaded = ansi_highlight_red();
435 on_circle = ansi_highlight_yellow();
436 off_loaded = off_circle = ansi_highlight_off();
440 if (streq(u->active_state, "failed")) {
441 on_circle = on_active = ansi_highlight_red();
442 off_circle = off_active = ansi_highlight_off();
447 j = strjoin(u->machine, ":", u->id, NULL);
456 e = ellipsize(id, id_len, 33);
464 printf("%s%s%s", on_circle, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_circle);
466 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
467 on_active, id_len, id, off_active,
468 on_loaded, load_len, u->load_state, off_loaded,
469 on_active, active_len, u->active_state,
470 sub_len, u->sub_state, off_active,
471 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
474 printf("%.*s\n", desc_len, u->description);
476 printf("%s\n", u->description);
479 if (!arg_no_legend) {
480 const char *on, *off;
484 "LOAD = Reflects whether the unit definition was properly loaded.\n"
485 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
486 "SUB = The low-level unit activation state, values depend on unit type.");
487 puts(job_count ? "JOB = Pending job for the unit.\n" : "");
488 on = ansi_highlight();
489 off = ansi_highlight_off();
491 on = ansi_highlight_red();
492 off = ansi_highlight_off();
496 printf("%s%u loaded units listed.%s\n"
497 "To show all installed unit files use 'systemctl list-unit-files'.\n",
500 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
501 "To show all installed unit files use 'systemctl list-unit-files'.\n",
508 static int get_unit_list(
512 UnitInfo **unit_infos,
514 sd_bus_message **_reply) {
516 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
517 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
526 r = sd_bus_call_method(
528 "org.freedesktop.systemd1",
529 "/org/freedesktop/systemd1",
530 "org.freedesktop.systemd1.Manager",
536 log_error("Failed to list units: %s", bus_error_message(&error, r));
540 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
542 return bus_log_parse_error(r);
544 while ((r = bus_parse_unit_info(reply, &u)) > 0) {
547 if (!output_show_unit(&u, patterns))
550 if (!GREEDY_REALLOC(*unit_infos, size, c+1))
553 (*unit_infos)[c++] = u;
556 return bus_log_parse_error(r);
558 r = sd_bus_message_exit_container(reply);
560 return bus_log_parse_error(r);
568 static void message_set_freep(Set **set) {
571 while ((m = set_steal_first(*set)))
572 sd_bus_message_unref(m);
577 static int get_unit_list_recursive(
580 UnitInfo **_unit_infos,
584 _cleanup_free_ UnitInfo *unit_infos = NULL;
585 _cleanup_(message_set_freep) Set *replies;
586 sd_bus_message *reply;
594 replies = set_new(NULL, NULL);
598 c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
602 r = set_put(replies, reply);
604 sd_bus_message_unref(reply);
609 _cleanup_strv_free_ char **machines = NULL;
612 r = sd_get_machine_names(&machines);
616 STRV_FOREACH(i, machines) {
617 _cleanup_bus_unref_ sd_bus *container = NULL;
620 r = sd_bus_open_system_container(&container, *i);
622 log_error("Failed to connect to container %s: %s", *i, strerror(-r));
626 k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
632 r = set_put(replies, reply);
634 sd_bus_message_unref(reply);
639 *_machines = machines;
644 *_unit_infos = unit_infos;
653 static int list_units(sd_bus *bus, char **args) {
654 _cleanup_free_ UnitInfo *unit_infos = NULL;
655 _cleanup_(message_set_freep) Set *replies = NULL;
656 _cleanup_strv_free_ char **machines = NULL;
659 pager_open_if_enabled();
661 r = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
665 qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
666 return output_units_list(unit_infos, r);
669 static int get_triggered_units(
674 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
677 r = sd_bus_get_property_strv(
679 "org.freedesktop.systemd1",
681 "org.freedesktop.systemd1.Unit",
687 log_error("Failed to determine triggers: %s", bus_error_message(&error, r));
692 static int get_listening(
694 const char* unit_path,
697 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
698 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
699 const char *type, *path;
702 r = sd_bus_get_property(
704 "org.freedesktop.systemd1",
706 "org.freedesktop.systemd1.Socket",
712 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r));
716 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
718 return bus_log_parse_error(r);
720 while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
722 r = strv_extend(listening, type);
726 r = strv_extend(listening, path);
733 return bus_log_parse_error(r);
735 r = sd_bus_message_exit_container(reply);
737 return bus_log_parse_error(r);
748 /* Note: triggered is a list here, although it almost certainly
749 * will always be one unit. Nevertheless, dbus API allows for multiple
750 * values, so let's follow that.*/
753 /* The strv above is shared. free is set only in the first one. */
757 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
763 o = strcmp(a->path, b->path);
765 o = strcmp(a->type, b->type);
770 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
771 struct socket_info *s;
772 unsigned pathlen = strlen("LISTEN"),
773 typelen = strlen("TYPE") * arg_show_types,
774 socklen = strlen("UNIT"),
775 servlen = strlen("ACTIVATES");
776 const char *on, *off;
778 for (s = socket_infos; s < socket_infos + cs; s++) {
782 socklen = MAX(socklen, strlen(s->id));
784 typelen = MAX(typelen, strlen(s->type));
785 pathlen = MAX(pathlen, strlen(s->path));
787 STRV_FOREACH(a, s->triggered)
788 tmp += strlen(*a) + 2*(a != s->triggered);
789 servlen = MAX(servlen, tmp);
794 printf("%-*s %-*.*s%-*s %s\n",
796 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
800 for (s = socket_infos; s < socket_infos + cs; s++) {
804 printf("%-*s %-*s %-*s",
805 pathlen, s->path, typelen, s->type, socklen, s->id);
808 pathlen, s->path, socklen, s->id);
809 STRV_FOREACH(a, s->triggered)
811 a == s->triggered ? "" : ",", *a);
815 on = ansi_highlight();
816 off = ansi_highlight_off();
820 on = ansi_highlight_red();
821 off = ansi_highlight_off();
824 if (!arg_no_legend) {
825 printf("%s%u sockets listed.%s\n", on, cs, off);
827 printf("Pass --all to see loaded but inactive sockets, too.\n");
833 static int list_sockets(sd_bus *bus, char **args) {
834 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
835 _cleanup_free_ UnitInfo *unit_infos = NULL;
836 _cleanup_free_ struct socket_info *socket_infos = NULL;
838 struct socket_info *s;
843 pager_open_if_enabled();
845 n = get_unit_list(bus, NULL, strv_skip_first(args), &unit_infos, 0, &reply);
849 for (u = unit_infos; u < unit_infos + n; u++) {
850 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
853 if (!endswith(u->id, ".socket"))
856 r = get_triggered_units(bus, u->unit_path, &triggered);
860 c = get_listening(bus, u->unit_path, &listening);
866 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
871 for (i = 0; i < c; i++)
872 socket_infos[cs + i] = (struct socket_info) {
874 .type = listening[i*2],
875 .path = listening[i*2 + 1],
876 .triggered = triggered,
877 .own_triggered = i==0,
880 /* from this point on we will cleanup those socket_infos */
883 listening = triggered = NULL; /* avoid cleanup */
886 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
887 (__compar_fn_t) socket_info_compare);
889 output_sockets_list(socket_infos, cs);
892 assert(cs == 0 || socket_infos);
893 for (s = socket_infos; s < socket_infos + cs; s++) {
896 if (s->own_triggered)
897 strv_free(s->triggered);
903 static int get_next_elapse(
906 dual_timestamp *next) {
908 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
916 r = sd_bus_get_property_trivial(
918 "org.freedesktop.systemd1",
920 "org.freedesktop.systemd1.Timer",
921 "NextElapseUSecMonotonic",
926 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
930 r = sd_bus_get_property_trivial(
932 "org.freedesktop.systemd1",
934 "org.freedesktop.systemd1.Timer",
935 "NextElapseUSecRealtime",
940 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
948 static int get_last_trigger(
953 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
960 r = sd_bus_get_property_trivial(
962 "org.freedesktop.systemd1",
964 "org.freedesktop.systemd1.Timer",
970 log_error("Failed to get last trigger time: %s", bus_error_message(&error, r));
984 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
988 if (a->next_elapse < b->next_elapse)
990 if (a->next_elapse > b->next_elapse)
993 return strcmp(a->id, b->id);
996 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
997 struct timer_info *t;
999 nextlen = strlen("NEXT"),
1000 leftlen = strlen("LEFT"),
1001 lastlen = strlen("LAST"),
1002 passedlen = strlen("PASSED"),
1003 unitlen = strlen("UNIT"),
1004 activatelen = strlen("ACTIVATES");
1006 const char *on, *off;
1008 assert(timer_infos || n == 0);
1010 for (t = timer_infos; t < timer_infos + n; t++) {
1014 if (t->next_elapse > 0) {
1015 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1017 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
1018 nextlen = MAX(nextlen, strlen(tstamp) + 1);
1020 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
1021 leftlen = MAX(leftlen, strlen(trel));
1024 if (t->last_trigger > 0) {
1025 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1027 format_timestamp(tstamp, sizeof(tstamp), t->last_trigger);
1028 lastlen = MAX(lastlen, strlen(tstamp) + 1);
1030 format_timestamp_relative(trel, sizeof(trel), t->last_trigger);
1031 passedlen = MAX(passedlen, strlen(trel));
1034 unitlen = MAX(unitlen, strlen(t->id));
1036 STRV_FOREACH(a, t->triggered)
1037 ul += strlen(*a) + 2*(a != t->triggered);
1039 activatelen = MAX(activatelen, ul);
1044 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1048 passedlen, "PASSED",
1052 for (t = timer_infos; t < timer_infos + n; t++) {
1053 char tstamp1[FORMAT_TIMESTAMP_MAX] = "n/a", trel1[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1054 char tstamp2[FORMAT_TIMESTAMP_MAX] = "n/a", trel2[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1057 format_timestamp(tstamp1, sizeof(tstamp1), t->next_elapse);
1058 format_timestamp_relative(trel1, sizeof(trel1), t->next_elapse);
1060 format_timestamp(tstamp2, sizeof(tstamp2), t->last_trigger);
1061 format_timestamp_relative(trel2, sizeof(trel2), t->last_trigger);
1063 printf("%-*s %-*s %-*s %-*s %-*s",
1064 nextlen, tstamp1, leftlen, trel1, lastlen, tstamp2, passedlen, trel2, unitlen, t->id);
1066 STRV_FOREACH(a, t->triggered)
1068 a == t->triggered ? "" : ",", *a);
1072 on = ansi_highlight();
1073 off = ansi_highlight_off();
1077 on = ansi_highlight_red();
1078 off = ansi_highlight_off();
1081 if (!arg_no_legend) {
1082 printf("%s%u timers listed.%s\n", on, n, off);
1084 printf("Pass --all to see loaded but inactive timers, too.\n");
1090 static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
1096 if (next->monotonic != (usec_t) -1 && next->monotonic > 0) {
1099 if (next->monotonic > nw->monotonic)
1100 converted = nw->realtime + (next->monotonic - nw->monotonic);
1102 converted = nw->realtime - (nw->monotonic - next->monotonic);
1104 if (next->realtime != (usec_t) -1 && next->realtime > 0)
1105 next_elapse = MIN(converted, next->realtime);
1107 next_elapse = converted;
1110 next_elapse = next->realtime;
1115 static int list_timers(sd_bus *bus, char **args) {
1117 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1118 _cleanup_free_ struct timer_info *timer_infos = NULL;
1119 _cleanup_free_ UnitInfo *unit_infos = NULL;
1120 struct timer_info *t;
1127 pager_open_if_enabled();
1129 n = get_unit_list(bus, NULL, strv_skip_first(args), &unit_infos, 0, &reply);
1133 dual_timestamp_get(&nw);
1135 for (u = unit_infos; u < unit_infos + n; u++) {
1136 _cleanup_strv_free_ char **triggered = NULL;
1137 dual_timestamp next = {};
1140 if (!endswith(u->id, ".timer"))
1143 r = get_triggered_units(bus, u->unit_path, &triggered);
1147 r = get_next_elapse(bus, u->unit_path, &next);
1151 get_last_trigger(bus, u->unit_path, &last);
1153 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
1158 m = calc_next_elapse(&nw, &next);
1160 timer_infos[c++] = (struct timer_info) {
1163 .last_trigger = last,
1164 .triggered = triggered,
1167 triggered = NULL; /* avoid cleanup */
1170 qsort_safe(timer_infos, c, sizeof(struct timer_info),
1171 (__compar_fn_t) timer_info_compare);
1173 output_timers_list(timer_infos, c);
1176 for (t = timer_infos; t < timer_infos + c; t++)
1177 strv_free(t->triggered);
1182 static int compare_unit_file_list(const void *a, const void *b) {
1183 const char *d1, *d2;
1184 const UnitFileList *u = a, *v = b;
1186 d1 = strrchr(u->path, '.');
1187 d2 = strrchr(v->path, '.');
1192 r = strcasecmp(d1, d2);
1197 return strcasecmp(basename(u->path), basename(v->path));
1200 static bool output_show_unit_file(const UnitFileList *u, char **patterns) {
1203 if (!strv_isempty(patterns)) {
1206 STRV_FOREACH(pattern, patterns)
1207 if (fnmatch(*pattern, basename(u->path), FNM_NOESCAPE) == 0)
1212 return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
1215 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
1216 unsigned max_id_len, id_cols, state_cols;
1217 const UnitFileList *u;
1219 max_id_len = strlen("UNIT FILE");
1220 state_cols = strlen("STATE");
1222 for (u = units; u < units + c; u++) {
1223 max_id_len = MAX(max_id_len, strlen(basename(u->path)));
1224 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1228 unsigned basic_cols;
1230 id_cols = MIN(max_id_len, 25u);
1231 basic_cols = 1 + id_cols + state_cols;
1232 if (basic_cols < (unsigned) columns())
1233 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1235 id_cols = max_id_len;
1238 printf("%-*s %-*s\n",
1239 id_cols, "UNIT FILE",
1240 state_cols, "STATE");
1242 for (u = units; u < units + c; u++) {
1243 _cleanup_free_ char *e = NULL;
1244 const char *on, *off;
1247 if (u->state == UNIT_FILE_MASKED ||
1248 u->state == UNIT_FILE_MASKED_RUNTIME ||
1249 u->state == UNIT_FILE_DISABLED ||
1250 u->state == UNIT_FILE_INVALID) {
1251 on = ansi_highlight_red();
1252 off = ansi_highlight_off();
1253 } else if (u->state == UNIT_FILE_ENABLED) {
1254 on = ansi_highlight_green();
1255 off = ansi_highlight_off();
1259 id = basename(u->path);
1261 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1263 printf("%-*s %s%-*s%s\n",
1264 id_cols, e ? e : id,
1265 on, state_cols, unit_file_state_to_string(u->state), off);
1269 printf("\n%u unit files listed.\n", c);
1272 static int list_unit_files(sd_bus *bus, char **args) {
1273 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1274 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1275 _cleanup_free_ UnitFileList *units = NULL;
1283 pager_open_if_enabled();
1291 h = hashmap_new(string_hash_func, string_compare_func);
1295 r = unit_file_get_list(arg_scope, arg_root, h);
1297 unit_file_list_free(h);
1298 log_error("Failed to get unit file list: %s", strerror(-r));
1302 n_units = hashmap_size(h);
1303 units = new(UnitFileList, n_units);
1305 unit_file_list_free(h);
1309 HASHMAP_FOREACH(u, h, i) {
1310 if (!output_show_unit_file(u, strv_skip_first(args)))
1317 assert(c <= n_units);
1320 r = sd_bus_call_method(
1322 "org.freedesktop.systemd1",
1323 "/org/freedesktop/systemd1",
1324 "org.freedesktop.systemd1.Manager",
1330 log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1334 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1336 return bus_log_parse_error(r);
1338 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1340 if (!GREEDY_REALLOC(units, size, c + 1))
1343 units[c] = (struct UnitFileList) {
1345 unit_file_state_from_string(state)
1348 if (output_show_unit_file(&units[c], strv_skip_first(args)))
1353 return bus_log_parse_error(r);
1355 r = sd_bus_message_exit_container(reply);
1357 return bus_log_parse_error(r);
1361 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
1362 output_unit_file_list(units, c);
1366 for (unit = units; unit < units + c; unit++)
1372 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1373 _cleanup_free_ char *n = NULL;
1374 size_t max_len = MAX(columns(),20u);
1380 for (i = level - 1; i >= 0; i--) {
1382 if (len > max_len - 3 && !arg_full) {
1383 printf("%s...\n",max_len % 2 ? "" : " ");
1386 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
1390 if (len > max_len - 3 && !arg_full) {
1391 printf("%s...\n",max_len % 2 ? "" : " ");
1395 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
1399 printf("%s\n", name);
1403 n = ellipsize(name, max_len-len, 100);
1411 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1413 static const char *dependencies[_DEPENDENCY_MAX] = {
1414 [DEPENDENCY_FORWARD] = "Requires\0"
1415 "RequiresOverridable\0"
1417 "RequisiteOverridable\0"
1419 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1420 "RequiredByOverridable\0"
1423 [DEPENDENCY_AFTER] = "After\0",
1424 [DEPENDENCY_BEFORE] = "Before\0",
1427 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1428 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1429 _cleanup_strv_free_ char **ret = NULL;
1430 _cleanup_free_ char *path = NULL;
1436 assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
1438 path = unit_dbus_path_from_name(name);
1442 r = sd_bus_call_method(
1444 "org.freedesktop.systemd1",
1446 "org.freedesktop.DBus.Properties",
1450 "s", "org.freedesktop.systemd1.Unit");
1452 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1456 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1458 return bus_log_parse_error(r);
1460 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1463 r = sd_bus_message_read(reply, "s", &prop);
1465 return bus_log_parse_error(r);
1467 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1468 r = sd_bus_message_skip(reply, "v");
1470 return bus_log_parse_error(r);
1473 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1475 return bus_log_parse_error(r);
1477 r = bus_message_read_strv_extend(reply, &ret);
1479 return bus_log_parse_error(r);
1481 r = sd_bus_message_exit_container(reply);
1483 return bus_log_parse_error(r);
1486 r = sd_bus_message_exit_container(reply);
1488 return bus_log_parse_error(r);
1492 return bus_log_parse_error(r);
1494 r = sd_bus_message_exit_container(reply);
1496 return bus_log_parse_error(r);
1504 static int list_dependencies_compare(const void *_a, const void *_b) {
1505 const char **a = (const char**) _a, **b = (const char**) _b;
1507 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1509 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1512 return strcasecmp(*a, *b);
1515 static int list_dependencies_one(
1520 unsigned int branches) {
1522 _cleanup_strv_free_ char **deps = NULL;
1530 r = strv_extend(units, name);
1534 r = list_dependencies_get_dependencies(bus, name, &deps);
1538 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1540 STRV_FOREACH(c, deps) {
1543 if (strv_contains(*units, *c)) {
1545 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1552 state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true);
1554 printf("%s%s%s", ansi_highlight_green(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1556 printf("%s%s%s", ansi_highlight_red(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1558 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1562 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1563 r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1570 strv_remove(*units, name);
1575 static int list_dependencies(sd_bus *bus, char **args) {
1576 _cleanup_strv_free_ char **units = NULL;
1577 _cleanup_free_ char *unit = NULL;
1583 unit = unit_name_mangle(args[1], MANGLE_NOGLOB);
1588 u = SPECIAL_DEFAULT_TARGET;
1590 pager_open_if_enabled();
1594 return list_dependencies_one(bus, u, 0, &units, 0);
1597 struct machine_info {
1601 char *control_group;
1602 uint32_t n_failed_units;
1607 static const struct bus_properties_map machine_info_property_map[] = {
1608 { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
1609 { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
1610 { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
1611 { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
1612 { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
1616 static void free_machines_list(struct machine_info *machine_infos, int n) {
1622 for (i = 0; i < n; i++) {
1623 free(machine_infos[i].name);
1624 free(machine_infos[i].state);
1625 free(machine_infos[i].control_group);
1628 free(machine_infos);
1631 static int compare_machine_info(const void *a, const void *b) {
1632 const struct machine_info *u = a, *v = b;
1634 if (u->is_host != v->is_host)
1635 return u->is_host > v->is_host ? -1 : 1;
1637 return strcasecmp(u->name, v->name);
1640 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1641 _cleanup_bus_unref_ sd_bus *container = NULL;
1647 r = sd_bus_open_system_container(&container, mi->name);
1654 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi);
1661 static bool output_show_machine(const char *name, char **patterns) {
1666 if (strv_isempty(patterns))
1669 STRV_FOREACH(i, patterns)
1670 if (fnmatch(*i, name, FNM_NOESCAPE) == 0)
1676 static int get_machine_list(
1678 struct machine_info **_machine_infos,
1681 struct machine_info *machine_infos = NULL;
1682 _cleanup_strv_free_ char **m = NULL;
1683 _cleanup_free_ char *hn = NULL;
1688 hn = gethostname_malloc();
1692 if (output_show_machine(hn, patterns)) {
1693 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1696 machine_infos[c].is_host = true;
1697 machine_infos[c].name = hn;
1700 get_machine_properties(bus, &machine_infos[c]);
1704 sd_get_machine_names(&m);
1705 STRV_FOREACH(i, m) {
1706 _cleanup_free_ char *class = NULL;
1708 if (!output_show_machine(*i, patterns))
1711 sd_machine_get_class(*i, &class);
1712 if (!streq_ptr(class, "container"))
1715 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1716 free_machines_list(machine_infos, c);
1720 machine_infos[c].is_host = false;
1721 machine_infos[c].name = strdup(*i);
1722 if (!machine_infos[c].name) {
1723 free_machines_list(machine_infos, c);
1727 get_machine_properties(NULL, &machine_infos[c]);
1731 *_machine_infos = machine_infos;
1735 static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1736 struct machine_info *m;
1739 namelen = sizeof("NAME") - 1,
1740 statelen = sizeof("STATE") - 1,
1741 failedlen = sizeof("FAILED") - 1,
1742 jobslen = sizeof("JOBS") - 1;
1744 assert(machine_infos || n == 0);
1746 for (m = machine_infos; m < machine_infos + n; m++) {
1747 namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
1748 statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
1749 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
1750 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
1752 if (!arg_no_legend && !streq_ptr(m->state, "running"))
1756 if (!arg_no_legend) {
1760 printf("%-*s %-*s %-*s %-*s\n",
1763 failedlen, "FAILED",
1767 for (m = machine_infos; m < machine_infos + n; m++) {
1768 const char *on_state = "", *off_state = "";
1769 const char *on_failed = "", *off_failed = "";
1770 bool circle = false;
1772 if (streq_ptr(m->state, "degraded")) {
1773 on_state = ansi_highlight_red();
1774 off_state = ansi_highlight_off();
1776 } else if (!streq_ptr(m->state, "running")) {
1777 on_state = ansi_highlight_yellow();
1778 off_state = ansi_highlight_off();
1782 if (m->n_failed_units > 0) {
1783 on_failed = ansi_highlight_red();
1784 off_failed = ansi_highlight_off();
1786 on_failed = off_failed = "";
1789 printf("%s%s%s", on_state, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_state);
1792 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1793 (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
1794 on_state, statelen, strna(m->state), off_state,
1795 on_failed, failedlen, m->n_failed_units, off_failed,
1796 jobslen, m->n_jobs);
1798 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1799 namelen, strna(m->name),
1800 on_state, statelen, strna(m->state), off_state,
1801 on_failed, failedlen, m->n_failed_units, off_failed,
1802 jobslen, m->n_jobs);
1806 printf("\n%u machines listed.\n", n);
1809 static int list_machines(sd_bus *bus, char **args) {
1810 struct machine_info *machine_infos = NULL;
1815 if (geteuid() != 0) {
1816 log_error("Must be root.");
1820 pager_open_if_enabled();
1822 r = get_machine_list(bus, &machine_infos, strv_skip_first(args));
1826 qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
1827 output_machines_list(machine_infos, r);
1828 free_machines_list(machine_infos, r);
1833 static int get_default(sd_bus *bus, char **args) {
1834 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1835 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1836 _cleanup_free_ char *_path = NULL;
1840 if (!bus || avoid_bus()) {
1841 r = unit_file_get_default(arg_scope, arg_root, &_path);
1843 log_error("Failed to get default target: %s", strerror(-r));
1849 r = sd_bus_call_method(
1851 "org.freedesktop.systemd1",
1852 "/org/freedesktop/systemd1",
1853 "org.freedesktop.systemd1.Manager",
1859 log_error("Failed to get default target: %s", bus_error_message(&error, -r));
1863 r = sd_bus_message_read(reply, "s", &path);
1865 return bus_log_parse_error(r);
1869 printf("%s\n", path);
1874 static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) {
1877 assert(changes || n_changes == 0);
1879 for (i = 0; i < n_changes; i++) {
1880 if (changes[i].type == UNIT_FILE_SYMLINK)
1881 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
1883 log_info("rm '%s'", changes[i].path);
1887 static int deserialize_and_dump_unit_file_changes(sd_bus_message *m) {
1888 const char *type, *path, *source;
1891 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1893 return bus_log_parse_error(r);
1895 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1897 if (streq(type, "symlink"))
1898 log_info("ln -s '%s' '%s'", source, path);
1900 log_info("rm '%s'", path);
1904 return bus_log_parse_error(r);
1906 r = sd_bus_message_exit_container(m);
1908 return bus_log_parse_error(r);
1913 static int set_default(sd_bus *bus, char **args) {
1914 _cleanup_free_ char *unit = NULL;
1915 UnitFileChange *changes = NULL;
1916 unsigned n_changes = 0;
1919 unit = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
1923 if (!bus || avoid_bus()) {
1924 r = unit_file_set_default(arg_scope, arg_root, unit, arg_force, &changes, &n_changes);
1926 log_error("Failed to set default target: %s", strerror(-r));
1931 dump_unit_file_changes(changes, n_changes);
1935 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1936 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1938 r = sd_bus_call_method(
1940 "org.freedesktop.systemd1",
1941 "/org/freedesktop/systemd1",
1942 "org.freedesktop.systemd1.Manager",
1946 "sb", unit, arg_force);
1948 log_error("Failed to set default target: %s", bus_error_message(&error, -r));
1952 r = deserialize_and_dump_unit_file_changes(reply);
1956 /* Try to reload if enabled */
1958 r = daemon_reload(bus, args);
1963 unit_file_changes_free(changes, n_changes);
1970 const char *name, *type, *state;
1973 static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
1974 unsigned id_len, unit_len, type_len, state_len;
1975 const struct job_info *j;
1976 const char *on, *off;
1977 bool shorten = false;
1979 assert(n == 0 || jobs);
1982 on = ansi_highlight_green();
1983 off = ansi_highlight_off();
1985 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
1989 pager_open_if_enabled();
1991 id_len = strlen("JOB");
1992 unit_len = strlen("UNIT");
1993 type_len = strlen("TYPE");
1994 state_len = strlen("STATE");
1996 for (j = jobs; j < jobs + n; j++) {
1997 uint32_t id = j->id;
1998 assert(j->name && j->type && j->state);
2000 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
2001 unit_len = MAX(unit_len, strlen(j->name));
2002 type_len = MAX(type_len, strlen(j->type));
2003 state_len = MAX(state_len, strlen(j->state));
2006 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
2007 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
2012 printf("%*s %-*s %-*s %-*s\n",
2016 state_len, "STATE");
2018 for (j = jobs; j < jobs + n; j++) {
2019 _cleanup_free_ char *e = NULL;
2021 if (streq(j->state, "running")) {
2022 on = ansi_highlight();
2023 off = ansi_highlight_off();
2027 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
2028 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2030 on, unit_len, e ? e : j->name, off,
2032 on, state_len, j->state, off);
2035 if (!arg_no_legend) {
2036 on = ansi_highlight();
2037 off = ansi_highlight_off();
2039 printf("\n%s%u jobs listed%s.\n", on, n, off);
2043 static bool output_show_job(struct job_info *job, char **patterns) {
2048 if (strv_isempty(patterns))
2051 STRV_FOREACH(pattern, patterns)
2052 if (fnmatch(*pattern, job->name, FNM_NOESCAPE) == 0)
2057 static int list_jobs(sd_bus *bus, char **args) {
2058 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2059 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2060 const char *name, *type, *state, *job_path, *unit_path;
2061 _cleanup_free_ struct job_info *jobs = NULL;
2066 bool skipped = false;
2068 r = sd_bus_call_method(
2070 "org.freedesktop.systemd1",
2071 "/org/freedesktop/systemd1",
2072 "org.freedesktop.systemd1.Manager",
2078 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
2082 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2084 return bus_log_parse_error(r);
2086 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
2087 struct job_info job = { id, name, type, state };
2089 if (!output_show_job(&job, strv_skip_first(args))) {
2094 if (!GREEDY_REALLOC(jobs, size, c + 1))
2100 return bus_log_parse_error(r);
2102 r = sd_bus_message_exit_container(reply);
2104 return bus_log_parse_error(r);
2106 output_jobs_list(jobs, c, skipped);
2110 static int cancel_job(sd_bus *bus, char **args) {
2111 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2116 if (strv_length(args) <= 1)
2117 return daemon_reload(bus, args);
2119 STRV_FOREACH(name, args+1) {
2123 r = safe_atou32(*name, &id);
2125 log_error("Failed to parse job id \"%s\": %s", *name, strerror(-r));
2129 r = sd_bus_call_method(
2131 "org.freedesktop.systemd1",
2132 "/org/freedesktop/systemd1",
2133 "org.freedesktop.systemd1.Manager",
2139 log_error("Failed to cancel job %u: %s", (unsigned) id, bus_error_message(&error, r));
2147 static int need_daemon_reload(sd_bus *bus, const char *unit) {
2148 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2152 /* We ignore all errors here, since this is used to show a
2155 /* We don't use unit_dbus_path_from_name() directly since we
2156 * don't want to load the unit if it isn't loaded. */
2158 r = sd_bus_call_method(
2160 "org.freedesktop.systemd1",
2161 "/org/freedesktop/systemd1",
2162 "org.freedesktop.systemd1.Manager",
2170 r = sd_bus_message_read(reply, "o", &path);
2174 r = sd_bus_get_property_trivial(
2176 "org.freedesktop.systemd1",
2178 "org.freedesktop.systemd1.Unit",
2188 typedef struct WaitData {
2195 static int wait_filter(sd_bus *bus, sd_bus_message *m, void *data, sd_bus_error *error) {
2202 log_debug("Got D-Bus request: %s.%s() on %s",
2203 sd_bus_message_get_interface(m),
2204 sd_bus_message_get_member(m),
2205 sd_bus_message_get_path(m));
2207 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
2208 log_error("Warning! D-Bus connection terminated.");
2210 } else if (sd_bus_message_is_signal(m, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
2212 const char *path, *result, *unit;
2216 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
2218 ret = set_remove(d->set, (char*) path);
2224 if (!isempty(result))
2225 d->result = strdup(result);
2228 d->name = strdup(unit);
2233 r = sd_bus_message_read(m, "uos", &id, &path, &result);
2235 ret = set_remove(d->set, (char*) path);
2242 d->result = strdup(result);
2248 bus_log_parse_error(r);
2254 static int enable_wait_for_jobs(sd_bus *bus) {
2259 r = sd_bus_add_match(
2262 "sender='org.freedesktop.systemd1',"
2263 "interface='org.freedesktop.systemd1.Manager',"
2264 "member='JobRemoved',"
2265 "path='/org/freedesktop/systemd1'",
2268 log_error("Failed to add match");
2272 /* This is slightly dirty, since we don't undo the match registrations. */
2276 static int bus_process_wait(sd_bus *bus) {
2280 r = sd_bus_process(bus, NULL);
2285 r = sd_bus_wait(bus, (uint64_t) -1);
2291 static int check_wait_response(WaitData *d) {
2297 if (streq(d->result, "timeout"))
2298 log_error("Job for %s timed out.", strna(d->name));
2299 else if (streq(d->result, "canceled"))
2300 log_error("Job for %s canceled.", strna(d->name));
2301 else if (streq(d->result, "dependency"))
2302 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d->name));
2303 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2304 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d->name), strna(d->name));
2307 if (streq(d->result, "timeout"))
2309 else if (streq(d->result, "canceled"))
2311 else if (streq(d->result, "dependency"))
2313 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2319 static int wait_for_jobs(sd_bus *bus, Set *s) {
2320 WaitData d = { .set = s };
2326 q = sd_bus_add_filter(bus, wait_filter, &d);
2330 while (!set_isempty(s)) {
2331 q = bus_process_wait(bus);
2333 log_error("Failed to wait for response: %s", strerror(-r));
2338 q = check_wait_response(&d);
2339 /* Return the first error as it is most likely to be
2341 if (q < 0 && r == 0)
2343 log_debug("Got result %s/%s for job %s",
2344 strna(d.result), strerror(-q), strna(d.name));
2354 q = sd_bus_remove_filter(bus, wait_filter, &d);
2355 if (q < 0 && r == 0)
2361 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2362 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2363 _cleanup_free_ char *n = NULL, *state = NULL;
2369 n = unit_name_mangle(name, MANGLE_NOGLOB);
2373 /* We don't use unit_dbus_path_from_name() directly since we
2374 * don't want to load the unit if it isn't loaded. */
2376 r = sd_bus_call_method(
2378 "org.freedesktop.systemd1",
2379 "/org/freedesktop/systemd1",
2380 "org.freedesktop.systemd1.Manager",
2391 r = sd_bus_message_read(reply, "o", &path);
2393 return bus_log_parse_error(r);
2395 r = sd_bus_get_property_string(
2397 "org.freedesktop.systemd1",
2399 "org.freedesktop.systemd1.Unit",
2412 return nulstr_contains(good_states, state);
2415 static int check_triggering_units(
2419 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2420 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2421 _cleanup_strv_free_ char **triggered_by = NULL;
2422 bool print_warning_label = true;
2426 n = unit_name_mangle(name, MANGLE_NOGLOB);
2430 path = unit_dbus_path_from_name(n);
2434 r = sd_bus_get_property_string(
2436 "org.freedesktop.systemd1",
2438 "org.freedesktop.systemd1.Unit",
2443 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2447 if (streq(state, "masked"))
2450 r = sd_bus_get_property_strv(
2452 "org.freedesktop.systemd1",
2454 "org.freedesktop.systemd1.Unit",
2459 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2463 STRV_FOREACH(i, triggered_by) {
2464 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2466 log_error("Failed to check unit: %s", strerror(-r));
2473 if (print_warning_label) {
2474 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2475 print_warning_label = false;
2478 log_warning(" %s", *i);
2484 static const char *verb_to_method(const char *verb) {
2487 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2488 if (streq_ptr(unit_actions[i].verb, verb))
2489 return unit_actions[i].method;
2494 static const char *method_to_verb(const char *method) {
2497 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2498 if (streq_ptr(unit_actions[i].method, method))
2499 return unit_actions[i].verb;
2504 static int start_unit_one(
2509 sd_bus_error *error,
2512 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2521 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2522 r = sd_bus_call_method(
2524 "org.freedesktop.systemd1",
2525 "/org/freedesktop/systemd1",
2526 "org.freedesktop.systemd1.Manager",
2534 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2535 /* There's always a fallback possible for
2536 * legacy actions. */
2537 return -EADDRNOTAVAIL;
2539 verb = method_to_verb(method);
2541 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2545 r = sd_bus_message_read(reply, "o", &path);
2547 return bus_log_parse_error(r);
2549 if (need_daemon_reload(bus, name) > 0)
2550 log_warning("Warning: Unit file of %s changed on disk, 'systemctl%s daemon-reload' recommended.",
2551 name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2560 log_debug("Adding %s to the set", p);
2561 r = set_consume(s, p);
2569 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2571 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2575 STRV_FOREACH(name, names) {
2579 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2581 t = unit_name_mangle(*name, MANGLE_GLOB);
2585 if (string_is_glob(t))
2586 r = strv_consume(&globs, t);
2588 r = strv_consume(&mangled, t);
2593 /* Query the manager only if any of the names are a glob, since
2594 * this is fairly expensive */
2595 if (!strv_isempty(globs)) {
2596 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2597 _cleanup_free_ UnitInfo *unit_infos = NULL;
2599 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2603 for (i = 0; i < r; i++)
2604 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2609 mangled = NULL; /* do not free */
2614 static const struct {
2618 } action_table[_ACTION_MAX] = {
2619 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2620 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2621 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2622 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2623 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
2624 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
2625 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
2626 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
2627 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2628 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2629 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2630 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2631 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2632 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2633 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2636 static enum action verb_to_action(const char *verb) {
2639 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2640 if (streq_ptr(action_table[i].verb, verb))
2643 return _ACTION_INVALID;
2646 static int start_unit(sd_bus *bus, char **args) {
2647 _cleanup_set_free_free_ Set *s = NULL;
2648 _cleanup_strv_free_ char **names = NULL;
2649 const char *method, *mode, *one_name;
2655 ask_password_agent_open_if_enabled();
2657 if (arg_action == ACTION_SYSTEMCTL) {
2659 method = verb_to_method(args[0]);
2660 action = verb_to_action(args[0]);
2662 mode = streq(args[0], "isolate") ? "isolate" :
2663 action_table[action].mode ?: arg_job_mode;
2665 one_name = action_table[action].target;
2667 assert(arg_action < ELEMENTSOF(action_table));
2668 assert(action_table[arg_action].target);
2670 method = "StartUnit";
2672 mode = action_table[arg_action].mode;
2673 one_name = action_table[arg_action].target;
2677 names = strv_new(one_name, NULL);
2679 r = expand_names(bus, args + 1, NULL, &names);
2681 log_error("Failed to expand names: %s", strerror(-r));
2684 if (!arg_no_block) {
2685 r = enable_wait_for_jobs(bus);
2687 log_error("Could not watch jobs: %s", strerror(-r));
2691 s = set_new(string_hash_func, string_compare_func);
2696 STRV_FOREACH(name, names) {
2697 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2700 q = start_unit_one(bus, method, *name, mode, &error, s);
2701 if (r >= 0 && q < 0)
2702 r = translate_bus_error_to_exit_status(q, &error);
2705 if (!arg_no_block) {
2708 q = wait_for_jobs(bus, s);
2712 /* When stopping units, warn if they can still be triggered by
2713 * another active unit (socket, path, timer) */
2714 if (!arg_quiet && streq(method, "StopUnit"))
2715 STRV_FOREACH(name, names)
2716 check_triggering_units(bus, *name);
2722 /* Ask systemd-logind, which might grant access to unprivileged users
2723 * through PolicyKit */
2724 static int reboot_with_logind(sd_bus *bus, enum action a) {
2726 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2733 polkit_agent_open_if_enabled();
2741 case ACTION_POWEROFF:
2742 method = "PowerOff";
2745 case ACTION_SUSPEND:
2749 case ACTION_HIBERNATE:
2750 method = "Hibernate";
2753 case ACTION_HYBRID_SLEEP:
2754 method = "HybridSleep";
2761 r = sd_bus_call_method(
2763 "org.freedesktop.login1",
2764 "/org/freedesktop/login1",
2765 "org.freedesktop.login1.Manager",
2771 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2779 static int check_inhibitors(sd_bus *bus, enum action a) {
2781 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2782 _cleanup_strv_free_ char **sessions = NULL;
2783 const char *what, *who, *why, *mode;
2792 if (arg_ignore_inhibitors || arg_force > 0)
2804 r = sd_bus_call_method(
2806 "org.freedesktop.login1",
2807 "/org/freedesktop/login1",
2808 "org.freedesktop.login1.Manager",
2814 /* If logind is not around, then there are no inhibitors... */
2817 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2819 return bus_log_parse_error(r);
2821 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2822 _cleanup_free_ char *comm = NULL, *user = NULL;
2823 _cleanup_strv_free_ char **sv = NULL;
2825 if (!streq(mode, "block"))
2828 sv = strv_split(what, ":");
2832 if (!strv_contains(sv,
2834 a == ACTION_POWEROFF ||
2835 a == ACTION_REBOOT ||
2836 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2839 get_process_comm(pid, &comm);
2840 user = uid_to_name(uid);
2842 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2843 who, (unsigned long) pid, strna(comm), strna(user), why);
2848 return bus_log_parse_error(r);
2850 r = sd_bus_message_exit_container(reply);
2852 return bus_log_parse_error(r);
2854 /* Check for current sessions */
2855 sd_get_sessions(&sessions);
2856 STRV_FOREACH(s, sessions) {
2857 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2859 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2862 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2865 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2868 sd_session_get_tty(*s, &tty);
2869 sd_session_get_seat(*s, &seat);
2870 sd_session_get_service(*s, &service);
2871 user = uid_to_name(uid);
2873 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2880 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2881 action_table[a].verb);
2889 static int start_special(sd_bus *bus, char **args) {
2895 a = verb_to_action(args[0]);
2897 r = check_inhibitors(bus, a);
2901 if (arg_force >= 2 && geteuid() != 0) {
2902 log_error("Must be root.");
2906 if (arg_force >= 2 &&
2907 (a == ACTION_HALT ||
2908 a == ACTION_POWEROFF ||
2909 a == ACTION_REBOOT))
2912 if (arg_force >= 1 &&
2913 (a == ACTION_HALT ||
2914 a == ACTION_POWEROFF ||
2915 a == ACTION_REBOOT ||
2916 a == ACTION_KEXEC ||
2918 return daemon_reload(bus, args);
2920 /* first try logind, to allow authentication with polkit */
2921 if (geteuid() != 0 &&
2922 (a == ACTION_POWEROFF ||
2923 a == ACTION_REBOOT ||
2924 a == ACTION_SUSPEND ||
2925 a == ACTION_HIBERNATE ||
2926 a == ACTION_HYBRID_SLEEP)) {
2927 r = reboot_with_logind(bus, a);
2932 r = start_unit(bus, args);
2933 if (r == EXIT_SUCCESS)
2939 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
2940 _cleanup_strv_free_ char **names = NULL;
2947 r = expand_names(bus, args, NULL, &names);
2949 log_error("Failed to expand names: %s", strerror(-r));
2953 STRV_FOREACH(name, names) {
2956 state = check_one_unit(bus, *name, good_states, arg_quiet);
2966 static int check_unit_active(sd_bus *bus, char **args) {
2967 /* According to LSB: 3, "program is not running" */
2968 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
2971 static int check_unit_failed(sd_bus *bus, char **args) {
2972 return check_unit_generic(bus, 1, "failed\0", args + 1);
2975 static int kill_unit(sd_bus *bus, char **args) {
2976 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2977 _cleanup_strv_free_ char **names = NULL;
2985 arg_kill_who = "all";
2987 r = expand_names(bus, args + 1, NULL, &names);
2989 log_error("Failed to expand names: %s", strerror(-r));
2991 STRV_FOREACH(name, names) {
2992 q = sd_bus_call_method(
2994 "org.freedesktop.systemd1",
2995 "/org/freedesktop/systemd1",
2996 "org.freedesktop.systemd1.Manager",
3000 "ssi", *names, arg_kill_who, arg_signal);
3002 log_error("Failed to kill unit %s: %s",
3003 *names, bus_error_message(&error, r));
3012 typedef struct ExecStatusInfo {
3020 usec_t start_timestamp;
3021 usec_t exit_timestamp;
3026 LIST_FIELDS(struct ExecStatusInfo, exec);
3029 static void exec_status_info_free(ExecStatusInfo *i) {
3038 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3039 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3042 int32_t code, status;
3048 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3050 return bus_log_parse_error(r);
3054 r = sd_bus_message_read(m, "s", &path);
3056 return bus_log_parse_error(r);
3058 i->path = strdup(path);
3062 r = sd_bus_message_read_strv(m, &i->argv);
3064 return bus_log_parse_error(r);
3066 r = sd_bus_message_read(m,
3069 &start_timestamp, &start_timestamp_monotonic,
3070 &exit_timestamp, &exit_timestamp_monotonic,
3074 return bus_log_parse_error(r);
3077 i->start_timestamp = (usec_t) start_timestamp;
3078 i->exit_timestamp = (usec_t) exit_timestamp;
3079 i->pid = (pid_t) pid;
3083 r = sd_bus_message_exit_container(m);
3085 return bus_log_parse_error(r);
3090 typedef struct UnitStatusInfo {
3092 const char *load_state;
3093 const char *active_state;
3094 const char *sub_state;
3095 const char *unit_file_state;
3097 const char *description;
3098 const char *following;
3100 char **documentation;
3102 const char *fragment_path;
3103 const char *source_path;
3104 const char *control_group;
3106 char **dropin_paths;
3108 const char *load_error;
3111 usec_t inactive_exit_timestamp;
3112 usec_t inactive_exit_timestamp_monotonic;
3113 usec_t active_enter_timestamp;
3114 usec_t active_exit_timestamp;
3115 usec_t inactive_enter_timestamp;
3117 bool need_daemon_reload;
3122 const char *status_text;
3123 const char *pid_file;
3126 usec_t start_timestamp;
3127 usec_t exit_timestamp;
3129 int exit_code, exit_status;
3131 usec_t condition_timestamp;
3132 bool condition_result;
3133 bool failed_condition_trigger;
3134 bool failed_condition_negate;
3135 const char *failed_condition;
3136 const char *failed_condition_param;
3139 unsigned n_accepted;
3140 unsigned n_connections;
3143 /* Pairs of type, path */
3147 const char *sysfs_path;
3149 /* Mount, Automount */
3155 LIST_HEAD(ExecStatusInfo, exec);
3158 static void print_status_info(
3163 const char *active_on, *active_off, *on, *off, *ss;
3165 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3166 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3169 arg_all * OUTPUT_SHOW_ALL |
3170 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
3171 on_tty() * OUTPUT_COLOR |
3172 !arg_quiet * OUTPUT_WARN_CUTOFF |
3173 arg_full * OUTPUT_FULL_WIDTH;
3178 /* This shows pretty information about a unit. See
3179 * print_property() for a low-level property printer */
3181 if (streq_ptr(i->active_state, "failed")) {
3182 active_on = ansi_highlight_red();
3183 active_off = ansi_highlight_off();
3184 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3185 active_on = ansi_highlight_green();
3186 active_off = ansi_highlight_off();
3188 active_on = active_off = "";
3190 printf("%s%s%s%s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3192 if (i->description && !streq_ptr(i->id, i->description))
3193 printf(" - %s", i->description);
3198 printf(" Follow: unit currently follows state of %s\n", i->following);
3200 if (streq_ptr(i->load_state, "error")) {
3201 on = ansi_highlight_red();
3202 off = ansi_highlight_off();
3206 path = i->source_path ? i->source_path : i->fragment_path;
3209 printf(" Loaded: %s%s%s (Reason: %s)\n",
3210 on, strna(i->load_state), off, i->load_error);
3211 else if (path && i->unit_file_state)
3212 printf(" Loaded: %s%s%s (%s; %s)\n",
3213 on, strna(i->load_state), off, path, i->unit_file_state);
3215 printf(" Loaded: %s%s%s (%s)\n",
3216 on, strna(i->load_state), off, path);
3218 printf(" Loaded: %s%s%s\n",
3219 on, strna(i->load_state), off);
3221 if (!strv_isempty(i->dropin_paths)) {
3222 _cleanup_free_ char *dir = NULL;
3226 STRV_FOREACH(dropin, i->dropin_paths) {
3227 if (! dir || last) {
3228 printf(dir ? " " : " Drop-In: ");
3233 if (path_get_parent(*dropin, &dir) < 0) {
3238 printf("%s\n %s", dir,
3239 draw_special_char(DRAW_TREE_RIGHT));
3242 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3244 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3248 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3250 printf(" Active: %s%s (%s)%s",
3251 active_on, strna(i->active_state), ss, active_off);
3253 printf(" Active: %s%s%s",
3254 active_on, strna(i->active_state), active_off);
3256 if (!isempty(i->result) && !streq(i->result, "success"))
3257 printf(" (Result: %s)", i->result);
3259 timestamp = (streq_ptr(i->active_state, "active") ||
3260 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
3261 (streq_ptr(i->active_state, "inactive") ||
3262 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
3263 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
3264 i->active_exit_timestamp;
3266 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3267 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3270 printf(" since %s; %s\n", s2, s1);
3272 printf(" since %s\n", s2);
3276 if (!i->condition_result && i->condition_timestamp > 0) {
3277 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3278 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3280 printf(" start condition failed at %s%s%s\n",
3281 s2, s1 ? "; " : "", s1 ? s1 : "");
3282 if (i->failed_condition_trigger)
3283 printf(" none of the trigger conditions were met\n");
3284 else if (i->failed_condition)
3285 printf(" %s=%s%s was not met\n",
3286 i->failed_condition,
3287 i->failed_condition_negate ? "!" : "",
3288 i->failed_condition_param);
3292 printf(" Device: %s\n", i->sysfs_path);
3294 printf(" Where: %s\n", i->where);
3296 printf(" What: %s\n", i->what);
3298 STRV_FOREACH(t, i->documentation)
3299 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3301 STRV_FOREACH_PAIR(t, t2, i->listen)
3302 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3305 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3307 LIST_FOREACH(exec, p, i->exec) {
3308 _cleanup_free_ char *argv = NULL;
3311 /* Only show exited processes here */
3315 argv = strv_join(p->argv, " ");
3316 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
3318 good = is_clean_exit_lsb(p->code, p->status, NULL);
3320 on = ansi_highlight_red();
3321 off = ansi_highlight_off();
3325 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3327 if (p->code == CLD_EXITED) {
3330 printf("status=%i", p->status);
3332 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3337 printf("signal=%s", signal_to_string(p->status));
3339 printf(")%s\n", off);
3341 if (i->main_pid == p->pid &&
3342 i->start_timestamp == p->start_timestamp &&
3343 i->exit_timestamp == p->start_timestamp)
3344 /* Let's not show this twice */
3347 if (p->pid == i->control_pid)
3351 if (i->main_pid > 0 || i->control_pid > 0) {
3352 if (i->main_pid > 0) {
3353 printf(" Main PID: %u", (unsigned) i->main_pid);
3356 _cleanup_free_ char *comm = NULL;
3357 get_process_comm(i->main_pid, &comm);
3359 printf(" (%s)", comm);
3360 } else if (i->exit_code > 0) {
3361 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3363 if (i->exit_code == CLD_EXITED) {
3366 printf("status=%i", i->exit_status);
3368 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3373 printf("signal=%s", signal_to_string(i->exit_status));
3377 if (i->control_pid > 0)
3381 if (i->control_pid > 0) {
3382 _cleanup_free_ char *c = NULL;
3384 printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
3386 get_process_comm(i->control_pid, &c);
3395 printf(" Status: \"%s\"\n", i->status_text);
3397 if (i->control_group &&
3398 (i->main_pid > 0 || i->control_pid > 0 ||
3399 ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_CONTAINER) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3402 printf(" CGroup: %s\n", i->control_group);
3404 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
3407 static const char prefix[] = " ";
3410 if (c > sizeof(prefix) - 1)
3411 c -= sizeof(prefix) - 1;
3415 if (i->main_pid > 0)
3416 extra[k++] = i->main_pid;
3418 if (i->control_pid > 0)
3419 extra[k++] = i->control_pid;
3421 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, flags);
3425 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3426 show_journal_by_unit(stdout,
3430 i->inactive_exit_timestamp_monotonic,
3433 flags | OUTPUT_BEGIN_NEWLINE,
3434 arg_scope == UNIT_FILE_SYSTEM,
3438 if (i->need_daemon_reload)
3439 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
3440 ansi_highlight_red(),
3441 ansi_highlight_off(),
3442 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
3445 static void show_unit_help(UnitStatusInfo *i) {
3450 if (!i->documentation) {
3451 log_info("Documentation for %s not known.", i->id);
3455 STRV_FOREACH(p, i->documentation) {
3457 if (startswith(*p, "man:")) {
3458 const char *args[4] = { "man", NULL, NULL, NULL };
3459 _cleanup_free_ char *page = NULL, *section = NULL;
3466 if ((*p)[k-1] == ')')
3467 e = strrchr(*p, '(');
3470 page = strndup((*p) + 4, e - *p - 4);
3471 section = strndup(e + 1, *p + k - e - 2);
3472 if (!page || !section) {
3484 log_error("Failed to fork: %m");
3490 execvp(args[0], (char**) args);
3491 log_error("Failed to execute man: %m");
3492 _exit(EXIT_FAILURE);
3495 wait_for_terminate(pid, NULL);
3497 log_info("Can't show: %s", *p);
3501 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3508 switch (contents[0]) {
3510 case SD_BUS_TYPE_STRING: {
3513 r = sd_bus_message_read(m, "s", &s);
3515 return bus_log_parse_error(r);
3518 if (streq(name, "Id"))
3520 else if (streq(name, "LoadState"))
3522 else if (streq(name, "ActiveState"))
3523 i->active_state = s;
3524 else if (streq(name, "SubState"))
3526 else if (streq(name, "Description"))
3528 else if (streq(name, "FragmentPath"))
3529 i->fragment_path = s;
3530 else if (streq(name, "SourcePath"))
3533 else if (streq(name, "DefaultControlGroup")) {
3535 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3537 i->control_group = e;
3540 else if (streq(name, "ControlGroup"))
3541 i->control_group = s;
3542 else if (streq(name, "StatusText"))
3544 else if (streq(name, "PIDFile"))
3546 else if (streq(name, "SysFSPath"))
3548 else if (streq(name, "Where"))
3550 else if (streq(name, "What"))
3552 else if (streq(name, "Following"))
3554 else if (streq(name, "UnitFileState"))
3555 i->unit_file_state = s;
3556 else if (streq(name, "Result"))
3563 case SD_BUS_TYPE_BOOLEAN: {
3566 r = sd_bus_message_read(m, "b", &b);
3568 return bus_log_parse_error(r);
3570 if (streq(name, "Accept"))
3572 else if (streq(name, "NeedDaemonReload"))
3573 i->need_daemon_reload = b;
3574 else if (streq(name, "ConditionResult"))
3575 i->condition_result = b;
3580 case SD_BUS_TYPE_UINT32: {
3583 r = sd_bus_message_read(m, "u", &u);
3585 return bus_log_parse_error(r);
3587 if (streq(name, "MainPID")) {
3589 i->main_pid = (pid_t) u;
3592 } else if (streq(name, "ControlPID"))
3593 i->control_pid = (pid_t) u;
3594 else if (streq(name, "ExecMainPID")) {
3596 i->main_pid = (pid_t) u;
3597 } else if (streq(name, "NAccepted"))
3599 else if (streq(name, "NConnections"))
3600 i->n_connections = u;
3605 case SD_BUS_TYPE_INT32: {
3608 r = sd_bus_message_read(m, "i", &j);
3610 return bus_log_parse_error(r);
3612 if (streq(name, "ExecMainCode"))
3613 i->exit_code = (int) j;
3614 else if (streq(name, "ExecMainStatus"))
3615 i->exit_status = (int) j;
3620 case SD_BUS_TYPE_UINT64: {
3623 r = sd_bus_message_read(m, "t", &u);
3625 return bus_log_parse_error(r);
3627 if (streq(name, "ExecMainStartTimestamp"))
3628 i->start_timestamp = (usec_t) u;
3629 else if (streq(name, "ExecMainExitTimestamp"))
3630 i->exit_timestamp = (usec_t) u;
3631 else if (streq(name, "ActiveEnterTimestamp"))
3632 i->active_enter_timestamp = (usec_t) u;
3633 else if (streq(name, "InactiveEnterTimestamp"))
3634 i->inactive_enter_timestamp = (usec_t) u;
3635 else if (streq(name, "InactiveExitTimestamp"))
3636 i->inactive_exit_timestamp = (usec_t) u;
3637 else if (streq(name, "InactiveExitTimestampMonotonic"))
3638 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3639 else if (streq(name, "ActiveExitTimestamp"))
3640 i->active_exit_timestamp = (usec_t) u;
3641 else if (streq(name, "ConditionTimestamp"))
3642 i->condition_timestamp = (usec_t) u;
3647 case SD_BUS_TYPE_ARRAY:
3649 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3650 _cleanup_free_ ExecStatusInfo *info = NULL;
3652 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3654 return bus_log_parse_error(r);
3656 info = new0(ExecStatusInfo, 1);
3660 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3662 info->name = strdup(name);
3666 LIST_PREPEND(exec, i->exec, info);
3668 info = new0(ExecStatusInfo, 1);
3674 return bus_log_parse_error(r);
3676 r = sd_bus_message_exit_container(m);
3678 return bus_log_parse_error(r);
3682 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3683 const char *type, *path;
3685 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3687 return bus_log_parse_error(r);
3689 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3691 r = strv_extend(&i->listen, type);
3695 r = strv_extend(&i->listen, path);
3700 return bus_log_parse_error(r);
3702 r = sd_bus_message_exit_container(m);
3704 return bus_log_parse_error(r);
3708 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3710 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3712 return bus_log_parse_error(r);
3714 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3716 r = sd_bus_message_read_strv(m, &i->documentation);
3718 return bus_log_parse_error(r);
3720 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3721 const char *cond, *param;
3722 int trigger, negate;
3725 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3727 return bus_log_parse_error(r);
3729 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3730 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3731 if (state < 0 && (!trigger || !i->failed_condition)) {
3732 i->failed_condition = cond;
3733 i->failed_condition_trigger = trigger;
3734 i->failed_condition_negate = negate;
3735 i->failed_condition_param = param;
3739 return bus_log_parse_error(r);
3741 r = sd_bus_message_exit_container(m);
3743 return bus_log_parse_error(r);
3750 case SD_BUS_TYPE_STRUCT_BEGIN:
3752 if (streq(name, "LoadError")) {
3753 const char *n, *message;
3755 r = sd_bus_message_read(m, "(ss)", &n, &message);
3757 return bus_log_parse_error(r);
3759 if (!isempty(message))
3760 i->load_error = message;
3773 r = sd_bus_message_skip(m, contents);
3775 return bus_log_parse_error(r);
3780 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3786 /* This is a low-level property printer, see
3787 * print_status_info() for the nicer output */
3789 if (arg_properties && !strv_find(arg_properties, name)) {
3790 /* skip what we didn't read */
3791 r = sd_bus_message_skip(m, contents);
3795 switch (contents[0]) {
3797 case SD_BUS_TYPE_STRUCT_BEGIN:
3799 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3802 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3804 return bus_log_parse_error(r);
3807 printf("%s=%u\n", name, (unsigned) u);
3809 printf("%s=\n", name);
3813 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3816 r = sd_bus_message_read(m, "(so)", &s, NULL);
3818 return bus_log_parse_error(r);
3820 if (arg_all || !isempty(s))
3821 printf("%s=%s\n", name, s);
3825 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3826 const char *a = NULL, *b = NULL;
3828 r = sd_bus_message_read(m, "(ss)", &a, &b);
3830 return bus_log_parse_error(r);
3832 if (arg_all || !isempty(a) || !isempty(b))
3833 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3836 } else if (streq_ptr(name, "SystemCallFilter")) {
3837 _cleanup_strv_free_ char **l = NULL;
3840 r = sd_bus_message_enter_container(m, 'r', "bas");
3842 return bus_log_parse_error(r);
3844 r = sd_bus_message_read(m, "b", &whitelist);
3846 return bus_log_parse_error(r);
3848 r = sd_bus_message_read_strv(m, &l);
3850 return bus_log_parse_error(r);
3852 r = sd_bus_message_exit_container(m);
3854 return bus_log_parse_error(r);
3856 if (arg_all || whitelist || !strv_isempty(l)) {
3860 fputs(name, stdout);
3866 STRV_FOREACH(i, l) {
3874 fputc('\n', stdout);
3882 case SD_BUS_TYPE_ARRAY:
3884 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
3888 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
3890 return bus_log_parse_error(r);
3892 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
3893 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3896 return bus_log_parse_error(r);
3898 r = sd_bus_message_exit_container(m);
3900 return bus_log_parse_error(r);
3904 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
3905 const char *type, *path;
3907 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3909 return bus_log_parse_error(r);
3911 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3912 printf("%s=%s\n", type, path);
3914 return bus_log_parse_error(r);
3916 r = sd_bus_message_exit_container(m);
3918 return bus_log_parse_error(r);
3922 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3923 const char *type, *path;
3925 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3927 return bus_log_parse_error(r);
3929 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3930 printf("Listen%s=%s\n", type, path);
3932 return bus_log_parse_error(r);
3934 r = sd_bus_message_exit_container(m);
3936 return bus_log_parse_error(r);
3940 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
3942 uint64_t value, next_elapse;
3944 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
3946 return bus_log_parse_error(r);
3948 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
3949 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3951 printf("%s={ value=%s ; next_elapse=%s }\n",
3953 format_timespan(timespan1, sizeof(timespan1), value, 0),
3954 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3957 return bus_log_parse_error(r);
3959 r = sd_bus_message_exit_container(m);
3961 return bus_log_parse_error(r);
3965 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3966 ExecStatusInfo info = {};
3968 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3970 return bus_log_parse_error(r);
3972 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
3973 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3974 _cleanup_free_ char *tt;
3976 tt = strv_join(info.argv, " ");
3978 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3982 yes_no(info.ignore),
3983 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3984 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3985 (unsigned) info. pid,
3986 sigchld_code_to_string(info.code),
3988 info.code == CLD_EXITED ? "" : "/",
3989 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3992 strv_free(info.argv);
3996 r = sd_bus_message_exit_container(m);
3998 return bus_log_parse_error(r);
4002 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
4003 const char *path, *rwm;
4005 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4007 return bus_log_parse_error(r);
4009 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
4010 printf("%s=%s %s\n", name, strna(path), strna(rwm));
4012 return bus_log_parse_error(r);
4014 r = sd_bus_message_exit_container(m);
4016 return bus_log_parse_error(r);
4020 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
4024 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4026 return bus_log_parse_error(r);
4028 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4029 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
4031 return bus_log_parse_error(r);
4033 r = sd_bus_message_exit_container(m);
4035 return bus_log_parse_error(r);
4039 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
4043 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4045 return bus_log_parse_error(r);
4047 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4048 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
4050 return bus_log_parse_error(r);
4052 r = sd_bus_message_exit_container(m);
4054 return bus_log_parse_error(r);
4062 r = bus_print_property(name, m, arg_all);
4064 return bus_log_parse_error(r);
4067 r = sd_bus_message_skip(m, contents);
4069 return bus_log_parse_error(r);
4072 printf("%s=[unprintable]\n", name);
4078 static int show_one(
4082 bool show_properties,
4086 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4087 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4088 UnitStatusInfo info = {};
4095 log_debug("Showing one %s", path);
4097 r = sd_bus_call_method(
4099 "org.freedesktop.systemd1",
4101 "org.freedesktop.DBus.Properties",
4107 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4111 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4113 return bus_log_parse_error(r);
4120 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4121 const char *name, *contents;
4123 r = sd_bus_message_read(reply, "s", &name);
4125 return bus_log_parse_error(r);
4127 r = sd_bus_message_peek_type(reply, NULL, &contents);
4129 return bus_log_parse_error(r);
4131 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4133 return bus_log_parse_error(r);
4135 if (show_properties)
4136 r = print_property(name, reply, contents);
4138 r = status_property(name, reply, &info, contents);
4142 r = sd_bus_message_exit_container(reply);
4144 return bus_log_parse_error(r);
4146 r = sd_bus_message_exit_container(reply);
4148 return bus_log_parse_error(r);
4151 return bus_log_parse_error(r);
4153 r = sd_bus_message_exit_container(reply);
4155 return bus_log_parse_error(r);
4159 if (!show_properties) {
4160 if (streq(verb, "help"))
4161 show_unit_help(&info);
4163 print_status_info(&info, ellipsized);
4166 strv_free(info.documentation);
4167 strv_free(info.dropin_paths);
4168 strv_free(info.listen);
4170 if (!streq_ptr(info.active_state, "active") &&
4171 !streq_ptr(info.active_state, "reloading") &&
4172 streq(verb, "status")) {
4173 /* According to LSB: "program not running" */
4174 /* 0: program is running or service is OK
4175 * 1: program is dead and /run PID file exists
4176 * 2: program is dead and /run/lock lock file exists
4177 * 3: program is not running
4178 * 4: program or service status is unknown
4180 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4186 while ((p = info.exec)) {
4187 LIST_REMOVE(exec, info.exec, p);
4188 exec_status_info_free(p);
4194 static int get_unit_dbus_path_by_pid(
4199 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4200 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4204 r = sd_bus_call_method(
4206 "org.freedesktop.systemd1",
4207 "/org/freedesktop/systemd1",
4208 "org.freedesktop.systemd1.Manager",
4214 log_error("Failed to get unit for PID %lu: %s", (unsigned long) pid, bus_error_message(&error, r));
4218 r = sd_bus_message_read(reply, "o", &u);
4220 return bus_log_parse_error(r);
4230 static int show_all(
4233 bool show_properties,
4237 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4238 _cleanup_free_ UnitInfo *unit_infos = NULL;
4243 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4247 pager_open_if_enabled();
4251 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4253 for (u = unit_infos; u < unit_infos + c; u++) {
4254 _cleanup_free_ char *p = NULL;
4256 p = unit_dbus_path_from_name(u->id);
4260 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4268 static int show_system_status(sd_bus *bus) {
4269 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4270 _cleanup_free_ char *hn = NULL;
4271 struct machine_info mi = {};
4272 const char *on, *off;
4275 hn = gethostname_malloc();
4279 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4281 log_error("Failed to read server status: %s", strerror(-r));
4285 if (streq_ptr(mi.state, "degraded")) {
4286 on = ansi_highlight_red();
4287 off = ansi_highlight_off();
4288 } else if (!streq_ptr(mi.state, "running")) {
4289 on = ansi_highlight_yellow();
4290 off = ansi_highlight_off();
4294 printf("%s%s%s%s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4296 printf(" State: %s%s%s\n",
4297 on, strna(mi.state), off);
4299 printf(" Jobs: %u queued\n", mi.n_jobs);
4300 printf(" Failed: %u units\n", mi.n_failed_units);
4302 printf(" Since: %s; %s\n",
4303 format_timestamp(since2, sizeof(since2), mi.timestamp),
4304 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4306 printf(" CGroup: %s\n", mi.control_group ?: "/");
4307 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
4309 arg_all * OUTPUT_SHOW_ALL |
4310 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
4311 on_tty() * OUTPUT_COLOR |
4312 !arg_quiet * OUTPUT_WARN_CUTOFF |
4313 arg_full * OUTPUT_FULL_WIDTH;
4315 static const char prefix[] = " ";
4319 if (c > sizeof(prefix) - 1)
4320 c -= sizeof(prefix) - 1;
4324 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
4328 free(mi.control_group);
4333 static int show(sd_bus *bus, char **args) {
4334 bool show_properties, show_status, new_line = false;
4335 bool ellipsized = false;
4341 show_properties = streq(args[0], "show");
4342 show_status = streq(args[0], "status");
4344 if (show_properties)
4345 pager_open_if_enabled();
4347 /* If no argument is specified inspect the manager itself */
4349 if (show_properties && strv_length(args) <= 1)
4350 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4352 if (show_status && strv_length(args) <= 1) {
4354 pager_open_if_enabled();
4355 show_system_status(bus);
4359 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4361 _cleanup_free_ char **patterns = NULL;
4364 STRV_FOREACH(name, args + 1) {
4365 _cleanup_free_ char *unit = NULL;
4368 if (safe_atou32(*name, &id) < 0) {
4369 if (strv_push(&patterns, *name) < 0)
4373 } else if (show_properties) {
4374 /* Interpret as job id */
4375 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4379 /* Interpret as PID */
4380 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4387 show_one(args[0], bus, unit, show_properties, &new_line, &ellipsized);
4390 if (!strv_isempty(patterns)) {
4391 _cleanup_strv_free_ char **names = NULL;
4393 r = expand_names(bus, patterns, NULL, &names);
4395 log_error("Failed to expand names: %s", strerror(-r));
4397 STRV_FOREACH(name, names) {
4398 _cleanup_free_ char *unit;
4400 unit = unit_dbus_path_from_name(*name);
4404 show_one(args[0], bus, unit, show_properties, &new_line, &ellipsized);
4409 if (ellipsized && !arg_quiet)
4410 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4415 static int cat(sd_bus *bus, char **args) {
4416 _cleanup_free_ char *unit = NULL;
4417 _cleanup_strv_free_ char **names = NULL;
4425 r = expand_names(bus, args + 1, NULL, &names);
4427 log_error("Failed to expand names: %s", strerror(-r));
4429 pager_open_if_enabled();
4431 STRV_FOREACH(name, names) {
4432 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4433 _cleanup_strv_free_ char **dropin_paths = NULL;
4434 _cleanup_free_ char *fragment_path = NULL;
4437 unit = unit_dbus_path_from_name(*name);
4441 if (need_daemon_reload(bus, *name) > 0)
4442 log_warning("Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'.",
4443 *name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
4445 r = sd_bus_get_property_string(
4447 "org.freedesktop.systemd1",
4449 "org.freedesktop.systemd1.Unit",
4454 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
4458 r = sd_bus_get_property_strv(
4460 "org.freedesktop.systemd1",
4462 "org.freedesktop.systemd1.Unit",
4467 log_warning("Failed to get DropInPaths: %s", bus_error_message(&error, r));
4476 if (!isempty(fragment_path)) {
4477 printf("%s# %s%s\n",
4478 ansi_highlight_blue(),
4480 ansi_highlight_off());
4483 r = sendfile_full(STDOUT_FILENO, fragment_path);
4485 log_warning("Failed to cat %s: %s", fragment_path, strerror(-r));
4490 STRV_FOREACH(path, dropin_paths) {
4491 printf("%s%s# %s%s\n",
4492 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4493 ansi_highlight_blue(),
4495 ansi_highlight_off());
4498 r = sendfile_full(STDOUT_FILENO, *path);
4500 log_warning("Failed to cat %s: %s", *path, strerror(-r));
4506 return r < 0 ? r : 0;
4509 static int set_property(sd_bus *bus, char **args) {
4510 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4511 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4512 _cleanup_free_ char *n = NULL;
4516 r = sd_bus_message_new_method_call(
4519 "org.freedesktop.systemd1",
4520 "/org/freedesktop/systemd1",
4521 "org.freedesktop.systemd1.Manager",
4522 "SetUnitProperties");
4524 return bus_log_create_error(r);
4526 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4530 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4532 return bus_log_create_error(r);
4534 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4536 return bus_log_create_error(r);
4538 STRV_FOREACH(i, args + 2) {
4539 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4541 return bus_log_create_error(r);
4543 r = bus_append_unit_property_assignment(m, *i);
4547 r = sd_bus_message_close_container(m);
4549 return bus_log_create_error(r);
4552 r = sd_bus_message_close_container(m);
4554 return bus_log_create_error(r);
4556 r = sd_bus_call(bus, m, 0, &error, NULL);
4558 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4565 static int snapshot(sd_bus *bus, char **args) {
4566 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4567 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4568 _cleanup_free_ char *n = NULL, *id = NULL;
4572 if (strv_length(args) > 1)
4573 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4579 r = sd_bus_call_method(
4581 "org.freedesktop.systemd1",
4582 "/org/freedesktop/systemd1",
4583 "org.freedesktop.systemd1.Manager",
4589 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4593 r = sd_bus_message_read(reply, "o", &path);
4595 return bus_log_parse_error(r);
4597 r = sd_bus_get_property_string(
4599 "org.freedesktop.systemd1",
4601 "org.freedesktop.systemd1.Unit",
4606 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4616 static int delete_snapshot(sd_bus *bus, char **args) {
4617 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4618 _cleanup_strv_free_ char **names = NULL;
4624 r = expand_names(bus, args + 1, ".snapshot", &names);
4626 log_error("Failed to expand names: %s", strerror(-r));
4628 STRV_FOREACH(name, names) {
4629 q = sd_bus_call_method(
4631 "org.freedesktop.systemd1",
4632 "/org/freedesktop/systemd1",
4633 "org.freedesktop.systemd1.Manager",
4639 log_error("Failed to remove snapshot %s: %s",
4640 *name, bus_error_message(&error, r));
4649 static int daemon_reload(sd_bus *bus, char **args) {
4650 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4654 if (arg_action == ACTION_RELOAD)
4656 else if (arg_action == ACTION_REEXEC)
4657 method = "Reexecute";
4659 assert(arg_action == ACTION_SYSTEMCTL);
4662 streq(args[0], "clear-jobs") ||
4663 streq(args[0], "cancel") ? "ClearJobs" :
4664 streq(args[0], "daemon-reexec") ? "Reexecute" :
4665 streq(args[0], "reset-failed") ? "ResetFailed" :
4666 streq(args[0], "halt") ? "Halt" :
4667 streq(args[0], "poweroff") ? "PowerOff" :
4668 streq(args[0], "reboot") ? "Reboot" :
4669 streq(args[0], "kexec") ? "KExec" :
4670 streq(args[0], "exit") ? "Exit" :
4671 /* "daemon-reload" */ "Reload";
4674 r = sd_bus_call_method(
4676 "org.freedesktop.systemd1",
4677 "/org/freedesktop/systemd1",
4678 "org.freedesktop.systemd1.Manager",
4684 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4685 /* There's always a fallback possible for
4686 * legacy actions. */
4688 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4689 /* On reexecution, we expect a disconnect, not a
4693 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4695 return r < 0 ? r : 0;
4698 static int reset_failed(sd_bus *bus, char **args) {
4699 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4700 _cleanup_strv_free_ char **names = NULL;
4704 if (strv_length(args) <= 1)
4705 return daemon_reload(bus, args);
4707 r = expand_names(bus, args + 1, NULL, &names);
4709 log_error("Failed to expand names: %s", strerror(-r));
4711 STRV_FOREACH(name, names) {
4712 q = sd_bus_call_method(
4714 "org.freedesktop.systemd1",
4715 "/org/freedesktop/systemd1",
4716 "org.freedesktop.systemd1.Manager",
4722 log_error("Failed to reset failed state of unit %s: %s",
4723 *name, bus_error_message(&error, r));
4732 static int show_environment(sd_bus *bus, char **args) {
4733 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4734 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4738 pager_open_if_enabled();
4740 r = sd_bus_get_property(
4742 "org.freedesktop.systemd1",
4743 "/org/freedesktop/systemd1",
4744 "org.freedesktop.systemd1.Manager",
4750 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4754 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4756 return bus_log_parse_error(r);
4758 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4761 return bus_log_parse_error(r);
4763 r = sd_bus_message_exit_container(reply);
4765 return bus_log_parse_error(r);
4770 static int switch_root(sd_bus *bus, char **args) {
4771 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4772 _cleanup_free_ char *cmdline_init = NULL;
4773 const char *root, *init;
4777 l = strv_length(args);
4778 if (l < 2 || l > 3) {
4779 log_error("Wrong number of arguments.");
4788 r = parse_env_file("/proc/cmdline", WHITESPACE,
4789 "init", &cmdline_init,
4792 log_debug("Failed to parse /proc/cmdline: %s", strerror(-r));
4794 init = cmdline_init;
4801 const char *root_systemd_path = NULL, *root_init_path = NULL;
4803 root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
4804 root_init_path = strappenda3(root, "/", init);
4806 /* If the passed init is actually the same as the
4807 * systemd binary, then let's suppress it. */
4808 if (files_same(root_init_path, root_systemd_path) > 0)
4812 log_debug("Switching root - root: %s; init: %s", root, strna(init));
4814 r = sd_bus_call_method(
4816 "org.freedesktop.systemd1",
4817 "/org/freedesktop/systemd1",
4818 "org.freedesktop.systemd1.Manager",
4824 log_error("Failed to switch root: %s", bus_error_message(&error, r));
4831 static int set_environment(sd_bus *bus, char **args) {
4832 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4833 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4840 method = streq(args[0], "set-environment")
4842 : "UnsetEnvironment";
4844 r = sd_bus_message_new_method_call(
4847 "org.freedesktop.systemd1",
4848 "/org/freedesktop/systemd1",
4849 "org.freedesktop.systemd1.Manager",
4852 return bus_log_create_error(r);
4854 r = sd_bus_message_append_strv(m, args + 1);
4856 return bus_log_create_error(r);
4858 r = sd_bus_call(bus, m, 0, &error, NULL);
4860 log_error("Failed to set environment: %s", bus_error_message(&error, r));
4867 static int import_environment(sd_bus *bus, char **args) {
4868 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4869 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4875 r = sd_bus_message_new_method_call(
4878 "org.freedesktop.systemd1",
4879 "/org/freedesktop/systemd1",
4880 "org.freedesktop.systemd1.Manager",
4883 return bus_log_create_error(r);
4885 if (strv_isempty(args + 1))
4886 r = sd_bus_message_append_strv(m, environ);
4890 r = sd_bus_message_open_container(m, 'a', "s");
4892 return bus_log_create_error(r);
4894 STRV_FOREACH(a, args + 1) {
4896 if (!env_name_is_valid(*a)) {
4897 log_error("Not a valid environment variable name: %s", *a);
4901 STRV_FOREACH(b, environ) {
4904 eq = startswith(*b, *a);
4905 if (eq && *eq == '=') {
4907 r = sd_bus_message_append(m, "s", *b);
4909 return bus_log_create_error(r);
4916 r = sd_bus_message_close_container(m);
4919 return bus_log_create_error(r);
4921 r = sd_bus_call(bus, m, 0, &error, NULL);
4923 log_error("Failed to import environment: %s", bus_error_message(&error, r));
4930 static int enable_sysv_units(const char *verb, char **args) {
4933 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4934 unsigned f = 1, t = 1;
4935 _cleanup_lookup_paths_free_ LookupPaths paths = {};
4937 if (arg_scope != UNIT_FILE_SYSTEM)
4940 if (!streq(verb, "enable") &&
4941 !streq(verb, "disable") &&
4942 !streq(verb, "is-enabled"))
4945 /* Processes all SysV units, and reshuffles the array so that
4946 * afterwards only the native units remain */
4948 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4953 for (f = 0; args[f]; f++) {
4955 _cleanup_free_ char *p = NULL, *q = NULL;
4956 bool found_native = false, found_sysv;
4958 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4966 if (!endswith(name, ".service"))
4969 if (path_is_absolute(name))
4972 STRV_FOREACH(k, paths.unit_path) {
4973 if (!isempty(arg_root))
4974 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4976 asprintf(&p, "%s/%s", *k, name);
4983 found_native = access(p, F_OK) >= 0;
4994 if (!isempty(arg_root))
4995 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4997 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
5003 p[strlen(p) - sizeof(".service") + 1] = 0;
5004 found_sysv = access(p, F_OK) >= 0;
5009 /* Mark this entry, so that we don't try enabling it as native unit */
5010 args[f] = (char*) "";
5012 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
5014 if (!isempty(arg_root))
5015 argv[c++] = q = strappend("--root=", arg_root);
5017 argv[c++] = basename(p);
5019 streq(verb, "enable") ? "on" :
5020 streq(verb, "disable") ? "off" : "--level=5";
5023 l = strv_join((char**)argv, " ");
5029 log_info("Executing %s", l);
5034 log_error("Failed to fork: %m");
5037 } else if (pid == 0) {
5040 execv(argv[0], (char**) argv);
5041 _exit(EXIT_FAILURE);
5044 j = wait_for_terminate(pid, &status);
5046 log_error("Failed to wait for child: %s", strerror(-r));
5051 if (status.si_code == CLD_EXITED) {
5052 if (streq(verb, "is-enabled")) {
5053 if (status.si_status == 0) {
5062 } else if (status.si_status != 0) {
5073 /* Drop all SysV units */
5074 for (f = 0, t = 0; args[f]; f++) {
5076 if (isempty(args[f]))
5079 args[t++] = args[f];
5088 static int mangle_names(char **original_names, char ***mangled_names) {
5089 char **i, **l, **name;
5091 l = new(char*, strv_length(original_names) + 1);
5096 STRV_FOREACH(name, original_names) {
5098 /* When enabling units qualified path names are OK,
5099 * too, hence allow them explicitly. */
5104 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5120 static int enable_unit(sd_bus *bus, char **args) {
5121 _cleanup_strv_free_ char **names = NULL;
5122 const char *verb = args[0];
5123 UnitFileChange *changes = NULL;
5124 unsigned n_changes = 0;
5125 int carries_install_info = -1;
5131 r = mangle_names(args+1, &names);
5135 r = enable_sysv_units(verb, names);
5139 /* If the operation was fully executed by the SysV compat,
5140 * let's finish early */
5141 if (strv_isempty(names))
5144 if (!bus || avoid_bus()) {
5145 if (streq(verb, "enable")) {
5146 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5147 carries_install_info = r;
5148 } else if (streq(verb, "disable"))
5149 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5150 else if (streq(verb, "reenable")) {
5151 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5152 carries_install_info = r;
5153 } else if (streq(verb, "link"))
5154 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5155 else if (streq(verb, "preset")) {
5156 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5157 carries_install_info = r;
5158 } else if (streq(verb, "mask"))
5159 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5160 else if (streq(verb, "unmask"))
5161 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5163 assert_not_reached("Unknown verb");
5166 log_error("Operation failed: %s", strerror(-r));
5171 dump_unit_file_changes(changes, n_changes);
5175 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5176 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5177 int expect_carries_install_info = false;
5178 bool send_force = true;
5181 if (streq(verb, "enable")) {
5182 method = "EnableUnitFiles";
5183 expect_carries_install_info = true;
5184 } else if (streq(verb, "disable")) {
5185 method = "DisableUnitFiles";
5187 } else if (streq(verb, "reenable")) {
5188 method = "ReenableUnitFiles";
5189 expect_carries_install_info = true;
5190 } else if (streq(verb, "link"))
5191 method = "LinkUnitFiles";
5192 else if (streq(verb, "preset")) {
5193 method = "PresetUnitFiles";
5194 expect_carries_install_info = true;
5195 } else if (streq(verb, "mask"))
5196 method = "MaskUnitFiles";
5197 else if (streq(verb, "unmask")) {
5198 method = "UnmaskUnitFiles";
5201 assert_not_reached("Unknown verb");
5203 r = sd_bus_message_new_method_call(
5206 "org.freedesktop.systemd1",
5207 "/org/freedesktop/systemd1",
5208 "org.freedesktop.systemd1.Manager",
5211 return bus_log_create_error(r);
5213 r = sd_bus_message_append_strv(m, names);
5215 return bus_log_create_error(r);
5217 r = sd_bus_message_append(m, "b", arg_runtime);
5219 return bus_log_create_error(r);
5222 r = sd_bus_message_append(m, "b", arg_force);
5224 return bus_log_create_error(r);
5227 r = sd_bus_call(bus, m, 0, &error, &reply);
5229 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5233 if (expect_carries_install_info) {
5234 r = sd_bus_message_read(reply, "b", &carries_install_info);
5236 return bus_log_parse_error(r);
5239 r = deserialize_and_dump_unit_file_changes(reply);
5243 /* Try to reload if enabled */
5245 r = daemon_reload(bus, args);
5250 if (carries_install_info == 0)
5251 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5252 "using systemctl.\n"
5253 "Possible reasons for having this kind of units are:\n"
5254 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5255 " .wants/ or .requires/ directory.\n"
5256 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5257 " a requirement dependency on it.\n"
5258 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5259 " D-Bus, udev, scripted systemctl call, ...).\n");
5262 unit_file_changes_free(changes, n_changes);
5267 static int unit_is_enabled(sd_bus *bus, char **args) {
5269 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5270 _cleanup_strv_free_ char **names = NULL;
5275 r = mangle_names(args+1, &names);
5279 r = enable_sysv_units(args[0], names);
5285 if (!bus || avoid_bus()) {
5287 STRV_FOREACH(name, names) {
5288 UnitFileState state;
5290 state = unit_file_get_state(arg_scope, arg_root, *name);
5292 log_error("Failed to get unit file state for %s: %s", *name, strerror(-state));
5296 if (state == UNIT_FILE_ENABLED ||
5297 state == UNIT_FILE_ENABLED_RUNTIME ||
5298 state == UNIT_FILE_STATIC)
5302 puts(unit_file_state_to_string(state));
5306 STRV_FOREACH(name, names) {
5307 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5310 r = sd_bus_call_method(
5312 "org.freedesktop.systemd1",
5313 "/org/freedesktop/systemd1",
5314 "org.freedesktop.systemd1.Manager",
5320 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5324 r = sd_bus_message_read(reply, "s", &s);
5326 return bus_log_parse_error(r);
5328 if (streq(s, "enabled") ||
5329 streq(s, "enabled-runtime") ||
5341 static int systemctl_help(void) {
5343 pager_open_if_enabled();
5345 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
5346 "Query or send control commands to the systemd manager.\n\n"
5347 " -h --help Show this help\n"
5348 " --version Show package version\n"
5349 " --system Connect to system manager\n"
5350 " --user Connect to user service manager\n"
5351 " -H --host=[USER@]HOST\n"
5352 " Operate on remote host\n"
5353 " -M --machine=CONTAINER\n"
5354 " Operate on local container\n"
5355 " -t --type=TYPE List only units of a particular type\n"
5356 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
5357 " -p --property=NAME Show only properties by this name\n"
5358 " -a --all Show all loaded units/properties, including dead/empty\n"
5359 " ones. To list all units installed on the system, use\n"
5360 " the 'list-unit-files' command instead.\n"
5361 " -l --full Don't ellipsize unit names on output\n"
5362 " -r --recursive Show unit list of host and local containers\n"
5363 " --reverse Show reverse dependencies with 'list-dependencies'\n"
5364 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
5365 " queueing a new job\n"
5366 " --show-types When showing sockets, explicitly show their type\n"
5367 " -i --ignore-inhibitors\n"
5368 " When shutting down or sleeping, ignore inhibitors\n"
5369 " --kill-who=WHO Who to send signal to\n"
5370 " -s --signal=SIGNAL Which signal to send\n"
5371 " -q --quiet Suppress output\n"
5372 " --no-block Do not wait until operation finished\n"
5373 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5374 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
5376 " --no-legend Do not print a legend (column headers and hints)\n"
5377 " --no-pager Do not pipe output into a pager\n"
5378 " --no-ask-password\n"
5379 " Do not ask for system passwords\n"
5380 " --global Enable/disable unit files globally\n"
5381 " --runtime Enable unit files only temporarily until next reboot\n"
5382 " -f --force When enabling unit files, override existing symlinks\n"
5383 " When shutting down, execute action immediately\n"
5384 " --root=PATH Enable unit files in the specified root directory\n"
5385 " -n --lines=INTEGER Number of journal entries to show\n"
5386 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
5387 " verbose, export, json, json-pretty, json-sse, cat)\n"
5388 " --plain Print unit dependencies as a list instead of a tree\n\n"
5390 " list-units [PATTERN...] List loaded units\n"
5391 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
5392 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
5393 " start NAME... Start (activate) one or more units\n"
5394 " stop NAME... Stop (deactivate) one or more units\n"
5395 " reload NAME... Reload one or more units\n"
5396 " restart NAME... Start or restart one or more units\n"
5397 " try-restart NAME... Restart one or more units if active\n"
5398 " reload-or-restart NAME... Reload one or more units if possible,\n"
5399 " otherwise start or restart\n"
5400 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
5401 " otherwise restart if active\n"
5402 " isolate NAME Start one unit and stop all others\n"
5403 " kill NAME... Send signal to processes of a unit\n"
5404 " is-active PATTERN... Check whether units are active\n"
5405 " is-failed PATTERN... Check whether units are failed\n"
5406 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
5407 " show [PATTERN...|JOB...] Show properties of one or more\n"
5408 " units/jobs or the manager\n"
5409 " cat PATTERN... Show files and drop-ins of one or more units\n"
5410 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
5411 " help PATTERN...|PID... Show manual for one or more units\n"
5412 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
5414 " list-dependencies [NAME] Recursively show units which are required\n"
5415 " or wanted by this unit or by which this\n"
5416 " unit is required or wanted\n\n"
5417 "Unit File Commands:\n"
5418 " list-unit-files [PATTERN...] List installed unit files\n"
5419 " enable NAME... Enable one or more unit files\n"
5420 " disable NAME... Disable one or more unit files\n"
5421 " reenable NAME... Reenable one or more unit files\n"
5422 " preset NAME... Enable/disable one or more unit files\n"
5423 " based on preset configuration\n"
5424 " is-enabled NAME... Check whether unit files are enabled\n\n"
5425 " mask NAME... Mask one or more units\n"
5426 " unmask NAME... Unmask one or more units\n"
5427 " link PATH... Link one or more units files into\n"
5428 " the search path\n"
5429 " get-default Get the name of the default target\n"
5430 " set-default NAME Set the default target\n\n"
5431 "Machine Commands:\n"
5432 " list-machines [PATTERN...] List local containers and host\n\n"
5434 " list-jobs [PATTERN...] List jobs\n"
5435 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
5436 "Snapshot Commands:\n"
5437 " snapshot [NAME] Create a snapshot\n"
5438 " delete NAME... Remove one or more snapshots\n\n"
5439 "Environment Commands:\n"
5440 " show-environment Dump environment\n"
5441 " set-environment NAME=VALUE... Set one or more environment variables\n"
5442 " unset-environment NAME... Unset one or more environment variables\n"
5443 " import-environment NAME... Import all, one or more environment variables\n\n"
5444 "Manager Lifecycle Commands:\n"
5445 " daemon-reload Reload systemd manager configuration\n"
5446 " daemon-reexec Reexecute systemd manager\n\n"
5447 "System Commands:\n"
5448 " default Enter system default mode\n"
5449 " rescue Enter system rescue mode\n"
5450 " emergency Enter system emergency mode\n"
5451 " halt Shut down and halt the system\n"
5452 " poweroff Shut down and power-off the system\n"
5453 " reboot [ARG] Shut down and reboot the system\n"
5454 " kexec Shut down and reboot the system with kexec\n"
5455 " exit Request user instance exit\n"
5456 " switch-root ROOT [INIT] Change to a different root file system\n"
5457 " suspend Suspend the system\n"
5458 " hibernate Hibernate the system\n"
5459 " hybrid-sleep Hibernate and suspend the system\n",
5460 program_invocation_short_name);
5465 static int halt_help(void) {
5467 printf("%s [OPTIONS...]%s\n\n"
5468 "%s the system.\n\n"
5469 " --help Show this help\n"
5470 " --halt Halt the machine\n"
5471 " -p --poweroff Switch off the machine\n"
5472 " --reboot Reboot the machine\n"
5473 " -f --force Force immediate halt/power-off/reboot\n"
5474 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
5475 " -d --no-wtmp Don't write wtmp record\n"
5476 " --no-wall Don't send wall message before halt/power-off/reboot\n",
5477 program_invocation_short_name,
5478 arg_action == ACTION_REBOOT ? " [ARG]" : "",
5479 arg_action == ACTION_REBOOT ? "Reboot" :
5480 arg_action == ACTION_POWEROFF ? "Power off" :
5486 static int shutdown_help(void) {
5488 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
5489 "Shut down the system.\n\n"
5490 " --help Show this help\n"
5491 " -H --halt Halt the machine\n"
5492 " -P --poweroff Power-off the machine\n"
5493 " -r --reboot Reboot the machine\n"
5494 " -h Equivalent to --poweroff, overridden by --halt\n"
5495 " -k Don't halt/power-off/reboot, just send warnings\n"
5496 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5497 " -c Cancel a pending shutdown\n",
5498 program_invocation_short_name);
5503 static int telinit_help(void) {
5505 printf("%s [OPTIONS...] {COMMAND}\n\n"
5506 "Send control commands to the init daemon.\n\n"
5507 " --help Show this help\n"
5508 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
5510 " 0 Power-off the machine\n"
5511 " 6 Reboot the machine\n"
5512 " 2, 3, 4, 5 Start runlevelX.target unit\n"
5513 " 1, s, S Enter rescue mode\n"
5514 " q, Q Reload init daemon configuration\n"
5515 " u, U Reexecute init daemon\n",
5516 program_invocation_short_name);
5521 static int runlevel_help(void) {
5523 printf("%s [OPTIONS...]\n\n"
5524 "Prints the previous and current runlevel of the init system.\n\n"
5525 " --help Show this help\n",
5526 program_invocation_short_name);
5531 static int help_types(void) {
5535 puts("Available unit types:");
5536 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
5537 t = unit_type_to_string(i);
5545 static int systemctl_parse_argv(int argc, char *argv[]) {
5554 ARG_IGNORE_DEPENDENCIES,
5566 ARG_NO_ASK_PASSWORD,
5575 static const struct option options[] = {
5576 { "help", no_argument, NULL, 'h' },
5577 { "version", no_argument, NULL, ARG_VERSION },
5578 { "type", required_argument, NULL, 't' },
5579 { "property", required_argument, NULL, 'p' },
5580 { "all", no_argument, NULL, 'a' },
5581 { "reverse", no_argument, NULL, ARG_REVERSE },
5582 { "after", no_argument, NULL, ARG_AFTER },
5583 { "before", no_argument, NULL, ARG_BEFORE },
5584 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
5585 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
5586 { "full", no_argument, NULL, 'l' },
5587 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
5588 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
5589 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
5590 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
5591 { "ignore-inhibitors", no_argument, NULL, 'i' },
5592 { "user", no_argument, NULL, ARG_USER },
5593 { "system", no_argument, NULL, ARG_SYSTEM },
5594 { "global", no_argument, NULL, ARG_GLOBAL },
5595 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
5596 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
5597 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
5598 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5599 { "quiet", no_argument, NULL, 'q' },
5600 { "root", required_argument, NULL, ARG_ROOT },
5601 { "force", no_argument, NULL, ARG_FORCE },
5602 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
5603 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
5604 { "signal", required_argument, NULL, 's' },
5605 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
5606 { "host", required_argument, NULL, 'H' },
5607 { "machine", required_argument, NULL, 'M' },
5608 { "runtime", no_argument, NULL, ARG_RUNTIME },
5609 { "lines", required_argument, NULL, 'n' },
5610 { "output", required_argument, NULL, 'o' },
5611 { "plain", no_argument, NULL, ARG_PLAIN },
5612 { "state", required_argument, NULL, ARG_STATE },
5613 { "recursive", no_argument, NULL, 'r' },
5622 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0) {
5627 return systemctl_help();
5630 puts(PACKAGE_STRING);
5631 puts(SYSTEMD_FEATURES);
5638 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5639 _cleanup_free_ char *type;
5641 type = strndup(word, size);
5645 if (streq(type, "help")) {
5650 if (unit_type_from_string(type) >= 0) {
5651 if (strv_push(&arg_types, type))
5657 /* It's much nicer to use --state= for
5658 * load states, but let's support this
5659 * in --types= too for compatibility
5660 * with old versions */
5661 if (unit_load_state_from_string(optarg) >= 0) {
5662 if (strv_push(&arg_states, type) < 0)
5668 log_error("Unknown unit type or load state '%s'.", type);
5669 log_info("Use -t help to see a list of allowed values.");
5677 /* Make sure that if the empty property list
5678 was specified, we won't show any properties. */
5679 if (isempty(optarg) && !arg_properties) {
5680 arg_properties = new0(char*, 1);
5681 if (!arg_properties)
5687 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5690 prop = strndup(word, size);
5694 if (strv_consume(&arg_properties, prop) < 0)
5699 /* If the user asked for a particular
5700 * property, show it to him, even if it is
5712 arg_dependency = DEPENDENCY_REVERSE;
5716 arg_dependency = DEPENDENCY_AFTER;
5720 arg_dependency = DEPENDENCY_BEFORE;
5723 case ARG_SHOW_TYPES:
5724 arg_show_types = true;
5728 arg_job_mode = optarg;
5732 arg_job_mode = "fail";
5735 case ARG_IRREVERSIBLE:
5736 arg_job_mode = "replace-irreversibly";
5739 case ARG_IGNORE_DEPENDENCIES:
5740 arg_job_mode = "ignore-dependencies";
5744 arg_scope = UNIT_FILE_USER;
5748 arg_scope = UNIT_FILE_SYSTEM;
5752 arg_scope = UNIT_FILE_GLOBAL;
5756 arg_no_block = true;
5760 arg_no_legend = true;
5764 arg_no_pager = true;
5780 if (strv_extend(&arg_states, "failed") < 0)
5798 arg_no_reload = true;
5802 arg_kill_who = optarg;
5806 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5807 log_error("Failed to parse signal string %s.", optarg);
5812 case ARG_NO_ASK_PASSWORD:
5813 arg_ask_password = false;
5817 arg_transport = BUS_TRANSPORT_REMOTE;
5822 arg_transport = BUS_TRANSPORT_CONTAINER;
5831 if (safe_atou(optarg, &arg_lines) < 0) {
5832 log_error("Failed to parse lines '%s'", optarg);
5838 arg_output = output_mode_from_string(optarg);
5839 if (arg_output < 0) {
5840 log_error("Unknown output '%s'.", optarg);
5846 arg_ignore_inhibitors = true;
5857 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5860 s = strndup(word, size);
5864 if (strv_consume(&arg_states, s) < 0)
5871 if (geteuid() != 0) {
5872 log_error("--recursive requires root priviliges.");
5876 arg_recursive = true;
5883 assert_not_reached("Unhandled option");
5887 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
5888 log_error("Cannot access user instance remotely.");
5895 static int halt_parse_argv(int argc, char *argv[]) {
5904 static const struct option options[] = {
5905 { "help", no_argument, NULL, ARG_HELP },
5906 { "halt", no_argument, NULL, ARG_HALT },
5907 { "poweroff", no_argument, NULL, 'p' },
5908 { "reboot", no_argument, NULL, ARG_REBOOT },
5909 { "force", no_argument, NULL, 'f' },
5910 { "wtmp-only", no_argument, NULL, 'w' },
5911 { "no-wtmp", no_argument, NULL, 'd' },
5912 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5921 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5922 if (runlevel == '0' || runlevel == '6')
5925 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5932 arg_action = ACTION_HALT;
5936 if (arg_action != ACTION_REBOOT)
5937 arg_action = ACTION_POWEROFF;
5941 arg_action = ACTION_REBOOT;
5963 /* Compatibility nops */
5970 assert_not_reached("Unhandled option");
5974 if (arg_action == ACTION_REBOOT && argc == optind + 1) {
5975 r = write_string_file(REBOOT_PARAM_FILE, argv[optind]);
5977 log_error("Failed to write reboot param to "
5978 REBOOT_PARAM_FILE": %s", strerror(-r));
5981 } else if (optind < argc) {
5982 log_error("Too many arguments.");
5989 static int parse_time_spec(const char *t, usec_t *_u) {
5993 if (streq(t, "now"))
5995 else if (!strchr(t, ':')) {
5998 if (safe_atou64(t, &u) < 0)
6001 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
6010 hour = strtol(t, &e, 10);
6011 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
6014 minute = strtol(e+1, &e, 10);
6015 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
6018 n = now(CLOCK_REALTIME);
6019 s = (time_t) (n / USEC_PER_SEC);
6021 assert_se(localtime_r(&s, &tm));
6023 tm.tm_hour = (int) hour;
6024 tm.tm_min = (int) minute;
6027 assert_se(s = mktime(&tm));
6029 *_u = (usec_t) s * USEC_PER_SEC;
6032 *_u += USEC_PER_DAY;
6038 static int shutdown_parse_argv(int argc, char *argv[]) {
6045 static const struct option options[] = {
6046 { "help", no_argument, NULL, ARG_HELP },
6047 { "halt", no_argument, NULL, 'H' },
6048 { "poweroff", no_argument, NULL, 'P' },
6049 { "reboot", no_argument, NULL, 'r' },
6050 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
6051 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6060 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
6064 return shutdown_help();
6067 arg_action = ACTION_HALT;
6071 arg_action = ACTION_POWEROFF;
6076 arg_action = ACTION_KEXEC;
6078 arg_action = ACTION_REBOOT;
6082 arg_action = ACTION_KEXEC;
6086 if (arg_action != ACTION_HALT)
6087 arg_action = ACTION_POWEROFF;
6100 /* Compatibility nops */
6104 arg_action = ACTION_CANCEL_SHUTDOWN;
6111 assert_not_reached("Unhandled option");
6115 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
6116 r = parse_time_spec(argv[optind], &arg_when);
6118 log_error("Failed to parse time specification: %s", argv[optind]);
6122 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
6124 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
6125 /* No time argument for shutdown cancel */
6126 arg_wall = argv + optind;
6127 else if (argc > optind + 1)
6128 /* We skip the time argument */
6129 arg_wall = argv + optind + 1;
6136 static int telinit_parse_argv(int argc, char *argv[]) {
6143 static const struct option options[] = {
6144 { "help", no_argument, NULL, ARG_HELP },
6145 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6149 static const struct {
6153 { '0', ACTION_POWEROFF },
6154 { '6', ACTION_REBOOT },
6155 { '1', ACTION_RESCUE },
6156 { '2', ACTION_RUNLEVEL2 },
6157 { '3', ACTION_RUNLEVEL3 },
6158 { '4', ACTION_RUNLEVEL4 },
6159 { '5', ACTION_RUNLEVEL5 },
6160 { 's', ACTION_RESCUE },
6161 { 'S', ACTION_RESCUE },
6162 { 'q', ACTION_RELOAD },
6163 { 'Q', ACTION_RELOAD },
6164 { 'u', ACTION_REEXEC },
6165 { 'U', ACTION_REEXEC }
6174 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
6178 return telinit_help();
6188 assert_not_reached("Unhandled option");
6192 if (optind >= argc) {
6197 if (optind + 1 < argc) {
6198 log_error("Too many arguments.");
6202 if (strlen(argv[optind]) != 1) {
6203 log_error("Expected single character argument.");
6207 for (i = 0; i < ELEMENTSOF(table); i++)
6208 if (table[i].from == argv[optind][0])
6211 if (i >= ELEMENTSOF(table)) {
6212 log_error("Unknown command '%s'.", argv[optind]);
6216 arg_action = table[i].to;
6223 static int runlevel_parse_argv(int argc, char *argv[]) {
6229 static const struct option options[] = {
6230 { "help", no_argument, NULL, ARG_HELP },
6239 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
6243 return runlevel_help();
6249 assert_not_reached("Unhandled option");
6253 if (optind < argc) {
6254 log_error("Too many arguments.");
6261 static int parse_argv(int argc, char *argv[]) {
6265 if (program_invocation_short_name) {
6267 if (strstr(program_invocation_short_name, "halt")) {
6268 arg_action = ACTION_HALT;
6269 return halt_parse_argv(argc, argv);
6270 } else if (strstr(program_invocation_short_name, "poweroff")) {
6271 arg_action = ACTION_POWEROFF;
6272 return halt_parse_argv(argc, argv);
6273 } else if (strstr(program_invocation_short_name, "reboot")) {
6275 arg_action = ACTION_KEXEC;
6277 arg_action = ACTION_REBOOT;
6278 return halt_parse_argv(argc, argv);
6279 } else if (strstr(program_invocation_short_name, "shutdown")) {
6280 arg_action = ACTION_POWEROFF;
6281 return shutdown_parse_argv(argc, argv);
6282 } else if (strstr(program_invocation_short_name, "init")) {
6284 if (sd_booted() > 0) {
6285 arg_action = _ACTION_INVALID;
6286 return telinit_parse_argv(argc, argv);
6288 /* Hmm, so some other init system is
6289 * running, we need to forward this
6290 * request to it. For now we simply
6291 * guess that it is Upstart. */
6293 execv(TELINIT, argv);
6295 log_error("Couldn't find an alternative telinit implementation to spawn.");
6299 } else if (strstr(program_invocation_short_name, "runlevel")) {
6300 arg_action = ACTION_RUNLEVEL;
6301 return runlevel_parse_argv(argc, argv);
6305 arg_action = ACTION_SYSTEMCTL;
6306 return systemctl_parse_argv(argc, argv);
6309 _pure_ static int action_to_runlevel(void) {
6311 static const char table[_ACTION_MAX] = {
6312 [ACTION_HALT] = '0',
6313 [ACTION_POWEROFF] = '0',
6314 [ACTION_REBOOT] = '6',
6315 [ACTION_RUNLEVEL2] = '2',
6316 [ACTION_RUNLEVEL3] = '3',
6317 [ACTION_RUNLEVEL4] = '4',
6318 [ACTION_RUNLEVEL5] = '5',
6319 [ACTION_RESCUE] = '1'
6322 assert(arg_action < _ACTION_MAX);
6324 return table[arg_action];
6327 static int talk_initctl(void) {
6329 struct init_request request = {
6330 .magic = INIT_MAGIC,
6332 .cmd = INIT_CMD_RUNLVL
6335 _cleanup_close_ int fd = -1;
6339 rl = action_to_runlevel();
6343 request.runlevel = rl;
6345 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
6347 if (errno == ENOENT)
6350 log_error("Failed to open "INIT_FIFO": %m");
6355 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
6357 log_error("Failed to write to "INIT_FIFO": %m");
6358 return errno > 0 ? -errno : -EIO;
6364 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
6366 static const struct {
6374 int (* const dispatch)(sd_bus *bus, char **args);
6380 { "list-units", MORE, 0, list_units },
6381 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
6382 { "list-sockets", MORE, 1, list_sockets },
6383 { "list-timers", MORE, 1, list_timers },
6384 { "list-jobs", MORE, 1, list_jobs },
6385 { "list-machines", MORE, 1, list_machines },
6386 { "clear-jobs", EQUAL, 1, daemon_reload },
6387 { "cancel", MORE, 2, cancel_job },
6388 { "start", MORE, 2, start_unit },
6389 { "stop", MORE, 2, start_unit },
6390 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6391 { "reload", MORE, 2, start_unit },
6392 { "restart", MORE, 2, start_unit },
6393 { "try-restart", MORE, 2, start_unit },
6394 { "reload-or-restart", MORE, 2, start_unit },
6395 { "reload-or-try-restart", MORE, 2, start_unit },
6396 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
6397 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6398 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
6399 { "isolate", EQUAL, 2, start_unit },
6400 { "kill", MORE, 2, kill_unit },
6401 { "is-active", MORE, 2, check_unit_active },
6402 { "check", MORE, 2, check_unit_active },
6403 { "is-failed", MORE, 2, check_unit_failed },
6404 { "show", MORE, 1, show },
6405 { "cat", MORE, 2, cat },
6406 { "status", MORE, 1, show },
6407 { "help", MORE, 2, show },
6408 { "snapshot", LESS, 2, snapshot },
6409 { "delete", MORE, 2, delete_snapshot },
6410 { "daemon-reload", EQUAL, 1, daemon_reload },
6411 { "daemon-reexec", EQUAL, 1, daemon_reload },
6412 { "show-environment", EQUAL, 1, show_environment },
6413 { "set-environment", MORE, 2, set_environment },
6414 { "unset-environment", MORE, 2, set_environment },
6415 { "import-environment", MORE, 1, import_environment},
6416 { "halt", EQUAL, 1, start_special, FORCE },
6417 { "poweroff", EQUAL, 1, start_special, FORCE },
6418 { "reboot", EQUAL, 1, start_special, FORCE },
6419 { "kexec", EQUAL, 1, start_special },
6420 { "suspend", EQUAL, 1, start_special },
6421 { "hibernate", EQUAL, 1, start_special },
6422 { "hybrid-sleep", EQUAL, 1, start_special },
6423 { "default", EQUAL, 1, start_special },
6424 { "rescue", EQUAL, 1, start_special },
6425 { "emergency", EQUAL, 1, start_special },
6426 { "exit", EQUAL, 1, start_special },
6427 { "reset-failed", MORE, 1, reset_failed },
6428 { "enable", MORE, 2, enable_unit, NOBUS },
6429 { "disable", MORE, 2, enable_unit, NOBUS },
6430 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
6431 { "reenable", MORE, 2, enable_unit, NOBUS },
6432 { "preset", MORE, 2, enable_unit, NOBUS },
6433 { "mask", MORE, 2, enable_unit, NOBUS },
6434 { "unmask", MORE, 2, enable_unit, NOBUS },
6435 { "link", MORE, 2, enable_unit, NOBUS },
6436 { "switch-root", MORE, 2, switch_root },
6437 { "list-dependencies", LESS, 2, list_dependencies },
6438 { "set-default", EQUAL, 2, set_default, NOBUS },
6439 { "get-default", EQUAL, 1, get_default, NOBUS },
6440 { "set-property", MORE, 3, set_property },
6449 left = argc - optind;
6451 /* Special rule: no arguments (left == 0) means "list-units" */
6453 if (streq(argv[optind], "help") && !argv[optind+1]) {
6454 log_error("This command expects one or more "
6455 "unit names. Did you mean --help?");
6459 for (; verb->verb; verb++)
6460 if (streq(argv[optind], verb->verb))
6463 log_error("Unknown operation '%s'.", argv[optind]);
6468 switch (verb->argc_cmp) {
6471 if (left != verb->argc) {
6472 log_error("Invalid number of arguments.");
6479 if (left < verb->argc) {
6480 log_error("Too few arguments.");
6487 if (left > verb->argc) {
6488 log_error("Too many arguments.");
6495 assert_not_reached("Unknown comparison operator.");
6498 /* Require a bus connection for all operations but
6500 if (verb->bus == NOBUS) {
6501 if (!bus && !avoid_bus()) {
6502 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6507 if (running_in_chroot() > 0) {
6508 log_info("Running in chroot, ignoring request.");
6512 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
6513 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6518 return verb->dispatch(bus, argv + optind);
6521 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
6523 struct sd_shutdown_command c = {
6530 union sockaddr_union sockaddr = {
6531 .un.sun_family = AF_UNIX,
6532 .un.sun_path = "/run/systemd/shutdownd",
6535 struct iovec iovec[2] = {{
6536 .iov_base = (char*) &c,
6537 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
6540 struct msghdr msghdr = {
6541 .msg_name = &sockaddr,
6542 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
6543 + strlen("/run/systemd/shutdownd"),
6548 _cleanup_close_ int fd;
6550 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
6554 if (!isempty(message)) {
6555 iovec[1].iov_base = (char*) message;
6556 iovec[1].iov_len = strlen(message);
6557 msghdr.msg_iovlen++;
6560 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
6566 static int reload_with_fallback(sd_bus *bus) {
6569 /* First, try systemd via D-Bus. */
6570 if (daemon_reload(bus, NULL) >= 0)
6574 /* Nothing else worked, so let's try signals */
6575 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
6577 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
6578 log_error("kill() failed: %m");
6585 static int start_with_fallback(sd_bus *bus) {
6588 /* First, try systemd via D-Bus. */
6589 if (start_unit(bus, NULL) >= 0)
6593 /* Nothing else worked, so let's try
6595 if (talk_initctl() > 0)
6598 log_error("Failed to talk to init daemon.");
6602 warn_wall(arg_action);
6606 static int halt_now(enum action a) {
6608 /* Make sure C-A-D is handled by the kernel from this
6610 reboot(RB_ENABLE_CAD);
6615 log_info("Halting.");
6616 reboot(RB_HALT_SYSTEM);
6619 case ACTION_POWEROFF:
6620 log_info("Powering off.");
6621 reboot(RB_POWER_OFF);
6624 case ACTION_REBOOT: {
6625 _cleanup_free_ char *param = NULL;
6627 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
6628 log_info("Rebooting with argument '%s'.", param);
6629 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
6630 LINUX_REBOOT_CMD_RESTART2, param);
6633 log_info("Rebooting.");
6634 reboot(RB_AUTOBOOT);
6639 assert_not_reached("Unknown action.");
6643 static int halt_main(sd_bus *bus) {
6646 r = check_inhibitors(bus, arg_action);
6650 if (geteuid() != 0) {
6651 /* Try logind if we are a normal user and no special
6652 * mode applies. Maybe PolicyKit allows us to shutdown
6655 if (arg_when <= 0 &&
6658 (arg_action == ACTION_POWEROFF ||
6659 arg_action == ACTION_REBOOT)) {
6660 r = reboot_with_logind(bus, arg_action);
6665 log_error("Must be root.");
6670 _cleanup_free_ char *m;
6672 m = strv_join(arg_wall, " ");
6676 r = send_shutdownd(arg_when,
6677 arg_action == ACTION_HALT ? 'H' :
6678 arg_action == ACTION_POWEROFF ? 'P' :
6679 arg_action == ACTION_KEXEC ? 'K' :
6686 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6688 char date[FORMAT_TIMESTAMP_MAX];
6690 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6691 format_timestamp(date, sizeof(date), arg_when));
6696 if (!arg_dry && !arg_force)
6697 return start_with_fallback(bus);
6700 if (sd_booted() > 0)
6701 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6703 r = utmp_put_shutdown();
6705 log_warning("Failed to write utmp record: %s", strerror(-r));
6712 r = halt_now(arg_action);
6713 log_error("Failed to reboot: %s", strerror(-r));
6718 static int runlevel_main(void) {
6719 int r, runlevel, previous;
6721 r = utmp_get_runlevel(&runlevel, &previous);
6728 previous <= 0 ? 'N' : previous,
6729 runlevel <= 0 ? 'N' : runlevel);
6734 int main(int argc, char*argv[]) {
6735 _cleanup_bus_unref_ sd_bus *bus = NULL;
6738 setlocale(LC_ALL, "");
6739 log_parse_environment();
6742 /* Explicitly not on_tty() to avoid setting cached value.
6743 * This becomes relevant for piping output which might be
6745 original_stdout_is_tty = isatty(STDOUT_FILENO);
6747 r = parse_argv(argc, argv);
6751 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6752 * let's shortcut this */
6753 if (arg_action == ACTION_RUNLEVEL) {
6754 r = runlevel_main();
6758 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6759 log_info("Running in chroot, ignoring request.");
6765 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
6767 /* systemctl_main() will print an error message for the bus
6768 * connection, but only if it needs to */
6770 switch (arg_action) {
6772 case ACTION_SYSTEMCTL:
6773 r = systemctl_main(bus, argc, argv, r);
6777 case ACTION_POWEROFF:
6783 case ACTION_RUNLEVEL2:
6784 case ACTION_RUNLEVEL3:
6785 case ACTION_RUNLEVEL4:
6786 case ACTION_RUNLEVEL5:
6788 case ACTION_EMERGENCY:
6789 case ACTION_DEFAULT:
6790 r = start_with_fallback(bus);
6795 r = reload_with_fallback(bus);
6798 case ACTION_CANCEL_SHUTDOWN: {
6799 _cleanup_free_ char *m = NULL;
6802 m = strv_join(arg_wall, " ");
6809 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6811 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6815 case ACTION_RUNLEVEL:
6816 case _ACTION_INVALID:
6818 assert_not_reached("Unknown action");
6823 ask_password_agent_close();
6824 polkit_agent_close();
6826 strv_free(arg_types);
6827 strv_free(arg_states);
6828 strv_free(arg_properties);
6830 return r < 0 ? EXIT_FAILURE : r;