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 size = sizeof(UnitInfo) * c;
528 r = sd_bus_call_method(
530 "org.freedesktop.systemd1",
531 "/org/freedesktop/systemd1",
532 "org.freedesktop.systemd1.Manager",
538 log_error("Failed to list units: %s", bus_error_message(&error, r));
542 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
544 return bus_log_parse_error(r);
546 while ((r = bus_parse_unit_info(reply, &u)) > 0) {
549 if (!output_show_unit(&u, patterns))
552 if (!GREEDY_REALLOC(*unit_infos, size, c+1))
555 (*unit_infos)[c++] = u;
558 return bus_log_parse_error(r);
560 r = sd_bus_message_exit_container(reply);
562 return bus_log_parse_error(r);
570 static void message_set_freep(Set **set) {
573 while ((m = set_steal_first(*set)))
574 sd_bus_message_unref(m);
579 static int get_unit_list_recursive(
582 UnitInfo **_unit_infos,
586 _cleanup_free_ UnitInfo *unit_infos = NULL;
587 _cleanup_(message_set_freep) Set *replies;
588 sd_bus_message *reply;
596 replies = set_new(NULL, NULL);
600 c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
604 r = set_put(replies, reply);
606 sd_bus_message_unref(reply);
611 _cleanup_strv_free_ char **machines = NULL;
614 r = sd_get_machine_names(&machines);
618 STRV_FOREACH(i, machines) {
619 _cleanup_bus_unref_ sd_bus *container = NULL;
622 r = sd_bus_open_system_container(&container, *i);
624 log_error("Failed to connect to container %s: %s", *i, strerror(-r));
628 k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
634 r = set_put(replies, reply);
636 sd_bus_message_unref(reply);
641 *_machines = machines;
646 *_unit_infos = unit_infos;
655 static int list_units(sd_bus *bus, char **args) {
656 _cleanup_free_ UnitInfo *unit_infos = NULL;
657 _cleanup_(message_set_freep) Set *replies = NULL;
658 _cleanup_strv_free_ char **machines = NULL;
661 pager_open_if_enabled();
663 r = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
667 qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
668 return output_units_list(unit_infos, r);
671 static int get_triggered_units(
676 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
679 r = sd_bus_get_property_strv(
681 "org.freedesktop.systemd1",
683 "org.freedesktop.systemd1.Unit",
689 log_error("Failed to determine triggers: %s", bus_error_message(&error, r));
694 static int get_listening(
696 const char* unit_path,
699 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
700 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
701 const char *type, *path;
704 r = sd_bus_get_property(
706 "org.freedesktop.systemd1",
708 "org.freedesktop.systemd1.Socket",
714 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r));
718 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
720 return bus_log_parse_error(r);
722 while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
724 r = strv_extend(listening, type);
728 r = strv_extend(listening, path);
735 return bus_log_parse_error(r);
737 r = sd_bus_message_exit_container(reply);
739 return bus_log_parse_error(r);
750 /* Note: triggered is a list here, although it almost certainly
751 * will always be one unit. Nevertheless, dbus API allows for multiple
752 * values, so let's follow that.*/
755 /* The strv above is shared. free is set only in the first one. */
759 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
765 o = strcmp(a->path, b->path);
767 o = strcmp(a->type, b->type);
772 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
773 struct socket_info *s;
774 unsigned pathlen = strlen("LISTEN"),
775 typelen = strlen("TYPE") * arg_show_types,
776 socklen = strlen("UNIT"),
777 servlen = strlen("ACTIVATES");
778 const char *on, *off;
780 for (s = socket_infos; s < socket_infos + cs; s++) {
784 socklen = MAX(socklen, strlen(s->id));
786 typelen = MAX(typelen, strlen(s->type));
787 pathlen = MAX(pathlen, strlen(s->path));
789 STRV_FOREACH(a, s->triggered)
790 tmp += strlen(*a) + 2*(a != s->triggered);
791 servlen = MAX(servlen, tmp);
796 printf("%-*s %-*.*s%-*s %s\n",
798 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
802 for (s = socket_infos; s < socket_infos + cs; s++) {
806 printf("%-*s %-*s %-*s",
807 pathlen, s->path, typelen, s->type, socklen, s->id);
810 pathlen, s->path, socklen, s->id);
811 STRV_FOREACH(a, s->triggered)
813 a == s->triggered ? "" : ",", *a);
817 on = ansi_highlight();
818 off = ansi_highlight_off();
822 on = ansi_highlight_red();
823 off = ansi_highlight_off();
826 if (!arg_no_legend) {
827 printf("%s%u sockets listed.%s\n", on, cs, off);
829 printf("Pass --all to see loaded but inactive sockets, too.\n");
835 static int list_sockets(sd_bus *bus, char **args) {
836 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
837 _cleanup_free_ UnitInfo *unit_infos = NULL;
838 _cleanup_free_ struct socket_info *socket_infos = NULL;
840 struct socket_info *s;
845 pager_open_if_enabled();
847 n = get_unit_list(bus, NULL, strv_skip_first(args), &unit_infos, 0, &reply);
851 for (u = unit_infos; u < unit_infos + n; u++) {
852 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
855 if (!endswith(u->id, ".socket"))
858 r = get_triggered_units(bus, u->unit_path, &triggered);
862 c = get_listening(bus, u->unit_path, &listening);
868 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
873 for (i = 0; i < c; i++)
874 socket_infos[cs + i] = (struct socket_info) {
876 .type = listening[i*2],
877 .path = listening[i*2 + 1],
878 .triggered = triggered,
879 .own_triggered = i==0,
882 /* from this point on we will cleanup those socket_infos */
885 listening = triggered = NULL; /* avoid cleanup */
888 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
889 (__compar_fn_t) socket_info_compare);
891 output_sockets_list(socket_infos, cs);
894 assert(cs == 0 || socket_infos);
895 for (s = socket_infos; s < socket_infos + cs; s++) {
898 if (s->own_triggered)
899 strv_free(s->triggered);
905 static int get_next_elapse(
908 dual_timestamp *next) {
910 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
918 r = sd_bus_get_property_trivial(
920 "org.freedesktop.systemd1",
922 "org.freedesktop.systemd1.Timer",
923 "NextElapseUSecMonotonic",
928 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
932 r = sd_bus_get_property_trivial(
934 "org.freedesktop.systemd1",
936 "org.freedesktop.systemd1.Timer",
937 "NextElapseUSecRealtime",
942 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
956 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
960 if (a->next_elapse < b->next_elapse)
962 if (a->next_elapse > b->next_elapse)
965 return strcmp(a->id, b->id);
968 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
969 struct timer_info *t;
971 nextlen = strlen("NEXT"),
972 leftlen = strlen("LEFT"),
973 unitlen = strlen("UNIT"),
974 activatelen = strlen("ACTIVATES");
976 const char *on, *off;
978 assert(timer_infos || n == 0);
980 for (t = timer_infos; t < timer_infos + n; t++) {
984 if (t->next_elapse > 0) {
985 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
987 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
988 nextlen = MAX(nextlen, strlen(tstamp) + 1);
990 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
991 leftlen = MAX(leftlen, strlen(trel));
994 unitlen = MAX(unitlen, strlen(t->id));
996 STRV_FOREACH(a, t->triggered)
997 ul += strlen(*a) + 2*(a != t->triggered);
998 activatelen = MAX(activatelen, ul);
1003 printf("%-*s %-*s %-*s %s\n",
1009 for (t = timer_infos; t < timer_infos + n; t++) {
1010 char tstamp[FORMAT_TIMESTAMP_MAX] = "n/a", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1013 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
1014 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
1016 printf("%-*s %-*s %-*s",
1017 nextlen, tstamp, leftlen, trel, unitlen, t->id);
1019 STRV_FOREACH(a, t->triggered)
1021 a == t->triggered ? "" : ",", *a);
1025 on = ansi_highlight();
1026 off = ansi_highlight_off();
1030 on = ansi_highlight_red();
1031 off = ansi_highlight_off();
1034 if (!arg_no_legend) {
1035 printf("%s%u timers listed.%s\n", on, n, off);
1037 printf("Pass --all to see loaded but inactive timers, too.\n");
1043 static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
1049 if (next->monotonic != (usec_t) -1 && next->monotonic > 0) {
1052 if (next->monotonic > nw->monotonic)
1053 converted = nw->realtime + (next->monotonic - nw->monotonic);
1055 converted = nw->realtime - (nw->monotonic - next->monotonic);
1057 if (next->realtime != (usec_t) -1 && next->realtime > 0)
1058 next_elapse = MIN(converted, next->realtime);
1060 next_elapse = converted;
1063 next_elapse = next->realtime;
1068 static int list_timers(sd_bus *bus, char **args) {
1070 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1071 _cleanup_free_ struct timer_info *timer_infos = NULL;
1072 _cleanup_free_ UnitInfo *unit_infos = NULL;
1073 struct timer_info *t;
1080 pager_open_if_enabled();
1082 n = get_unit_list(bus, NULL, strv_skip_first(args), &unit_infos, 0, &reply);
1086 dual_timestamp_get(&nw);
1088 for (u = unit_infos; u < unit_infos + n; u++) {
1089 _cleanup_strv_free_ char **triggered = NULL;
1090 dual_timestamp next = {};
1093 if (!endswith(u->id, ".timer"))
1096 r = get_triggered_units(bus, u->unit_path, &triggered);
1100 r = get_next_elapse(bus, u->unit_path, &next);
1104 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
1109 m = calc_next_elapse(&nw, &next);
1111 timer_infos[c++] = (struct timer_info) {
1114 .triggered = triggered,
1117 triggered = NULL; /* avoid cleanup */
1120 qsort_safe(timer_infos, c, sizeof(struct timer_info),
1121 (__compar_fn_t) timer_info_compare);
1123 output_timers_list(timer_infos, c);
1126 for (t = timer_infos; t < timer_infos + c; t++)
1127 strv_free(t->triggered);
1132 static int compare_unit_file_list(const void *a, const void *b) {
1133 const char *d1, *d2;
1134 const UnitFileList *u = a, *v = b;
1136 d1 = strrchr(u->path, '.');
1137 d2 = strrchr(v->path, '.');
1142 r = strcasecmp(d1, d2);
1147 return strcasecmp(basename(u->path), basename(v->path));
1150 static bool output_show_unit_file(const UnitFileList *u, char **patterns) {
1153 if (!strv_isempty(patterns)) {
1156 STRV_FOREACH(pattern, patterns)
1157 if (fnmatch(*pattern, basename(u->path), FNM_NOESCAPE) == 0)
1162 return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
1165 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
1166 unsigned max_id_len, id_cols, state_cols;
1167 const UnitFileList *u;
1169 max_id_len = strlen("UNIT FILE");
1170 state_cols = strlen("STATE");
1172 for (u = units; u < units + c; u++) {
1173 max_id_len = MAX(max_id_len, strlen(basename(u->path)));
1174 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1178 unsigned basic_cols;
1180 id_cols = MIN(max_id_len, 25u);
1181 basic_cols = 1 + id_cols + state_cols;
1182 if (basic_cols < (unsigned) columns())
1183 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1185 id_cols = max_id_len;
1188 printf("%-*s %-*s\n",
1189 id_cols, "UNIT FILE",
1190 state_cols, "STATE");
1192 for (u = units; u < units + c; u++) {
1193 _cleanup_free_ char *e = NULL;
1194 const char *on, *off;
1197 if (u->state == UNIT_FILE_MASKED ||
1198 u->state == UNIT_FILE_MASKED_RUNTIME ||
1199 u->state == UNIT_FILE_DISABLED ||
1200 u->state == UNIT_FILE_INVALID) {
1201 on = ansi_highlight_red();
1202 off = ansi_highlight_off();
1203 } else if (u->state == UNIT_FILE_ENABLED) {
1204 on = ansi_highlight_green();
1205 off = ansi_highlight_off();
1209 id = basename(u->path);
1211 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1213 printf("%-*s %s%-*s%s\n",
1214 id_cols, e ? e : id,
1215 on, state_cols, unit_file_state_to_string(u->state), off);
1219 printf("\n%u unit files listed.\n", c);
1222 static int list_unit_files(sd_bus *bus, char **args) {
1223 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1224 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1225 _cleanup_free_ UnitFileList *units = NULL;
1233 pager_open_if_enabled();
1241 h = hashmap_new(string_hash_func, string_compare_func);
1245 r = unit_file_get_list(arg_scope, arg_root, h);
1247 unit_file_list_free(h);
1248 log_error("Failed to get unit file list: %s", strerror(-r));
1252 n_units = hashmap_size(h);
1253 units = new(UnitFileList, n_units);
1255 unit_file_list_free(h);
1259 HASHMAP_FOREACH(u, h, i) {
1260 if (!output_show_unit_file(u, strv_skip_first(args)))
1267 assert(c <= n_units);
1270 r = sd_bus_call_method(
1272 "org.freedesktop.systemd1",
1273 "/org/freedesktop/systemd1",
1274 "org.freedesktop.systemd1.Manager",
1280 log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1284 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1286 return bus_log_parse_error(r);
1288 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1290 if (!GREEDY_REALLOC(units, size, c + 1))
1293 units[c] = (struct UnitFileList) {
1295 unit_file_state_from_string(state)
1298 if (output_show_unit_file(&units[c], strv_skip_first(args)))
1303 return bus_log_parse_error(r);
1305 r = sd_bus_message_exit_container(reply);
1307 return bus_log_parse_error(r);
1311 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
1312 output_unit_file_list(units, c);
1316 for (unit = units; unit < units + c; unit++)
1322 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1323 _cleanup_free_ char *n = NULL;
1324 size_t max_len = MAX(columns(),20u);
1330 for (i = level - 1; i >= 0; i--) {
1332 if (len > max_len - 3 && !arg_full) {
1333 printf("%s...\n",max_len % 2 ? "" : " ");
1336 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
1340 if (len > max_len - 3 && !arg_full) {
1341 printf("%s...\n",max_len % 2 ? "" : " ");
1345 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
1349 printf("%s\n", name);
1353 n = ellipsize(name, max_len-len, 100);
1361 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1363 static const char *dependencies[_DEPENDENCY_MAX] = {
1364 [DEPENDENCY_FORWARD] = "Requires\0"
1365 "RequiresOverridable\0"
1367 "RequisiteOverridable\0"
1369 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1370 "RequiredByOverridable\0"
1373 [DEPENDENCY_AFTER] = "After\0",
1374 [DEPENDENCY_BEFORE] = "Before\0",
1377 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1378 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1379 _cleanup_strv_free_ char **ret = NULL;
1380 _cleanup_free_ char *path = NULL;
1386 assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
1388 path = unit_dbus_path_from_name(name);
1392 r = sd_bus_call_method(
1394 "org.freedesktop.systemd1",
1396 "org.freedesktop.DBus.Properties",
1400 "s", "org.freedesktop.systemd1.Unit");
1402 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1406 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1408 return bus_log_parse_error(r);
1410 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1413 r = sd_bus_message_read(reply, "s", &prop);
1415 return bus_log_parse_error(r);
1417 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1418 r = sd_bus_message_skip(reply, "v");
1420 return bus_log_parse_error(r);
1423 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1425 return bus_log_parse_error(r);
1427 r = bus_message_read_strv_extend(reply, &ret);
1429 return bus_log_parse_error(r);
1431 r = sd_bus_message_exit_container(reply);
1433 return bus_log_parse_error(r);
1436 r = sd_bus_message_exit_container(reply);
1438 return bus_log_parse_error(r);
1442 return bus_log_parse_error(r);
1444 r = sd_bus_message_exit_container(reply);
1446 return bus_log_parse_error(r);
1454 static int list_dependencies_compare(const void *_a, const void *_b) {
1455 const char **a = (const char**) _a, **b = (const char**) _b;
1457 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1459 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1462 return strcasecmp(*a, *b);
1465 static int list_dependencies_one(
1470 unsigned int branches) {
1472 _cleanup_strv_free_ char **deps = NULL;
1480 r = strv_extend(units, name);
1484 r = list_dependencies_get_dependencies(bus, name, &deps);
1488 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1490 STRV_FOREACH(c, deps) {
1493 if (strv_contains(*units, *c)) {
1495 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1502 state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true);
1504 printf("%s%s%s", ansi_highlight_green(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1506 printf("%s%s%s", ansi_highlight_red(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1508 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1512 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1513 r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1520 strv_remove(*units, name);
1525 static int list_dependencies(sd_bus *bus, char **args) {
1526 _cleanup_strv_free_ char **units = NULL;
1527 _cleanup_free_ char *unit = NULL;
1533 unit = unit_name_mangle(args[1], MANGLE_NOGLOB);
1538 u = SPECIAL_DEFAULT_TARGET;
1540 pager_open_if_enabled();
1544 return list_dependencies_one(bus, u, 0, &units, 0);
1547 struct machine_info {
1551 char *control_group;
1552 uint32_t n_failed_units;
1557 static const struct bus_properties_map machine_info_property_map[] = {
1558 { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
1559 { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
1560 { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
1561 { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
1562 { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
1566 static void free_machines_list(struct machine_info *machine_infos, int n) {
1572 for (i = 0; i < n; i++) {
1573 free(machine_infos[i].name);
1574 free(machine_infos[i].state);
1575 free(machine_infos[i].control_group);
1578 free(machine_infos);
1581 static int compare_machine_info(const void *a, const void *b) {
1582 const struct machine_info *u = a, *v = b;
1584 if (u->is_host != v->is_host)
1585 return u->is_host > v->is_host ? -1 : 1;
1587 return strcasecmp(u->name, v->name);
1590 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1591 _cleanup_bus_unref_ sd_bus *container = NULL;
1597 r = sd_bus_open_system_container(&container, mi->name);
1604 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi);
1611 static bool output_show_machine(const char *name, char **patterns) {
1616 if (strv_isempty(patterns))
1619 STRV_FOREACH(i, patterns)
1620 if (fnmatch(*i, name, FNM_NOESCAPE) == 0)
1626 static int get_machine_list(
1628 struct machine_info **_machine_infos,
1631 struct machine_info *machine_infos = NULL;
1632 _cleanup_strv_free_ char **m = NULL;
1633 _cleanup_free_ char *hn = NULL;
1638 hn = gethostname_malloc();
1642 if (output_show_machine(hn, patterns)) {
1643 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1646 machine_infos[c].is_host = true;
1647 machine_infos[c].name = hn;
1650 get_machine_properties(bus, &machine_infos[c]);
1654 sd_get_machine_names(&m);
1655 STRV_FOREACH(i, m) {
1656 _cleanup_free_ char *class = NULL;
1658 if (!output_show_machine(*i, patterns))
1661 sd_machine_get_class(*i, &class);
1662 if (!streq_ptr(class, "container"))
1665 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1666 free_machines_list(machine_infos, c);
1670 machine_infos[c].is_host = false;
1671 machine_infos[c].name = strdup(*i);
1672 if (!machine_infos[c].name) {
1673 free_machines_list(machine_infos, c);
1677 get_machine_properties(NULL, &machine_infos[c]);
1681 *_machine_infos = machine_infos;
1685 static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1686 struct machine_info *m;
1689 namelen = sizeof("NAME") - 1,
1690 statelen = sizeof("STATE") - 1,
1691 failedlen = sizeof("FAILED") - 1,
1692 jobslen = sizeof("JOBS") - 1;
1694 assert(machine_infos || n == 0);
1696 for (m = machine_infos; m < machine_infos + n; m++) {
1697 namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
1698 statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
1699 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
1700 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
1702 if (!arg_no_legend && !streq_ptr(m->state, "running"))
1706 if (!arg_no_legend) {
1710 printf("%-*s %-*s %-*s %-*s\n",
1713 failedlen, "FAILED",
1717 for (m = machine_infos; m < machine_infos + n; m++) {
1718 const char *on_state = "", *off_state = "";
1719 const char *on_failed = "", *off_failed = "";
1720 bool circle = false;
1722 if (streq_ptr(m->state, "degraded")) {
1723 on_state = ansi_highlight_red();
1724 off_state = ansi_highlight_off();
1726 } else if (!streq_ptr(m->state, "running")) {
1727 on_state = ansi_highlight_yellow();
1728 off_state = ansi_highlight_off();
1732 if (m->n_failed_units > 0) {
1733 on_failed = ansi_highlight_red();
1734 off_failed = ansi_highlight_off();
1736 on_failed = off_failed = "";
1739 printf("%s%s%s", on_state, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_state);
1742 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1743 (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
1744 on_state, statelen, strna(m->state), off_state,
1745 on_failed, failedlen, m->n_failed_units, off_failed,
1746 jobslen, m->n_jobs);
1748 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1749 namelen, strna(m->name),
1750 on_state, statelen, strna(m->state), off_state,
1751 on_failed, failedlen, m->n_failed_units, off_failed,
1752 jobslen, m->n_jobs);
1756 printf("\n%u machines listed.\n", n);
1759 static int list_machines(sd_bus *bus, char **args) {
1760 struct machine_info *machine_infos = NULL;
1765 if (geteuid() != 0) {
1766 log_error("Must be root.");
1770 pager_open_if_enabled();
1772 r = get_machine_list(bus, &machine_infos, strv_skip_first(args));
1776 qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
1777 output_machines_list(machine_infos, r);
1778 free_machines_list(machine_infos, r);
1783 static int get_default(sd_bus *bus, char **args) {
1784 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1785 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1786 _cleanup_free_ char *_path = NULL;
1790 if (!bus || avoid_bus()) {
1791 r = unit_file_get_default(arg_scope, arg_root, &_path);
1793 log_error("Failed to get default target: %s", strerror(-r));
1799 r = sd_bus_call_method(
1801 "org.freedesktop.systemd1",
1802 "/org/freedesktop/systemd1",
1803 "org.freedesktop.systemd1.Manager",
1809 log_error("Failed to get default target: %s", bus_error_message(&error, -r));
1813 r = sd_bus_message_read(reply, "s", &path);
1815 return bus_log_parse_error(r);
1819 printf("%s\n", path);
1824 static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) {
1827 assert(changes || n_changes == 0);
1829 for (i = 0; i < n_changes; i++) {
1830 if (changes[i].type == UNIT_FILE_SYMLINK)
1831 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
1833 log_info("rm '%s'", changes[i].path);
1837 static int deserialize_and_dump_unit_file_changes(sd_bus_message *m) {
1838 const char *type, *path, *source;
1841 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1843 return bus_log_parse_error(r);
1845 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1847 if (streq(type, "symlink"))
1848 log_info("ln -s '%s' '%s'", source, path);
1850 log_info("rm '%s'", path);
1854 return bus_log_parse_error(r);
1856 r = sd_bus_message_exit_container(m);
1858 return bus_log_parse_error(r);
1863 static int set_default(sd_bus *bus, char **args) {
1864 _cleanup_free_ char *unit = NULL;
1865 UnitFileChange *changes = NULL;
1866 unsigned n_changes = 0;
1869 unit = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
1873 if (!bus || avoid_bus()) {
1874 r = unit_file_set_default(arg_scope, arg_root, unit, arg_force, &changes, &n_changes);
1876 log_error("Failed to set default target: %s", strerror(-r));
1881 dump_unit_file_changes(changes, n_changes);
1885 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1886 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1888 r = sd_bus_call_method(
1890 "org.freedesktop.systemd1",
1891 "/org/freedesktop/systemd1",
1892 "org.freedesktop.systemd1.Manager",
1896 "sb", unit, arg_force);
1898 log_error("Failed to set default target: %s", bus_error_message(&error, -r));
1902 r = deserialize_and_dump_unit_file_changes(reply);
1906 /* Try to reload if enabeld */
1908 r = daemon_reload(bus, args);
1913 unit_file_changes_free(changes, n_changes);
1920 const char *name, *type, *state;
1923 static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
1924 unsigned id_len, unit_len, type_len, state_len;
1925 const struct job_info *j;
1926 const char *on, *off;
1927 bool shorten = false;
1929 assert(n == 0 || jobs);
1932 on = ansi_highlight_green();
1933 off = ansi_highlight_off();
1935 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
1939 pager_open_if_enabled();
1941 id_len = strlen("JOB");
1942 unit_len = strlen("UNIT");
1943 type_len = strlen("TYPE");
1944 state_len = strlen("STATE");
1946 for (j = jobs; j < jobs + n; j++) {
1947 uint32_t id = j->id;
1948 assert(j->name && j->type && j->state);
1950 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
1951 unit_len = MAX(unit_len, strlen(j->name));
1952 type_len = MAX(type_len, strlen(j->type));
1953 state_len = MAX(state_len, strlen(j->state));
1956 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
1957 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
1962 printf("%*s %-*s %-*s %-*s\n",
1966 state_len, "STATE");
1968 for (j = jobs; j < jobs + n; j++) {
1969 _cleanup_free_ char *e = NULL;
1971 if (streq(j->state, "running")) {
1972 on = ansi_highlight();
1973 off = ansi_highlight_off();
1977 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
1978 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
1980 on, unit_len, e ? e : j->name, off,
1982 on, state_len, j->state, off);
1985 if (!arg_no_legend) {
1986 on = ansi_highlight();
1987 off = ansi_highlight_off();
1989 printf("\n%s%u jobs listed%s.\n", on, n, off);
1993 static bool output_show_job(struct job_info *job, char **patterns) {
1998 if (strv_isempty(patterns))
2001 STRV_FOREACH(pattern, patterns)
2002 if (fnmatch(*pattern, job->name, FNM_NOESCAPE) == 0)
2007 static int list_jobs(sd_bus *bus, char **args) {
2008 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2009 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2010 const char *name, *type, *state, *job_path, *unit_path;
2011 _cleanup_free_ struct job_info *jobs = NULL;
2016 bool skipped = false;
2018 r = sd_bus_call_method(
2020 "org.freedesktop.systemd1",
2021 "/org/freedesktop/systemd1",
2022 "org.freedesktop.systemd1.Manager",
2028 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
2032 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2034 return bus_log_parse_error(r);
2036 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
2037 struct job_info job = { id, name, type, state };
2039 if (!output_show_job(&job, strv_skip_first(args))) {
2044 if (!GREEDY_REALLOC(jobs, size, c + 1))
2050 return bus_log_parse_error(r);
2052 r = sd_bus_message_exit_container(reply);
2054 return bus_log_parse_error(r);
2056 output_jobs_list(jobs, c, skipped);
2060 static int cancel_job(sd_bus *bus, char **args) {
2061 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2066 if (strv_length(args) <= 1)
2067 return daemon_reload(bus, args);
2069 STRV_FOREACH(name, args+1) {
2073 r = safe_atou32(*name, &id);
2075 log_error("Failed to parse job id \"%s\": %s", *name, strerror(-r));
2079 r = sd_bus_call_method(
2081 "org.freedesktop.systemd1",
2082 "/org/freedesktop/systemd1",
2083 "org.freedesktop.systemd1.Manager",
2089 log_error("Failed to cancel job %u: %s", (unsigned) id, bus_error_message(&error, r));
2097 static int need_daemon_reload(sd_bus *bus, const char *unit) {
2098 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2102 /* We ignore all errors here, since this is used to show a
2105 /* We don't use unit_dbus_path_from_name() directly since we
2106 * don't want to load the unit if it isn't loaded. */
2108 r = sd_bus_call_method(
2110 "org.freedesktop.systemd1",
2111 "/org/freedesktop/systemd1",
2112 "org.freedesktop.systemd1.Manager",
2120 r = sd_bus_message_read(reply, "o", &path);
2124 r = sd_bus_get_property_trivial(
2126 "org.freedesktop.systemd1",
2128 "org.freedesktop.systemd1.Unit",
2138 typedef struct WaitData {
2145 static int wait_filter(sd_bus *bus, sd_bus_message *m, void *data, sd_bus_error *error) {
2152 log_debug("Got D-Bus request: %s.%s() on %s",
2153 sd_bus_message_get_interface(m),
2154 sd_bus_message_get_member(m),
2155 sd_bus_message_get_path(m));
2157 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
2158 log_error("Warning! D-Bus connection terminated.");
2160 } else if (sd_bus_message_is_signal(m, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
2162 const char *path, *result, *unit;
2166 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
2168 ret = set_remove(d->set, (char*) path);
2174 if (!isempty(result))
2175 d->result = strdup(result);
2178 d->name = strdup(unit);
2183 r = sd_bus_message_read(m, "uos", &id, &path, &result);
2185 ret = set_remove(d->set, (char*) path);
2192 d->result = strdup(result);
2198 bus_log_parse_error(r);
2204 static int enable_wait_for_jobs(sd_bus *bus) {
2209 r = sd_bus_add_match(
2212 "sender='org.freedesktop.systemd1',"
2213 "interface='org.freedesktop.systemd1.Manager',"
2214 "member='JobRemoved',"
2215 "path='/org/freedesktop/systemd1'",
2218 log_error("Failed to add match");
2222 /* This is slightly dirty, since we don't undo the match registrations. */
2226 static int bus_process_wait(sd_bus *bus) {
2230 r = sd_bus_process(bus, NULL);
2235 r = sd_bus_wait(bus, (uint64_t) -1);
2241 static int check_wait_response(WaitData *d) {
2247 if (streq(d->result, "timeout"))
2248 log_error("Job for %s timed out.", strna(d->name));
2249 else if (streq(d->result, "canceled"))
2250 log_error("Job for %s canceled.", strna(d->name));
2251 else if (streq(d->result, "dependency"))
2252 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d->name));
2253 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2254 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d->name), strna(d->name));
2257 if (streq(d->result, "timeout"))
2259 else if (streq(d->result, "canceled"))
2261 else if (streq(d->result, "dependency"))
2263 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2269 static int wait_for_jobs(sd_bus *bus, Set *s) {
2270 WaitData d = { .set = s };
2276 q = sd_bus_add_filter(bus, wait_filter, &d);
2280 while (!set_isempty(s)) {
2281 q = bus_process_wait(bus);
2283 log_error("Failed to wait for response: %s", strerror(-r));
2288 q = check_wait_response(&d);
2289 /* Return the first error as it is most likely to be
2291 if (q < 0 && r == 0)
2293 log_debug("Got result %s/%s for job %s",
2294 strna(d.result), strerror(-q), strna(d.name));
2304 q = sd_bus_remove_filter(bus, wait_filter, &d);
2305 if (q < 0 && r == 0)
2311 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2312 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2313 _cleanup_free_ char *n = NULL, *state = NULL;
2319 n = unit_name_mangle(name, MANGLE_NOGLOB);
2323 /* We don't use unit_dbus_path_from_name() directly since we
2324 * don't want to load the unit if it isn't loaded. */
2326 r = sd_bus_call_method(
2328 "org.freedesktop.systemd1",
2329 "/org/freedesktop/systemd1",
2330 "org.freedesktop.systemd1.Manager",
2341 r = sd_bus_message_read(reply, "o", &path);
2343 return bus_log_parse_error(r);
2345 r = sd_bus_get_property_string(
2347 "org.freedesktop.systemd1",
2349 "org.freedesktop.systemd1.Unit",
2362 return nulstr_contains(good_states, state);
2365 static int check_triggering_units(
2369 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2370 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2371 _cleanup_strv_free_ char **triggered_by = NULL;
2372 bool print_warning_label = true;
2376 n = unit_name_mangle(name, MANGLE_NOGLOB);
2380 path = unit_dbus_path_from_name(n);
2384 r = sd_bus_get_property_string(
2386 "org.freedesktop.systemd1",
2388 "org.freedesktop.systemd1.Unit",
2393 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2397 if (streq(state, "masked"))
2400 r = sd_bus_get_property_strv(
2402 "org.freedesktop.systemd1",
2404 "org.freedesktop.systemd1.Unit",
2409 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2413 STRV_FOREACH(i, triggered_by) {
2414 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2416 log_error("Failed to check unit: %s", strerror(-r));
2423 if (print_warning_label) {
2424 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2425 print_warning_label = false;
2428 log_warning(" %s", *i);
2434 static const char *verb_to_method(const char *verb) {
2437 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2438 if (streq_ptr(unit_actions[i].verb, verb))
2439 return unit_actions[i].method;
2444 static const char *method_to_verb(const char *method) {
2447 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2448 if (streq_ptr(unit_actions[i].method, method))
2449 return unit_actions[i].verb;
2454 static int start_unit_one(
2459 sd_bus_error *error,
2462 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2471 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2472 r = sd_bus_call_method(
2474 "org.freedesktop.systemd1",
2475 "/org/freedesktop/systemd1",
2476 "org.freedesktop.systemd1.Manager",
2484 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2485 /* There's always a fallback possible for
2486 * legacy actions. */
2487 return -EADDRNOTAVAIL;
2489 verb = method_to_verb(method);
2491 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2495 r = sd_bus_message_read(reply, "o", &path);
2497 return bus_log_parse_error(r);
2499 if (need_daemon_reload(bus, name) > 0)
2500 log_warning("Warning: Unit file of %s changed on disk, 'systemctl%s daemon-reload' recommended.",
2501 name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2510 log_debug("Adding %s to the set", p);
2511 r = set_consume(s, p);
2519 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2521 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2525 STRV_FOREACH(name, names) {
2529 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2531 t = unit_name_mangle(*name, MANGLE_GLOB);
2535 if (string_is_glob(t))
2536 r = strv_consume(&globs, t);
2538 r = strv_consume(&mangled, t);
2543 /* Query the manager only if any of the names are a glob, since
2544 * this is fairly expensive */
2545 if (!strv_isempty(globs)) {
2546 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2547 _cleanup_free_ UnitInfo *unit_infos = NULL;
2549 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2553 for (i = 0; i < r; i++)
2554 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2559 mangled = NULL; /* do not free */
2564 static const struct {
2568 } action_table[_ACTION_MAX] = {
2569 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2570 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2571 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2572 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2573 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
2574 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
2575 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
2576 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
2577 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2578 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2579 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2580 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2581 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2582 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2583 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2586 static enum action verb_to_action(const char *verb) {
2589 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2590 if (streq_ptr(action_table[i].verb, verb))
2593 return _ACTION_INVALID;
2596 static int start_unit(sd_bus *bus, char **args) {
2597 _cleanup_set_free_free_ Set *s = NULL;
2598 _cleanup_strv_free_ char **names = NULL;
2599 const char *method, *mode, *one_name;
2605 ask_password_agent_open_if_enabled();
2607 if (arg_action == ACTION_SYSTEMCTL) {
2609 method = verb_to_method(args[0]);
2610 action = verb_to_action(args[0]);
2612 mode = streq(args[0], "isolate") ? "isolate" :
2613 action_table[action].mode ?: arg_job_mode;
2615 one_name = action_table[action].target;
2617 assert(arg_action < ELEMENTSOF(action_table));
2618 assert(action_table[arg_action].target);
2620 method = "StartUnit";
2622 mode = action_table[arg_action].mode;
2623 one_name = action_table[arg_action].target;
2627 names = strv_new(one_name, NULL);
2629 r = expand_names(bus, args + 1, NULL, &names);
2631 log_error("Failed to expand names: %s", strerror(-r));
2634 if (!arg_no_block) {
2635 r = enable_wait_for_jobs(bus);
2637 log_error("Could not watch jobs: %s", strerror(-r));
2641 s = set_new(string_hash_func, string_compare_func);
2646 STRV_FOREACH(name, names) {
2647 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2650 q = start_unit_one(bus, method, *name, mode, &error, s);
2651 if (r >= 0 && q < 0)
2652 r = translate_bus_error_to_exit_status(q, &error);
2655 if (!arg_no_block) {
2658 q = wait_for_jobs(bus, s);
2662 /* When stopping units, warn if they can still be triggered by
2663 * another active unit (socket, path, timer) */
2664 if (!arg_quiet && streq(method, "StopUnit"))
2665 STRV_FOREACH(name, names)
2666 check_triggering_units(bus, *name);
2672 /* Ask systemd-logind, which might grant access to unprivileged users
2673 * through PolicyKit */
2674 static int reboot_with_logind(sd_bus *bus, enum action a) {
2676 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2683 polkit_agent_open_if_enabled();
2691 case ACTION_POWEROFF:
2692 method = "PowerOff";
2695 case ACTION_SUSPEND:
2699 case ACTION_HIBERNATE:
2700 method = "Hibernate";
2703 case ACTION_HYBRID_SLEEP:
2704 method = "HybridSleep";
2711 r = sd_bus_call_method(
2713 "org.freedesktop.login1",
2714 "/org/freedesktop/login1",
2715 "org.freedesktop.login1.Manager",
2721 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2729 static int check_inhibitors(sd_bus *bus, enum action a) {
2731 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2732 _cleanup_strv_free_ char **sessions = NULL;
2733 const char *what, *who, *why, *mode;
2742 if (arg_ignore_inhibitors || arg_force > 0)
2754 r = sd_bus_call_method(
2756 "org.freedesktop.login1",
2757 "/org/freedesktop/login1",
2758 "org.freedesktop.login1.Manager",
2764 /* If logind is not around, then there are no inhibitors... */
2767 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2769 return bus_log_parse_error(r);
2771 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2772 _cleanup_free_ char *comm = NULL, *user = NULL;
2773 _cleanup_strv_free_ char **sv = NULL;
2775 if (!streq(mode, "block"))
2778 sv = strv_split(what, ":");
2782 if (!strv_contains(sv,
2784 a == ACTION_POWEROFF ||
2785 a == ACTION_REBOOT ||
2786 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2789 get_process_comm(pid, &comm);
2790 user = uid_to_name(uid);
2792 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2793 who, (unsigned long) pid, strna(comm), strna(user), why);
2798 return bus_log_parse_error(r);
2800 r = sd_bus_message_exit_container(reply);
2802 return bus_log_parse_error(r);
2804 /* Check for current sessions */
2805 sd_get_sessions(&sessions);
2806 STRV_FOREACH(s, sessions) {
2807 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2809 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2812 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2815 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2818 sd_session_get_tty(*s, &tty);
2819 sd_session_get_seat(*s, &seat);
2820 sd_session_get_service(*s, &service);
2821 user = uid_to_name(uid);
2823 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2830 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2831 action_table[a].verb);
2839 static int start_special(sd_bus *bus, char **args) {
2845 a = verb_to_action(args[0]);
2847 r = check_inhibitors(bus, a);
2851 if (arg_force >= 2 && geteuid() != 0) {
2852 log_error("Must be root.");
2856 if (arg_force >= 2 &&
2857 (a == ACTION_HALT ||
2858 a == ACTION_POWEROFF ||
2859 a == ACTION_REBOOT))
2862 if (arg_force >= 1 &&
2863 (a == ACTION_HALT ||
2864 a == ACTION_POWEROFF ||
2865 a == ACTION_REBOOT ||
2866 a == ACTION_KEXEC ||
2868 return daemon_reload(bus, args);
2870 /* first try logind, to allow authentication with polkit */
2871 if (geteuid() != 0 &&
2872 (a == ACTION_POWEROFF ||
2873 a == ACTION_REBOOT ||
2874 a == ACTION_SUSPEND ||
2875 a == ACTION_HIBERNATE ||
2876 a == ACTION_HYBRID_SLEEP)) {
2877 r = reboot_with_logind(bus, a);
2882 r = start_unit(bus, args);
2883 if (r == EXIT_SUCCESS)
2889 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
2890 _cleanup_strv_free_ char **names = NULL;
2897 r = expand_names(bus, args, NULL, &names);
2899 log_error("Failed to expand names: %s", strerror(-r));
2903 STRV_FOREACH(name, names) {
2906 state = check_one_unit(bus, *name, good_states, arg_quiet);
2916 static int check_unit_active(sd_bus *bus, char **args) {
2917 /* According to LSB: 3, "program is not running" */
2918 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
2921 static int check_unit_failed(sd_bus *bus, char **args) {
2922 return check_unit_generic(bus, 1, "failed\0", args + 1);
2925 static int kill_unit(sd_bus *bus, char **args) {
2926 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2927 _cleanup_strv_free_ char **names = NULL;
2935 arg_kill_who = "all";
2937 r = expand_names(bus, args + 1, NULL, &names);
2939 log_error("Failed to expand names: %s", strerror(-r));
2941 STRV_FOREACH(name, names) {
2942 q = sd_bus_call_method(
2944 "org.freedesktop.systemd1",
2945 "/org/freedesktop/systemd1",
2946 "org.freedesktop.systemd1.Manager",
2950 "ssi", *names, arg_kill_who, arg_signal);
2952 log_error("Failed to kill unit %s: %s",
2953 *names, bus_error_message(&error, r));
2962 typedef struct ExecStatusInfo {
2970 usec_t start_timestamp;
2971 usec_t exit_timestamp;
2976 LIST_FIELDS(struct ExecStatusInfo, exec);
2979 static void exec_status_info_free(ExecStatusInfo *i) {
2988 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
2989 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2992 int32_t code, status;
2998 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3000 return bus_log_parse_error(r);
3004 r = sd_bus_message_read(m, "s", &path);
3006 return bus_log_parse_error(r);
3008 i->path = strdup(path);
3012 r = sd_bus_message_read_strv(m, &i->argv);
3014 return bus_log_parse_error(r);
3016 r = sd_bus_message_read(m,
3019 &start_timestamp, &start_timestamp_monotonic,
3020 &exit_timestamp, &exit_timestamp_monotonic,
3024 return bus_log_parse_error(r);
3027 i->start_timestamp = (usec_t) start_timestamp;
3028 i->exit_timestamp = (usec_t) exit_timestamp;
3029 i->pid = (pid_t) pid;
3033 r = sd_bus_message_exit_container(m);
3035 return bus_log_parse_error(r);
3040 typedef struct UnitStatusInfo {
3042 const char *load_state;
3043 const char *active_state;
3044 const char *sub_state;
3045 const char *unit_file_state;
3047 const char *description;
3048 const char *following;
3050 char **documentation;
3052 const char *fragment_path;
3053 const char *source_path;
3054 const char *control_group;
3056 char **dropin_paths;
3058 const char *load_error;
3061 usec_t inactive_exit_timestamp;
3062 usec_t inactive_exit_timestamp_monotonic;
3063 usec_t active_enter_timestamp;
3064 usec_t active_exit_timestamp;
3065 usec_t inactive_enter_timestamp;
3067 bool need_daemon_reload;
3072 const char *status_text;
3073 const char *pid_file;
3076 usec_t start_timestamp;
3077 usec_t exit_timestamp;
3079 int exit_code, exit_status;
3081 usec_t condition_timestamp;
3082 bool condition_result;
3083 bool failed_condition_trigger;
3084 bool failed_condition_negate;
3085 const char *failed_condition;
3086 const char *failed_condition_param;
3089 unsigned n_accepted;
3090 unsigned n_connections;
3093 /* Pairs of type, path */
3097 const char *sysfs_path;
3099 /* Mount, Automount */
3105 LIST_HEAD(ExecStatusInfo, exec);
3108 static void print_status_info(
3113 const char *active_on, *active_off, *on, *off, *ss;
3115 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3116 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3119 arg_all * OUTPUT_SHOW_ALL |
3120 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
3121 on_tty() * OUTPUT_COLOR |
3122 !arg_quiet * OUTPUT_WARN_CUTOFF |
3123 arg_full * OUTPUT_FULL_WIDTH;
3128 /* This shows pretty information about a unit. See
3129 * print_property() for a low-level property printer */
3131 if (streq_ptr(i->active_state, "failed")) {
3132 active_on = ansi_highlight_red();
3133 active_off = ansi_highlight_off();
3134 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3135 active_on = ansi_highlight_green();
3136 active_off = ansi_highlight_off();
3138 active_on = active_off = "";
3140 printf("%s%s%s%s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3142 if (i->description && !streq_ptr(i->id, i->description))
3143 printf(" - %s", i->description);
3148 printf(" Follow: unit currently follows state of %s\n", i->following);
3150 if (streq_ptr(i->load_state, "error")) {
3151 on = ansi_highlight_red();
3152 off = ansi_highlight_off();
3156 path = i->source_path ? i->source_path : i->fragment_path;
3159 printf(" Loaded: %s%s%s (Reason: %s)\n",
3160 on, strna(i->load_state), off, i->load_error);
3161 else if (path && i->unit_file_state)
3162 printf(" Loaded: %s%s%s (%s; %s)\n",
3163 on, strna(i->load_state), off, path, i->unit_file_state);
3165 printf(" Loaded: %s%s%s (%s)\n",
3166 on, strna(i->load_state), off, path);
3168 printf(" Loaded: %s%s%s\n",
3169 on, strna(i->load_state), off);
3171 if (!strv_isempty(i->dropin_paths)) {
3172 _cleanup_free_ char *dir = NULL;
3176 STRV_FOREACH(dropin, i->dropin_paths) {
3177 if (! dir || last) {
3178 printf(dir ? " " : " Drop-In: ");
3183 if (path_get_parent(*dropin, &dir) < 0) {
3188 printf("%s\n %s", dir,
3189 draw_special_char(DRAW_TREE_RIGHT));
3192 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3194 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3198 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3200 printf(" Active: %s%s (%s)%s",
3201 active_on, strna(i->active_state), ss, active_off);
3203 printf(" Active: %s%s%s",
3204 active_on, strna(i->active_state), active_off);
3206 if (!isempty(i->result) && !streq(i->result, "success"))
3207 printf(" (Result: %s)", i->result);
3209 timestamp = (streq_ptr(i->active_state, "active") ||
3210 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
3211 (streq_ptr(i->active_state, "inactive") ||
3212 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
3213 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
3214 i->active_exit_timestamp;
3216 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3217 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3220 printf(" since %s; %s\n", s2, s1);
3222 printf(" since %s\n", s2);
3226 if (!i->condition_result && i->condition_timestamp > 0) {
3227 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3228 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3230 printf(" start condition failed at %s%s%s\n",
3231 s2, s1 ? "; " : "", s1 ? s1 : "");
3232 if (i->failed_condition_trigger)
3233 printf(" none of the trigger conditions were met\n");
3234 else if (i->failed_condition)
3235 printf(" %s=%s%s was not met\n",
3236 i->failed_condition,
3237 i->failed_condition_negate ? "!" : "",
3238 i->failed_condition_param);
3242 printf(" Device: %s\n", i->sysfs_path);
3244 printf(" Where: %s\n", i->where);
3246 printf(" What: %s\n", i->what);
3248 STRV_FOREACH(t, i->documentation)
3249 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3251 STRV_FOREACH_PAIR(t, t2, i->listen)
3252 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3255 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3257 LIST_FOREACH(exec, p, i->exec) {
3258 _cleanup_free_ char *argv = NULL;
3261 /* Only show exited processes here */
3265 argv = strv_join(p->argv, " ");
3266 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
3268 good = is_clean_exit_lsb(p->code, p->status, NULL);
3270 on = ansi_highlight_red();
3271 off = ansi_highlight_off();
3275 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3277 if (p->code == CLD_EXITED) {
3280 printf("status=%i", p->status);
3282 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3287 printf("signal=%s", signal_to_string(p->status));
3289 printf(")%s\n", off);
3291 if (i->main_pid == p->pid &&
3292 i->start_timestamp == p->start_timestamp &&
3293 i->exit_timestamp == p->start_timestamp)
3294 /* Let's not show this twice */
3297 if (p->pid == i->control_pid)
3301 if (i->main_pid > 0 || i->control_pid > 0) {
3302 if (i->main_pid > 0) {
3303 printf(" Main PID: %u", (unsigned) i->main_pid);
3306 _cleanup_free_ char *comm = NULL;
3307 get_process_comm(i->main_pid, &comm);
3309 printf(" (%s)", comm);
3310 } else if (i->exit_code > 0) {
3311 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3313 if (i->exit_code == CLD_EXITED) {
3316 printf("status=%i", i->exit_status);
3318 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3323 printf("signal=%s", signal_to_string(i->exit_status));
3327 if (i->control_pid > 0)
3331 if (i->control_pid > 0) {
3332 _cleanup_free_ char *c = NULL;
3334 printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
3336 get_process_comm(i->control_pid, &c);
3345 printf(" Status: \"%s\"\n", i->status_text);
3347 if (i->control_group &&
3348 (i->main_pid > 0 || i->control_pid > 0 ||
3349 ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_CONTAINER) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3352 printf(" CGroup: %s\n", i->control_group);
3354 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
3357 static const char prefix[] = " ";
3360 if (c > sizeof(prefix) - 1)
3361 c -= sizeof(prefix) - 1;
3365 if (i->main_pid > 0)
3366 extra[k++] = i->main_pid;
3368 if (i->control_pid > 0)
3369 extra[k++] = i->control_pid;
3371 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, flags);
3375 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3376 show_journal_by_unit(stdout,
3380 i->inactive_exit_timestamp_monotonic,
3383 flags | OUTPUT_BEGIN_NEWLINE,
3384 arg_scope == UNIT_FILE_SYSTEM,
3388 if (i->need_daemon_reload)
3389 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
3390 ansi_highlight_red(),
3391 ansi_highlight_off(),
3392 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
3395 static void show_unit_help(UnitStatusInfo *i) {
3400 if (!i->documentation) {
3401 log_info("Documentation for %s not known.", i->id);
3405 STRV_FOREACH(p, i->documentation) {
3407 if (startswith(*p, "man:")) {
3408 const char *args[4] = { "man", NULL, NULL, NULL };
3409 _cleanup_free_ char *page = NULL, *section = NULL;
3416 if ((*p)[k-1] == ')')
3417 e = strrchr(*p, '(');
3420 page = strndup((*p) + 4, e - *p - 4);
3421 section = strndup(e + 1, *p + k - e - 2);
3422 if (!page || !section) {
3434 log_error("Failed to fork: %m");
3440 execvp(args[0], (char**) args);
3441 log_error("Failed to execute man: %m");
3442 _exit(EXIT_FAILURE);
3445 wait_for_terminate(pid, NULL);
3447 log_info("Can't show: %s", *p);
3451 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3458 switch (contents[0]) {
3460 case SD_BUS_TYPE_STRING: {
3463 r = sd_bus_message_read(m, "s", &s);
3465 return bus_log_parse_error(r);
3468 if (streq(name, "Id"))
3470 else if (streq(name, "LoadState"))
3472 else if (streq(name, "ActiveState"))
3473 i->active_state = s;
3474 else if (streq(name, "SubState"))
3476 else if (streq(name, "Description"))
3478 else if (streq(name, "FragmentPath"))
3479 i->fragment_path = s;
3480 else if (streq(name, "SourcePath"))
3483 else if (streq(name, "DefaultControlGroup")) {
3485 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3487 i->control_group = e;
3490 else if (streq(name, "ControlGroup"))
3491 i->control_group = s;
3492 else if (streq(name, "StatusText"))
3494 else if (streq(name, "PIDFile"))
3496 else if (streq(name, "SysFSPath"))
3498 else if (streq(name, "Where"))
3500 else if (streq(name, "What"))
3502 else if (streq(name, "Following"))
3504 else if (streq(name, "UnitFileState"))
3505 i->unit_file_state = s;
3506 else if (streq(name, "Result"))
3513 case SD_BUS_TYPE_BOOLEAN: {
3516 r = sd_bus_message_read(m, "b", &b);
3518 return bus_log_parse_error(r);
3520 if (streq(name, "Accept"))
3522 else if (streq(name, "NeedDaemonReload"))
3523 i->need_daemon_reload = b;
3524 else if (streq(name, "ConditionResult"))
3525 i->condition_result = b;
3530 case SD_BUS_TYPE_UINT32: {
3533 r = sd_bus_message_read(m, "u", &u);
3535 return bus_log_parse_error(r);
3537 if (streq(name, "MainPID")) {
3539 i->main_pid = (pid_t) u;
3542 } else if (streq(name, "ControlPID"))
3543 i->control_pid = (pid_t) u;
3544 else if (streq(name, "ExecMainPID")) {
3546 i->main_pid = (pid_t) u;
3547 } else if (streq(name, "NAccepted"))
3549 else if (streq(name, "NConnections"))
3550 i->n_connections = u;
3555 case SD_BUS_TYPE_INT32: {
3558 r = sd_bus_message_read(m, "i", &j);
3560 return bus_log_parse_error(r);
3562 if (streq(name, "ExecMainCode"))
3563 i->exit_code = (int) j;
3564 else if (streq(name, "ExecMainStatus"))
3565 i->exit_status = (int) j;
3570 case SD_BUS_TYPE_UINT64: {
3573 r = sd_bus_message_read(m, "t", &u);
3575 return bus_log_parse_error(r);
3577 if (streq(name, "ExecMainStartTimestamp"))
3578 i->start_timestamp = (usec_t) u;
3579 else if (streq(name, "ExecMainExitTimestamp"))
3580 i->exit_timestamp = (usec_t) u;
3581 else if (streq(name, "ActiveEnterTimestamp"))
3582 i->active_enter_timestamp = (usec_t) u;
3583 else if (streq(name, "InactiveEnterTimestamp"))
3584 i->inactive_enter_timestamp = (usec_t) u;
3585 else if (streq(name, "InactiveExitTimestamp"))
3586 i->inactive_exit_timestamp = (usec_t) u;
3587 else if (streq(name, "InactiveExitTimestampMonotonic"))
3588 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3589 else if (streq(name, "ActiveExitTimestamp"))
3590 i->active_exit_timestamp = (usec_t) u;
3591 else if (streq(name, "ConditionTimestamp"))
3592 i->condition_timestamp = (usec_t) u;
3597 case SD_BUS_TYPE_ARRAY:
3599 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3600 _cleanup_free_ ExecStatusInfo *info = NULL;
3602 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3604 return bus_log_parse_error(r);
3606 info = new0(ExecStatusInfo, 1);
3610 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3612 info->name = strdup(name);
3616 LIST_PREPEND(exec, i->exec, info);
3618 info = new0(ExecStatusInfo, 1);
3624 return bus_log_parse_error(r);
3626 r = sd_bus_message_exit_container(m);
3628 return bus_log_parse_error(r);
3632 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3633 const char *type, *path;
3635 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3637 return bus_log_parse_error(r);
3639 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3641 r = strv_extend(&i->listen, type);
3645 r = strv_extend(&i->listen, path);
3650 return bus_log_parse_error(r);
3652 r = sd_bus_message_exit_container(m);
3654 return bus_log_parse_error(r);
3658 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3660 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3662 return bus_log_parse_error(r);
3664 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3666 r = sd_bus_message_read_strv(m, &i->documentation);
3668 return bus_log_parse_error(r);
3670 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3671 const char *cond, *param;
3672 int trigger, negate;
3675 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3677 return bus_log_parse_error(r);
3679 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3680 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3681 if (state < 0 && (!trigger || !i->failed_condition)) {
3682 i->failed_condition = cond;
3683 i->failed_condition_trigger = trigger;
3684 i->failed_condition_negate = negate;
3685 i->failed_condition_param = param;
3689 return bus_log_parse_error(r);
3691 r = sd_bus_message_exit_container(m);
3693 return bus_log_parse_error(r);
3700 case SD_BUS_TYPE_STRUCT_BEGIN:
3702 if (streq(name, "LoadError")) {
3703 const char *n, *message;
3705 r = sd_bus_message_read(m, "(ss)", &n, &message);
3707 return bus_log_parse_error(r);
3709 if (!isempty(message))
3710 i->load_error = message;
3723 r = sd_bus_message_skip(m, contents);
3725 return bus_log_parse_error(r);
3730 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3736 /* This is a low-level property printer, see
3737 * print_status_info() for the nicer output */
3739 if (arg_properties && !strv_find(arg_properties, name)) {
3740 /* skip what we didn't read */
3741 r = sd_bus_message_skip(m, contents);
3745 switch (contents[0]) {
3747 case SD_BUS_TYPE_STRUCT_BEGIN:
3749 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3752 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3754 return bus_log_parse_error(r);
3757 printf("%s=%u\n", name, (unsigned) u);
3759 printf("%s=\n", name);
3763 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3766 r = sd_bus_message_read(m, "(so)", &s, NULL);
3768 return bus_log_parse_error(r);
3770 if (arg_all || !isempty(s))
3771 printf("%s=%s\n", name, s);
3775 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3776 const char *a = NULL, *b = NULL;
3778 r = sd_bus_message_read(m, "(ss)", &a, &b);
3780 return bus_log_parse_error(r);
3782 if (arg_all || !isempty(a) || !isempty(b))
3783 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3786 } else if (streq_ptr(name, "SystemCallFilter")) {
3787 _cleanup_strv_free_ char **l = NULL;
3790 r = sd_bus_message_enter_container(m, 'r', "bas");
3792 return bus_log_parse_error(r);
3794 r = sd_bus_message_read(m, "b", &whitelist);
3796 return bus_log_parse_error(r);
3798 r = sd_bus_message_read_strv(m, &l);
3800 return bus_log_parse_error(r);
3802 r = sd_bus_message_exit_container(m);
3804 return bus_log_parse_error(r);
3806 if (arg_all || whitelist || !strv_isempty(l)) {
3810 fputs(name, stdout);
3816 STRV_FOREACH(i, l) {
3824 fputc('\n', stdout);
3832 case SD_BUS_TYPE_ARRAY:
3834 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
3838 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
3840 return bus_log_parse_error(r);
3842 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
3843 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3846 return bus_log_parse_error(r);
3848 r = sd_bus_message_exit_container(m);
3850 return bus_log_parse_error(r);
3854 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
3855 const char *type, *path;
3857 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3859 return bus_log_parse_error(r);
3861 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3862 printf("%s=%s\n", type, path);
3864 return bus_log_parse_error(r);
3866 r = sd_bus_message_exit_container(m);
3868 return bus_log_parse_error(r);
3872 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3873 const char *type, *path;
3875 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3877 return bus_log_parse_error(r);
3879 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3880 printf("Listen%s=%s\n", type, path);
3882 return bus_log_parse_error(r);
3884 r = sd_bus_message_exit_container(m);
3886 return bus_log_parse_error(r);
3890 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
3892 uint64_t value, next_elapse;
3894 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
3896 return bus_log_parse_error(r);
3898 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
3899 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3901 printf("%s={ value=%s ; next_elapse=%s }\n",
3903 format_timespan(timespan1, sizeof(timespan1), value, 0),
3904 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3907 return bus_log_parse_error(r);
3909 r = sd_bus_message_exit_container(m);
3911 return bus_log_parse_error(r);
3915 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3916 ExecStatusInfo info = {};
3918 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3920 return bus_log_parse_error(r);
3922 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
3923 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3924 _cleanup_free_ char *tt;
3926 tt = strv_join(info.argv, " ");
3928 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3932 yes_no(info.ignore),
3933 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3934 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3935 (unsigned) info. pid,
3936 sigchld_code_to_string(info.code),
3938 info.code == CLD_EXITED ? "" : "/",
3939 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3942 strv_free(info.argv);
3946 r = sd_bus_message_exit_container(m);
3948 return bus_log_parse_error(r);
3952 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
3953 const char *path, *rwm;
3955 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3957 return bus_log_parse_error(r);
3959 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
3960 printf("%s=%s %s\n", name, strna(path), strna(rwm));
3962 return bus_log_parse_error(r);
3964 r = sd_bus_message_exit_container(m);
3966 return bus_log_parse_error(r);
3970 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
3974 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
3976 return bus_log_parse_error(r);
3978 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
3979 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
3981 return bus_log_parse_error(r);
3983 r = sd_bus_message_exit_container(m);
3985 return bus_log_parse_error(r);
3989 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
3993 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
3995 return bus_log_parse_error(r);
3997 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
3998 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
4000 return bus_log_parse_error(r);
4002 r = sd_bus_message_exit_container(m);
4004 return bus_log_parse_error(r);
4012 r = bus_print_property(name, m, arg_all);
4014 return bus_log_parse_error(r);
4017 r = sd_bus_message_skip(m, contents);
4019 return bus_log_parse_error(r);
4022 printf("%s=[unprintable]\n", name);
4028 static int show_one(
4032 bool show_properties,
4036 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4037 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4038 UnitStatusInfo info = {};
4045 log_debug("Showing one %s", path);
4047 r = sd_bus_call_method(
4049 "org.freedesktop.systemd1",
4051 "org.freedesktop.DBus.Properties",
4057 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4061 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4063 return bus_log_parse_error(r);
4070 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4071 const char *name, *contents;
4073 r = sd_bus_message_read(reply, "s", &name);
4075 return bus_log_parse_error(r);
4077 r = sd_bus_message_peek_type(reply, NULL, &contents);
4079 return bus_log_parse_error(r);
4081 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4083 return bus_log_parse_error(r);
4085 if (show_properties)
4086 r = print_property(name, reply, contents);
4088 r = status_property(name, reply, &info, contents);
4092 r = sd_bus_message_exit_container(reply);
4094 return bus_log_parse_error(r);
4096 r = sd_bus_message_exit_container(reply);
4098 return bus_log_parse_error(r);
4101 return bus_log_parse_error(r);
4103 r = sd_bus_message_exit_container(reply);
4105 return bus_log_parse_error(r);
4109 if (!show_properties) {
4110 if (streq(verb, "help"))
4111 show_unit_help(&info);
4113 print_status_info(&info, ellipsized);
4116 strv_free(info.documentation);
4117 strv_free(info.dropin_paths);
4118 strv_free(info.listen);
4120 if (!streq_ptr(info.active_state, "active") &&
4121 !streq_ptr(info.active_state, "reloading") &&
4122 streq(verb, "status")) {
4123 /* According to LSB: "program not running" */
4124 /* 0: program is running or service is OK
4125 * 1: program is dead and /run PID file exists
4126 * 2: program is dead and /run/lock lock file exists
4127 * 3: program is not running
4128 * 4: program or service status is unknown
4130 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4136 while ((p = info.exec)) {
4137 LIST_REMOVE(exec, info.exec, p);
4138 exec_status_info_free(p);
4144 static int get_unit_dbus_path_by_pid(
4149 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4150 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4154 r = sd_bus_call_method(
4156 "org.freedesktop.systemd1",
4157 "/org/freedesktop/systemd1",
4158 "org.freedesktop.systemd1.Manager",
4164 log_error("Failed to get unit for PID %lu: %s", (unsigned long) pid, bus_error_message(&error, r));
4168 r = sd_bus_message_read(reply, "o", &u);
4170 return bus_log_parse_error(r);
4180 static int show_all(
4183 bool show_properties,
4187 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4188 _cleanup_free_ UnitInfo *unit_infos = NULL;
4193 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4197 pager_open_if_enabled();
4201 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4203 for (u = unit_infos; u < unit_infos + c; u++) {
4204 _cleanup_free_ char *p = NULL;
4206 p = unit_dbus_path_from_name(u->id);
4210 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4218 static int show_system_status(sd_bus *bus) {
4219 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4220 _cleanup_free_ char *hn = NULL;
4221 struct machine_info mi = {};
4222 const char *on, *off;
4225 hn = gethostname_malloc();
4229 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4231 log_error("Failed to read server status: %s", strerror(-r));
4235 if (streq_ptr(mi.state, "degraded")) {
4236 on = ansi_highlight_red();
4237 off = ansi_highlight_off();
4238 } else if (!streq_ptr(mi.state, "running")) {
4239 on = ansi_highlight_yellow();
4240 off = ansi_highlight_off();
4244 printf("%s%s%s%s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4246 printf(" State: %s%s%s\n",
4247 on, strna(mi.state), off);
4249 printf(" Jobs: %u queued\n", mi.n_jobs);
4250 printf(" Failed: %u units\n", mi.n_failed_units);
4252 printf(" Since: %s; %s\n",
4253 format_timestamp(since2, sizeof(since2), mi.timestamp),
4254 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4256 printf(" CGroup: %s\n", mi.control_group ?: "/");
4257 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
4259 arg_all * OUTPUT_SHOW_ALL |
4260 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
4261 on_tty() * OUTPUT_COLOR |
4262 !arg_quiet * OUTPUT_WARN_CUTOFF |
4263 arg_full * OUTPUT_FULL_WIDTH;
4265 static const char prefix[] = " ";
4269 if (c > sizeof(prefix) - 1)
4270 c -= sizeof(prefix) - 1;
4274 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
4278 free(mi.control_group);
4283 static int show(sd_bus *bus, char **args) {
4284 bool show_properties, show_status, new_line = false;
4285 bool ellipsized = false;
4291 show_properties = streq(args[0], "show");
4292 show_status = streq(args[0], "status");
4294 if (show_properties)
4295 pager_open_if_enabled();
4297 /* If no argument is specified inspect the manager itself */
4299 if (show_properties && strv_length(args) <= 1)
4300 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4302 if (show_status && strv_length(args) <= 1) {
4304 pager_open_if_enabled();
4305 show_system_status(bus);
4309 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4311 _cleanup_free_ char **patterns = NULL;
4314 STRV_FOREACH(name, args + 1) {
4315 _cleanup_free_ char *unit = NULL;
4318 if (safe_atou32(*name, &id) < 0) {
4319 if (strv_push(&patterns, *name) < 0)
4323 } else if (show_properties) {
4324 /* Interpret as job id */
4325 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4329 /* Interpret as PID */
4330 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4337 show_one(args[0], bus, unit, show_properties, &new_line, &ellipsized);
4340 if (!strv_isempty(patterns)) {
4341 _cleanup_strv_free_ char **names = NULL;
4343 r = expand_names(bus, patterns, NULL, &names);
4345 log_error("Failed to expand names: %s", strerror(-r));
4347 STRV_FOREACH(name, names) {
4348 _cleanup_free_ char *unit;
4350 unit = unit_dbus_path_from_name(*name);
4354 show_one(args[0], bus, unit, show_properties, &new_line, &ellipsized);
4359 if (ellipsized && !arg_quiet)
4360 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4365 static int cat(sd_bus *bus, char **args) {
4366 _cleanup_free_ char *unit = NULL;
4367 _cleanup_strv_free_ char **names = NULL;
4375 r = expand_names(bus, args + 1, NULL, &names);
4377 log_error("Failed to expand names: %s", strerror(-r));
4379 pager_open_if_enabled();
4381 STRV_FOREACH(name, names) {
4382 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4383 _cleanup_strv_free_ char **dropin_paths = NULL;
4384 _cleanup_free_ char *fragment_path = NULL;
4387 unit = unit_dbus_path_from_name(*name);
4391 if (need_daemon_reload(bus, *name) > 0)
4392 log_warning("Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'.",
4393 *name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
4395 r = sd_bus_get_property_string(
4397 "org.freedesktop.systemd1",
4399 "org.freedesktop.systemd1.Unit",
4404 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
4408 r = sd_bus_get_property_strv(
4410 "org.freedesktop.systemd1",
4412 "org.freedesktop.systemd1.Unit",
4417 log_warning("Failed to get DropInPaths: %s", bus_error_message(&error, r));
4426 if (!isempty(fragment_path)) {
4427 printf("%s# %s%s\n",
4428 ansi_highlight_blue(),
4430 ansi_highlight_off());
4433 r = sendfile_full(STDOUT_FILENO, fragment_path);
4435 log_warning("Failed to cat %s: %s", fragment_path, strerror(-r));
4440 STRV_FOREACH(path, dropin_paths) {
4441 printf("%s%s# %s%s\n",
4442 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4443 ansi_highlight_blue(),
4445 ansi_highlight_off());
4448 r = sendfile_full(STDOUT_FILENO, *path);
4450 log_warning("Failed to cat %s: %s", *path, strerror(-r));
4456 return r < 0 ? r : 0;
4459 static int set_property(sd_bus *bus, char **args) {
4460 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4461 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4462 _cleanup_free_ char *n = NULL;
4466 r = sd_bus_message_new_method_call(
4469 "org.freedesktop.systemd1",
4470 "/org/freedesktop/systemd1",
4471 "org.freedesktop.systemd1.Manager",
4472 "SetUnitProperties");
4474 return bus_log_create_error(r);
4476 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4480 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4482 return bus_log_create_error(r);
4484 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4486 return bus_log_create_error(r);
4488 STRV_FOREACH(i, args + 2) {
4489 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4491 return bus_log_create_error(r);
4493 r = bus_append_unit_property_assignment(m, *i);
4497 r = sd_bus_message_close_container(m);
4499 return bus_log_create_error(r);
4502 r = sd_bus_message_close_container(m);
4504 return bus_log_create_error(r);
4506 r = sd_bus_call(bus, m, 0, &error, NULL);
4508 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4515 static int snapshot(sd_bus *bus, char **args) {
4516 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4517 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4518 _cleanup_free_ char *n = NULL, *id = NULL;
4522 if (strv_length(args) > 1)
4523 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4529 r = sd_bus_call_method(
4531 "org.freedesktop.systemd1",
4532 "/org/freedesktop/systemd1",
4533 "org.freedesktop.systemd1.Manager",
4539 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4543 r = sd_bus_message_read(reply, "o", &path);
4545 return bus_log_parse_error(r);
4547 r = sd_bus_get_property_string(
4549 "org.freedesktop.systemd1",
4551 "org.freedesktop.systemd1.Unit",
4556 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4566 static int delete_snapshot(sd_bus *bus, char **args) {
4567 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4568 _cleanup_strv_free_ char **names = NULL;
4574 r = expand_names(bus, args + 1, ".snapshot", &names);
4576 log_error("Failed to expand names: %s", strerror(-r));
4578 STRV_FOREACH(name, names) {
4579 q = sd_bus_call_method(
4581 "org.freedesktop.systemd1",
4582 "/org/freedesktop/systemd1",
4583 "org.freedesktop.systemd1.Manager",
4589 log_error("Failed to remove snapshot %s: %s",
4590 *name, bus_error_message(&error, r));
4599 static int daemon_reload(sd_bus *bus, char **args) {
4600 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4604 if (arg_action == ACTION_RELOAD)
4606 else if (arg_action == ACTION_REEXEC)
4607 method = "Reexecute";
4609 assert(arg_action == ACTION_SYSTEMCTL);
4612 streq(args[0], "clear-jobs") ||
4613 streq(args[0], "cancel") ? "ClearJobs" :
4614 streq(args[0], "daemon-reexec") ? "Reexecute" :
4615 streq(args[0], "reset-failed") ? "ResetFailed" :
4616 streq(args[0], "halt") ? "Halt" :
4617 streq(args[0], "poweroff") ? "PowerOff" :
4618 streq(args[0], "reboot") ? "Reboot" :
4619 streq(args[0], "kexec") ? "KExec" :
4620 streq(args[0], "exit") ? "Exit" :
4621 /* "daemon-reload" */ "Reload";
4624 r = sd_bus_call_method(
4626 "org.freedesktop.systemd1",
4627 "/org/freedesktop/systemd1",
4628 "org.freedesktop.systemd1.Manager",
4634 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4635 /* There's always a fallback possible for
4636 * legacy actions. */
4638 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4639 /* On reexecution, we expect a disconnect, not a
4643 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4645 return r < 0 ? r : 0;
4648 static int reset_failed(sd_bus *bus, char **args) {
4649 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4650 _cleanup_strv_free_ char **names = NULL;
4654 if (strv_length(args) <= 1)
4655 return daemon_reload(bus, args);
4657 r = expand_names(bus, args + 1, NULL, &names);
4659 log_error("Failed to expand names: %s", strerror(-r));
4661 STRV_FOREACH(name, names) {
4662 q = sd_bus_call_method(
4664 "org.freedesktop.systemd1",
4665 "/org/freedesktop/systemd1",
4666 "org.freedesktop.systemd1.Manager",
4672 log_error("Failed to reset failed state of unit %s: %s",
4673 *name, bus_error_message(&error, r));
4682 static int show_environment(sd_bus *bus, char **args) {
4683 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4684 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4688 pager_open_if_enabled();
4690 r = sd_bus_get_property(
4692 "org.freedesktop.systemd1",
4693 "/org/freedesktop/systemd1",
4694 "org.freedesktop.systemd1.Manager",
4700 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4704 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4706 return bus_log_parse_error(r);
4708 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4711 return bus_log_parse_error(r);
4713 r = sd_bus_message_exit_container(reply);
4715 return bus_log_parse_error(r);
4720 static int switch_root(sd_bus *bus, char **args) {
4721 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4722 _cleanup_free_ char *cmdline_init = NULL;
4723 const char *root, *init;
4727 l = strv_length(args);
4728 if (l < 2 || l > 3) {
4729 log_error("Wrong number of arguments.");
4738 r = parse_env_file("/proc/cmdline", WHITESPACE,
4739 "init", &cmdline_init,
4742 log_debug("Failed to parse /proc/cmdline: %s", strerror(-r));
4744 init = cmdline_init;
4751 const char *root_systemd_path = NULL, *root_init_path = NULL;
4753 root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
4754 root_init_path = strappenda3(root, "/", init);
4756 /* If the passed init is actually the same as the
4757 * systemd binary, then let's suppress it. */
4758 if (files_same(root_init_path, root_systemd_path) > 0)
4762 log_debug("Switching root - root: %s; init: %s", root, strna(init));
4764 r = sd_bus_call_method(
4766 "org.freedesktop.systemd1",
4767 "/org/freedesktop/systemd1",
4768 "org.freedesktop.systemd1.Manager",
4774 log_error("Failed to switch root: %s", bus_error_message(&error, r));
4781 static int set_environment(sd_bus *bus, char **args) {
4782 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4783 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4790 method = streq(args[0], "set-environment")
4792 : "UnsetEnvironment";
4794 r = sd_bus_message_new_method_call(
4797 "org.freedesktop.systemd1",
4798 "/org/freedesktop/systemd1",
4799 "org.freedesktop.systemd1.Manager",
4802 return bus_log_create_error(r);
4804 r = sd_bus_message_append_strv(m, args + 1);
4806 return bus_log_create_error(r);
4808 r = sd_bus_call(bus, m, 0, &error, NULL);
4810 log_error("Failed to set environment: %s", bus_error_message(&error, r));
4817 static int import_environment(sd_bus *bus, char **args) {
4818 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4819 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4825 r = sd_bus_message_new_method_call(
4828 "org.freedesktop.systemd1",
4829 "/org/freedesktop/systemd1",
4830 "org.freedesktop.systemd1.Manager",
4833 return bus_log_create_error(r);
4835 if (strv_isempty(args + 1))
4836 r = sd_bus_message_append_strv(m, environ);
4840 r = sd_bus_message_open_container(m, 'a', "s");
4842 return bus_log_create_error(r);
4844 STRV_FOREACH(a, args + 1) {
4846 if (!env_name_is_valid(*a)) {
4847 log_error("Not a valid environment variable name: %s", *a);
4851 STRV_FOREACH(b, environ) {
4854 eq = startswith(*b, *a);
4855 if (eq && *eq == '=') {
4857 r = sd_bus_message_append(m, "s", *b);
4859 return bus_log_create_error(r);
4866 r = sd_bus_message_close_container(m);
4869 return bus_log_create_error(r);
4871 r = sd_bus_call(bus, m, 0, &error, NULL);
4873 log_error("Failed to import environment: %s", bus_error_message(&error, r));
4880 static int enable_sysv_units(const char *verb, char **args) {
4883 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4884 unsigned f = 1, t = 1;
4885 _cleanup_lookup_paths_free_ LookupPaths paths = {};
4887 if (arg_scope != UNIT_FILE_SYSTEM)
4890 if (!streq(verb, "enable") &&
4891 !streq(verb, "disable") &&
4892 !streq(verb, "is-enabled"))
4895 /* Processes all SysV units, and reshuffles the array so that
4896 * afterwards only the native units remain */
4898 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4903 for (f = 0; args[f]; f++) {
4905 _cleanup_free_ char *p = NULL, *q = NULL;
4906 bool found_native = false, found_sysv;
4908 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4916 if (!endswith(name, ".service"))
4919 if (path_is_absolute(name))
4922 STRV_FOREACH(k, paths.unit_path) {
4923 if (!isempty(arg_root))
4924 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4926 asprintf(&p, "%s/%s", *k, name);
4933 found_native = access(p, F_OK) >= 0;
4944 if (!isempty(arg_root))
4945 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4947 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4953 p[strlen(p) - sizeof(".service") + 1] = 0;
4954 found_sysv = access(p, F_OK) >= 0;
4959 /* Mark this entry, so that we don't try enabling it as native unit */
4960 args[f] = (char*) "";
4962 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4964 if (!isempty(arg_root))
4965 argv[c++] = q = strappend("--root=", arg_root);
4967 argv[c++] = basename(p);
4969 streq(verb, "enable") ? "on" :
4970 streq(verb, "disable") ? "off" : "--level=5";
4973 l = strv_join((char**)argv, " ");
4979 log_info("Executing %s", l);
4984 log_error("Failed to fork: %m");
4987 } else if (pid == 0) {
4990 execv(argv[0], (char**) argv);
4991 _exit(EXIT_FAILURE);
4994 j = wait_for_terminate(pid, &status);
4996 log_error("Failed to wait for child: %s", strerror(-r));
5001 if (status.si_code == CLD_EXITED) {
5002 if (streq(verb, "is-enabled")) {
5003 if (status.si_status == 0) {
5012 } else if (status.si_status != 0) {
5023 /* Drop all SysV units */
5024 for (f = 0, t = 0; args[f]; f++) {
5026 if (isempty(args[f]))
5029 args[t++] = args[f];
5038 static int mangle_names(char **original_names, char ***mangled_names) {
5039 char **i, **l, **name;
5041 l = new(char*, strv_length(original_names) + 1);
5046 STRV_FOREACH(name, original_names) {
5048 /* When enabling units qualified path names are OK,
5049 * too, hence allow them explicitly. */
5054 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5070 static int enable_unit(sd_bus *bus, char **args) {
5071 _cleanup_strv_free_ char **names = NULL;
5072 const char *verb = args[0];
5073 UnitFileChange *changes = NULL;
5074 unsigned n_changes = 0;
5075 int carries_install_info = -1;
5081 r = mangle_names(args+1, &names);
5085 r = enable_sysv_units(verb, names);
5089 /* If the operation was fully executed by the SysV compat,
5090 * let's finish early */
5091 if (strv_isempty(names))
5094 if (!bus || avoid_bus()) {
5095 if (streq(verb, "enable")) {
5096 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5097 carries_install_info = r;
5098 } else if (streq(verb, "disable"))
5099 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5100 else if (streq(verb, "reenable")) {
5101 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5102 carries_install_info = r;
5103 } else if (streq(verb, "link"))
5104 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5105 else if (streq(verb, "preset")) {
5106 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5107 carries_install_info = r;
5108 } else if (streq(verb, "mask"))
5109 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5110 else if (streq(verb, "unmask"))
5111 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5113 assert_not_reached("Unknown verb");
5116 log_error("Operation failed: %s", strerror(-r));
5121 dump_unit_file_changes(changes, n_changes);
5125 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5126 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5127 int expect_carries_install_info = false;
5128 bool send_force = true;
5131 if (streq(verb, "enable")) {
5132 method = "EnableUnitFiles";
5133 expect_carries_install_info = true;
5134 } else if (streq(verb, "disable")) {
5135 method = "DisableUnitFiles";
5137 } else if (streq(verb, "reenable")) {
5138 method = "ReenableUnitFiles";
5139 expect_carries_install_info = true;
5140 } else if (streq(verb, "link"))
5141 method = "LinkUnitFiles";
5142 else if (streq(verb, "preset")) {
5143 method = "PresetUnitFiles";
5144 expect_carries_install_info = true;
5145 } else if (streq(verb, "mask"))
5146 method = "MaskUnitFiles";
5147 else if (streq(verb, "unmask")) {
5148 method = "UnmaskUnitFiles";
5151 assert_not_reached("Unknown verb");
5153 r = sd_bus_message_new_method_call(
5156 "org.freedesktop.systemd1",
5157 "/org/freedesktop/systemd1",
5158 "org.freedesktop.systemd1.Manager",
5161 return bus_log_create_error(r);
5163 r = sd_bus_message_append_strv(m, names);
5165 return bus_log_create_error(r);
5167 r = sd_bus_message_append(m, "b", arg_runtime);
5169 return bus_log_create_error(r);
5172 r = sd_bus_message_append(m, "b", arg_force);
5174 return bus_log_create_error(r);
5177 r = sd_bus_call(bus, m, 0, &error, &reply);
5179 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5183 if (expect_carries_install_info) {
5184 r = sd_bus_message_read(reply, "b", &carries_install_info);
5186 return bus_log_parse_error(r);
5189 r = deserialize_and_dump_unit_file_changes(reply);
5193 /* Try to reload if enabeld */
5195 r = daemon_reload(bus, args);
5200 if (carries_install_info == 0)
5201 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5202 "using systemctl.\n"
5203 "Possible reasons for having this kind of units are:\n"
5204 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5205 " .wants/ or .requires/ directory.\n"
5206 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5207 " a requirement dependency on it.\n"
5208 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5209 " D-Bus, udev, scripted systemctl call, ...).\n");
5212 unit_file_changes_free(changes, n_changes);
5217 static int unit_is_enabled(sd_bus *bus, char **args) {
5219 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5220 _cleanup_strv_free_ char **names = NULL;
5225 r = mangle_names(args+1, &names);
5229 r = enable_sysv_units(args[0], names);
5235 if (!bus || avoid_bus()) {
5237 STRV_FOREACH(name, names) {
5238 UnitFileState state;
5240 state = unit_file_get_state(arg_scope, arg_root, *name);
5242 log_error("Failed to get unit file state for %s: %s", *name, strerror(-state));
5246 if (state == UNIT_FILE_ENABLED ||
5247 state == UNIT_FILE_ENABLED_RUNTIME ||
5248 state == UNIT_FILE_STATIC)
5252 puts(unit_file_state_to_string(state));
5256 STRV_FOREACH(name, names) {
5257 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5260 r = sd_bus_call_method(
5262 "org.freedesktop.systemd1",
5263 "/org/freedesktop/systemd1",
5264 "org.freedesktop.systemd1.Manager",
5270 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5274 r = sd_bus_message_read(reply, "s", &s);
5276 return bus_log_parse_error(r);
5278 if (streq(s, "enabled") ||
5279 streq(s, "enabled-runtime") ||
5291 static int systemctl_help(void) {
5293 pager_open_if_enabled();
5295 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
5296 "Query or send control commands to the systemd manager.\n\n"
5297 " -h --help Show this help\n"
5298 " --version Show package version\n"
5299 " --system Connect to system manager\n"
5300 " --user Connect to user service manager\n"
5301 " -H --host=[USER@]HOST\n"
5302 " Operate on remote host\n"
5303 " -M --machine=CONTAINER\n"
5304 " Operate on local container\n"
5305 " -t --type=TYPE List only units of a particular type\n"
5306 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
5307 " -p --property=NAME Show only properties by this name\n"
5308 " -a --all Show all loaded units/properties, including dead/empty\n"
5309 " ones. To list all units installed on the system, use\n"
5310 " the 'list-unit-files' command instead.\n"
5311 " -l --full Don't ellipsize unit names on output\n"
5312 " -r --recursive Show unit list of host and local containers\n"
5313 " --reverse Show reverse dependencies with 'list-dependencies'\n"
5314 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
5315 " queueing a new job\n"
5316 " --show-types When showing sockets, explicitly show their type\n"
5317 " -i --ignore-inhibitors\n"
5318 " When shutting down or sleeping, ignore inhibitors\n"
5319 " --kill-who=WHO Who to send signal to\n"
5320 " -s --signal=SIGNAL Which signal to send\n"
5321 " -q --quiet Suppress output\n"
5322 " --no-block Do not wait until operation finished\n"
5323 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5324 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
5326 " --no-legend Do not print a legend (column headers and hints)\n"
5327 " --no-pager Do not pipe output into a pager\n"
5328 " --no-ask-password\n"
5329 " Do not ask for system passwords\n"
5330 " --global Enable/disable unit files globally\n"
5331 " --runtime Enable unit files only temporarily until next reboot\n"
5332 " -f --force When enabling unit files, override existing symlinks\n"
5333 " When shutting down, execute action immediately\n"
5334 " --root=PATH Enable unit files in the specified root directory\n"
5335 " -n --lines=INTEGER Number of journal entries to show\n"
5336 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
5337 " verbose, export, json, json-pretty, json-sse, cat)\n"
5338 " --plain Print unit dependencies as a list instead of a tree\n\n"
5340 " list-units [PATTERN...] List loaded units\n"
5341 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
5342 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
5343 " start NAME... Start (activate) one or more units\n"
5344 " stop NAME... Stop (deactivate) one or more units\n"
5345 " reload NAME... Reload one or more units\n"
5346 " restart NAME... Start or restart one or more units\n"
5347 " try-restart NAME... Restart one or more units if active\n"
5348 " reload-or-restart NAME... Reload one or more units if possible,\n"
5349 " otherwise start or restart\n"
5350 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
5351 " otherwise restart if active\n"
5352 " isolate NAME Start one unit and stop all others\n"
5353 " kill NAME... Send signal to processes of a unit\n"
5354 " is-active NAME... Check whether units are active\n"
5355 " is-failed NAME... Check whether units are failed\n"
5356 " status [NAME...|PID...] Show runtime status of one or more units\n"
5357 " show [NAME...|JOB...] Show properties of one or more\n"
5358 " units/jobs or the manager\n"
5359 " cat NAME... Show files and drop-ins of one or more units\n"
5360 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
5361 " help NAME...|PID... Show manual for one or more units\n"
5362 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
5364 " list-dependencies [NAME] Recursively show units which are required\n"
5365 " or wanted by this unit or by which this\n"
5366 " unit is required or wanted\n\n"
5367 "Unit File Commands:\n"
5368 " list-unit-files [PATTERN...] List installed unit files\n"
5369 " enable NAME... Enable one or more unit files\n"
5370 " disable NAME... Disable one or more unit files\n"
5371 " reenable NAME... Reenable one or more unit files\n"
5372 " preset NAME... Enable/disable one or more unit files\n"
5373 " based on preset configuration\n"
5374 " is-enabled NAME... Check whether unit files are enabled\n\n"
5375 " mask NAME... Mask one or more units\n"
5376 " unmask NAME... Unmask one or more units\n"
5377 " link PATH... Link one or more units files into\n"
5378 " the search path\n"
5379 " get-default Get the name of the default target\n"
5380 " set-default NAME Set the default target\n\n"
5381 "Machine Commands:\n"
5382 " list-machines [PATTERN...] List local containers and host\n\n"
5384 " list-jobs [PATTERN...] List jobs\n"
5385 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
5386 "Snapshot Commands:\n"
5387 " snapshot [NAME] Create a snapshot\n"
5388 " delete NAME... Remove one or more snapshots\n\n"
5389 "Environment Commands:\n"
5390 " show-environment Dump environment\n"
5391 " set-environment NAME=VALUE... Set one or more environment variables\n"
5392 " unset-environment NAME... Unset one or more environment variables\n"
5393 " import-environment NAME... Import all, one or more environment variables\n\n"
5394 "Manager Lifecycle Commands:\n"
5395 " daemon-reload Reload systemd manager configuration\n"
5396 " daemon-reexec Reexecute systemd manager\n\n"
5397 "System Commands:\n"
5398 " default Enter system default mode\n"
5399 " rescue Enter system rescue mode\n"
5400 " emergency Enter system emergency mode\n"
5401 " halt Shut down and halt the system\n"
5402 " poweroff Shut down and power-off the system\n"
5403 " reboot [ARG] Shut down and reboot the system\n"
5404 " kexec Shut down and reboot the system with kexec\n"
5405 " exit Request user instance exit\n"
5406 " switch-root ROOT [INIT] Change to a different root file system\n"
5407 " suspend Suspend the system\n"
5408 " hibernate Hibernate the system\n"
5409 " hybrid-sleep Hibernate and suspend the system\n",
5410 program_invocation_short_name);
5415 static int halt_help(void) {
5417 printf("%s [OPTIONS...]%s\n\n"
5418 "%s the system.\n\n"
5419 " --help Show this help\n"
5420 " --halt Halt the machine\n"
5421 " -p --poweroff Switch off the machine\n"
5422 " --reboot Reboot the machine\n"
5423 " -f --force Force immediate halt/power-off/reboot\n"
5424 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
5425 " -d --no-wtmp Don't write wtmp record\n"
5426 " --no-wall Don't send wall message before halt/power-off/reboot\n",
5427 program_invocation_short_name,
5428 arg_action == ACTION_REBOOT ? " [ARG]" : "",
5429 arg_action == ACTION_REBOOT ? "Reboot" :
5430 arg_action == ACTION_POWEROFF ? "Power off" :
5436 static int shutdown_help(void) {
5438 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
5439 "Shut down the system.\n\n"
5440 " --help Show this help\n"
5441 " -H --halt Halt the machine\n"
5442 " -P --poweroff Power-off the machine\n"
5443 " -r --reboot Reboot the machine\n"
5444 " -h Equivalent to --poweroff, overridden by --halt\n"
5445 " -k Don't halt/power-off/reboot, just send warnings\n"
5446 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5447 " -c Cancel a pending shutdown\n",
5448 program_invocation_short_name);
5453 static int telinit_help(void) {
5455 printf("%s [OPTIONS...] {COMMAND}\n\n"
5456 "Send control commands to the init daemon.\n\n"
5457 " --help Show this help\n"
5458 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
5460 " 0 Power-off the machine\n"
5461 " 6 Reboot the machine\n"
5462 " 2, 3, 4, 5 Start runlevelX.target unit\n"
5463 " 1, s, S Enter rescue mode\n"
5464 " q, Q Reload init daemon configuration\n"
5465 " u, U Reexecute init daemon\n",
5466 program_invocation_short_name);
5471 static int runlevel_help(void) {
5473 printf("%s [OPTIONS...]\n\n"
5474 "Prints the previous and current runlevel of the init system.\n\n"
5475 " --help Show this help\n",
5476 program_invocation_short_name);
5481 static int help_types(void) {
5485 puts("Available unit types:");
5486 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
5487 t = unit_type_to_string(i);
5495 static int systemctl_parse_argv(int argc, char *argv[]) {
5504 ARG_IGNORE_DEPENDENCIES,
5516 ARG_NO_ASK_PASSWORD,
5525 static const struct option options[] = {
5526 { "help", no_argument, NULL, 'h' },
5527 { "version", no_argument, NULL, ARG_VERSION },
5528 { "type", required_argument, NULL, 't' },
5529 { "property", required_argument, NULL, 'p' },
5530 { "all", no_argument, NULL, 'a' },
5531 { "reverse", no_argument, NULL, ARG_REVERSE },
5532 { "after", no_argument, NULL, ARG_AFTER },
5533 { "before", no_argument, NULL, ARG_BEFORE },
5534 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
5535 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
5536 { "full", no_argument, NULL, 'l' },
5537 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
5538 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
5539 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
5540 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
5541 { "ignore-inhibitors", no_argument, NULL, 'i' },
5542 { "user", no_argument, NULL, ARG_USER },
5543 { "system", no_argument, NULL, ARG_SYSTEM },
5544 { "global", no_argument, NULL, ARG_GLOBAL },
5545 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
5546 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
5547 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
5548 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5549 { "quiet", no_argument, NULL, 'q' },
5550 { "root", required_argument, NULL, ARG_ROOT },
5551 { "force", no_argument, NULL, ARG_FORCE },
5552 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
5553 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
5554 { "signal", required_argument, NULL, 's' },
5555 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
5556 { "host", required_argument, NULL, 'H' },
5557 { "machine", required_argument, NULL, 'M' },
5558 { "runtime", no_argument, NULL, ARG_RUNTIME },
5559 { "lines", required_argument, NULL, 'n' },
5560 { "output", required_argument, NULL, 'o' },
5561 { "plain", no_argument, NULL, ARG_PLAIN },
5562 { "state", required_argument, NULL, ARG_STATE },
5563 { "recursive", no_argument, NULL, 'r' },
5572 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0) {
5577 return systemctl_help();
5580 puts(PACKAGE_STRING);
5581 puts(SYSTEMD_FEATURES);
5588 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5589 _cleanup_free_ char *type;
5591 type = strndup(word, size);
5595 if (streq(type, "help")) {
5600 if (unit_type_from_string(type) >= 0) {
5601 if (strv_push(&arg_types, type))
5607 /* It's much nicer to use --state= for
5608 * load states, but let's support this
5609 * in --types= too for compatibility
5610 * with old versions */
5611 if (unit_load_state_from_string(optarg) >= 0) {
5612 if (strv_push(&arg_states, type) < 0)
5618 log_error("Unknown unit type or load state '%s'.", type);
5619 log_info("Use -t help to see a list of allowed values.");
5627 /* Make sure that if the empty property list
5628 was specified, we won't show any properties. */
5629 if (isempty(optarg) && !arg_properties) {
5630 arg_properties = new0(char*, 1);
5631 if (!arg_properties)
5637 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5640 prop = strndup(word, size);
5644 if (strv_consume(&arg_properties, prop) < 0)
5649 /* If the user asked for a particular
5650 * property, show it to him, even if it is
5662 arg_dependency = DEPENDENCY_REVERSE;
5666 arg_dependency = DEPENDENCY_AFTER;
5670 arg_dependency = DEPENDENCY_BEFORE;
5673 case ARG_SHOW_TYPES:
5674 arg_show_types = true;
5678 arg_job_mode = optarg;
5682 arg_job_mode = "fail";
5685 case ARG_IRREVERSIBLE:
5686 arg_job_mode = "replace-irreversibly";
5689 case ARG_IGNORE_DEPENDENCIES:
5690 arg_job_mode = "ignore-dependencies";
5694 arg_scope = UNIT_FILE_USER;
5698 arg_scope = UNIT_FILE_SYSTEM;
5702 arg_scope = UNIT_FILE_GLOBAL;
5706 arg_no_block = true;
5710 arg_no_legend = true;
5714 arg_no_pager = true;
5730 if (strv_extend(&arg_states, "failed") < 0)
5748 arg_no_reload = true;
5752 arg_kill_who = optarg;
5756 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5757 log_error("Failed to parse signal string %s.", optarg);
5762 case ARG_NO_ASK_PASSWORD:
5763 arg_ask_password = false;
5767 arg_transport = BUS_TRANSPORT_REMOTE;
5772 arg_transport = BUS_TRANSPORT_CONTAINER;
5781 if (safe_atou(optarg, &arg_lines) < 0) {
5782 log_error("Failed to parse lines '%s'", optarg);
5788 arg_output = output_mode_from_string(optarg);
5789 if (arg_output < 0) {
5790 log_error("Unknown output '%s'.", optarg);
5796 arg_ignore_inhibitors = true;
5807 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5810 s = strndup(word, size);
5814 if (strv_consume(&arg_states, s) < 0)
5821 if (geteuid() != 0) {
5822 log_error("--recursive requires root priviliges.");
5826 arg_recursive = true;
5833 assert_not_reached("Unhandled option");
5837 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
5838 log_error("Cannot access user instance remotely.");
5845 static int halt_parse_argv(int argc, char *argv[]) {
5854 static const struct option options[] = {
5855 { "help", no_argument, NULL, ARG_HELP },
5856 { "halt", no_argument, NULL, ARG_HALT },
5857 { "poweroff", no_argument, NULL, 'p' },
5858 { "reboot", no_argument, NULL, ARG_REBOOT },
5859 { "force", no_argument, NULL, 'f' },
5860 { "wtmp-only", no_argument, NULL, 'w' },
5861 { "no-wtmp", no_argument, NULL, 'd' },
5862 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5871 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5872 if (runlevel == '0' || runlevel == '6')
5875 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5882 arg_action = ACTION_HALT;
5886 if (arg_action != ACTION_REBOOT)
5887 arg_action = ACTION_POWEROFF;
5891 arg_action = ACTION_REBOOT;
5913 /* Compatibility nops */
5920 assert_not_reached("Unhandled option");
5924 if (arg_action == ACTION_REBOOT && argc == optind + 1) {
5925 r = write_string_file(REBOOT_PARAM_FILE, argv[optind]);
5927 log_error("Failed to write reboot param to "
5928 REBOOT_PARAM_FILE": %s", strerror(-r));
5931 } else if (optind < argc) {
5932 log_error("Too many arguments.");
5939 static int parse_time_spec(const char *t, usec_t *_u) {
5943 if (streq(t, "now"))
5945 else if (!strchr(t, ':')) {
5948 if (safe_atou64(t, &u) < 0)
5951 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5960 hour = strtol(t, &e, 10);
5961 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5964 minute = strtol(e+1, &e, 10);
5965 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5968 n = now(CLOCK_REALTIME);
5969 s = (time_t) (n / USEC_PER_SEC);
5971 assert_se(localtime_r(&s, &tm));
5973 tm.tm_hour = (int) hour;
5974 tm.tm_min = (int) minute;
5977 assert_se(s = mktime(&tm));
5979 *_u = (usec_t) s * USEC_PER_SEC;
5982 *_u += USEC_PER_DAY;
5988 static int shutdown_parse_argv(int argc, char *argv[]) {
5995 static const struct option options[] = {
5996 { "help", no_argument, NULL, ARG_HELP },
5997 { "halt", no_argument, NULL, 'H' },
5998 { "poweroff", no_argument, NULL, 'P' },
5999 { "reboot", no_argument, NULL, 'r' },
6000 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
6001 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6010 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
6014 return shutdown_help();
6017 arg_action = ACTION_HALT;
6021 arg_action = ACTION_POWEROFF;
6026 arg_action = ACTION_KEXEC;
6028 arg_action = ACTION_REBOOT;
6032 arg_action = ACTION_KEXEC;
6036 if (arg_action != ACTION_HALT)
6037 arg_action = ACTION_POWEROFF;
6050 /* Compatibility nops */
6054 arg_action = ACTION_CANCEL_SHUTDOWN;
6061 assert_not_reached("Unhandled option");
6065 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
6066 r = parse_time_spec(argv[optind], &arg_when);
6068 log_error("Failed to parse time specification: %s", argv[optind]);
6072 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
6074 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
6075 /* No time argument for shutdown cancel */
6076 arg_wall = argv + optind;
6077 else if (argc > optind + 1)
6078 /* We skip the time argument */
6079 arg_wall = argv + optind + 1;
6086 static int telinit_parse_argv(int argc, char *argv[]) {
6093 static const struct option options[] = {
6094 { "help", no_argument, NULL, ARG_HELP },
6095 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6099 static const struct {
6103 { '0', ACTION_POWEROFF },
6104 { '6', ACTION_REBOOT },
6105 { '1', ACTION_RESCUE },
6106 { '2', ACTION_RUNLEVEL2 },
6107 { '3', ACTION_RUNLEVEL3 },
6108 { '4', ACTION_RUNLEVEL4 },
6109 { '5', ACTION_RUNLEVEL5 },
6110 { 's', ACTION_RESCUE },
6111 { 'S', ACTION_RESCUE },
6112 { 'q', ACTION_RELOAD },
6113 { 'Q', ACTION_RELOAD },
6114 { 'u', ACTION_REEXEC },
6115 { 'U', ACTION_REEXEC }
6124 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
6128 return telinit_help();
6138 assert_not_reached("Unhandled option");
6142 if (optind >= argc) {
6147 if (optind + 1 < argc) {
6148 log_error("Too many arguments.");
6152 if (strlen(argv[optind]) != 1) {
6153 log_error("Expected single character argument.");
6157 for (i = 0; i < ELEMENTSOF(table); i++)
6158 if (table[i].from == argv[optind][0])
6161 if (i >= ELEMENTSOF(table)) {
6162 log_error("Unknown command '%s'.", argv[optind]);
6166 arg_action = table[i].to;
6173 static int runlevel_parse_argv(int argc, char *argv[]) {
6179 static const struct option options[] = {
6180 { "help", no_argument, NULL, ARG_HELP },
6189 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
6193 return runlevel_help();
6199 assert_not_reached("Unhandled option");
6203 if (optind < argc) {
6204 log_error("Too many arguments.");
6211 static int parse_argv(int argc, char *argv[]) {
6215 if (program_invocation_short_name) {
6217 if (strstr(program_invocation_short_name, "halt")) {
6218 arg_action = ACTION_HALT;
6219 return halt_parse_argv(argc, argv);
6220 } else if (strstr(program_invocation_short_name, "poweroff")) {
6221 arg_action = ACTION_POWEROFF;
6222 return halt_parse_argv(argc, argv);
6223 } else if (strstr(program_invocation_short_name, "reboot")) {
6225 arg_action = ACTION_KEXEC;
6227 arg_action = ACTION_REBOOT;
6228 return halt_parse_argv(argc, argv);
6229 } else if (strstr(program_invocation_short_name, "shutdown")) {
6230 arg_action = ACTION_POWEROFF;
6231 return shutdown_parse_argv(argc, argv);
6232 } else if (strstr(program_invocation_short_name, "init")) {
6234 if (sd_booted() > 0) {
6235 arg_action = _ACTION_INVALID;
6236 return telinit_parse_argv(argc, argv);
6238 /* Hmm, so some other init system is
6239 * running, we need to forward this
6240 * request to it. For now we simply
6241 * guess that it is Upstart. */
6243 execv(TELINIT, argv);
6245 log_error("Couldn't find an alternative telinit implementation to spawn.");
6249 } else if (strstr(program_invocation_short_name, "runlevel")) {
6250 arg_action = ACTION_RUNLEVEL;
6251 return runlevel_parse_argv(argc, argv);
6255 arg_action = ACTION_SYSTEMCTL;
6256 return systemctl_parse_argv(argc, argv);
6259 _pure_ static int action_to_runlevel(void) {
6261 static const char table[_ACTION_MAX] = {
6262 [ACTION_HALT] = '0',
6263 [ACTION_POWEROFF] = '0',
6264 [ACTION_REBOOT] = '6',
6265 [ACTION_RUNLEVEL2] = '2',
6266 [ACTION_RUNLEVEL3] = '3',
6267 [ACTION_RUNLEVEL4] = '4',
6268 [ACTION_RUNLEVEL5] = '5',
6269 [ACTION_RESCUE] = '1'
6272 assert(arg_action < _ACTION_MAX);
6274 return table[arg_action];
6277 static int talk_initctl(void) {
6279 struct init_request request = {
6280 .magic = INIT_MAGIC,
6282 .cmd = INIT_CMD_RUNLVL
6285 _cleanup_close_ int fd = -1;
6289 rl = action_to_runlevel();
6293 request.runlevel = rl;
6295 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
6297 if (errno == ENOENT)
6300 log_error("Failed to open "INIT_FIFO": %m");
6305 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
6307 log_error("Failed to write to "INIT_FIFO": %m");
6308 return errno > 0 ? -errno : -EIO;
6314 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
6316 static const struct {
6324 int (* const dispatch)(sd_bus *bus, char **args);
6330 { "list-units", MORE, 0, list_units },
6331 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
6332 { "list-sockets", MORE, 1, list_sockets },
6333 { "list-timers", MORE, 1, list_timers },
6334 { "list-jobs", MORE, 1, list_jobs },
6335 { "list-machines", MORE, 1, list_machines },
6336 { "clear-jobs", EQUAL, 1, daemon_reload },
6337 { "cancel", MORE, 2, cancel_job },
6338 { "start", MORE, 2, start_unit },
6339 { "stop", MORE, 2, start_unit },
6340 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6341 { "reload", MORE, 2, start_unit },
6342 { "restart", MORE, 2, start_unit },
6343 { "try-restart", MORE, 2, start_unit },
6344 { "reload-or-restart", MORE, 2, start_unit },
6345 { "reload-or-try-restart", MORE, 2, start_unit },
6346 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
6347 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6348 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
6349 { "isolate", EQUAL, 2, start_unit },
6350 { "kill", MORE, 2, kill_unit },
6351 { "is-active", MORE, 2, check_unit_active },
6352 { "check", MORE, 2, check_unit_active },
6353 { "is-failed", MORE, 2, check_unit_failed },
6354 { "show", MORE, 1, show },
6355 { "cat", MORE, 2, cat },
6356 { "status", MORE, 1, show },
6357 { "help", MORE, 2, show },
6358 { "snapshot", LESS, 2, snapshot },
6359 { "delete", MORE, 2, delete_snapshot },
6360 { "daemon-reload", EQUAL, 1, daemon_reload },
6361 { "daemon-reexec", EQUAL, 1, daemon_reload },
6362 { "show-environment", EQUAL, 1, show_environment },
6363 { "set-environment", MORE, 2, set_environment },
6364 { "unset-environment", MORE, 2, set_environment },
6365 { "import-environment", MORE, 1, import_environment},
6366 { "halt", EQUAL, 1, start_special, FORCE },
6367 { "poweroff", EQUAL, 1, start_special, FORCE },
6368 { "reboot", EQUAL, 1, start_special, FORCE },
6369 { "kexec", EQUAL, 1, start_special },
6370 { "suspend", EQUAL, 1, start_special },
6371 { "hibernate", EQUAL, 1, start_special },
6372 { "hybrid-sleep", EQUAL, 1, start_special },
6373 { "default", EQUAL, 1, start_special },
6374 { "rescue", EQUAL, 1, start_special },
6375 { "emergency", EQUAL, 1, start_special },
6376 { "exit", EQUAL, 1, start_special },
6377 { "reset-failed", MORE, 1, reset_failed },
6378 { "enable", MORE, 2, enable_unit, NOBUS },
6379 { "disable", MORE, 2, enable_unit, NOBUS },
6380 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
6381 { "reenable", MORE, 2, enable_unit, NOBUS },
6382 { "preset", MORE, 2, enable_unit, NOBUS },
6383 { "mask", MORE, 2, enable_unit, NOBUS },
6384 { "unmask", MORE, 2, enable_unit, NOBUS },
6385 { "link", MORE, 2, enable_unit, NOBUS },
6386 { "switch-root", MORE, 2, switch_root },
6387 { "list-dependencies", LESS, 2, list_dependencies },
6388 { "set-default", EQUAL, 2, set_default, NOBUS },
6389 { "get-default", EQUAL, 1, get_default, NOBUS },
6390 { "set-property", MORE, 3, set_property },
6399 left = argc - optind;
6401 /* Special rule: no arguments (left == 0) means "list-units" */
6403 if (streq(argv[optind], "help") && !argv[optind+1]) {
6404 log_error("This command expects one or more "
6405 "unit names. Did you mean --help?");
6409 for (; verb->verb; verb++)
6410 if (streq(argv[optind], verb->verb))
6413 log_error("Unknown operation '%s'.", argv[optind]);
6418 switch (verb->argc_cmp) {
6421 if (left != verb->argc) {
6422 log_error("Invalid number of arguments.");
6429 if (left < verb->argc) {
6430 log_error("Too few arguments.");
6437 if (left > verb->argc) {
6438 log_error("Too many arguments.");
6445 assert_not_reached("Unknown comparison operator.");
6448 /* Require a bus connection for all operations but
6450 if (verb->bus == NOBUS) {
6451 if (!bus && !avoid_bus()) {
6452 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6457 if (running_in_chroot() > 0) {
6458 log_info("Running in chroot, ignoring request.");
6462 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
6463 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6468 return verb->dispatch(bus, argv + optind);
6471 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
6473 struct sd_shutdown_command c = {
6480 union sockaddr_union sockaddr = {
6481 .un.sun_family = AF_UNIX,
6482 .un.sun_path = "/run/systemd/shutdownd",
6485 struct iovec iovec[2] = {{
6486 .iov_base = (char*) &c,
6487 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
6490 struct msghdr msghdr = {
6491 .msg_name = &sockaddr,
6492 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
6493 + strlen("/run/systemd/shutdownd"),
6498 _cleanup_close_ int fd;
6500 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
6504 if (!isempty(message)) {
6505 iovec[1].iov_base = (char*) message;
6506 iovec[1].iov_len = strlen(message);
6507 msghdr.msg_iovlen++;
6510 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
6516 static int reload_with_fallback(sd_bus *bus) {
6519 /* First, try systemd via D-Bus. */
6520 if (daemon_reload(bus, NULL) >= 0)
6524 /* Nothing else worked, so let's try signals */
6525 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
6527 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
6528 log_error("kill() failed: %m");
6535 static int start_with_fallback(sd_bus *bus) {
6538 /* First, try systemd via D-Bus. */
6539 if (start_unit(bus, NULL) >= 0)
6543 /* Nothing else worked, so let's try
6545 if (talk_initctl() > 0)
6548 log_error("Failed to talk to init daemon.");
6552 warn_wall(arg_action);
6556 static int halt_now(enum action a) {
6558 /* Make sure C-A-D is handled by the kernel from this
6560 reboot(RB_ENABLE_CAD);
6565 log_info("Halting.");
6566 reboot(RB_HALT_SYSTEM);
6569 case ACTION_POWEROFF:
6570 log_info("Powering off.");
6571 reboot(RB_POWER_OFF);
6574 case ACTION_REBOOT: {
6575 _cleanup_free_ char *param = NULL;
6577 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
6578 log_info("Rebooting with argument '%s'.", param);
6579 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
6580 LINUX_REBOOT_CMD_RESTART2, param);
6583 log_info("Rebooting.");
6584 reboot(RB_AUTOBOOT);
6589 assert_not_reached("Unknown action.");
6593 static int halt_main(sd_bus *bus) {
6596 r = check_inhibitors(bus, arg_action);
6600 if (geteuid() != 0) {
6601 /* Try logind if we are a normal user and no special
6602 * mode applies. Maybe PolicyKit allows us to shutdown
6605 if (arg_when <= 0 &&
6608 (arg_action == ACTION_POWEROFF ||
6609 arg_action == ACTION_REBOOT)) {
6610 r = reboot_with_logind(bus, arg_action);
6615 log_error("Must be root.");
6620 _cleanup_free_ char *m;
6622 m = strv_join(arg_wall, " ");
6626 r = send_shutdownd(arg_when,
6627 arg_action == ACTION_HALT ? 'H' :
6628 arg_action == ACTION_POWEROFF ? 'P' :
6629 arg_action == ACTION_KEXEC ? 'K' :
6636 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6638 char date[FORMAT_TIMESTAMP_MAX];
6640 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6641 format_timestamp(date, sizeof(date), arg_when));
6646 if (!arg_dry && !arg_force)
6647 return start_with_fallback(bus);
6650 if (sd_booted() > 0)
6651 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6653 r = utmp_put_shutdown();
6655 log_warning("Failed to write utmp record: %s", strerror(-r));
6662 r = halt_now(arg_action);
6663 log_error("Failed to reboot: %s", strerror(-r));
6668 static int runlevel_main(void) {
6669 int r, runlevel, previous;
6671 r = utmp_get_runlevel(&runlevel, &previous);
6678 previous <= 0 ? 'N' : previous,
6679 runlevel <= 0 ? 'N' : runlevel);
6684 int main(int argc, char*argv[]) {
6685 _cleanup_bus_unref_ sd_bus *bus = NULL;
6688 setlocale(LC_ALL, "");
6689 log_parse_environment();
6692 /* Explicitly not on_tty() to avoid setting cached value.
6693 * This becomes relevant for piping output which might be
6695 original_stdout_is_tty = isatty(STDOUT_FILENO);
6697 r = parse_argv(argc, argv);
6701 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6702 * let's shortcut this */
6703 if (arg_action == ACTION_RUNLEVEL) {
6704 r = runlevel_main();
6708 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6709 log_info("Running in chroot, ignoring request.");
6715 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
6717 /* systemctl_main() will print an error message for the bus
6718 * connection, but only if it needs to */
6720 switch (arg_action) {
6722 case ACTION_SYSTEMCTL:
6723 r = systemctl_main(bus, argc, argv, r);
6727 case ACTION_POWEROFF:
6733 case ACTION_RUNLEVEL2:
6734 case ACTION_RUNLEVEL3:
6735 case ACTION_RUNLEVEL4:
6736 case ACTION_RUNLEVEL5:
6738 case ACTION_EMERGENCY:
6739 case ACTION_DEFAULT:
6740 r = start_with_fallback(bus);
6745 r = reload_with_fallback(bus);
6748 case ACTION_CANCEL_SHUTDOWN: {
6749 _cleanup_free_ char *m = NULL;
6752 m = strv_join(arg_wall, " ");
6759 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6761 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6765 case ACTION_RUNLEVEL:
6766 case _ACTION_INVALID:
6768 assert_not_reached("Unknown action");
6773 ask_password_agent_close();
6774 polkit_agent_close();
6776 strv_free(arg_types);
6777 strv_free(arg_states);
6778 strv_free(arg_properties);
6780 return r < 0 ? EXIT_FAILURE : r;