1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Marc-Antoine Perennou
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/reboot.h>
24 #include <linux/reboot.h>
25 #include <sys/syscall.h>
32 #include <sys/ioctl.h>
36 #include <sys/socket.h>
39 #include <sys/prctl.h>
42 #include "sd-daemon.h"
43 #include "sd-shutdown.h"
50 #include "utmp-wtmp.h"
53 #include "path-util.h"
55 #include "cgroup-show.h"
56 #include "cgroup-util.h"
58 #include "path-lookup.h"
59 #include "conf-parser.h"
60 #include "exit-status.h"
62 #include "unit-name.h"
64 #include "spawn-ask-password-agent.h"
65 #include "spawn-polkit-agent.h"
67 #include "logs-show.h"
68 #include "socket-util.h"
73 #include "bus-message.h"
74 #include "bus-error.h"
75 #include "bus-errors.h"
79 static char **arg_types = NULL;
80 static char **arg_states = NULL;
81 static char **arg_properties = NULL;
82 static bool arg_all = false;
83 static enum dependency {
89 } arg_dependency = DEPENDENCY_FORWARD;
90 static const char *arg_job_mode = "replace";
91 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
92 static bool arg_no_block = false;
93 static bool arg_no_legend = false;
94 static bool arg_no_pager = false;
95 static bool arg_no_wtmp = false;
96 static bool arg_no_wall = false;
97 static bool arg_no_reload = false;
98 static bool arg_show_types = false;
99 static bool arg_ignore_inhibitors = false;
100 static bool arg_dry = false;
101 static bool arg_quiet = false;
102 static bool arg_full = false;
103 static bool arg_recursive = false;
104 static int arg_force = 0;
105 static bool arg_ask_password = true;
106 static bool arg_runtime = false;
107 static UnitFilePresetMode arg_preset_mode = UNIT_FILE_PRESET_FULL;
108 static char **arg_wall = NULL;
109 static const char *arg_kill_who = NULL;
110 static int arg_signal = SIGTERM;
111 static const char *arg_root = NULL;
112 static usec_t arg_when = 0;
134 ACTION_CANCEL_SHUTDOWN,
136 } arg_action = ACTION_SYSTEMCTL;
137 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
138 static char *arg_host = NULL;
139 static unsigned arg_lines = 10;
140 static OutputMode arg_output = OUTPUT_SHORT;
141 static bool arg_plain = false;
143 static bool original_stdout_is_tty;
145 static int daemon_reload(sd_bus *bus, char **args);
146 static int halt_now(enum action a);
147 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet);
149 static char** strv_skip_first(char **strv) {
150 if (strv_length(strv) > 0)
155 static void pager_open_if_enabled(void) {
163 static void ask_password_agent_open_if_enabled(void) {
165 /* Open the password agent as a child process if necessary */
167 if (!arg_ask_password)
170 if (arg_scope != UNIT_FILE_SYSTEM)
173 if (arg_transport != BUS_TRANSPORT_LOCAL)
176 ask_password_agent_open();
180 static void polkit_agent_open_if_enabled(void) {
182 /* Open the polkit agent as a child process if necessary */
184 if (!arg_ask_password)
187 if (arg_scope != UNIT_FILE_SYSTEM)
190 if (arg_transport != BUS_TRANSPORT_LOCAL)
197 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
200 if (!sd_bus_error_is_set(error))
203 if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) ||
204 sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
205 sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
206 sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
207 return EXIT_NOPERMISSION;
209 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
210 return EXIT_NOTINSTALLED;
212 if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
213 sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED))
214 return EXIT_NOTIMPLEMENTED;
216 if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
217 return EXIT_NOTCONFIGURED;
225 static void warn_wall(enum action a) {
226 static const char *table[_ACTION_MAX] = {
227 [ACTION_HALT] = "The system is going down for system halt NOW!",
228 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
229 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
230 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
231 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
232 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
233 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
240 _cleanup_free_ char *p;
242 p = strv_join(arg_wall, " ");
249 utmp_wall(p, NULL, NULL);
257 utmp_wall(table[a], NULL, NULL);
260 static bool avoid_bus(void) {
262 if (running_in_chroot() > 0)
265 if (sd_booted() <= 0)
268 if (!isempty(arg_root))
271 if (arg_scope == UNIT_FILE_GLOBAL)
277 static int compare_unit_info(const void *a, const void *b) {
278 const UnitInfo *u = a, *v = b;
282 /* First, order by machine */
283 if (!u->machine && v->machine)
285 if (u->machine && !v->machine)
287 if (u->machine && v->machine) {
288 r = strcasecmp(u->machine, v->machine);
293 /* Second, order by unit type */
294 d1 = strrchr(u->id, '.');
295 d2 = strrchr(v->id, '.');
297 r = strcasecmp(d1, d2);
302 /* Third, order by name */
303 return strcasecmp(u->id, v->id);
306 static bool output_show_unit(const UnitInfo *u, char **patterns) {
307 if (!strv_isempty(patterns)) {
310 STRV_FOREACH(pattern, patterns)
311 if (fnmatch(*pattern, u->id, FNM_NOESCAPE) == 0)
320 dot = strrchr(u->id, '.');
324 if (!strv_find(arg_types, dot+1))
334 if (streq(u->active_state, "inactive") || u->following[0])
340 static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
341 unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
343 unsigned n_shown = 0;
346 max_id_len = strlen("UNIT");
347 load_len = strlen("LOAD");
348 active_len = strlen("ACTIVE");
349 sub_len = strlen("SUB");
350 job_len = strlen("JOB");
353 for (u = unit_infos; u < unit_infos + c; u++) {
354 max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0));
355 load_len = MAX(load_len, strlen(u->load_state));
356 active_len = MAX(active_len, strlen(u->active_state));
357 sub_len = MAX(sub_len, strlen(u->sub_state));
359 if (u->job_id != 0) {
360 job_len = MAX(job_len, strlen(u->job_type));
364 if (!arg_no_legend &&
365 (streq(u->active_state, "failed") ||
366 STR_IN_SET(u->load_state, "error", "not-found", "masked")))
370 if (!arg_full && original_stdout_is_tty) {
373 id_len = MIN(max_id_len, 25u);
374 basic_len = circle_len + 5 + id_len + 5 + active_len + sub_len;
377 basic_len += job_len + 1;
379 if (basic_len < (unsigned) columns()) {
380 unsigned extra_len, incr;
381 extra_len = columns() - basic_len;
383 /* Either UNIT already got 25, or is fully satisfied.
384 * Grant up to 25 to DESC now. */
385 incr = MIN(extra_len, 25u);
389 /* split the remaining space between UNIT and DESC,
390 * but do not give UNIT more than it needs. */
392 incr = MIN(extra_len / 2, max_id_len - id_len);
394 desc_len += extra_len - incr;
400 for (u = unit_infos; u < unit_infos + c; u++) {
401 _cleanup_free_ char *e = NULL, *j = NULL;
402 const char *on_loaded = "", *off_loaded = "";
403 const char *on_active = "", *off_active = "";
404 const char *on_circle = "", *off_circle = "";
408 if (!n_shown && !arg_no_legend) {
413 printf("%-*s %-*s %-*s %-*s ",
416 active_len, "ACTIVE",
420 printf("%-*s ", job_len, "JOB");
422 if (!arg_full && arg_no_pager)
423 printf("%.*s\n", desc_len, "DESCRIPTION");
425 printf("%s\n", "DESCRIPTION");
430 if (STR_IN_SET(u->load_state, "error", "not-found", "masked")) {
431 on_loaded = ansi_highlight_red();
432 on_circle = ansi_highlight_yellow();
433 off_loaded = off_circle = ansi_highlight_off();
437 if (streq(u->active_state, "failed")) {
438 on_circle = on_active = ansi_highlight_red();
439 off_circle = off_active = ansi_highlight_off();
444 j = strjoin(u->machine, ":", u->id, NULL);
453 e = ellipsize(id, id_len, 33);
461 printf("%s%s%s ", on_circle, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_circle);
463 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
464 on_active, id_len, id, off_active,
465 on_loaded, load_len, u->load_state, off_loaded,
466 on_active, active_len, u->active_state,
467 sub_len, u->sub_state, off_active,
468 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
471 printf("%.*s\n", desc_len, u->description);
473 printf("%s\n", u->description);
476 if (!arg_no_legend) {
477 const char *on, *off;
481 "LOAD = Reflects whether the unit definition was properly loaded.\n"
482 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
483 "SUB = The low-level unit activation state, values depend on unit type.");
484 puts(job_count ? "JOB = Pending job for the unit.\n" : "");
485 on = ansi_highlight();
486 off = ansi_highlight_off();
488 on = ansi_highlight_red();
489 off = ansi_highlight_off();
493 printf("%s%u loaded units listed.%s\n"
494 "To show all installed unit files use 'systemctl list-unit-files'.\n",
497 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
498 "To show all installed unit files use 'systemctl list-unit-files'.\n",
505 static int get_unit_list(
509 UnitInfo **unit_infos,
511 sd_bus_message **_reply) {
513 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
514 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
515 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
524 r = sd_bus_message_new_method_call(
527 "org.freedesktop.systemd1",
528 "/org/freedesktop/systemd1",
529 "org.freedesktop.systemd1.Manager",
530 "ListUnitsFiltered");
533 return bus_log_create_error(r);
535 r = sd_bus_message_append_strv(m, arg_states);
537 return bus_log_create_error(r);
539 r = sd_bus_call(bus, m, 0, &error, &reply);
541 log_error("Failed to list units: %s", bus_error_message(&error, r));
545 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
547 return bus_log_parse_error(r);
549 while ((r = bus_parse_unit_info(reply, &u)) > 0) {
552 if (!output_show_unit(&u, patterns))
555 if (!GREEDY_REALLOC(*unit_infos, size, c+1))
558 (*unit_infos)[c++] = u;
561 return bus_log_parse_error(r);
563 r = sd_bus_message_exit_container(reply);
565 return bus_log_parse_error(r);
573 static void message_set_freep(Set **set) {
576 while ((m = set_steal_first(*set)))
577 sd_bus_message_unref(m);
582 static int get_unit_list_recursive(
585 UnitInfo **_unit_infos,
589 _cleanup_free_ UnitInfo *unit_infos = NULL;
590 _cleanup_(message_set_freep) Set *replies;
591 sd_bus_message *reply;
599 replies = set_new(NULL);
603 c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
607 r = set_put(replies, reply);
609 sd_bus_message_unref(reply);
614 _cleanup_strv_free_ char **machines = NULL;
617 r = sd_get_machine_names(&machines);
621 STRV_FOREACH(i, machines) {
622 _cleanup_bus_close_unref_ sd_bus *container = NULL;
625 r = sd_bus_open_system_container(&container, *i);
627 log_error_errno(r, "Failed to connect to container %s: %m", *i);
631 k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
637 r = set_put(replies, reply);
639 sd_bus_message_unref(reply);
644 *_machines = machines;
649 *_unit_infos = unit_infos;
658 static int list_units(sd_bus *bus, char **args) {
659 _cleanup_free_ UnitInfo *unit_infos = NULL;
660 _cleanup_(message_set_freep) Set *replies = NULL;
661 _cleanup_strv_free_ char **machines = NULL;
664 pager_open_if_enabled();
666 r = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
670 qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
671 return output_units_list(unit_infos, r);
674 static int get_triggered_units(
679 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
682 r = sd_bus_get_property_strv(
684 "org.freedesktop.systemd1",
686 "org.freedesktop.systemd1.Unit",
692 log_error("Failed to determine triggers: %s", bus_error_message(&error, r));
697 static int get_listening(
699 const char* unit_path,
702 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
703 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
704 const char *type, *path;
707 r = sd_bus_get_property(
709 "org.freedesktop.systemd1",
711 "org.freedesktop.systemd1.Socket",
717 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r));
721 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
723 return bus_log_parse_error(r);
725 while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
727 r = strv_extend(listening, type);
731 r = strv_extend(listening, path);
738 return bus_log_parse_error(r);
740 r = sd_bus_message_exit_container(reply);
742 return bus_log_parse_error(r);
754 /* Note: triggered is a list here, although it almost certainly
755 * will always be one unit. Nevertheless, dbus API allows for multiple
756 * values, so let's follow that.*/
759 /* The strv above is shared. free is set only in the first one. */
763 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
769 if (!a->machine && b->machine)
771 if (a->machine && !b->machine)
773 if (a->machine && b->machine) {
774 o = strcasecmp(a->machine, b->machine);
779 o = strcmp(a->path, b->path);
781 o = strcmp(a->type, b->type);
786 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
787 struct socket_info *s;
788 unsigned pathlen = strlen("LISTEN"),
789 typelen = strlen("TYPE") * arg_show_types,
790 socklen = strlen("UNIT"),
791 servlen = strlen("ACTIVATES");
792 const char *on, *off;
794 for (s = socket_infos; s < socket_infos + cs; s++) {
798 socklen = MAX(socklen, strlen(s->id));
800 typelen = MAX(typelen, strlen(s->type));
801 pathlen = MAX(pathlen, strlen(s->path) + (s->machine ? strlen(s->machine)+1 : 0));
803 STRV_FOREACH(a, s->triggered)
804 tmp += strlen(*a) + 2*(a != s->triggered);
805 servlen = MAX(servlen, tmp);
810 printf("%-*s %-*.*s%-*s %s\n",
812 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
816 for (s = socket_infos; s < socket_infos + cs; s++) {
817 _cleanup_free_ char *j = NULL;
822 j = strjoin(s->machine, ":", s->path, NULL);
830 printf("%-*s %-*s %-*s",
831 pathlen, path, typelen, s->type, socklen, s->id);
834 pathlen, path, socklen, s->id);
835 STRV_FOREACH(a, s->triggered)
837 a == s->triggered ? "" : ",", *a);
841 on = ansi_highlight();
842 off = ansi_highlight_off();
846 on = ansi_highlight_red();
847 off = ansi_highlight_off();
850 if (!arg_no_legend) {
851 printf("%s%u sockets listed.%s\n", on, cs, off);
853 printf("Pass --all to see loaded but inactive sockets, too.\n");
859 static int list_sockets(sd_bus *bus, char **args) {
860 _cleanup_(message_set_freep) Set *replies = NULL;
861 _cleanup_strv_free_ char **machines = NULL;
862 _cleanup_free_ UnitInfo *unit_infos = NULL;
863 _cleanup_free_ struct socket_info *socket_infos = NULL;
865 struct socket_info *s;
870 pager_open_if_enabled();
872 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
876 for (u = unit_infos; u < unit_infos + n; u++) {
877 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
880 if (!endswith(u->id, ".socket"))
883 r = get_triggered_units(bus, u->unit_path, &triggered);
887 c = get_listening(bus, u->unit_path, &listening);
893 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
898 for (i = 0; i < c; i++)
899 socket_infos[cs + i] = (struct socket_info) {
900 .machine = u->machine,
902 .type = listening[i*2],
903 .path = listening[i*2 + 1],
904 .triggered = triggered,
905 .own_triggered = i==0,
908 /* from this point on we will cleanup those socket_infos */
911 listening = triggered = NULL; /* avoid cleanup */
914 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
915 (__compar_fn_t) socket_info_compare);
917 output_sockets_list(socket_infos, cs);
920 assert(cs == 0 || socket_infos);
921 for (s = socket_infos; s < socket_infos + cs; s++) {
924 if (s->own_triggered)
925 strv_free(s->triggered);
931 static int get_next_elapse(
934 dual_timestamp *next) {
936 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
944 r = sd_bus_get_property_trivial(
946 "org.freedesktop.systemd1",
948 "org.freedesktop.systemd1.Timer",
949 "NextElapseUSecMonotonic",
954 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
958 r = sd_bus_get_property_trivial(
960 "org.freedesktop.systemd1",
962 "org.freedesktop.systemd1.Timer",
963 "NextElapseUSecRealtime",
968 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
976 static int get_last_trigger(
981 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
988 r = sd_bus_get_property_trivial(
990 "org.freedesktop.systemd1",
992 "org.freedesktop.systemd1.Timer",
998 log_error("Failed to get last trigger time: %s", bus_error_message(&error, r));
1006 const char* machine;
1009 usec_t last_trigger;
1013 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
1019 if (!a->machine && b->machine)
1021 if (a->machine && !b->machine)
1023 if (a->machine && b->machine) {
1024 o = strcasecmp(a->machine, b->machine);
1029 if (a->next_elapse < b->next_elapse)
1031 if (a->next_elapse > b->next_elapse)
1034 return strcmp(a->id, b->id);
1037 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
1038 struct timer_info *t;
1040 nextlen = strlen("NEXT"),
1041 leftlen = strlen("LEFT"),
1042 lastlen = strlen("LAST"),
1043 passedlen = strlen("PASSED"),
1044 unitlen = strlen("UNIT"),
1045 activatelen = strlen("ACTIVATES");
1047 const char *on, *off;
1049 assert(timer_infos || n == 0);
1051 for (t = timer_infos; t < timer_infos + n; t++) {
1055 if (t->next_elapse > 0) {
1056 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1058 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
1059 nextlen = MAX(nextlen, strlen(tstamp) + 1);
1061 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
1062 leftlen = MAX(leftlen, strlen(trel));
1065 if (t->last_trigger > 0) {
1066 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1068 format_timestamp(tstamp, sizeof(tstamp), t->last_trigger);
1069 lastlen = MAX(lastlen, strlen(tstamp) + 1);
1071 format_timestamp_relative(trel, sizeof(trel), t->last_trigger);
1072 passedlen = MAX(passedlen, strlen(trel));
1075 unitlen = MAX(unitlen, strlen(t->id) + (t->machine ? strlen(t->machine)+1 : 0));
1077 STRV_FOREACH(a, t->triggered)
1078 ul += strlen(*a) + 2*(a != t->triggered);
1080 activatelen = MAX(activatelen, ul);
1085 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1089 passedlen, "PASSED",
1093 for (t = timer_infos; t < timer_infos + n; t++) {
1094 _cleanup_free_ char *j = NULL;
1096 char tstamp1[FORMAT_TIMESTAMP_MAX] = "n/a", trel1[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1097 char tstamp2[FORMAT_TIMESTAMP_MAX] = "n/a", trel2[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1100 format_timestamp(tstamp1, sizeof(tstamp1), t->next_elapse);
1101 format_timestamp_relative(trel1, sizeof(trel1), t->next_elapse);
1103 format_timestamp(tstamp2, sizeof(tstamp2), t->last_trigger);
1104 format_timestamp_relative(trel2, sizeof(trel2), t->last_trigger);
1107 j = strjoin(t->machine, ":", t->id, NULL);
1114 printf("%-*s %-*s %-*s %-*s %-*s",
1115 nextlen, tstamp1, leftlen, trel1, lastlen, tstamp2, passedlen, trel2, unitlen, unit);
1117 STRV_FOREACH(a, t->triggered)
1119 a == t->triggered ? "" : ",", *a);
1123 on = ansi_highlight();
1124 off = ansi_highlight_off();
1128 on = ansi_highlight_red();
1129 off = ansi_highlight_off();
1132 if (!arg_no_legend) {
1133 printf("%s%u timers listed.%s\n", on, n, off);
1135 printf("Pass --all to see loaded but inactive timers, too.\n");
1141 static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
1147 if (next->monotonic != USEC_INFINITY && next->monotonic > 0) {
1150 if (next->monotonic > nw->monotonic)
1151 converted = nw->realtime + (next->monotonic - nw->monotonic);
1153 converted = nw->realtime - (nw->monotonic - next->monotonic);
1155 if (next->realtime != USEC_INFINITY && next->realtime > 0)
1156 next_elapse = MIN(converted, next->realtime);
1158 next_elapse = converted;
1161 next_elapse = next->realtime;
1166 static int list_timers(sd_bus *bus, char **args) {
1167 _cleanup_(message_set_freep) Set *replies = NULL;
1168 _cleanup_strv_free_ char **machines = NULL;
1169 _cleanup_free_ struct timer_info *timer_infos = NULL;
1170 _cleanup_free_ UnitInfo *unit_infos = NULL;
1171 struct timer_info *t;
1178 pager_open_if_enabled();
1180 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
1184 dual_timestamp_get(&nw);
1186 for (u = unit_infos; u < unit_infos + n; u++) {
1187 _cleanup_strv_free_ char **triggered = NULL;
1188 dual_timestamp next = {};
1191 if (!endswith(u->id, ".timer"))
1194 r = get_triggered_units(bus, u->unit_path, &triggered);
1198 r = get_next_elapse(bus, u->unit_path, &next);
1202 get_last_trigger(bus, u->unit_path, &last);
1204 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
1209 m = calc_next_elapse(&nw, &next);
1211 timer_infos[c++] = (struct timer_info) {
1212 .machine = u->machine,
1215 .last_trigger = last,
1216 .triggered = triggered,
1219 triggered = NULL; /* avoid cleanup */
1222 qsort_safe(timer_infos, c, sizeof(struct timer_info),
1223 (__compar_fn_t) timer_info_compare);
1225 output_timers_list(timer_infos, c);
1228 for (t = timer_infos; t < timer_infos + c; t++)
1229 strv_free(t->triggered);
1234 static int compare_unit_file_list(const void *a, const void *b) {
1235 const char *d1, *d2;
1236 const UnitFileList *u = a, *v = b;
1238 d1 = strrchr(u->path, '.');
1239 d2 = strrchr(v->path, '.');
1244 r = strcasecmp(d1, d2);
1249 return strcasecmp(basename(u->path), basename(v->path));
1252 static bool output_show_unit_file(const UnitFileList *u, char **patterns) {
1253 if (!strv_isempty(patterns)) {
1256 STRV_FOREACH(pattern, patterns)
1257 if (fnmatch(*pattern, basename(u->path), FNM_NOESCAPE) == 0)
1263 if (!strv_isempty(arg_types)) {
1266 dot = strrchr(u->path, '.');
1270 if (!strv_find(arg_types, dot+1))
1274 if (!strv_isempty(arg_states)) {
1275 if (!strv_find(arg_states, unit_file_state_to_string(u->state)))
1282 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
1283 unsigned max_id_len, id_cols, state_cols;
1284 const UnitFileList *u;
1286 max_id_len = strlen("UNIT FILE");
1287 state_cols = strlen("STATE");
1289 for (u = units; u < units + c; u++) {
1290 max_id_len = MAX(max_id_len, strlen(basename(u->path)));
1291 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1295 unsigned basic_cols;
1297 id_cols = MIN(max_id_len, 25u);
1298 basic_cols = 1 + id_cols + state_cols;
1299 if (basic_cols < (unsigned) columns())
1300 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1302 id_cols = max_id_len;
1305 printf("%-*s %-*s\n",
1306 id_cols, "UNIT FILE",
1307 state_cols, "STATE");
1309 for (u = units; u < units + c; u++) {
1310 _cleanup_free_ char *e = NULL;
1311 const char *on, *off;
1314 if (u->state == UNIT_FILE_MASKED ||
1315 u->state == UNIT_FILE_MASKED_RUNTIME ||
1316 u->state == UNIT_FILE_DISABLED ||
1317 u->state == UNIT_FILE_INVALID) {
1318 on = ansi_highlight_red();
1319 off = ansi_highlight_off();
1320 } else if (u->state == UNIT_FILE_ENABLED) {
1321 on = ansi_highlight_green();
1322 off = ansi_highlight_off();
1326 id = basename(u->path);
1328 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1330 printf("%-*s %s%-*s%s\n",
1331 id_cols, e ? e : id,
1332 on, state_cols, unit_file_state_to_string(u->state), off);
1336 printf("\n%u unit files listed.\n", c);
1339 static int list_unit_files(sd_bus *bus, char **args) {
1340 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1341 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1342 _cleanup_free_ UnitFileList *units = NULL;
1350 pager_open_if_enabled();
1358 h = hashmap_new(&string_hash_ops);
1362 r = unit_file_get_list(arg_scope, arg_root, h);
1364 unit_file_list_free(h);
1365 log_error_errno(r, "Failed to get unit file list: %m");
1369 n_units = hashmap_size(h);
1371 units = new(UnitFileList, n_units);
1372 if (!units && n_units > 0) {
1373 unit_file_list_free(h);
1377 HASHMAP_FOREACH(u, h, i) {
1378 if (!output_show_unit_file(u, strv_skip_first(args)))
1385 assert(c <= n_units);
1388 r = sd_bus_call_method(
1390 "org.freedesktop.systemd1",
1391 "/org/freedesktop/systemd1",
1392 "org.freedesktop.systemd1.Manager",
1398 log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1402 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1404 return bus_log_parse_error(r);
1406 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1408 if (!GREEDY_REALLOC(units, size, c + 1))
1411 units[c] = (struct UnitFileList) {
1413 unit_file_state_from_string(state)
1416 if (output_show_unit_file(&units[c], strv_skip_first(args)))
1421 return bus_log_parse_error(r);
1423 r = sd_bus_message_exit_container(reply);
1425 return bus_log_parse_error(r);
1428 qsort_safe(units, c, sizeof(UnitFileList), compare_unit_file_list);
1429 output_unit_file_list(units, c);
1432 for (unit = units; unit < units + c; unit++)
1439 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1440 _cleanup_free_ char *n = NULL;
1441 size_t max_len = MAX(columns(),20u);
1447 for (i = level - 1; i >= 0; i--) {
1449 if (len > max_len - 3 && !arg_full) {
1450 printf("%s...\n",max_len % 2 ? "" : " ");
1453 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERTICAL : DRAW_TREE_SPACE));
1457 if (len > max_len - 3 && !arg_full) {
1458 printf("%s...\n",max_len % 2 ? "" : " ");
1462 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
1466 printf("%s\n", name);
1470 n = ellipsize(name, max_len-len, 100);
1478 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1480 static const char *dependencies[_DEPENDENCY_MAX] = {
1481 [DEPENDENCY_FORWARD] = "Requires\0"
1482 "RequiresOverridable\0"
1484 "RequisiteOverridable\0"
1487 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1488 "RequiredByOverridable\0"
1492 [DEPENDENCY_AFTER] = "After\0",
1493 [DEPENDENCY_BEFORE] = "Before\0",
1496 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1497 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1498 _cleanup_strv_free_ char **ret = NULL;
1499 _cleanup_free_ char *path = NULL;
1505 assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
1507 path = unit_dbus_path_from_name(name);
1511 r = sd_bus_call_method(
1513 "org.freedesktop.systemd1",
1515 "org.freedesktop.DBus.Properties",
1519 "s", "org.freedesktop.systemd1.Unit");
1521 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1525 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1527 return bus_log_parse_error(r);
1529 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1532 r = sd_bus_message_read(reply, "s", &prop);
1534 return bus_log_parse_error(r);
1536 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1537 r = sd_bus_message_skip(reply, "v");
1539 return bus_log_parse_error(r);
1542 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1544 return bus_log_parse_error(r);
1546 r = bus_message_read_strv_extend(reply, &ret);
1548 return bus_log_parse_error(r);
1550 r = sd_bus_message_exit_container(reply);
1552 return bus_log_parse_error(r);
1555 r = sd_bus_message_exit_container(reply);
1557 return bus_log_parse_error(r);
1561 return bus_log_parse_error(r);
1563 r = sd_bus_message_exit_container(reply);
1565 return bus_log_parse_error(r);
1573 static int list_dependencies_compare(const void *_a, const void *_b) {
1574 const char **a = (const char**) _a, **b = (const char**) _b;
1576 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1578 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1581 return strcasecmp(*a, *b);
1584 static int list_dependencies_one(
1589 unsigned int branches) {
1591 _cleanup_strv_free_ char **deps = NULL;
1599 r = strv_extend(units, name);
1603 r = list_dependencies_get_dependencies(bus, name, &deps);
1607 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1609 STRV_FOREACH(c, deps) {
1612 if (strv_contains(*units, *c)) {
1614 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1621 state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true);
1623 printf("%s%s%s ", ansi_highlight_green(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1625 printf("%s%s%s ", ansi_highlight_red(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1627 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1631 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1632 r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1639 strv_remove(*units, name);
1644 static int list_dependencies(sd_bus *bus, char **args) {
1645 _cleanup_strv_free_ char **units = NULL;
1646 _cleanup_free_ char *unit = NULL;
1652 unit = unit_name_mangle(args[1], MANGLE_NOGLOB);
1657 u = SPECIAL_DEFAULT_TARGET;
1659 pager_open_if_enabled();
1663 return list_dependencies_one(bus, u, 0, &units, 0);
1666 struct machine_info {
1670 char *control_group;
1671 uint32_t n_failed_units;
1676 static const struct bus_properties_map machine_info_property_map[] = {
1677 { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
1678 { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
1679 { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
1680 { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
1681 { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
1685 static void free_machines_list(struct machine_info *machine_infos, int n) {
1691 for (i = 0; i < n; i++) {
1692 free(machine_infos[i].name);
1693 free(machine_infos[i].state);
1694 free(machine_infos[i].control_group);
1697 free(machine_infos);
1700 static int compare_machine_info(const void *a, const void *b) {
1701 const struct machine_info *u = a, *v = b;
1703 if (u->is_host != v->is_host)
1704 return u->is_host > v->is_host ? -1 : 1;
1706 return strcasecmp(u->name, v->name);
1709 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1710 _cleanup_bus_close_unref_ sd_bus *container = NULL;
1716 r = sd_bus_open_system_container(&container, mi->name);
1723 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi);
1730 static bool output_show_machine(const char *name, char **patterns) {
1735 if (strv_isempty(patterns))
1738 STRV_FOREACH(i, patterns)
1739 if (fnmatch(*i, name, FNM_NOESCAPE) == 0)
1745 static int get_machine_list(
1747 struct machine_info **_machine_infos,
1750 struct machine_info *machine_infos = NULL;
1751 _cleanup_strv_free_ char **m = NULL;
1752 _cleanup_free_ char *hn = NULL;
1757 hn = gethostname_malloc();
1761 if (output_show_machine(hn, patterns)) {
1762 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1765 machine_infos[c].is_host = true;
1766 machine_infos[c].name = hn;
1769 get_machine_properties(bus, &machine_infos[c]);
1773 sd_get_machine_names(&m);
1774 STRV_FOREACH(i, m) {
1775 _cleanup_free_ char *class = NULL;
1777 if (!output_show_machine(*i, patterns))
1780 sd_machine_get_class(*i, &class);
1781 if (!streq_ptr(class, "container"))
1784 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1785 free_machines_list(machine_infos, c);
1789 machine_infos[c].is_host = false;
1790 machine_infos[c].name = strdup(*i);
1791 if (!machine_infos[c].name) {
1792 free_machines_list(machine_infos, c);
1796 get_machine_properties(NULL, &machine_infos[c]);
1800 *_machine_infos = machine_infos;
1804 static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1805 struct machine_info *m;
1808 namelen = sizeof("NAME") - 1,
1809 statelen = sizeof("STATE") - 1,
1810 failedlen = sizeof("FAILED") - 1,
1811 jobslen = sizeof("JOBS") - 1;
1813 assert(machine_infos || n == 0);
1815 for (m = machine_infos; m < machine_infos + n; m++) {
1816 namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
1817 statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
1818 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
1819 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
1821 if (!arg_no_legend && !streq_ptr(m->state, "running"))
1825 if (!arg_no_legend) {
1829 printf("%-*s %-*s %-*s %-*s\n",
1832 failedlen, "FAILED",
1836 for (m = machine_infos; m < machine_infos + n; m++) {
1837 const char *on_state = "", *off_state = "";
1838 const char *on_failed = "", *off_failed = "";
1839 bool circle = false;
1841 if (streq_ptr(m->state, "degraded")) {
1842 on_state = ansi_highlight_red();
1843 off_state = ansi_highlight_off();
1845 } else if (!streq_ptr(m->state, "running")) {
1846 on_state = ansi_highlight_yellow();
1847 off_state = ansi_highlight_off();
1851 if (m->n_failed_units > 0) {
1852 on_failed = ansi_highlight_red();
1853 off_failed = ansi_highlight_off();
1855 on_failed = off_failed = "";
1858 printf("%s%s%s ", on_state, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_state);
1861 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1862 (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
1863 on_state, statelen, strna(m->state), off_state,
1864 on_failed, failedlen, m->n_failed_units, off_failed,
1865 jobslen, m->n_jobs);
1867 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1868 namelen, strna(m->name),
1869 on_state, statelen, strna(m->state), off_state,
1870 on_failed, failedlen, m->n_failed_units, off_failed,
1871 jobslen, m->n_jobs);
1875 printf("\n%u machines listed.\n", n);
1878 static int list_machines(sd_bus *bus, char **args) {
1879 struct machine_info *machine_infos = NULL;
1884 if (geteuid() != 0) {
1885 log_error("Must be root.");
1889 pager_open_if_enabled();
1891 r = get_machine_list(bus, &machine_infos, strv_skip_first(args));
1895 qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
1896 output_machines_list(machine_infos, r);
1897 free_machines_list(machine_infos, r);
1902 static int get_default(sd_bus *bus, char **args) {
1903 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1904 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1905 _cleanup_free_ char *_path = NULL;
1909 if (!bus || avoid_bus()) {
1910 r = unit_file_get_default(arg_scope, arg_root, &_path);
1912 return log_error_errno(r, "Failed to get default target: %m");
1916 r = sd_bus_call_method(
1918 "org.freedesktop.systemd1",
1919 "/org/freedesktop/systemd1",
1920 "org.freedesktop.systemd1.Manager",
1926 log_error("Failed to get default target: %s", bus_error_message(&error, -r));
1930 r = sd_bus_message_read(reply, "s", &path);
1932 return bus_log_parse_error(r);
1936 printf("%s\n", path);
1941 static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) {
1944 assert(changes || n_changes == 0);
1946 for (i = 0; i < n_changes; i++) {
1947 if (changes[i].type == UNIT_FILE_SYMLINK)
1948 log_info("Created symlink from %s to %s.", changes[i].path, changes[i].source);
1950 log_info("Removed symlink %s.", changes[i].path);
1954 static int deserialize_and_dump_unit_file_changes(sd_bus_message *m) {
1955 const char *type, *path, *source;
1958 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1960 return bus_log_parse_error(r);
1962 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1964 if (streq(type, "symlink"))
1965 log_info("Created symlink from %s to %s.", path, source);
1967 log_info("Removed symlink %s.", path);
1971 return bus_log_parse_error(r);
1973 r = sd_bus_message_exit_container(m);
1975 return bus_log_parse_error(r);
1980 static int set_default(sd_bus *bus, char **args) {
1981 _cleanup_free_ char *unit = NULL;
1982 UnitFileChange *changes = NULL;
1983 unsigned n_changes = 0;
1986 unit = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
1990 if (!bus || avoid_bus()) {
1991 r = unit_file_set_default(arg_scope, arg_root, unit, true, &changes, &n_changes);
1993 return log_error_errno(r, "Failed to set default target: %m");
1996 dump_unit_file_changes(changes, n_changes);
2000 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
2001 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2003 r = sd_bus_message_new_method_call(
2006 "org.freedesktop.systemd1",
2007 "/org/freedesktop/systemd1",
2008 "org.freedesktop.systemd1.Manager",
2009 "SetDefaultTarget");
2011 return bus_log_create_error(r);
2013 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2015 return bus_log_create_error(r);
2017 r = sd_bus_message_append(m, "sb", unit, 1);
2019 return bus_log_create_error(r);
2021 r = sd_bus_call(bus, m, 0, &error, &reply);
2023 log_error("Failed to set default target: %s", bus_error_message(&error, -r));
2027 r = deserialize_and_dump_unit_file_changes(reply);
2031 /* Try to reload if enabled */
2033 r = daemon_reload(bus, args);
2038 unit_file_changes_free(changes, n_changes);
2045 const char *name, *type, *state;
2048 static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
2049 unsigned id_len, unit_len, type_len, state_len;
2050 const struct job_info *j;
2051 const char *on, *off;
2052 bool shorten = false;
2054 assert(n == 0 || jobs);
2057 on = ansi_highlight_green();
2058 off = ansi_highlight_off();
2060 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
2064 pager_open_if_enabled();
2066 id_len = strlen("JOB");
2067 unit_len = strlen("UNIT");
2068 type_len = strlen("TYPE");
2069 state_len = strlen("STATE");
2071 for (j = jobs; j < jobs + n; j++) {
2072 uint32_t id = j->id;
2073 assert(j->name && j->type && j->state);
2075 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
2076 unit_len = MAX(unit_len, strlen(j->name));
2077 type_len = MAX(type_len, strlen(j->type));
2078 state_len = MAX(state_len, strlen(j->state));
2081 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
2082 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
2087 printf("%*s %-*s %-*s %-*s\n",
2091 state_len, "STATE");
2093 for (j = jobs; j < jobs + n; j++) {
2094 _cleanup_free_ char *e = NULL;
2096 if (streq(j->state, "running")) {
2097 on = ansi_highlight();
2098 off = ansi_highlight_off();
2102 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
2103 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2105 on, unit_len, e ? e : j->name, off,
2107 on, state_len, j->state, off);
2110 if (!arg_no_legend) {
2111 on = ansi_highlight();
2112 off = ansi_highlight_off();
2114 printf("\n%s%u jobs listed%s.\n", on, n, off);
2118 static bool output_show_job(struct job_info *job, char **patterns) {
2123 if (strv_isempty(patterns))
2126 STRV_FOREACH(pattern, patterns)
2127 if (fnmatch(*pattern, job->name, FNM_NOESCAPE) == 0)
2132 static int list_jobs(sd_bus *bus, char **args) {
2133 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2134 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2135 const char *name, *type, *state, *job_path, *unit_path;
2136 _cleanup_free_ struct job_info *jobs = NULL;
2141 bool skipped = false;
2143 r = sd_bus_call_method(
2145 "org.freedesktop.systemd1",
2146 "/org/freedesktop/systemd1",
2147 "org.freedesktop.systemd1.Manager",
2153 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
2157 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2159 return bus_log_parse_error(r);
2161 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
2162 struct job_info job = { id, name, type, state };
2164 if (!output_show_job(&job, strv_skip_first(args))) {
2169 if (!GREEDY_REALLOC(jobs, size, c + 1))
2175 return bus_log_parse_error(r);
2177 r = sd_bus_message_exit_container(reply);
2179 return bus_log_parse_error(r);
2181 output_jobs_list(jobs, c, skipped);
2185 static int cancel_job(sd_bus *bus, char **args) {
2186 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2192 if (strv_length(args) <= 1)
2193 return daemon_reload(bus, args);
2195 STRV_FOREACH(name, args+1) {
2196 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2200 q = safe_atou32(*name, &id);
2202 return log_error_errno(q, "Failed to parse job id \"%s\": %m", *name);
2204 q = sd_bus_message_new_method_call(
2207 "org.freedesktop.systemd1",
2208 "/org/freedesktop/systemd1",
2209 "org.freedesktop.systemd1.Manager",
2212 return bus_log_create_error(q);
2214 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2216 return bus_log_create_error(1);
2218 q = sd_bus_message_append(m, "u", id);
2220 return bus_log_create_error(q);
2222 q = sd_bus_call(bus, m, 0, &error, NULL);
2224 log_error("Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, q));
2233 static int need_daemon_reload(sd_bus *bus, const char *unit) {
2234 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2238 /* We ignore all errors here, since this is used to show a
2241 /* We don't use unit_dbus_path_from_name() directly since we
2242 * don't want to load the unit if it isn't loaded. */
2244 r = sd_bus_call_method(
2246 "org.freedesktop.systemd1",
2247 "/org/freedesktop/systemd1",
2248 "org.freedesktop.systemd1.Manager",
2256 r = sd_bus_message_read(reply, "o", &path);
2260 r = sd_bus_get_property_trivial(
2262 "org.freedesktop.systemd1",
2264 "org.freedesktop.systemd1.Unit",
2274 typedef struct WaitData {
2281 static int wait_filter(sd_bus *bus, sd_bus_message *m, void *data, sd_bus_error *error) {
2288 log_debug("Got D-Bus request: %s.%s() on %s",
2289 sd_bus_message_get_interface(m),
2290 sd_bus_message_get_member(m),
2291 sd_bus_message_get_path(m));
2293 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
2294 log_error("Warning! D-Bus connection terminated.");
2296 } else if (sd_bus_message_is_signal(m, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
2298 const char *path, *result, *unit;
2302 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
2304 ret = set_remove(d->set, (char*) path);
2310 if (!isempty(result))
2311 d->result = strdup(result);
2314 d->name = strdup(unit);
2319 r = sd_bus_message_read(m, "uos", &id, &path, &result);
2321 ret = set_remove(d->set, (char*) path);
2328 d->result = strdup(result);
2334 bus_log_parse_error(r);
2340 static int enable_wait_for_jobs(sd_bus *bus) {
2345 r = sd_bus_add_match(
2349 "sender='org.freedesktop.systemd1',"
2350 "interface='org.freedesktop.systemd1.Manager',"
2351 "member='JobRemoved',"
2352 "path='/org/freedesktop/systemd1'",
2355 log_error("Failed to add match");
2359 /* This is slightly dirty, since we don't undo the match registrations. */
2363 static int bus_process_wait(sd_bus *bus) {
2367 r = sd_bus_process(bus, NULL);
2372 r = sd_bus_wait(bus, (uint64_t) -1);
2378 static int check_wait_response(WaitData *d) {
2384 if (streq(d->result, "timeout"))
2385 log_error("Job for %s timed out.", strna(d->name));
2386 else if (streq(d->result, "canceled"))
2387 log_error("Job for %s canceled.", strna(d->name));
2388 else if (streq(d->result, "dependency"))
2389 log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
2390 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
2394 quotes = chars_intersect(d->name, SHELL_NEED_QUOTES);
2396 log_error("Job for %s failed. See \"systemctl status %s%s%s\" and \"journalctl -xe\" for details.",
2398 quotes ? "'" : "", d->name, quotes ? "'" : "");
2400 log_error("Job failed. See \"journalctl -xe\" for details.");
2404 if (streq(d->result, "timeout"))
2406 else if (streq(d->result, "canceled"))
2408 else if (streq(d->result, "dependency"))
2410 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2416 static int wait_for_jobs(sd_bus *bus, Set *s) {
2417 _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
2418 WaitData d = { .set = s };
2424 q = sd_bus_add_filter(bus, &slot, wait_filter, &d);
2428 while (!set_isempty(s)) {
2429 q = bus_process_wait(bus);
2431 return log_error_errno(q, "Failed to wait for response: %m");
2434 q = check_wait_response(&d);
2435 /* Return the first error as it is most likely to be
2437 if (q < 0 && r == 0)
2439 log_debug("Got result %s/%s for job %s",
2440 strna(d.result), strerror(-q), strna(d.name));
2453 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2454 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2455 _cleanup_free_ char *n = NULL, *state = NULL;
2461 n = unit_name_mangle(name, MANGLE_NOGLOB);
2465 /* We don't use unit_dbus_path_from_name() directly since we
2466 * don't want to load the unit if it isn't loaded. */
2468 r = sd_bus_call_method(
2470 "org.freedesktop.systemd1",
2471 "/org/freedesktop/systemd1",
2472 "org.freedesktop.systemd1.Manager",
2483 r = sd_bus_message_read(reply, "o", &path);
2485 return bus_log_parse_error(r);
2487 r = sd_bus_get_property_string(
2489 "org.freedesktop.systemd1",
2491 "org.freedesktop.systemd1.Unit",
2504 return nulstr_contains(good_states, state);
2507 static int check_triggering_units(
2511 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2512 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2513 _cleanup_strv_free_ char **triggered_by = NULL;
2514 bool print_warning_label = true;
2518 n = unit_name_mangle(name, MANGLE_NOGLOB);
2522 path = unit_dbus_path_from_name(n);
2526 r = sd_bus_get_property_string(
2528 "org.freedesktop.systemd1",
2530 "org.freedesktop.systemd1.Unit",
2535 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2539 if (streq(state, "masked"))
2542 r = sd_bus_get_property_strv(
2544 "org.freedesktop.systemd1",
2546 "org.freedesktop.systemd1.Unit",
2551 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2555 STRV_FOREACH(i, triggered_by) {
2556 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2558 return log_error_errno(r, "Failed to check unit: %m");
2563 if (print_warning_label) {
2564 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2565 print_warning_label = false;
2568 log_warning(" %s", *i);
2574 static const struct {
2577 } unit_actions[] = {
2578 { "start", "StartUnit" },
2579 { "stop", "StopUnit" },
2580 { "condstop", "StopUnit" },
2581 { "reload", "ReloadUnit" },
2582 { "restart", "RestartUnit" },
2583 { "try-restart", "TryRestartUnit" },
2584 { "condrestart", "TryRestartUnit" },
2585 { "reload-or-restart", "ReloadOrRestartUnit" },
2586 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2587 { "condreload", "ReloadOrTryRestartUnit" },
2588 { "force-reload", "ReloadOrTryRestartUnit" }
2591 static const char *verb_to_method(const char *verb) {
2594 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2595 if (streq_ptr(unit_actions[i].verb, verb))
2596 return unit_actions[i].method;
2601 static const char *method_to_verb(const char *method) {
2604 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2605 if (streq_ptr(unit_actions[i].method, method))
2606 return unit_actions[i].verb;
2611 static int start_unit_one(
2616 sd_bus_error *error,
2619 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2628 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2630 r = sd_bus_message_new_method_call(
2633 "org.freedesktop.systemd1",
2634 "/org/freedesktop/systemd1",
2635 "org.freedesktop.systemd1.Manager",
2638 return bus_log_create_error(r);
2640 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2642 return bus_log_create_error(r);
2644 r = sd_bus_message_append(m, "ss", name, mode);
2646 return bus_log_create_error(r);
2648 r = sd_bus_call(bus, m, 0, error, &reply);
2652 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2653 /* There's always a fallback possible for
2654 * legacy actions. */
2655 return -EADDRNOTAVAIL;
2657 verb = method_to_verb(method);
2659 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2663 r = sd_bus_message_read(reply, "o", &path);
2665 return bus_log_parse_error(r);
2667 if (need_daemon_reload(bus, name) > 0)
2668 log_warning("Warning: Unit file of %s changed on disk, 'systemctl%s daemon-reload' recommended.",
2669 name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2678 log_debug("Adding %s to the set", p);
2679 r = set_consume(s, p);
2687 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2689 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2693 STRV_FOREACH(name, names) {
2697 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2699 t = unit_name_mangle(*name, MANGLE_GLOB);
2703 if (string_is_glob(t))
2704 r = strv_consume(&globs, t);
2706 r = strv_consume(&mangled, t);
2711 /* Query the manager only if any of the names are a glob, since
2712 * this is fairly expensive */
2713 if (!strv_isempty(globs)) {
2714 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2715 _cleanup_free_ UnitInfo *unit_infos = NULL;
2717 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2721 for (i = 0; i < r; i++)
2722 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2727 mangled = NULL; /* do not free */
2732 static const struct {
2736 } action_table[_ACTION_MAX] = {
2737 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2738 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2739 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2740 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2741 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
2742 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
2743 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
2744 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
2745 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2746 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2747 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2748 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2749 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2750 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2751 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2754 static enum action verb_to_action(const char *verb) {
2757 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2758 if (streq_ptr(action_table[i].verb, verb))
2761 return _ACTION_INVALID;
2764 static int start_unit(sd_bus *bus, char **args) {
2765 _cleanup_set_free_free_ Set *s = NULL;
2766 _cleanup_strv_free_ char **names = NULL;
2767 const char *method, *mode, *one_name, *suffix = NULL;
2773 ask_password_agent_open_if_enabled();
2775 if (arg_action == ACTION_SYSTEMCTL) {
2777 method = verb_to_method(args[0]);
2778 action = verb_to_action(args[0]);
2780 if (streq(args[0], "isolate")) {
2784 mode = action_table[action].mode ?: arg_job_mode;
2786 one_name = action_table[action].target;
2788 assert(arg_action < ELEMENTSOF(action_table));
2789 assert(action_table[arg_action].target);
2791 method = "StartUnit";
2793 mode = action_table[arg_action].mode;
2794 one_name = action_table[arg_action].target;
2798 names = strv_new(one_name, NULL);
2800 r = expand_names(bus, args + 1, suffix, &names);
2802 log_error_errno(r, "Failed to expand names: %m");
2805 if (!arg_no_block) {
2806 r = enable_wait_for_jobs(bus);
2808 return log_error_errno(r, "Could not watch jobs: %m");
2810 s = set_new(&string_hash_ops);
2815 STRV_FOREACH(name, names) {
2816 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2819 q = start_unit_one(bus, method, *name, mode, &error, s);
2820 if (r >= 0 && q < 0)
2821 r = translate_bus_error_to_exit_status(q, &error);
2824 if (!arg_no_block) {
2827 q = wait_for_jobs(bus, s);
2831 /* When stopping units, warn if they can still be triggered by
2832 * another active unit (socket, path, timer) */
2833 if (!arg_quiet && streq(method, "StopUnit"))
2834 STRV_FOREACH(name, names)
2835 check_triggering_units(bus, *name);
2841 /* Ask systemd-logind, which might grant access to unprivileged users
2842 * through PolicyKit */
2843 static int reboot_with_logind(sd_bus *bus, enum action a) {
2845 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2852 polkit_agent_open_if_enabled();
2860 case ACTION_POWEROFF:
2861 method = "PowerOff";
2864 case ACTION_SUSPEND:
2868 case ACTION_HIBERNATE:
2869 method = "Hibernate";
2872 case ACTION_HYBRID_SLEEP:
2873 method = "HybridSleep";
2880 r = sd_bus_call_method(
2882 "org.freedesktop.login1",
2883 "/org/freedesktop/login1",
2884 "org.freedesktop.login1.Manager",
2888 "b", arg_ask_password);
2890 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2898 static int check_inhibitors(sd_bus *bus, enum action a) {
2900 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2901 _cleanup_strv_free_ char **sessions = NULL;
2902 const char *what, *who, *why, *mode;
2911 if (arg_ignore_inhibitors || arg_force > 0)
2923 r = sd_bus_call_method(
2925 "org.freedesktop.login1",
2926 "/org/freedesktop/login1",
2927 "org.freedesktop.login1.Manager",
2933 /* If logind is not around, then there are no inhibitors... */
2936 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2938 return bus_log_parse_error(r);
2940 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2941 _cleanup_free_ char *comm = NULL, *user = NULL;
2942 _cleanup_strv_free_ char **sv = NULL;
2944 if (!streq(mode, "block"))
2947 sv = strv_split(what, ":");
2951 if (!strv_contains(sv,
2953 a == ACTION_POWEROFF ||
2954 a == ACTION_REBOOT ||
2955 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2958 get_process_comm(pid, &comm);
2959 user = uid_to_name(uid);
2961 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
2962 who, pid, strna(comm), strna(user), why);
2967 return bus_log_parse_error(r);
2969 r = sd_bus_message_exit_container(reply);
2971 return bus_log_parse_error(r);
2973 /* Check for current sessions */
2974 sd_get_sessions(&sessions);
2975 STRV_FOREACH(s, sessions) {
2976 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2978 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2981 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2984 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2987 sd_session_get_tty(*s, &tty);
2988 sd_session_get_seat(*s, &seat);
2989 sd_session_get_service(*s, &service);
2990 user = uid_to_name(uid);
2992 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2999 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3000 action_table[a].verb);
3008 static int start_special(sd_bus *bus, char **args) {
3014 a = verb_to_action(args[0]);
3016 r = check_inhibitors(bus, a);
3020 if (arg_force >= 2 && geteuid() != 0) {
3021 log_error("Must be root.");
3025 if (arg_force >= 2 &&
3026 (a == ACTION_HALT ||
3027 a == ACTION_POWEROFF ||
3028 a == ACTION_REBOOT))
3031 if (arg_force >= 1 &&
3032 (a == ACTION_HALT ||
3033 a == ACTION_POWEROFF ||
3034 a == ACTION_REBOOT ||
3035 a == ACTION_KEXEC ||
3037 return daemon_reload(bus, args);
3039 /* first try logind, to allow authentication with polkit */
3040 if (geteuid() != 0 &&
3041 (a == ACTION_POWEROFF ||
3042 a == ACTION_REBOOT ||
3043 a == ACTION_SUSPEND ||
3044 a == ACTION_HIBERNATE ||
3045 a == ACTION_HYBRID_SLEEP)) {
3046 r = reboot_with_logind(bus, a);
3051 r = start_unit(bus, args);
3052 if (r == EXIT_SUCCESS)
3058 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
3059 _cleanup_strv_free_ char **names = NULL;
3066 r = expand_names(bus, args, NULL, &names);
3068 return log_error_errno(r, "Failed to expand names: %m");
3070 STRV_FOREACH(name, names) {
3073 state = check_one_unit(bus, *name, good_states, arg_quiet);
3083 static int check_unit_active(sd_bus *bus, char **args) {
3084 /* According to LSB: 3, "program is not running" */
3085 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
3088 static int check_unit_failed(sd_bus *bus, char **args) {
3089 return check_unit_generic(bus, 1, "failed\0", args + 1);
3092 static int kill_unit(sd_bus *bus, char **args) {
3093 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3094 _cleanup_strv_free_ char **names = NULL;
3102 arg_kill_who = "all";
3104 r = expand_names(bus, args + 1, NULL, &names);
3106 log_error_errno(r, "Failed to expand names: %m");
3108 STRV_FOREACH(name, names) {
3109 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3111 q = sd_bus_message_new_method_call(
3114 "org.freedesktop.systemd1",
3115 "/org/freedesktop/systemd1",
3116 "org.freedesktop.systemd1.Manager",
3119 return bus_log_create_error(q);
3121 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
3123 return bus_log_create_error(q);
3125 q = sd_bus_message_append(m, "ssi", *names, arg_kill_who, arg_signal);
3127 return bus_log_create_error(q);
3129 q = sd_bus_call(bus, m, 0, &error, NULL);
3131 log_error("Failed to kill unit %s: %s", *names, bus_error_message(&error, q));
3140 typedef struct ExecStatusInfo {
3148 usec_t start_timestamp;
3149 usec_t exit_timestamp;
3154 LIST_FIELDS(struct ExecStatusInfo, exec);
3157 static void exec_status_info_free(ExecStatusInfo *i) {
3166 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3167 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3170 int32_t code, status;
3176 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3178 return bus_log_parse_error(r);
3182 r = sd_bus_message_read(m, "s", &path);
3184 return bus_log_parse_error(r);
3186 i->path = strdup(path);
3190 r = sd_bus_message_read_strv(m, &i->argv);
3192 return bus_log_parse_error(r);
3194 r = sd_bus_message_read(m,
3197 &start_timestamp, &start_timestamp_monotonic,
3198 &exit_timestamp, &exit_timestamp_monotonic,
3202 return bus_log_parse_error(r);
3205 i->start_timestamp = (usec_t) start_timestamp;
3206 i->exit_timestamp = (usec_t) exit_timestamp;
3207 i->pid = (pid_t) pid;
3211 r = sd_bus_message_exit_container(m);
3213 return bus_log_parse_error(r);
3218 typedef struct UnitStatusInfo {
3220 const char *load_state;
3221 const char *active_state;
3222 const char *sub_state;
3223 const char *unit_file_state;
3224 const char *unit_file_preset;
3226 const char *description;
3227 const char *following;
3229 char **documentation;
3231 const char *fragment_path;
3232 const char *source_path;
3233 const char *control_group;
3235 char **dropin_paths;
3237 const char *load_error;
3240 usec_t inactive_exit_timestamp;
3241 usec_t inactive_exit_timestamp_monotonic;
3242 usec_t active_enter_timestamp;
3243 usec_t active_exit_timestamp;
3244 usec_t inactive_enter_timestamp;
3246 bool need_daemon_reload;
3251 const char *status_text;
3252 const char *pid_file;
3256 usec_t start_timestamp;
3257 usec_t exit_timestamp;
3259 int exit_code, exit_status;
3261 usec_t condition_timestamp;
3262 bool condition_result;
3263 bool failed_condition_trigger;
3264 bool failed_condition_negate;
3265 const char *failed_condition;
3266 const char *failed_condition_parameter;
3268 usec_t assert_timestamp;
3270 bool failed_assert_trigger;
3271 bool failed_assert_negate;
3272 const char *failed_assert;
3273 const char *failed_assert_parameter;
3276 unsigned n_accepted;
3277 unsigned n_connections;
3280 /* Pairs of type, path */
3284 const char *sysfs_path;
3286 /* Mount, Automount */
3292 LIST_HEAD(ExecStatusInfo, exec);
3295 static void print_status_info(
3300 const char *active_on, *active_off, *on, *off, *ss;
3302 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3303 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3306 arg_all * OUTPUT_SHOW_ALL |
3307 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
3308 on_tty() * OUTPUT_COLOR |
3309 !arg_quiet * OUTPUT_WARN_CUTOFF |
3310 arg_full * OUTPUT_FULL_WIDTH;
3315 /* This shows pretty information about a unit. See
3316 * print_property() for a low-level property printer */
3318 if (streq_ptr(i->active_state, "failed")) {
3319 active_on = ansi_highlight_red();
3320 active_off = ansi_highlight_off();
3321 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3322 active_on = ansi_highlight_green();
3323 active_off = ansi_highlight_off();
3325 active_on = active_off = "";
3327 printf("%s%s%s %s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3329 if (i->description && !streq_ptr(i->id, i->description))
3330 printf(" - %s", i->description);
3335 printf(" Follow: unit currently follows state of %s\n", i->following);
3337 if (streq_ptr(i->load_state, "error")) {
3338 on = ansi_highlight_red();
3339 off = ansi_highlight_off();
3343 path = i->source_path ? i->source_path : i->fragment_path;
3346 printf(" Loaded: %s%s%s (Reason: %s)\n",
3347 on, strna(i->load_state), off, i->load_error);
3348 else if (path && !isempty(i->unit_file_state) && !isempty(i->unit_file_preset))
3349 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3350 on, strna(i->load_state), off, path, i->unit_file_state, i->unit_file_preset);
3351 else if (path && !isempty(i->unit_file_state))
3352 printf(" Loaded: %s%s%s (%s; %s)\n",
3353 on, strna(i->load_state), off, path, i->unit_file_state);
3355 printf(" Loaded: %s%s%s (%s)\n",
3356 on, strna(i->load_state), off, path);
3358 printf(" Loaded: %s%s%s\n",
3359 on, strna(i->load_state), off);
3361 if (!strv_isempty(i->dropin_paths)) {
3362 _cleanup_free_ char *dir = NULL;
3366 STRV_FOREACH(dropin, i->dropin_paths) {
3367 if (! dir || last) {
3368 printf(dir ? " " : " Drop-In: ");
3373 if (path_get_parent(*dropin, &dir) < 0) {
3378 printf("%s\n %s", dir,
3379 draw_special_char(DRAW_TREE_RIGHT));
3382 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3384 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3388 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3390 printf(" Active: %s%s (%s)%s",
3391 active_on, strna(i->active_state), ss, active_off);
3393 printf(" Active: %s%s%s",
3394 active_on, strna(i->active_state), active_off);
3396 if (!isempty(i->result) && !streq(i->result, "success"))
3397 printf(" (Result: %s)", i->result);
3399 timestamp = (streq_ptr(i->active_state, "active") ||
3400 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
3401 (streq_ptr(i->active_state, "inactive") ||
3402 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
3403 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
3404 i->active_exit_timestamp;
3406 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3407 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3410 printf(" since %s; %s\n", s2, s1);
3412 printf(" since %s\n", s2);
3416 if (!i->condition_result && i->condition_timestamp > 0) {
3417 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3418 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3420 printf("Condition: start %scondition failed%s at %s%s%s\n",
3421 ansi_highlight_yellow(), ansi_highlight_off(),
3422 s2, s1 ? "; " : "", s1 ? s1 : "");
3423 if (i->failed_condition_trigger)
3424 printf(" none of the trigger conditions were met\n");
3425 else if (i->failed_condition)
3426 printf(" %s=%s%s was not met\n",
3427 i->failed_condition,
3428 i->failed_condition_negate ? "!" : "",
3429 i->failed_condition_parameter);
3432 if (!i->assert_result && i->assert_timestamp > 0) {
3433 s1 = format_timestamp_relative(since1, sizeof(since1), i->assert_timestamp);
3434 s2 = format_timestamp(since2, sizeof(since2), i->assert_timestamp);
3436 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3437 ansi_highlight_red(), ansi_highlight_off(),
3438 s2, s1 ? "; " : "", s1 ? s1 : "");
3439 if (i->failed_assert_trigger)
3440 printf(" none of the trigger assertions were met\n");
3441 else if (i->failed_assert)
3442 printf(" %s=%s%s was not met\n",
3444 i->failed_assert_negate ? "!" : "",
3445 i->failed_assert_parameter);
3449 printf(" Device: %s\n", i->sysfs_path);
3451 printf(" Where: %s\n", i->where);
3453 printf(" What: %s\n", i->what);
3455 STRV_FOREACH(t, i->documentation)
3456 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3458 STRV_FOREACH_PAIR(t, t2, i->listen)
3459 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3462 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3464 LIST_FOREACH(exec, p, i->exec) {
3465 _cleanup_free_ char *argv = NULL;
3468 /* Only show exited processes here */
3472 argv = strv_join(p->argv, " ");
3473 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
3475 good = is_clean_exit_lsb(p->code, p->status, NULL);
3477 on = ansi_highlight_red();
3478 off = ansi_highlight_off();
3482 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3484 if (p->code == CLD_EXITED) {
3487 printf("status=%i", p->status);
3489 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3494 printf("signal=%s", signal_to_string(p->status));
3496 printf(")%s\n", off);
3498 if (i->main_pid == p->pid &&
3499 i->start_timestamp == p->start_timestamp &&
3500 i->exit_timestamp == p->start_timestamp)
3501 /* Let's not show this twice */
3504 if (p->pid == i->control_pid)
3508 if (i->main_pid > 0 || i->control_pid > 0) {
3509 if (i->main_pid > 0) {
3510 printf(" Main PID: "PID_FMT, i->main_pid);
3513 _cleanup_free_ char *comm = NULL;
3514 get_process_comm(i->main_pid, &comm);
3516 printf(" (%s)", comm);
3517 } else if (i->exit_code > 0) {
3518 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3520 if (i->exit_code == CLD_EXITED) {
3523 printf("status=%i", i->exit_status);
3525 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3530 printf("signal=%s", signal_to_string(i->exit_status));
3534 if (i->control_pid > 0)
3538 if (i->control_pid > 0) {
3539 _cleanup_free_ char *c = NULL;
3541 printf(" %8s: "PID_FMT, i->main_pid ? "" : " Control", i->control_pid);
3543 get_process_comm(i->control_pid, &c);
3552 printf(" Status: \"%s\"\n", i->status_text);
3553 if (i->status_errno > 0)
3554 printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
3556 if (i->control_group &&
3557 (i->main_pid > 0 || i->control_pid > 0 ||
3558 ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_CONTAINER) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3561 printf(" CGroup: %s\n", i->control_group);
3563 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
3566 static const char prefix[] = " ";
3569 if (c > sizeof(prefix) - 1)
3570 c -= sizeof(prefix) - 1;
3574 if (i->main_pid > 0)
3575 extra[k++] = i->main_pid;
3577 if (i->control_pid > 0)
3578 extra[k++] = i->control_pid;
3580 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, flags);
3584 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3585 show_journal_by_unit(stdout,
3589 i->inactive_exit_timestamp_monotonic,
3592 flags | OUTPUT_BEGIN_NEWLINE,
3593 arg_scope == UNIT_FILE_SYSTEM,
3597 if (i->need_daemon_reload)
3598 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
3599 ansi_highlight_red(),
3600 ansi_highlight_off(),
3601 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
3604 static void show_unit_help(UnitStatusInfo *i) {
3609 if (!i->documentation) {
3610 log_info("Documentation for %s not known.", i->id);
3614 STRV_FOREACH(p, i->documentation)
3615 if (startswith(*p, "man:"))
3616 show_man_page(*p + 4, false);
3618 log_info("Can't show: %s", *p);
3621 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3628 switch (contents[0]) {
3630 case SD_BUS_TYPE_STRING: {
3633 r = sd_bus_message_read(m, "s", &s);
3635 return bus_log_parse_error(r);
3638 if (streq(name, "Id"))
3640 else if (streq(name, "LoadState"))
3642 else if (streq(name, "ActiveState"))
3643 i->active_state = s;
3644 else if (streq(name, "SubState"))
3646 else if (streq(name, "Description"))
3648 else if (streq(name, "FragmentPath"))
3649 i->fragment_path = s;
3650 else if (streq(name, "SourcePath"))
3653 else if (streq(name, "DefaultControlGroup")) {
3655 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3657 i->control_group = e;
3660 else if (streq(name, "ControlGroup"))
3661 i->control_group = s;
3662 else if (streq(name, "StatusText"))
3664 else if (streq(name, "PIDFile"))
3666 else if (streq(name, "SysFSPath"))
3668 else if (streq(name, "Where"))
3670 else if (streq(name, "What"))
3672 else if (streq(name, "Following"))
3674 else if (streq(name, "UnitFileState"))
3675 i->unit_file_state = s;
3676 else if (streq(name, "UnitFilePreset"))
3677 i->unit_file_preset = s;
3678 else if (streq(name, "Result"))
3685 case SD_BUS_TYPE_BOOLEAN: {
3688 r = sd_bus_message_read(m, "b", &b);
3690 return bus_log_parse_error(r);
3692 if (streq(name, "Accept"))
3694 else if (streq(name, "NeedDaemonReload"))
3695 i->need_daemon_reload = b;
3696 else if (streq(name, "ConditionResult"))
3697 i->condition_result = b;
3698 else if (streq(name, "AssertResult"))
3699 i->assert_result = b;
3704 case SD_BUS_TYPE_UINT32: {
3707 r = sd_bus_message_read(m, "u", &u);
3709 return bus_log_parse_error(r);
3711 if (streq(name, "MainPID")) {
3713 i->main_pid = (pid_t) u;
3716 } else if (streq(name, "ControlPID"))
3717 i->control_pid = (pid_t) u;
3718 else if (streq(name, "ExecMainPID")) {
3720 i->main_pid = (pid_t) u;
3721 } else if (streq(name, "NAccepted"))
3723 else if (streq(name, "NConnections"))
3724 i->n_connections = u;
3729 case SD_BUS_TYPE_INT32: {
3732 r = sd_bus_message_read(m, "i", &j);
3734 return bus_log_parse_error(r);
3736 if (streq(name, "ExecMainCode"))
3737 i->exit_code = (int) j;
3738 else if (streq(name, "ExecMainStatus"))
3739 i->exit_status = (int) j;
3740 else if (streq(name, "StatusErrno"))
3741 i->status_errno = (int) j;
3746 case SD_BUS_TYPE_UINT64: {
3749 r = sd_bus_message_read(m, "t", &u);
3751 return bus_log_parse_error(r);
3753 if (streq(name, "ExecMainStartTimestamp"))
3754 i->start_timestamp = (usec_t) u;
3755 else if (streq(name, "ExecMainExitTimestamp"))
3756 i->exit_timestamp = (usec_t) u;
3757 else if (streq(name, "ActiveEnterTimestamp"))
3758 i->active_enter_timestamp = (usec_t) u;
3759 else if (streq(name, "InactiveEnterTimestamp"))
3760 i->inactive_enter_timestamp = (usec_t) u;
3761 else if (streq(name, "InactiveExitTimestamp"))
3762 i->inactive_exit_timestamp = (usec_t) u;
3763 else if (streq(name, "InactiveExitTimestampMonotonic"))
3764 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3765 else if (streq(name, "ActiveExitTimestamp"))
3766 i->active_exit_timestamp = (usec_t) u;
3767 else if (streq(name, "ConditionTimestamp"))
3768 i->condition_timestamp = (usec_t) u;
3769 else if (streq(name, "AssertTimestamp"))
3770 i->assert_timestamp = (usec_t) u;
3775 case SD_BUS_TYPE_ARRAY:
3777 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3778 _cleanup_free_ ExecStatusInfo *info = NULL;
3780 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3782 return bus_log_parse_error(r);
3784 info = new0(ExecStatusInfo, 1);
3788 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3790 info->name = strdup(name);
3794 LIST_PREPEND(exec, i->exec, info);
3796 info = new0(ExecStatusInfo, 1);
3802 return bus_log_parse_error(r);
3804 r = sd_bus_message_exit_container(m);
3806 return bus_log_parse_error(r);
3810 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3811 const char *type, *path;
3813 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3815 return bus_log_parse_error(r);
3817 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3819 r = strv_extend(&i->listen, type);
3823 r = strv_extend(&i->listen, path);
3828 return bus_log_parse_error(r);
3830 r = sd_bus_message_exit_container(m);
3832 return bus_log_parse_error(r);
3836 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3838 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3840 return bus_log_parse_error(r);
3842 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3844 r = sd_bus_message_read_strv(m, &i->documentation);
3846 return bus_log_parse_error(r);
3848 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3849 const char *cond, *param;
3850 int trigger, negate;
3853 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3855 return bus_log_parse_error(r);
3857 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3858 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3859 if (state < 0 && (!trigger || !i->failed_condition)) {
3860 i->failed_condition = cond;
3861 i->failed_condition_trigger = trigger;
3862 i->failed_condition_negate = negate;
3863 i->failed_condition_parameter = param;
3867 return bus_log_parse_error(r);
3869 r = sd_bus_message_exit_container(m);
3871 return bus_log_parse_error(r);
3873 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Asserts")) {
3874 const char *cond, *param;
3875 int trigger, negate;
3878 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3880 return bus_log_parse_error(r);
3882 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3883 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3884 if (state < 0 && (!trigger || !i->failed_assert)) {
3885 i->failed_assert = cond;
3886 i->failed_assert_trigger = trigger;
3887 i->failed_assert_negate = negate;
3888 i->failed_assert_parameter = param;
3892 return bus_log_parse_error(r);
3894 r = sd_bus_message_exit_container(m);
3896 return bus_log_parse_error(r);
3903 case SD_BUS_TYPE_STRUCT_BEGIN:
3905 if (streq(name, "LoadError")) {
3906 const char *n, *message;
3908 r = sd_bus_message_read(m, "(ss)", &n, &message);
3910 return bus_log_parse_error(r);
3912 if (!isempty(message))
3913 i->load_error = message;
3926 r = sd_bus_message_skip(m, contents);
3928 return bus_log_parse_error(r);
3933 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3939 /* This is a low-level property printer, see
3940 * print_status_info() for the nicer output */
3942 if (arg_properties && !strv_find(arg_properties, name)) {
3943 /* skip what we didn't read */
3944 r = sd_bus_message_skip(m, contents);
3948 switch (contents[0]) {
3950 case SD_BUS_TYPE_STRUCT_BEGIN:
3952 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3955 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3957 return bus_log_parse_error(r);
3960 printf("%s=%"PRIu32"\n", name, u);
3962 printf("%s=\n", name);
3966 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3969 r = sd_bus_message_read(m, "(so)", &s, NULL);
3971 return bus_log_parse_error(r);
3973 if (arg_all || !isempty(s))
3974 printf("%s=%s\n", name, s);
3978 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3979 const char *a = NULL, *b = NULL;
3981 r = sd_bus_message_read(m, "(ss)", &a, &b);
3983 return bus_log_parse_error(r);
3985 if (arg_all || !isempty(a) || !isempty(b))
3986 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3989 } else if (streq_ptr(name, "SystemCallFilter")) {
3990 _cleanup_strv_free_ char **l = NULL;
3993 r = sd_bus_message_enter_container(m, 'r', "bas");
3995 return bus_log_parse_error(r);
3997 r = sd_bus_message_read(m, "b", &whitelist);
3999 return bus_log_parse_error(r);
4001 r = sd_bus_message_read_strv(m, &l);
4003 return bus_log_parse_error(r);
4005 r = sd_bus_message_exit_container(m);
4007 return bus_log_parse_error(r);
4009 if (arg_all || whitelist || !strv_isempty(l)) {
4013 fputs(name, stdout);
4019 STRV_FOREACH(i, l) {
4027 fputc('\n', stdout);
4035 case SD_BUS_TYPE_ARRAY:
4037 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
4041 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
4043 return bus_log_parse_error(r);
4045 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
4046 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
4049 return bus_log_parse_error(r);
4051 r = sd_bus_message_exit_container(m);
4053 return bus_log_parse_error(r);
4057 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
4058 const char *type, *path;
4060 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4062 return bus_log_parse_error(r);
4064 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4065 printf("%s=%s\n", type, path);
4067 return bus_log_parse_error(r);
4069 r = sd_bus_message_exit_container(m);
4071 return bus_log_parse_error(r);
4075 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
4076 const char *type, *path;
4078 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4080 return bus_log_parse_error(r);
4082 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4083 printf("Listen%s=%s\n", type, path);
4085 return bus_log_parse_error(r);
4087 r = sd_bus_message_exit_container(m);
4089 return bus_log_parse_error(r);
4093 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
4095 uint64_t value, next_elapse;
4097 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
4099 return bus_log_parse_error(r);
4101 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
4102 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
4104 printf("%s={ value=%s ; next_elapse=%s }\n",
4106 format_timespan(timespan1, sizeof(timespan1), value, 0),
4107 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
4110 return bus_log_parse_error(r);
4112 r = sd_bus_message_exit_container(m);
4114 return bus_log_parse_error(r);
4118 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
4119 ExecStatusInfo info = {};
4121 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
4123 return bus_log_parse_error(r);
4125 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
4126 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
4127 _cleanup_free_ char *tt;
4129 tt = strv_join(info.argv, " ");
4131 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid="PID_FMT" ; code=%s ; status=%i%s%s }\n",
4135 yes_no(info.ignore),
4136 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
4137 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
4139 sigchld_code_to_string(info.code),
4141 info.code == CLD_EXITED ? "" : "/",
4142 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
4145 strv_free(info.argv);
4149 r = sd_bus_message_exit_container(m);
4151 return bus_log_parse_error(r);
4155 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
4156 const char *path, *rwm;
4158 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4160 return bus_log_parse_error(r);
4162 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
4163 printf("%s=%s %s\n", name, strna(path), strna(rwm));
4165 return bus_log_parse_error(r);
4167 r = sd_bus_message_exit_container(m);
4169 return bus_log_parse_error(r);
4173 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
4177 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4179 return bus_log_parse_error(r);
4181 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4182 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
4184 return bus_log_parse_error(r);
4186 r = sd_bus_message_exit_container(m);
4188 return bus_log_parse_error(r);
4192 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
4196 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4198 return bus_log_parse_error(r);
4200 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4201 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
4203 return bus_log_parse_error(r);
4205 r = sd_bus_message_exit_container(m);
4207 return bus_log_parse_error(r);
4215 r = bus_print_property(name, m, arg_all);
4217 return bus_log_parse_error(r);
4220 r = sd_bus_message_skip(m, contents);
4222 return bus_log_parse_error(r);
4225 printf("%s=[unprintable]\n", name);
4231 static int show_one(
4235 bool show_properties,
4239 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4240 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4241 UnitStatusInfo info = {};
4248 log_debug("Showing one %s", path);
4250 r = sd_bus_call_method(
4252 "org.freedesktop.systemd1",
4254 "org.freedesktop.DBus.Properties",
4260 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4264 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4266 return bus_log_parse_error(r);
4273 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4274 const char *name, *contents;
4276 r = sd_bus_message_read(reply, "s", &name);
4278 return bus_log_parse_error(r);
4280 r = sd_bus_message_peek_type(reply, NULL, &contents);
4282 return bus_log_parse_error(r);
4284 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4286 return bus_log_parse_error(r);
4288 if (show_properties)
4289 r = print_property(name, reply, contents);
4291 r = status_property(name, reply, &info, contents);
4295 r = sd_bus_message_exit_container(reply);
4297 return bus_log_parse_error(r);
4299 r = sd_bus_message_exit_container(reply);
4301 return bus_log_parse_error(r);
4304 return bus_log_parse_error(r);
4306 r = sd_bus_message_exit_container(reply);
4308 return bus_log_parse_error(r);
4312 if (!show_properties) {
4313 if (streq(verb, "help"))
4314 show_unit_help(&info);
4316 print_status_info(&info, ellipsized);
4319 strv_free(info.documentation);
4320 strv_free(info.dropin_paths);
4321 strv_free(info.listen);
4323 if (!streq_ptr(info.active_state, "active") &&
4324 !streq_ptr(info.active_state, "reloading") &&
4325 streq(verb, "status")) {
4326 /* According to LSB: "program not running" */
4327 /* 0: program is running or service is OK
4328 * 1: program is dead and /run PID file exists
4329 * 2: program is dead and /run/lock lock file exists
4330 * 3: program is not running
4331 * 4: program or service status is unknown
4333 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4339 while ((p = info.exec)) {
4340 LIST_REMOVE(exec, info.exec, p);
4341 exec_status_info_free(p);
4347 static int get_unit_dbus_path_by_pid(
4352 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4353 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4357 r = sd_bus_call_method(
4359 "org.freedesktop.systemd1",
4360 "/org/freedesktop/systemd1",
4361 "org.freedesktop.systemd1.Manager",
4367 log_error("Failed to get unit for PID "PID_FMT": %s", pid, bus_error_message(&error, r));
4371 r = sd_bus_message_read(reply, "o", &u);
4373 return bus_log_parse_error(r);
4383 static int show_all(
4386 bool show_properties,
4390 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4391 _cleanup_free_ UnitInfo *unit_infos = NULL;
4396 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4400 pager_open_if_enabled();
4404 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4406 for (u = unit_infos; u < unit_infos + c; u++) {
4407 _cleanup_free_ char *p = NULL;
4409 p = unit_dbus_path_from_name(u->id);
4413 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4416 else if (r > 0 && ret == 0)
4423 static int show_system_status(sd_bus *bus) {
4424 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4425 _cleanup_free_ char *hn = NULL;
4426 struct machine_info mi = {};
4427 const char *on, *off;
4430 hn = gethostname_malloc();
4434 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4436 return log_error_errno(r, "Failed to read server status: %m");
4438 if (streq_ptr(mi.state, "degraded")) {
4439 on = ansi_highlight_red();
4440 off = ansi_highlight_off();
4441 } else if (!streq_ptr(mi.state, "running")) {
4442 on = ansi_highlight_yellow();
4443 off = ansi_highlight_off();
4447 printf("%s%s%s %s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4449 printf(" State: %s%s%s\n",
4450 on, strna(mi.state), off);
4452 printf(" Jobs: %u queued\n", mi.n_jobs);
4453 printf(" Failed: %u units\n", mi.n_failed_units);
4455 printf(" Since: %s; %s\n",
4456 format_timestamp(since2, sizeof(since2), mi.timestamp),
4457 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4459 printf(" CGroup: %s\n", mi.control_group ?: "/");
4460 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
4462 arg_all * OUTPUT_SHOW_ALL |
4463 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
4464 on_tty() * OUTPUT_COLOR |
4465 !arg_quiet * OUTPUT_WARN_CUTOFF |
4466 arg_full * OUTPUT_FULL_WIDTH;
4468 static const char prefix[] = " ";
4472 if (c > sizeof(prefix) - 1)
4473 c -= sizeof(prefix) - 1;
4477 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
4481 free(mi.control_group);
4486 static int show(sd_bus *bus, char **args) {
4487 bool show_properties, show_status, new_line = false;
4488 bool ellipsized = false;
4494 show_properties = streq(args[0], "show");
4495 show_status = streq(args[0], "status");
4497 if (show_properties)
4498 pager_open_if_enabled();
4500 /* If no argument is specified inspect the manager itself */
4502 if (show_properties && strv_length(args) <= 1)
4503 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4505 if (show_status && strv_length(args) <= 1) {
4507 pager_open_if_enabled();
4508 show_system_status(bus);
4512 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4514 _cleanup_free_ char **patterns = NULL;
4517 STRV_FOREACH(name, args + 1) {
4518 _cleanup_free_ char *unit = NULL;
4521 if (safe_atou32(*name, &id) < 0) {
4522 if (strv_push(&patterns, *name) < 0)
4526 } else if (show_properties) {
4527 /* Interpret as job id */
4528 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4532 /* Interpret as PID */
4533 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4540 r = show_one(args[0], bus, unit, show_properties,
4541 &new_line, &ellipsized);
4544 else if (r > 0 && ret == 0)
4548 if (!strv_isempty(patterns)) {
4549 _cleanup_strv_free_ char **names = NULL;
4551 r = expand_names(bus, patterns, NULL, &names);
4553 log_error_errno(r, "Failed to expand names: %m");
4555 STRV_FOREACH(name, names) {
4556 _cleanup_free_ char *unit;
4558 unit = unit_dbus_path_from_name(*name);
4562 r = show_one(args[0], bus, unit, show_properties,
4563 &new_line, &ellipsized);
4566 else if (r > 0 && ret == 0)
4572 if (ellipsized && !arg_quiet)
4573 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4578 static int cat(sd_bus *bus, char **args) {
4579 _cleanup_strv_free_ char **names = NULL;
4587 r = expand_names(bus, args + 1, NULL, &names);
4589 log_error_errno(r, "Failed to expand names: %m");
4591 pager_open_if_enabled();
4593 STRV_FOREACH(name, names) {
4594 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4595 _cleanup_strv_free_ char **dropin_paths = NULL;
4596 _cleanup_free_ char *fragment_path = NULL, *unit = NULL;
4599 unit = unit_dbus_path_from_name(*name);
4603 if (need_daemon_reload(bus, *name) > 0)
4604 log_warning("Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'.",
4605 *name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
4607 r = sd_bus_get_property_string(
4609 "org.freedesktop.systemd1",
4611 "org.freedesktop.systemd1.Unit",
4616 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
4620 r = sd_bus_get_property_strv(
4622 "org.freedesktop.systemd1",
4624 "org.freedesktop.systemd1.Unit",
4629 log_warning("Failed to get DropInPaths: %s", bus_error_message(&error, r));
4638 if (!isempty(fragment_path)) {
4639 printf("%s# %s%s\n",
4640 ansi_highlight_blue(),
4642 ansi_highlight_off());
4645 r = copy_file_fd(fragment_path, STDOUT_FILENO);
4647 log_warning_errno(r, "Failed to cat %s: %m", fragment_path);
4652 STRV_FOREACH(path, dropin_paths) {
4653 printf("%s%s# %s%s\n",
4654 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4655 ansi_highlight_blue(),
4657 ansi_highlight_off());
4660 r = copy_file_fd(*path, STDOUT_FILENO);
4662 log_warning_errno(r, "Failed to cat %s: %m", *path);
4668 return r < 0 ? r : 0;
4671 static int set_property(sd_bus *bus, char **args) {
4672 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4673 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4674 _cleanup_free_ char *n = NULL;
4678 r = sd_bus_message_new_method_call(
4681 "org.freedesktop.systemd1",
4682 "/org/freedesktop/systemd1",
4683 "org.freedesktop.systemd1.Manager",
4684 "SetUnitProperties");
4686 return bus_log_create_error(r);
4688 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4690 return bus_log_create_error(r);
4692 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4696 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4698 return bus_log_create_error(r);
4700 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4702 return bus_log_create_error(r);
4704 STRV_FOREACH(i, args + 2) {
4705 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4707 return bus_log_create_error(r);
4709 r = bus_append_unit_property_assignment(m, *i);
4713 r = sd_bus_message_close_container(m);
4715 return bus_log_create_error(r);
4718 r = sd_bus_message_close_container(m);
4720 return bus_log_create_error(r);
4722 r = sd_bus_call(bus, m, 0, &error, NULL);
4724 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4731 static int snapshot(sd_bus *bus, char **args) {
4732 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4733 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
4734 _cleanup_free_ char *n = NULL, *id = NULL;
4738 if (strv_length(args) > 1)
4739 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4745 r = sd_bus_message_new_method_call(
4748 "org.freedesktop.systemd1",
4749 "/org/freedesktop/systemd1",
4750 "org.freedesktop.systemd1.Manager",
4753 return bus_log_create_error(r);
4755 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4757 return bus_log_create_error(r);
4759 r = sd_bus_message_append(m, "sb", n, false);
4761 return bus_log_create_error(r);
4763 r = sd_bus_call(bus, m, 0, &error, &reply);
4765 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4769 r = sd_bus_message_read(reply, "o", &path);
4771 return bus_log_parse_error(r);
4773 r = sd_bus_get_property_string(
4775 "org.freedesktop.systemd1",
4777 "org.freedesktop.systemd1.Unit",
4782 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4792 static int delete_snapshot(sd_bus *bus, char **args) {
4793 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4794 _cleanup_strv_free_ char **names = NULL;
4800 r = expand_names(bus, args + 1, ".snapshot", &names);
4802 log_error_errno(r, "Failed to expand names: %m");
4804 STRV_FOREACH(name, names) {
4805 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4808 q = sd_bus_message_new_method_call(
4811 "org.freedesktop.systemd1",
4812 "/org/freedesktop/systemd1",
4813 "org.freedesktop.systemd1.Manager",
4816 return bus_log_create_error(q);
4818 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4820 return bus_log_create_error(q);
4822 q = sd_bus_message_append(m, "s", *name);
4824 return bus_log_create_error(q);
4826 q = sd_bus_call(bus, m, 0, &error, NULL);
4828 log_error("Failed to remove snapshot %s: %s", *name, bus_error_message(&error, q));
4837 static int daemon_reload(sd_bus *bus, char **args) {
4838 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4839 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4843 if (arg_action == ACTION_RELOAD)
4845 else if (arg_action == ACTION_REEXEC)
4846 method = "Reexecute";
4848 assert(arg_action == ACTION_SYSTEMCTL);
4851 streq(args[0], "clear-jobs") ||
4852 streq(args[0], "cancel") ? "ClearJobs" :
4853 streq(args[0], "daemon-reexec") ? "Reexecute" :
4854 streq(args[0], "reset-failed") ? "ResetFailed" :
4855 streq(args[0], "halt") ? "Halt" :
4856 streq(args[0], "poweroff") ? "PowerOff" :
4857 streq(args[0], "reboot") ? "Reboot" :
4858 streq(args[0], "kexec") ? "KExec" :
4859 streq(args[0], "exit") ? "Exit" :
4860 /* "daemon-reload" */ "Reload";
4863 r = sd_bus_message_new_method_call(
4866 "org.freedesktop.systemd1",
4867 "/org/freedesktop/systemd1",
4868 "org.freedesktop.systemd1.Manager",
4871 return bus_log_create_error(r);
4873 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4875 return bus_log_create_error(r);
4877 r = sd_bus_call(bus, m, 0, &error, NULL);
4878 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4879 /* There's always a fallback possible for
4880 * legacy actions. */
4882 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4883 /* On reexecution, we expect a disconnect, not a
4887 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4889 return r < 0 ? r : 0;
4892 static int reset_failed(sd_bus *bus, char **args) {
4893 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4894 _cleanup_strv_free_ char **names = NULL;
4898 if (strv_length(args) <= 1)
4899 return daemon_reload(bus, args);
4901 r = expand_names(bus, args + 1, NULL, &names);
4903 log_error_errno(r, "Failed to expand names: %m");
4905 STRV_FOREACH(name, names) {
4906 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4908 q = sd_bus_message_new_method_call(
4911 "org.freedesktop.systemd1",
4912 "/org/freedesktop/systemd1",
4913 "org.freedesktop.systemd1.Manager",
4916 return bus_log_create_error(q);
4918 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4920 return bus_log_create_error(q);
4922 q = sd_bus_message_append(m, "s", *name);
4924 return bus_log_create_error(q);
4926 q = sd_bus_call(bus, m, 0, &error, NULL);
4928 log_error("Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q));
4937 static int show_environment(sd_bus *bus, char **args) {
4938 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4939 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4943 pager_open_if_enabled();
4945 r = sd_bus_get_property(
4947 "org.freedesktop.systemd1",
4948 "/org/freedesktop/systemd1",
4949 "org.freedesktop.systemd1.Manager",
4955 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4959 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4961 return bus_log_parse_error(r);
4963 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4966 return bus_log_parse_error(r);
4968 r = sd_bus_message_exit_container(reply);
4970 return bus_log_parse_error(r);
4975 static int switch_root(sd_bus *bus, char **args) {
4976 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4977 _cleanup_free_ char *cmdline_init = NULL;
4978 const char *root, *init;
4982 l = strv_length(args);
4983 if (l < 2 || l > 3) {
4984 log_error("Wrong number of arguments.");
4993 r = parse_env_file("/proc/cmdline", WHITESPACE,
4994 "init", &cmdline_init,
4997 log_debug_errno(r, "Failed to parse /proc/cmdline: %m");
4999 init = cmdline_init;
5006 const char *root_systemd_path = NULL, *root_init_path = NULL;
5008 root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
5009 root_init_path = strappenda(root, "/", init);
5011 /* If the passed init is actually the same as the
5012 * systemd binary, then let's suppress it. */
5013 if (files_same(root_init_path, root_systemd_path) > 0)
5017 log_debug("Switching root - root: %s; init: %s", root, strna(init));
5019 r = sd_bus_call_method(
5021 "org.freedesktop.systemd1",
5022 "/org/freedesktop/systemd1",
5023 "org.freedesktop.systemd1.Manager",
5029 log_error("Failed to switch root: %s", bus_error_message(&error, r));
5036 static int set_environment(sd_bus *bus, char **args) {
5037 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5038 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
5045 method = streq(args[0], "set-environment")
5047 : "UnsetEnvironment";
5049 r = sd_bus_message_new_method_call(
5052 "org.freedesktop.systemd1",
5053 "/org/freedesktop/systemd1",
5054 "org.freedesktop.systemd1.Manager",
5057 return bus_log_create_error(r);
5059 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5061 return bus_log_create_error(r);
5063 r = sd_bus_message_append_strv(m, args + 1);
5065 return bus_log_create_error(r);
5067 r = sd_bus_call(bus, m, 0, &error, NULL);
5069 log_error("Failed to set environment: %s", bus_error_message(&error, r));
5076 static int import_environment(sd_bus *bus, char **args) {
5077 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5078 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
5084 r = sd_bus_message_new_method_call(
5087 "org.freedesktop.systemd1",
5088 "/org/freedesktop/systemd1",
5089 "org.freedesktop.systemd1.Manager",
5092 return bus_log_create_error(r);
5094 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5096 return bus_log_create_error(r);
5098 if (strv_isempty(args + 1))
5099 r = sd_bus_message_append_strv(m, environ);
5103 r = sd_bus_message_open_container(m, 'a', "s");
5105 return bus_log_create_error(r);
5107 STRV_FOREACH(a, args + 1) {
5109 if (!env_name_is_valid(*a)) {
5110 log_error("Not a valid environment variable name: %s", *a);
5114 STRV_FOREACH(b, environ) {
5117 eq = startswith(*b, *a);
5118 if (eq && *eq == '=') {
5120 r = sd_bus_message_append(m, "s", *b);
5122 return bus_log_create_error(r);
5129 r = sd_bus_message_close_container(m);
5132 return bus_log_create_error(r);
5134 r = sd_bus_call(bus, m, 0, &error, NULL);
5136 log_error("Failed to import environment: %s", bus_error_message(&error, r));
5143 static int enable_sysv_units(const char *verb, char **args) {
5146 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
5147 unsigned f = 1, t = 1;
5148 _cleanup_lookup_paths_free_ LookupPaths paths = {};
5150 if (arg_scope != UNIT_FILE_SYSTEM)
5153 if (!streq(verb, "enable") &&
5154 !streq(verb, "disable") &&
5155 !streq(verb, "is-enabled"))
5158 /* Processes all SysV units, and reshuffles the array so that
5159 * afterwards only the native units remain */
5161 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, arg_root, NULL, NULL, NULL);
5166 for (f = 0; args[f]; f++) {
5168 _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL;
5169 bool found_native = false, found_sysv;
5171 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
5179 if (!endswith(name, ".service"))
5182 if (path_is_absolute(name))
5185 STRV_FOREACH(k, paths.unit_path) {
5186 _cleanup_free_ char *path = NULL;
5188 path = path_join(arg_root, *k, name);
5192 found_native = access(path, F_OK) >= 0;
5200 p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name);
5204 p[strlen(p) - strlen(".service")] = 0;
5205 found_sysv = access(p, F_OK) >= 0;
5209 /* Mark this entry, so that we don't try enabling it as native unit */
5210 args[f] = (char*) "";
5212 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
5214 if (!isempty(arg_root))
5215 argv[c++] = q = strappend("--root=", arg_root);
5217 argv[c++] = basename(p);
5219 streq(verb, "enable") ? "on" :
5220 streq(verb, "disable") ? "off" : "--level=5";
5223 l = strv_join((char**)argv, " ");
5227 log_info("Executing %s", l);
5231 return log_error_errno(errno, "Failed to fork: %m");
5232 else if (pid == 0) {
5235 execv(argv[0], (char**) argv);
5236 _exit(EXIT_FAILURE);
5239 j = wait_for_terminate(pid, &status);
5241 log_error_errno(r, "Failed to wait for child: %m");
5245 if (status.si_code == CLD_EXITED) {
5246 if (streq(verb, "is-enabled")) {
5247 if (status.si_status == 0) {
5256 } else if (status.si_status != 0)
5262 /* Drop all SysV units */
5263 for (f = 0, t = 0; args[f]; f++) {
5265 if (isempty(args[f]))
5268 args[t++] = args[f];
5277 static int mangle_names(char **original_names, char ***mangled_names) {
5278 char **i, **l, **name;
5280 l = new(char*, strv_length(original_names) + 1);
5285 STRV_FOREACH(name, original_names) {
5287 /* When enabling units qualified path names are OK,
5288 * too, hence allow them explicitly. */
5293 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5309 static int enable_unit(sd_bus *bus, char **args) {
5310 _cleanup_strv_free_ char **names = NULL;
5311 const char *verb = args[0];
5312 UnitFileChange *changes = NULL;
5313 unsigned n_changes = 0;
5314 int carries_install_info = -1;
5320 r = mangle_names(args+1, &names);
5324 r = enable_sysv_units(verb, names);
5328 /* If the operation was fully executed by the SysV compat,
5329 * let's finish early */
5330 if (strv_isempty(names))
5333 if (!bus || avoid_bus()) {
5334 if (streq(verb, "enable")) {
5335 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5336 carries_install_info = r;
5337 } else if (streq(verb, "disable"))
5338 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5339 else if (streq(verb, "reenable")) {
5340 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5341 carries_install_info = r;
5342 } else if (streq(verb, "link"))
5343 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5344 else if (streq(verb, "preset")) {
5345 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_preset_mode, arg_force, &changes, &n_changes);
5346 carries_install_info = r;
5347 } else if (streq(verb, "mask"))
5348 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5349 else if (streq(verb, "unmask"))
5350 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5352 assert_not_reached("Unknown verb");
5355 log_error_errno(r, "Operation failed: %m");
5360 dump_unit_file_changes(changes, n_changes);
5364 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5365 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5366 int expect_carries_install_info = false;
5367 bool send_force = true, send_preset_mode = false;
5370 if (streq(verb, "enable")) {
5371 method = "EnableUnitFiles";
5372 expect_carries_install_info = true;
5373 } else if (streq(verb, "disable")) {
5374 method = "DisableUnitFiles";
5376 } else if (streq(verb, "reenable")) {
5377 method = "ReenableUnitFiles";
5378 expect_carries_install_info = true;
5379 } else if (streq(verb, "link"))
5380 method = "LinkUnitFiles";
5381 else if (streq(verb, "preset")) {
5383 if (arg_preset_mode != UNIT_FILE_PRESET_FULL) {
5384 method = "PresetUnitFilesWithMode";
5385 send_preset_mode = true;
5387 method = "PresetUnitFiles";
5389 expect_carries_install_info = true;
5390 } else if (streq(verb, "mask"))
5391 method = "MaskUnitFiles";
5392 else if (streq(verb, "unmask")) {
5393 method = "UnmaskUnitFiles";
5396 assert_not_reached("Unknown verb");
5398 r = sd_bus_message_new_method_call(
5401 "org.freedesktop.systemd1",
5402 "/org/freedesktop/systemd1",
5403 "org.freedesktop.systemd1.Manager",
5406 return bus_log_create_error(r);
5408 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5410 return bus_log_create_error(r);
5412 r = sd_bus_message_append_strv(m, names);
5414 return bus_log_create_error(r);
5416 if (send_preset_mode) {
5417 r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode));
5419 return bus_log_create_error(r);
5422 r = sd_bus_message_append(m, "b", arg_runtime);
5424 return bus_log_create_error(r);
5427 r = sd_bus_message_append(m, "b", arg_force);
5429 return bus_log_create_error(r);
5432 r = sd_bus_call(bus, m, 0, &error, &reply);
5434 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5438 if (expect_carries_install_info) {
5439 r = sd_bus_message_read(reply, "b", &carries_install_info);
5441 return bus_log_parse_error(r);
5444 r = deserialize_and_dump_unit_file_changes(reply);
5448 /* Try to reload if enabled */
5450 r = daemon_reload(bus, args);
5455 if (carries_install_info == 0)
5456 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5457 "using systemctl.\n"
5458 "Possible reasons for having this kind of units are:\n"
5459 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5460 " .wants/ or .requires/ directory.\n"
5461 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5462 " a requirement dependency on it.\n"
5463 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5464 " D-Bus, udev, scripted systemctl call, ...).\n");
5467 unit_file_changes_free(changes, n_changes);
5472 static int add_dependency(sd_bus *bus, char **args) {
5473 _cleanup_strv_free_ char **names = NULL;
5474 _cleanup_free_ char *target = NULL;
5475 const char *verb = args[0];
5482 target = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
5486 r = mangle_names(args+2, &names);
5490 if (streq(verb, "add-wants"))
5492 else if (streq(verb, "add-requires"))
5493 dep = UNIT_REQUIRES;
5495 assert_not_reached("Unknown verb");
5497 if (!bus || avoid_bus()) {
5498 UnitFileChange *changes = NULL;
5499 unsigned n_changes = 0;
5501 r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes);
5504 return log_error_errno(r, "Can't add dependency: %m");
5507 dump_unit_file_changes(changes, n_changes);
5509 unit_file_changes_free(changes, n_changes);
5512 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5513 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5515 r = sd_bus_message_new_method_call(
5518 "org.freedesktop.systemd1",
5519 "/org/freedesktop/systemd1",
5520 "org.freedesktop.systemd1.Manager",
5521 "AddDependencyUnitFiles");
5523 return bus_log_create_error(r);
5525 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5527 return bus_log_create_error(r);
5529 r = sd_bus_message_append_strv(m, names);
5531 return bus_log_create_error(r);
5533 r = sd_bus_message_append(m, "ssbb", target, unit_dependency_to_string(dep), arg_runtime, arg_force);
5535 return bus_log_create_error(r);
5537 r = sd_bus_call(bus, m, 0, &error, &reply);
5539 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5543 r = deserialize_and_dump_unit_file_changes(reply);
5548 r = daemon_reload(bus, args);
5556 static int preset_all(sd_bus *bus, char **args) {
5557 UnitFileChange *changes = NULL;
5558 unsigned n_changes = 0;
5561 if (!bus || avoid_bus()) {
5563 r = unit_file_preset_all(arg_scope, arg_runtime, arg_root, arg_preset_mode, arg_force, &changes, &n_changes);
5565 log_error_errno(r, "Operation failed: %m");
5570 dump_unit_file_changes(changes, n_changes);
5575 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
5576 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5578 r = sd_bus_message_new_method_call(
5581 "org.freedesktop.systemd1",
5582 "/org/freedesktop/systemd1",
5583 "org.freedesktop.systemd1.Manager",
5584 "PresetAllUnitFiles");
5586 return bus_log_create_error(r);
5588 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5590 return bus_log_create_error(r);
5592 r = sd_bus_message_append(
5595 unit_file_preset_mode_to_string(arg_preset_mode),
5599 return bus_log_create_error(r);
5601 r = sd_bus_call(bus, m, 0, &error, &reply);
5603 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5607 r = deserialize_and_dump_unit_file_changes(reply);
5612 r = daemon_reload(bus, args);
5618 unit_file_changes_free(changes, n_changes);
5623 static int unit_is_enabled(sd_bus *bus, char **args) {
5625 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5626 _cleanup_strv_free_ char **names = NULL;
5631 r = mangle_names(args+1, &names);
5635 r = enable_sysv_units(args[0], names);
5641 if (!bus || avoid_bus()) {
5643 STRV_FOREACH(name, names) {
5644 UnitFileState state;
5646 state = unit_file_get_state(arg_scope, arg_root, *name);
5648 return log_error_errno(state, "Failed to get unit file state for %s: %m", *name);
5650 if (state == UNIT_FILE_ENABLED ||
5651 state == UNIT_FILE_ENABLED_RUNTIME ||
5652 state == UNIT_FILE_STATIC ||
5653 state == UNIT_FILE_INDIRECT)
5657 puts(unit_file_state_to_string(state));
5661 STRV_FOREACH(name, names) {
5662 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5665 r = sd_bus_call_method(
5667 "org.freedesktop.systemd1",
5668 "/org/freedesktop/systemd1",
5669 "org.freedesktop.systemd1.Manager",
5675 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5679 r = sd_bus_message_read(reply, "s", &s);
5681 return bus_log_parse_error(r);
5683 if (STR_IN_SET(s, "enabled", "enabled-runtime", "static", "indirect"))
5694 static int is_system_running(sd_bus *bus, char **args) {
5695 _cleanup_free_ char *state = NULL;
5698 r = sd_bus_get_property_string(
5700 "org.freedesktop.systemd1",
5701 "/org/freedesktop/systemd1",
5702 "org.freedesktop.systemd1.Manager",
5715 return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE;
5718 static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **unit_path) {
5725 STRV_FOREACH(p, lp->unit_path) {
5728 path = path_join(arg_root, *p, unit_name);
5732 if (access(path, F_OK) == 0) {
5743 static int create_edit_temp_file(const char *new_path, const char *original_path, char **ret_tmp_fn) {
5748 assert(original_path);
5751 t = tempfn_random(new_path);
5755 r = mkdir_parents(new_path, 0755);
5757 return log_error_errno(r, "Failed to create directories for %s: %m", new_path);
5759 r = copy_file(original_path, t, 0, 0644);
5763 log_error_errno(r, "Failed to create temporary file %s: %m", t);
5768 log_error_errno(r, "Failed to copy %s to %s: %m", original_path, t);
5778 static int get_drop_in_to_edit(const char *unit_name, const char *user_home, const char *user_runtime, char **ret_path) {
5785 switch (arg_scope) {
5786 case UNIT_FILE_SYSTEM:
5787 tmp = strappenda(arg_runtime ? "/run/systemd/system/" : SYSTEM_CONFIG_UNIT_PATH "/", unit_name, ".d/override.conf");
5789 case UNIT_FILE_GLOBAL:
5790 tmp = strappenda(arg_runtime ? "/run/systemd/user/" : USER_CONFIG_UNIT_PATH "/", unit_name, ".d/override.conf");
5792 case UNIT_FILE_USER:
5794 assert(user_runtime);
5796 tmp = strappenda(arg_runtime ? user_runtime : user_home, "/", unit_name, ".d/override.conf");
5799 assert_not_reached("Invalid scope");
5802 tmp_new_path = path_join(arg_root, tmp, NULL);
5806 *ret_path = tmp_new_path;
5811 static int unit_file_create_drop_in(const char *unit_name, const char *user_home, const char *user_runtime, char **ret_new_path, char **ret_tmp_path) {
5817 assert(ret_new_path);
5818 assert(ret_tmp_path);
5820 r = get_drop_in_to_edit(unit_name, user_home, user_runtime, &tmp_new_path);
5824 r = create_edit_temp_file(tmp_new_path, tmp_new_path, &tmp_tmp_path);
5830 *ret_new_path = tmp_new_path;
5831 *ret_tmp_path = tmp_tmp_path;
5836 static bool unit_is_editable(const char *unit_name, const char *fragment_path, const char *user_home) {
5837 bool editable = true;
5838 const char *invalid_path;
5845 switch (arg_scope) {
5846 case UNIT_FILE_SYSTEM:
5847 if (path_startswith(fragment_path, "/etc/systemd/system")) {
5849 invalid_path = "/etc/systemd/system";
5850 } else if (path_startswith(fragment_path, SYSTEM_CONFIG_UNIT_PATH)) {
5852 invalid_path = SYSTEM_CONFIG_UNIT_PATH;
5855 case UNIT_FILE_GLOBAL:
5856 if (path_startswith(fragment_path, "/etc/systemd/user")) {
5858 invalid_path = "/etc/systemd/user";
5859 } else if (path_startswith(fragment_path, USER_CONFIG_UNIT_PATH)) {
5861 invalid_path = USER_CONFIG_UNIT_PATH;
5864 case UNIT_FILE_USER:
5867 if (path_startswith(fragment_path, "/etc/systemd/user")) {
5869 invalid_path = "/etc/systemd/user";
5870 } else if (path_startswith(fragment_path, USER_CONFIG_UNIT_PATH)) {
5872 invalid_path = USER_CONFIG_UNIT_PATH;
5873 } else if (path_startswith(fragment_path, user_home)) {
5875 invalid_path = user_home;
5879 assert_not_reached("Invalid scope");
5883 log_error("%s ignored: cannot temporarily edit units from %s", unit_name, invalid_path);
5888 static int get_copy_to_edit(const char *unit_name, const char *fragment_path, const char *user_home, const char *user_runtime, char **ret_path) {
5894 if (!unit_is_editable(unit_name, fragment_path, user_home))
5897 switch (arg_scope) {
5898 case UNIT_FILE_SYSTEM:
5899 tmp_new_path = path_join(arg_root, arg_runtime ? "/run/systemd/system/" : SYSTEM_CONFIG_UNIT_PATH, unit_name);
5901 case UNIT_FILE_GLOBAL:
5902 tmp_new_path = path_join(arg_root, arg_runtime ? "/run/systemd/user/" : USER_CONFIG_UNIT_PATH, unit_name);
5904 case UNIT_FILE_USER:
5906 assert(user_runtime);
5908 tmp_new_path = path_join(arg_root, arg_runtime ? user_runtime : user_home, unit_name);
5911 assert_not_reached("Invalid scope");
5916 *ret_path = tmp_new_path;
5921 static int unit_file_create_copy(const char *unit_name,
5922 const char *fragment_path,
5923 const char *user_home,
5924 const char *user_runtime,
5925 char **ret_new_path,
5926 char **ret_tmp_path) {
5931 assert(fragment_path);
5933 assert(ret_new_path);
5934 assert(ret_tmp_path);
5936 r = get_copy_to_edit(unit_name, fragment_path, user_home, user_runtime, &tmp_new_path);
5940 if (!path_equal(fragment_path, tmp_new_path) && access(tmp_new_path, F_OK) == 0) {
5943 r = ask_char(&response, "yn", "%s already exists, are you sure to overwrite it with %s? [(y)es, (n)o] ", tmp_new_path, fragment_path);
5948 if (response != 'y') {
5949 log_warning("%s ignored", unit_name);
5955 r = create_edit_temp_file(tmp_new_path, fragment_path, &tmp_tmp_path);
5957 log_error_errno(r, "Failed to create temporary file for %s: %m", tmp_new_path);
5962 *ret_new_path = tmp_new_path;
5963 *ret_tmp_path = tmp_tmp_path;
5968 static int run_editor(char **paths) {
5976 log_error_errno(errno, "Failed to fork: %m");
5982 char **backup_editors = STRV_MAKE("nano", "vim", "vi");
5984 char **tmp_path, **original_path, **p;
5988 argc = strv_length(paths)/2 + 1;
5989 args = newa(const char*, argc + 1);
5992 STRV_FOREACH_PAIR(original_path, tmp_path, paths) {
5993 args[i] = *tmp_path;
5998 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
5999 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
6000 * we try to execute well known editors
6002 editor = getenv("SYSTEMD_EDITOR");
6004 editor = getenv("EDITOR");
6006 editor = getenv("VISUAL");
6008 if (!isempty(editor)) {
6010 execvp(editor, (char* const*) args);
6013 STRV_FOREACH(p, backup_editors) {
6015 execvp(*p, (char* const*) args);
6016 /* We do not fail if the editor doesn't exist
6017 * because we want to try each one of them before
6020 if (errno != ENOENT) {
6021 log_error("Failed to execute %s: %m", editor);
6022 _exit(EXIT_FAILURE);
6026 log_error("Cannot edit unit(s): No editor available. Please set either SYSTEMD_EDITOR or EDITOR or VISUAL environment variable");
6027 _exit(EXIT_FAILURE);
6030 r = wait_for_terminate_and_warn("editor", pid, true);
6032 return log_error_errno(r, "Failed to wait for child: %m");
6037 static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
6038 _cleanup_free_ char *user_home = NULL;
6039 _cleanup_free_ char *user_runtime = NULL;
6046 if (arg_scope == UNIT_FILE_USER) {
6047 r = user_config_home(&user_home);
6051 log_error("Cannot edit units for the user instance: home directory unknown");
6055 r = user_runtime_dir(&user_runtime);
6059 log_error("Cannot edit units for the user instance: runtime directory unknown");
6064 if (!bus || avoid_bus()) {
6065 _cleanup_lookup_paths_free_ LookupPaths lp = {};
6067 /* If there is no bus, we try to find the units by testing each available directory
6068 * according to the scope.
6070 r = lookup_paths_init(&lp,
6071 arg_scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
6072 arg_scope == UNIT_FILE_USER,
6076 log_error_errno(r, "Failed get lookup paths: %m");
6080 STRV_FOREACH(name, names) {
6081 _cleanup_free_ char *path = NULL;
6082 char *new_path, *tmp_path;
6084 r = unit_file_find_path(&lp, *name, &path);
6088 log_warning("%s ignored: not found", *name);
6093 r = unit_file_create_copy(*name, path, user_home, user_runtime, &new_path, &tmp_path);
6095 r = unit_file_create_drop_in(*name, user_home, user_runtime, &new_path, &tmp_path);
6100 r = strv_push(paths, new_path);
6104 r = strv_push(paths, tmp_path);
6109 STRV_FOREACH(name, names) {
6110 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
6111 _cleanup_free_ char *fragment_path = NULL;
6112 _cleanup_free_ char *unit = NULL;
6113 char *new_path, *tmp_path;
6115 unit = unit_dbus_path_from_name(*name);
6119 if (need_daemon_reload(bus, *name) > 0) {
6120 log_warning("%s ignored: unit file changed on disk. Run 'systemctl%s daemon-reload'.",
6121 *name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
6125 r = sd_bus_get_property_string(
6127 "org.freedesktop.systemd1",
6129 "org.freedesktop.systemd1.Unit",
6134 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
6138 if (isempty(fragment_path)) {
6139 log_warning("%s ignored: not found", *name);
6144 r = unit_file_create_copy(*name, fragment_path, user_home, user_runtime, &new_path, &tmp_path);
6146 r = unit_file_create_drop_in(*name, user_home, user_runtime, &new_path, &tmp_path);
6150 r = strv_push(paths, new_path);
6154 r = strv_push(paths, tmp_path);
6163 static int edit(sd_bus *bus, char **args) {
6164 _cleanup_strv_free_ char **names = NULL;
6165 _cleanup_strv_free_ char **paths = NULL;
6166 char **original, **tmp;
6172 log_error("Cannot edit units if we are not on a tty");
6176 if (arg_transport != BUS_TRANSPORT_LOCAL) {
6177 log_error("Cannot remotely edit units");
6181 r = expand_names(bus, args + 1, NULL, &names);
6183 return log_error_errno(r, "Failed to expand names: %m");
6186 log_error("No unit name found by expanding names");
6190 r = find_paths_to_edit(bus, names, &paths);
6194 if (strv_isempty(paths)) {
6195 log_error("Cannot find any units to edit");
6199 r = run_editor(paths);
6203 STRV_FOREACH_PAIR(original, tmp, paths) {
6204 /* If the temporary file is empty we ignore it.
6205 * It's useful if the user wants to cancel its modification
6207 if (null_or_empty_path(*tmp)) {
6208 log_warning("Edition of %s canceled: temporary file empty", *original);
6211 r = rename(*tmp, *original);
6213 r = log_error_errno(errno, "Failed to rename %s to %s: %m", *tmp, *original);
6218 if (!arg_no_reload && bus && !avoid_bus())
6219 r = daemon_reload(bus, args);
6222 STRV_FOREACH_PAIR(original, tmp, paths)
6223 unlink_noerrno(*tmp);
6228 static void systemctl_help(void) {
6230 pager_open_if_enabled();
6232 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
6233 "Query or send control commands to the systemd manager.\n\n"
6234 " -h --help Show this help\n"
6235 " --version Show package version\n"
6236 " --system Connect to system manager\n"
6237 " --user Connect to user service manager\n"
6238 " -H --host=[USER@]HOST\n"
6239 " Operate on remote host\n"
6240 " -M --machine=CONTAINER\n"
6241 " Operate on local container\n"
6242 " -t --type=TYPE List only units of a particular type\n"
6243 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
6244 " -p --property=NAME Show only properties by this name\n"
6245 " -a --all Show all loaded units/properties, including dead/empty\n"
6246 " ones. To list all units installed on the system, use\n"
6247 " the 'list-unit-files' command instead.\n"
6248 " -l --full Don't ellipsize unit names on output\n"
6249 " -r --recursive Show unit list of host and local containers\n"
6250 " --reverse Show reverse dependencies with 'list-dependencies'\n"
6251 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
6252 " queueing a new job\n"
6253 " --show-types When showing sockets, explicitly show their type\n"
6254 " -i --ignore-inhibitors\n"
6255 " When shutting down or sleeping, ignore inhibitors\n"
6256 " --kill-who=WHO Who to send signal to\n"
6257 " -s --signal=SIGNAL Which signal to send\n"
6258 " -q --quiet Suppress output\n"
6259 " --no-block Do not wait until operation finished\n"
6260 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6261 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
6263 " --no-legend Do not print a legend (column headers and hints)\n"
6264 " --no-pager Do not pipe output into a pager\n"
6265 " --no-ask-password\n"
6266 " Do not ask for system passwords\n"
6267 " --global Enable/disable unit files globally\n"
6268 " --runtime Enable unit files only temporarily until next reboot\n"
6269 " -f --force When enabling unit files, override existing symlinks\n"
6270 " When shutting down, execute action immediately\n"
6271 " --preset-mode= Specifies whether fully apply presets, or only enable,\n"
6272 " or only disable\n"
6273 " --root=PATH Enable unit files in the specified root directory\n"
6274 " -n --lines=INTEGER Number of journal entries to show\n"
6275 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
6276 " verbose, export, json, json-pretty, json-sse, cat)\n"
6277 " --plain Print unit dependencies as a list instead of a tree\n\n"
6279 " list-units [PATTERN...] List loaded units\n"
6280 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
6281 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
6282 " start NAME... Start (activate) one or more units\n"
6283 " stop NAME... Stop (deactivate) one or more units\n"
6284 " reload NAME... Reload one or more units\n"
6285 " restart NAME... Start or restart one or more units\n"
6286 " try-restart NAME... Restart one or more units if active\n"
6287 " reload-or-restart NAME... Reload one or more units if possible,\n"
6288 " otherwise start or restart\n"
6289 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
6290 " otherwise restart if active\n"
6291 " isolate NAME Start one unit and stop all others\n"
6292 " kill NAME... Send signal to processes of a unit\n"
6293 " is-active PATTERN... Check whether units are active\n"
6294 " is-failed PATTERN... Check whether units are failed\n"
6295 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
6296 " show [PATTERN...|JOB...] Show properties of one or more\n"
6297 " units/jobs or the manager\n"
6298 " cat PATTERN... Show files and drop-ins of one or more units\n"
6299 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
6300 " help PATTERN...|PID... Show manual for one or more units\n"
6301 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
6303 " list-dependencies [NAME] Recursively show units which are required\n"
6304 " or wanted by this unit or by which this\n"
6305 " unit is required or wanted\n\n"
6306 "Unit File Commands:\n"
6307 " list-unit-files [PATTERN...] List installed unit files\n"
6308 " enable NAME... Enable one or more unit files\n"
6309 " disable NAME... Disable one or more unit files\n"
6310 " reenable NAME... Reenable one or more unit files\n"
6311 " preset NAME... Enable/disable one or more unit files\n"
6312 " based on preset configuration\n"
6313 " preset-all Enable/disable all unit files based on\n"
6314 " preset configuration\n"
6315 " is-enabled NAME... Check whether unit files are enabled\n\n"
6316 " mask NAME... Mask one or more units\n"
6317 " unmask NAME... Unmask one or more units\n"
6318 " link PATH... Link one or more units files into\n"
6319 " the search path\n"
6320 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6321 " on specified one or more units\n"
6322 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6323 " on specified one or more units\n"
6324 " get-default Get the name of the default target\n"
6325 " set-default NAME Set the default target\n"
6326 " edit NAME... Edit one or more unit files\n"
6328 "Machine Commands:\n"
6329 " list-machines [PATTERN...] List local containers and host\n\n"
6331 " list-jobs [PATTERN...] List jobs\n"
6332 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
6333 "Snapshot Commands:\n"
6334 " snapshot [NAME] Create a snapshot\n"
6335 " delete NAME... Remove one or more snapshots\n\n"
6336 "Environment Commands:\n"
6337 " show-environment Dump environment\n"
6338 " set-environment NAME=VALUE... Set one or more environment variables\n"
6339 " unset-environment NAME... Unset one or more environment variables\n"
6340 " import-environment NAME... Import all, one or more environment variables\n\n"
6341 "Manager Lifecycle Commands:\n"
6342 " daemon-reload Reload systemd manager configuration\n"
6343 " daemon-reexec Reexecute systemd manager\n\n"
6344 "System Commands:\n"
6345 " is-system-running Check whether system is fully running\n"
6346 " default Enter system default mode\n"
6347 " rescue Enter system rescue mode\n"
6348 " emergency Enter system emergency mode\n"
6349 " halt Shut down and halt the system\n"
6350 " poweroff Shut down and power-off the system\n"
6351 " reboot [ARG] Shut down and reboot the system\n"
6352 " kexec Shut down and reboot the system with kexec\n"
6353 " exit Request user instance exit\n"
6354 " switch-root ROOT [INIT] Change to a different root file system\n"
6355 " suspend Suspend the system\n"
6356 " hibernate Hibernate the system\n"
6357 " hybrid-sleep Hibernate and suspend the system\n",
6358 program_invocation_short_name);
6361 static void halt_help(void) {
6362 printf("%s [OPTIONS...]%s\n\n"
6363 "%s the system.\n\n"
6364 " --help Show this help\n"
6365 " --halt Halt the machine\n"
6366 " -p --poweroff Switch off the machine\n"
6367 " --reboot Reboot the machine\n"
6368 " -f --force Force immediate halt/power-off/reboot\n"
6369 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
6370 " -d --no-wtmp Don't write wtmp record\n"
6371 " --no-wall Don't send wall message before halt/power-off/reboot\n",
6372 program_invocation_short_name,
6373 arg_action == ACTION_REBOOT ? " [ARG]" : "",
6374 arg_action == ACTION_REBOOT ? "Reboot" :
6375 arg_action == ACTION_POWEROFF ? "Power off" :
6379 static void shutdown_help(void) {
6380 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
6381 "Shut down the system.\n\n"
6382 " --help Show this help\n"
6383 " -H --halt Halt the machine\n"
6384 " -P --poweroff Power-off the machine\n"
6385 " -r --reboot Reboot the machine\n"
6386 " -h Equivalent to --poweroff, overridden by --halt\n"
6387 " -k Don't halt/power-off/reboot, just send warnings\n"
6388 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6389 " -c Cancel a pending shutdown\n",
6390 program_invocation_short_name);
6393 static void telinit_help(void) {
6394 printf("%s [OPTIONS...] {COMMAND}\n\n"
6395 "Send control commands to the init daemon.\n\n"
6396 " --help Show this help\n"
6397 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
6399 " 0 Power-off the machine\n"
6400 " 6 Reboot the machine\n"
6401 " 2, 3, 4, 5 Start runlevelX.target unit\n"
6402 " 1, s, S Enter rescue mode\n"
6403 " q, Q Reload init daemon configuration\n"
6404 " u, U Reexecute init daemon\n",
6405 program_invocation_short_name);
6408 static void runlevel_help(void) {
6409 printf("%s [OPTIONS...]\n\n"
6410 "Prints the previous and current runlevel of the init system.\n\n"
6411 " --help Show this help\n",
6412 program_invocation_short_name);
6415 static void help_types(void) {
6420 puts("Available unit types:");
6421 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
6422 t = unit_type_to_string(i);
6428 static int systemctl_parse_argv(int argc, char *argv[]) {
6437 ARG_IGNORE_DEPENDENCIES,
6449 ARG_NO_ASK_PASSWORD,
6459 static const struct option options[] = {
6460 { "help", no_argument, NULL, 'h' },
6461 { "version", no_argument, NULL, ARG_VERSION },
6462 { "type", required_argument, NULL, 't' },
6463 { "property", required_argument, NULL, 'p' },
6464 { "all", no_argument, NULL, 'a' },
6465 { "reverse", no_argument, NULL, ARG_REVERSE },
6466 { "after", no_argument, NULL, ARG_AFTER },
6467 { "before", no_argument, NULL, ARG_BEFORE },
6468 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
6469 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
6470 { "full", no_argument, NULL, 'l' },
6471 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
6472 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
6473 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
6474 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
6475 { "ignore-inhibitors", no_argument, NULL, 'i' },
6476 { "user", no_argument, NULL, ARG_USER },
6477 { "system", no_argument, NULL, ARG_SYSTEM },
6478 { "global", no_argument, NULL, ARG_GLOBAL },
6479 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
6480 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
6481 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
6482 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6483 { "quiet", no_argument, NULL, 'q' },
6484 { "root", required_argument, NULL, ARG_ROOT },
6485 { "force", no_argument, NULL, ARG_FORCE },
6486 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
6487 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
6488 { "signal", required_argument, NULL, 's' },
6489 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
6490 { "host", required_argument, NULL, 'H' },
6491 { "machine", required_argument, NULL, 'M' },
6492 { "runtime", no_argument, NULL, ARG_RUNTIME },
6493 { "lines", required_argument, NULL, 'n' },
6494 { "output", required_argument, NULL, 'o' },
6495 { "plain", no_argument, NULL, ARG_PLAIN },
6496 { "state", required_argument, NULL, ARG_STATE },
6497 { "recursive", no_argument, NULL, 'r' },
6498 { "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
6507 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
6516 puts(PACKAGE_STRING);
6517 puts(SYSTEMD_FEATURES);
6521 const char *word, *state;
6524 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6525 _cleanup_free_ char *type;
6527 type = strndup(word, size);
6531 if (streq(type, "help")) {
6536 if (unit_type_from_string(type) >= 0) {
6537 if (strv_push(&arg_types, type))
6543 /* It's much nicer to use --state= for
6544 * load states, but let's support this
6545 * in --types= too for compatibility
6546 * with old versions */
6547 if (unit_load_state_from_string(optarg) >= 0) {
6548 if (strv_push(&arg_states, type) < 0)
6554 log_error("Unknown unit type or load state '%s'.", type);
6555 log_info("Use -t help to see a list of allowed values.");
6563 /* Make sure that if the empty property list
6564 was specified, we won't show any properties. */
6565 if (isempty(optarg) && !arg_properties) {
6566 arg_properties = new0(char*, 1);
6567 if (!arg_properties)
6570 const char *word, *state;
6573 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6576 prop = strndup(word, size);
6580 if (strv_consume(&arg_properties, prop) < 0)
6585 /* If the user asked for a particular
6586 * property, show it to him, even if it is
6598 arg_dependency = DEPENDENCY_REVERSE;
6602 arg_dependency = DEPENDENCY_AFTER;
6606 arg_dependency = DEPENDENCY_BEFORE;
6609 case ARG_SHOW_TYPES:
6610 arg_show_types = true;
6614 arg_job_mode = optarg;
6618 arg_job_mode = "fail";
6621 case ARG_IRREVERSIBLE:
6622 arg_job_mode = "replace-irreversibly";
6625 case ARG_IGNORE_DEPENDENCIES:
6626 arg_job_mode = "ignore-dependencies";
6630 arg_scope = UNIT_FILE_USER;
6634 arg_scope = UNIT_FILE_SYSTEM;
6638 arg_scope = UNIT_FILE_GLOBAL;
6642 arg_no_block = true;
6646 arg_no_legend = true;
6650 arg_no_pager = true;
6666 if (strv_extend(&arg_states, "failed") < 0)
6684 arg_no_reload = true;
6688 arg_kill_who = optarg;
6692 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
6693 log_error("Failed to parse signal string %s.", optarg);
6698 case ARG_NO_ASK_PASSWORD:
6699 arg_ask_password = false;
6703 arg_transport = BUS_TRANSPORT_REMOTE;
6708 arg_transport = BUS_TRANSPORT_CONTAINER;
6717 if (safe_atou(optarg, &arg_lines) < 0) {
6718 log_error("Failed to parse lines '%s'", optarg);
6724 arg_output = output_mode_from_string(optarg);
6725 if (arg_output < 0) {
6726 log_error("Unknown output '%s'.", optarg);
6732 arg_ignore_inhibitors = true;
6740 const char *word, *state;
6743 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6746 s = strndup(word, size);
6750 if (strv_consume(&arg_states, s) < 0)
6757 if (geteuid() != 0) {
6758 log_error("--recursive requires root privileges.");
6762 arg_recursive = true;
6765 case ARG_PRESET_MODE:
6767 arg_preset_mode = unit_file_preset_mode_from_string(optarg);
6768 if (arg_preset_mode < 0) {
6769 log_error("Failed to parse preset mode: %s.", optarg);
6779 assert_not_reached("Unhandled option");
6782 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
6783 log_error("Cannot access user instance remotely.");
6790 static int halt_parse_argv(int argc, char *argv[]) {
6799 static const struct option options[] = {
6800 { "help", no_argument, NULL, ARG_HELP },
6801 { "halt", no_argument, NULL, ARG_HALT },
6802 { "poweroff", no_argument, NULL, 'p' },
6803 { "reboot", no_argument, NULL, ARG_REBOOT },
6804 { "force", no_argument, NULL, 'f' },
6805 { "wtmp-only", no_argument, NULL, 'w' },
6806 { "no-wtmp", no_argument, NULL, 'd' },
6807 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6816 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
6817 if (runlevel == '0' || runlevel == '6')
6820 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
6828 arg_action = ACTION_HALT;
6832 if (arg_action != ACTION_REBOOT)
6833 arg_action = ACTION_POWEROFF;
6837 arg_action = ACTION_REBOOT;
6859 /* Compatibility nops */
6866 assert_not_reached("Unhandled option");
6869 if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
6870 r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL);
6873 } else if (optind < argc) {
6874 log_error("Too many arguments.");
6881 static int parse_time_spec(const char *t, usec_t *_u) {
6885 if (streq(t, "now"))
6887 else if (!strchr(t, ':')) {
6890 if (safe_atou64(t, &u) < 0)
6893 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
6902 hour = strtol(t, &e, 10);
6903 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
6906 minute = strtol(e+1, &e, 10);
6907 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
6910 n = now(CLOCK_REALTIME);
6911 s = (time_t) (n / USEC_PER_SEC);
6913 assert_se(localtime_r(&s, &tm));
6915 tm.tm_hour = (int) hour;
6916 tm.tm_min = (int) minute;
6919 assert_se(s = mktime(&tm));
6921 *_u = (usec_t) s * USEC_PER_SEC;
6924 *_u += USEC_PER_DAY;
6930 static int shutdown_parse_argv(int argc, char *argv[]) {
6937 static const struct option options[] = {
6938 { "help", no_argument, NULL, ARG_HELP },
6939 { "halt", no_argument, NULL, 'H' },
6940 { "poweroff", no_argument, NULL, 'P' },
6941 { "reboot", no_argument, NULL, 'r' },
6942 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
6943 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6952 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0)
6960 arg_action = ACTION_HALT;
6964 arg_action = ACTION_POWEROFF;
6969 arg_action = ACTION_KEXEC;
6971 arg_action = ACTION_REBOOT;
6975 arg_action = ACTION_KEXEC;
6979 if (arg_action != ACTION_HALT)
6980 arg_action = ACTION_POWEROFF;
6993 /* Compatibility nops */
6997 arg_action = ACTION_CANCEL_SHUTDOWN;
7004 assert_not_reached("Unhandled option");
7007 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
7008 r = parse_time_spec(argv[optind], &arg_when);
7010 log_error("Failed to parse time specification: %s", argv[optind]);
7014 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
7016 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
7017 /* No time argument for shutdown cancel */
7018 arg_wall = argv + optind;
7019 else if (argc > optind + 1)
7020 /* We skip the time argument */
7021 arg_wall = argv + optind + 1;
7028 static int telinit_parse_argv(int argc, char *argv[]) {
7035 static const struct option options[] = {
7036 { "help", no_argument, NULL, ARG_HELP },
7037 { "no-wall", no_argument, NULL, ARG_NO_WALL },
7041 static const struct {
7045 { '0', ACTION_POWEROFF },
7046 { '6', ACTION_REBOOT },
7047 { '1', ACTION_RESCUE },
7048 { '2', ACTION_RUNLEVEL2 },
7049 { '3', ACTION_RUNLEVEL3 },
7050 { '4', ACTION_RUNLEVEL4 },
7051 { '5', ACTION_RUNLEVEL5 },
7052 { 's', ACTION_RESCUE },
7053 { 'S', ACTION_RESCUE },
7054 { 'q', ACTION_RELOAD },
7055 { 'Q', ACTION_RELOAD },
7056 { 'u', ACTION_REEXEC },
7057 { 'U', ACTION_REEXEC }
7066 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
7081 assert_not_reached("Unhandled option");
7084 if (optind >= argc) {
7085 log_error("%s: required argument missing.",
7086 program_invocation_short_name);
7090 if (optind + 1 < argc) {
7091 log_error("Too many arguments.");
7095 if (strlen(argv[optind]) != 1) {
7096 log_error("Expected single character argument.");
7100 for (i = 0; i < ELEMENTSOF(table); i++)
7101 if (table[i].from == argv[optind][0])
7104 if (i >= ELEMENTSOF(table)) {
7105 log_error("Unknown command '%s'.", argv[optind]);
7109 arg_action = table[i].to;
7116 static int runlevel_parse_argv(int argc, char *argv[]) {
7122 static const struct option options[] = {
7123 { "help", no_argument, NULL, ARG_HELP },
7132 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
7143 assert_not_reached("Unhandled option");
7146 if (optind < argc) {
7147 log_error("Too many arguments.");
7154 static int parse_argv(int argc, char *argv[]) {
7158 if (program_invocation_short_name) {
7160 if (strstr(program_invocation_short_name, "halt")) {
7161 arg_action = ACTION_HALT;
7162 return halt_parse_argv(argc, argv);
7163 } else if (strstr(program_invocation_short_name, "poweroff")) {
7164 arg_action = ACTION_POWEROFF;
7165 return halt_parse_argv(argc, argv);
7166 } else if (strstr(program_invocation_short_name, "reboot")) {
7168 arg_action = ACTION_KEXEC;
7170 arg_action = ACTION_REBOOT;
7171 return halt_parse_argv(argc, argv);
7172 } else if (strstr(program_invocation_short_name, "shutdown")) {
7173 arg_action = ACTION_POWEROFF;
7174 return shutdown_parse_argv(argc, argv);
7175 } else if (strstr(program_invocation_short_name, "init")) {
7177 if (sd_booted() > 0) {
7178 arg_action = _ACTION_INVALID;
7179 return telinit_parse_argv(argc, argv);
7181 /* Hmm, so some other init system is
7182 * running, we need to forward this
7183 * request to it. For now we simply
7184 * guess that it is Upstart. */
7186 execv(TELINIT, argv);
7188 log_error("Couldn't find an alternative telinit implementation to spawn.");
7192 } else if (strstr(program_invocation_short_name, "runlevel")) {
7193 arg_action = ACTION_RUNLEVEL;
7194 return runlevel_parse_argv(argc, argv);
7198 arg_action = ACTION_SYSTEMCTL;
7199 return systemctl_parse_argv(argc, argv);
7202 _pure_ static int action_to_runlevel(void) {
7204 static const char table[_ACTION_MAX] = {
7205 [ACTION_HALT] = '0',
7206 [ACTION_POWEROFF] = '0',
7207 [ACTION_REBOOT] = '6',
7208 [ACTION_RUNLEVEL2] = '2',
7209 [ACTION_RUNLEVEL3] = '3',
7210 [ACTION_RUNLEVEL4] = '4',
7211 [ACTION_RUNLEVEL5] = '5',
7212 [ACTION_RESCUE] = '1'
7215 assert(arg_action < _ACTION_MAX);
7217 return table[arg_action];
7220 static int talk_initctl(void) {
7222 struct init_request request = {
7223 .magic = INIT_MAGIC,
7225 .cmd = INIT_CMD_RUNLVL
7228 _cleanup_close_ int fd = -1;
7232 rl = action_to_runlevel();
7236 request.runlevel = rl;
7238 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
7240 if (errno == ENOENT)
7243 log_error_errno(errno, "Failed to open "INIT_FIFO": %m");
7248 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
7250 log_error_errno(errno, "Failed to write to "INIT_FIFO": %m");
7251 return errno > 0 ? -errno : -EIO;
7257 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
7259 static const struct {
7267 int (* const dispatch)(sd_bus *bus, char **args);
7273 { "list-units", MORE, 0, list_units },
7274 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
7275 { "list-sockets", MORE, 1, list_sockets },
7276 { "list-timers", MORE, 1, list_timers },
7277 { "list-jobs", MORE, 1, list_jobs },
7278 { "list-machines", MORE, 1, list_machines },
7279 { "clear-jobs", EQUAL, 1, daemon_reload },
7280 { "cancel", MORE, 2, cancel_job },
7281 { "start", MORE, 2, start_unit },
7282 { "stop", MORE, 2, start_unit },
7283 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
7284 { "reload", MORE, 2, start_unit },
7285 { "restart", MORE, 2, start_unit },
7286 { "try-restart", MORE, 2, start_unit },
7287 { "reload-or-restart", MORE, 2, start_unit },
7288 { "reload-or-try-restart", MORE, 2, start_unit },
7289 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
7290 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
7291 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
7292 { "isolate", EQUAL, 2, start_unit },
7293 { "kill", MORE, 2, kill_unit },
7294 { "is-active", MORE, 2, check_unit_active },
7295 { "check", MORE, 2, check_unit_active },
7296 { "is-failed", MORE, 2, check_unit_failed },
7297 { "show", MORE, 1, show },
7298 { "cat", MORE, 2, cat },
7299 { "status", MORE, 1, show },
7300 { "help", MORE, 2, show },
7301 { "snapshot", LESS, 2, snapshot },
7302 { "delete", MORE, 2, delete_snapshot },
7303 { "daemon-reload", EQUAL, 1, daemon_reload },
7304 { "daemon-reexec", EQUAL, 1, daemon_reload },
7305 { "show-environment", EQUAL, 1, show_environment },
7306 { "set-environment", MORE, 2, set_environment },
7307 { "unset-environment", MORE, 2, set_environment },
7308 { "import-environment", MORE, 1, import_environment},
7309 { "halt", EQUAL, 1, start_special, FORCE },
7310 { "poweroff", EQUAL, 1, start_special, FORCE },
7311 { "reboot", EQUAL, 1, start_special, FORCE },
7312 { "kexec", EQUAL, 1, start_special },
7313 { "suspend", EQUAL, 1, start_special },
7314 { "hibernate", EQUAL, 1, start_special },
7315 { "hybrid-sleep", EQUAL, 1, start_special },
7316 { "default", EQUAL, 1, start_special },
7317 { "rescue", EQUAL, 1, start_special },
7318 { "emergency", EQUAL, 1, start_special },
7319 { "exit", EQUAL, 1, start_special },
7320 { "reset-failed", MORE, 1, reset_failed },
7321 { "enable", MORE, 2, enable_unit, NOBUS },
7322 { "disable", MORE, 2, enable_unit, NOBUS },
7323 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
7324 { "reenable", MORE, 2, enable_unit, NOBUS },
7325 { "preset", MORE, 2, enable_unit, NOBUS },
7326 { "preset-all", EQUAL, 1, preset_all, NOBUS },
7327 { "mask", MORE, 2, enable_unit, NOBUS },
7328 { "unmask", MORE, 2, enable_unit, NOBUS },
7329 { "link", MORE, 2, enable_unit, NOBUS },
7330 { "switch-root", MORE, 2, switch_root },
7331 { "list-dependencies", LESS, 2, list_dependencies },
7332 { "set-default", EQUAL, 2, set_default, NOBUS },
7333 { "get-default", EQUAL, 1, get_default, NOBUS },
7334 { "set-property", MORE, 3, set_property },
7335 { "is-system-running", EQUAL, 1, is_system_running },
7336 { "add-wants", MORE, 3, add_dependency, NOBUS },
7337 { "add-requires", MORE, 3, add_dependency, NOBUS },
7338 { "edit", MORE, 2, edit, NOBUS },
7347 left = argc - optind;
7349 /* Special rule: no arguments (left == 0) means "list-units" */
7351 if (streq(argv[optind], "help") && !argv[optind+1]) {
7352 log_error("This command expects one or more "
7353 "unit names. Did you mean --help?");
7357 for (; verb->verb; verb++)
7358 if (streq(argv[optind], verb->verb))
7361 log_error("Unknown operation '%s'.", argv[optind]);
7366 switch (verb->argc_cmp) {
7369 if (left != verb->argc) {
7370 log_error("Invalid number of arguments.");
7377 if (left < verb->argc) {
7378 log_error("Too few arguments.");
7385 if (left > verb->argc) {
7386 log_error("Too many arguments.");
7393 assert_not_reached("Unknown comparison operator.");
7396 /* Require a bus connection for all operations but
7398 if (verb->bus == NOBUS) {
7399 if (!bus && !avoid_bus()) {
7400 log_error_errno(bus_error, "Failed to get D-Bus connection: %m");
7405 if (running_in_chroot() > 0) {
7406 log_info("Running in chroot, ignoring request.");
7410 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
7411 log_error_errno(bus_error, "Failed to get D-Bus connection: %m");
7416 return verb->dispatch(bus, argv + optind);
7419 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
7421 struct sd_shutdown_command c = {
7428 union sockaddr_union sockaddr = {
7429 .un.sun_family = AF_UNIX,
7430 .un.sun_path = "/run/systemd/shutdownd",
7433 struct iovec iovec[2] = {{
7434 .iov_base = (char*) &c,
7435 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
7438 struct msghdr msghdr = {
7439 .msg_name = &sockaddr,
7440 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
7441 + strlen("/run/systemd/shutdownd"),
7446 _cleanup_close_ int fd;
7448 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
7452 if (!isempty(message)) {
7453 iovec[1].iov_base = (char*) message;
7454 iovec[1].iov_len = strlen(message);
7455 msghdr.msg_iovlen++;
7458 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
7464 static int reload_with_fallback(sd_bus *bus) {
7467 /* First, try systemd via D-Bus. */
7468 if (daemon_reload(bus, NULL) >= 0)
7472 /* Nothing else worked, so let's try signals */
7473 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
7475 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0)
7476 return log_error_errno(errno, "kill() failed: %m");
7481 static int start_with_fallback(sd_bus *bus) {
7484 /* First, try systemd via D-Bus. */
7485 if (start_unit(bus, NULL) >= 0)
7489 /* Nothing else worked, so let's try
7491 if (talk_initctl() > 0)
7494 log_error("Failed to talk to init daemon.");
7498 warn_wall(arg_action);
7502 static int halt_now(enum action a) {
7504 /* The kernel will automaticall flush ATA disks and suchlike
7505 * on reboot(), but the file systems need to be synce'd
7506 * explicitly in advance. */
7509 /* Make sure C-A-D is handled by the kernel from this point
7511 reboot(RB_ENABLE_CAD);
7516 log_info("Halting.");
7517 reboot(RB_HALT_SYSTEM);
7520 case ACTION_POWEROFF:
7521 log_info("Powering off.");
7522 reboot(RB_POWER_OFF);
7525 case ACTION_REBOOT: {
7526 _cleanup_free_ char *param = NULL;
7528 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
7529 log_info("Rebooting with argument '%s'.", param);
7530 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
7531 LINUX_REBOOT_CMD_RESTART2, param);
7534 log_info("Rebooting.");
7535 reboot(RB_AUTOBOOT);
7540 assert_not_reached("Unknown action.");
7544 static int halt_main(sd_bus *bus) {
7547 r = check_inhibitors(bus, arg_action);
7551 if (geteuid() != 0) {
7552 /* Try logind if we are a normal user and no special
7553 * mode applies. Maybe PolicyKit allows us to shutdown
7556 if (arg_when <= 0 &&
7559 (arg_action == ACTION_POWEROFF ||
7560 arg_action == ACTION_REBOOT)) {
7561 r = reboot_with_logind(bus, arg_action);
7566 log_error("Must be root.");
7571 _cleanup_free_ char *m;
7573 m = strv_join(arg_wall, " ");
7577 r = send_shutdownd(arg_when,
7578 arg_action == ACTION_HALT ? 'H' :
7579 arg_action == ACTION_POWEROFF ? 'P' :
7580 arg_action == ACTION_KEXEC ? 'K' :
7587 log_warning_errno(r, "Failed to talk to shutdownd, proceeding with immediate shutdown: %m");
7589 char date[FORMAT_TIMESTAMP_MAX];
7591 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
7592 format_timestamp(date, sizeof(date), arg_when));
7597 if (!arg_dry && !arg_force)
7598 return start_with_fallback(bus);
7601 if (sd_booted() > 0)
7602 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7604 r = utmp_put_shutdown();
7606 log_warning_errno(r, "Failed to write utmp record: %m");
7613 r = halt_now(arg_action);
7614 log_error_errno(r, "Failed to reboot: %m");
7619 static int runlevel_main(void) {
7620 int r, runlevel, previous;
7622 r = utmp_get_runlevel(&runlevel, &previous);
7629 previous <= 0 ? 'N' : previous,
7630 runlevel <= 0 ? 'N' : runlevel);
7635 int main(int argc, char*argv[]) {
7636 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
7639 setlocale(LC_ALL, "");
7640 log_parse_environment();
7643 /* Explicitly not on_tty() to avoid setting cached value.
7644 * This becomes relevant for piping output which might be
7646 original_stdout_is_tty = isatty(STDOUT_FILENO);
7648 r = parse_argv(argc, argv);
7652 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
7653 * let's shortcut this */
7654 if (arg_action == ACTION_RUNLEVEL) {
7655 r = runlevel_main();
7659 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
7660 log_info("Running in chroot, ignoring request.");
7666 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
7668 /* systemctl_main() will print an error message for the bus
7669 * connection, but only if it needs to */
7671 switch (arg_action) {
7673 case ACTION_SYSTEMCTL:
7674 r = systemctl_main(bus, argc, argv, r);
7678 case ACTION_POWEROFF:
7684 case ACTION_RUNLEVEL2:
7685 case ACTION_RUNLEVEL3:
7686 case ACTION_RUNLEVEL4:
7687 case ACTION_RUNLEVEL5:
7689 case ACTION_EMERGENCY:
7690 case ACTION_DEFAULT:
7691 r = start_with_fallback(bus);
7696 r = reload_with_fallback(bus);
7699 case ACTION_CANCEL_SHUTDOWN: {
7700 _cleanup_free_ char *m = NULL;
7703 m = strv_join(arg_wall, " ");
7710 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
7712 log_warning_errno(r, "Failed to talk to shutdownd, shutdown hasn't been cancelled: %m");
7716 case ACTION_RUNLEVEL:
7717 case _ACTION_INVALID:
7719 assert_not_reached("Unknown action");
7724 ask_password_agent_close();
7725 polkit_agent_close();
7727 strv_free(arg_types);
7728 strv_free(arg_states);
7729 strv_free(arg_properties);
7731 return r < 0 ? EXIT_FAILURE : r;