1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Marc-Antoine Perennou
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/reboot.h>
24 #include <linux/reboot.h>
25 #include <sys/syscall.h>
32 #include <sys/ioctl.h>
36 #include <sys/socket.h>
39 #include <sys/prctl.h>
42 #include "sd-daemon.h"
43 #include "sd-shutdown.h"
50 #include "utmp-wtmp.h"
53 #include "path-util.h"
55 #include "cgroup-show.h"
56 #include "cgroup-util.h"
58 #include "path-lookup.h"
59 #include "conf-parser.h"
60 #include "exit-status.h"
62 #include "unit-name.h"
64 #include "spawn-ask-password-agent.h"
65 #include "spawn-polkit-agent.h"
67 #include "logs-show.h"
68 #include "socket-util.h"
73 #include "bus-message.h"
74 #include "bus-error.h"
75 #include "bus-common-errors.h"
78 static char **arg_types = NULL;
79 static char **arg_states = NULL;
80 static char **arg_properties = NULL;
81 static bool arg_all = false;
82 static enum dependency {
88 } arg_dependency = DEPENDENCY_FORWARD;
89 static const char *arg_job_mode = "replace";
90 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
91 static bool arg_no_block = false;
92 static bool arg_no_legend = false;
93 static bool arg_no_pager = false;
94 static bool arg_no_wtmp = false;
95 static bool arg_no_wall = false;
96 static bool arg_no_reload = false;
97 static bool arg_show_types = false;
98 static bool arg_ignore_inhibitors = false;
99 static bool arg_dry = false;
100 static bool arg_quiet = false;
101 static bool arg_full = false;
102 static bool arg_recursive = false;
103 static int arg_force = 0;
104 static bool arg_ask_password = true;
105 static bool arg_runtime = false;
106 static UnitFilePresetMode arg_preset_mode = UNIT_FILE_PRESET_FULL;
107 static char **arg_wall = NULL;
108 static const char *arg_kill_who = NULL;
109 static int arg_signal = SIGTERM;
110 static const char *arg_root = NULL;
111 static usec_t arg_when = 0;
133 ACTION_CANCEL_SHUTDOWN,
135 } arg_action = ACTION_SYSTEMCTL;
136 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
137 static char *arg_host = NULL;
138 static unsigned arg_lines = 10;
139 static OutputMode arg_output = OUTPUT_SHORT;
140 static bool arg_plain = false;
142 static bool original_stdout_is_tty;
144 static int daemon_reload(sd_bus *bus, char **args);
145 static int halt_now(enum action a);
146 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet);
148 static char** strv_skip_first(char **strv) {
149 if (strv_length(strv) > 0)
154 static void pager_open_if_enabled(void) {
162 static void ask_password_agent_open_if_enabled(void) {
164 /* Open the password agent as a child process if necessary */
166 if (!arg_ask_password)
169 if (arg_scope != UNIT_FILE_SYSTEM)
172 if (arg_transport != BUS_TRANSPORT_LOCAL)
175 ask_password_agent_open();
179 static void polkit_agent_open_if_enabled(void) {
181 /* Open the polkit agent as a child process if necessary */
183 if (!arg_ask_password)
186 if (arg_scope != UNIT_FILE_SYSTEM)
189 if (arg_transport != BUS_TRANSPORT_LOCAL)
196 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
199 if (!sd_bus_error_is_set(error))
202 if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) ||
203 sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
204 sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
205 sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
206 return EXIT_NOPERMISSION;
208 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
209 return EXIT_NOTINSTALLED;
211 if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
212 sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED))
213 return EXIT_NOTIMPLEMENTED;
215 if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
216 return EXIT_NOTCONFIGURED;
224 static void warn_wall(enum action a) {
225 static const char *table[_ACTION_MAX] = {
226 [ACTION_HALT] = "The system is going down for system halt NOW!",
227 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
228 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
229 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
230 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
231 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
232 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
239 _cleanup_free_ char *p;
241 p = strv_join(arg_wall, " ");
248 utmp_wall(p, NULL, NULL);
256 utmp_wall(table[a], NULL, NULL);
259 static bool avoid_bus(void) {
261 if (running_in_chroot() > 0)
264 if (sd_booted() <= 0)
267 if (!isempty(arg_root))
270 if (arg_scope == UNIT_FILE_GLOBAL)
276 static int compare_unit_info(const void *a, const void *b) {
277 const UnitInfo *u = a, *v = b;
281 /* First, order by machine */
282 if (!u->machine && v->machine)
284 if (u->machine && !v->machine)
286 if (u->machine && v->machine) {
287 r = strcasecmp(u->machine, v->machine);
292 /* Second, order by unit type */
293 d1 = strrchr(u->id, '.');
294 d2 = strrchr(v->id, '.');
296 r = strcasecmp(d1, d2);
301 /* Third, order by name */
302 return strcasecmp(u->id, v->id);
305 static bool output_show_unit(const UnitInfo *u, char **patterns) {
306 if (!strv_isempty(patterns)) {
309 STRV_FOREACH(pattern, patterns)
310 if (fnmatch(*pattern, u->id, FNM_NOESCAPE) == 0)
319 dot = strrchr(u->id, '.');
323 if (!strv_find(arg_types, dot+1))
333 if (streq(u->active_state, "inactive") || u->following[0])
339 static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
340 unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
342 unsigned n_shown = 0;
345 max_id_len = strlen("UNIT");
346 load_len = strlen("LOAD");
347 active_len = strlen("ACTIVE");
348 sub_len = strlen("SUB");
349 job_len = strlen("JOB");
352 for (u = unit_infos; u < unit_infos + c; u++) {
353 max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0));
354 load_len = MAX(load_len, strlen(u->load_state));
355 active_len = MAX(active_len, strlen(u->active_state));
356 sub_len = MAX(sub_len, strlen(u->sub_state));
358 if (u->job_id != 0) {
359 job_len = MAX(job_len, strlen(u->job_type));
363 if (!arg_no_legend &&
364 (streq(u->active_state, "failed") ||
365 STR_IN_SET(u->load_state, "error", "not-found", "masked")))
369 if (!arg_full && original_stdout_is_tty) {
372 id_len = MIN(max_id_len, 25u);
373 basic_len = circle_len + 5 + id_len + 5 + active_len + sub_len;
376 basic_len += job_len + 1;
378 if (basic_len < (unsigned) columns()) {
379 unsigned extra_len, incr;
380 extra_len = columns() - basic_len;
382 /* Either UNIT already got 25, or is fully satisfied.
383 * Grant up to 25 to DESC now. */
384 incr = MIN(extra_len, 25u);
388 /* split the remaining space between UNIT and DESC,
389 * but do not give UNIT more than it needs. */
391 incr = MIN(extra_len / 2, max_id_len - id_len);
393 desc_len += extra_len - incr;
399 for (u = unit_infos; u < unit_infos + c; u++) {
400 _cleanup_free_ char *e = NULL, *j = NULL;
401 const char *on_loaded = "", *off_loaded = "";
402 const char *on_active = "", *off_active = "";
403 const char *on_circle = "", *off_circle = "";
407 if (!n_shown && !arg_no_legend) {
412 printf("%-*s %-*s %-*s %-*s ",
415 active_len, "ACTIVE",
419 printf("%-*s ", job_len, "JOB");
421 if (!arg_full && arg_no_pager)
422 printf("%.*s\n", desc_len, "DESCRIPTION");
424 printf("%s\n", "DESCRIPTION");
429 if (STR_IN_SET(u->load_state, "error", "not-found", "masked")) {
430 on_loaded = ansi_highlight_red();
431 on_circle = ansi_highlight_yellow();
432 off_loaded = off_circle = ansi_highlight_off();
436 if (streq(u->active_state, "failed")) {
437 on_circle = on_active = ansi_highlight_red();
438 off_circle = off_active = ansi_highlight_off();
443 j = strjoin(u->machine, ":", u->id, NULL);
452 e = ellipsize(id, id_len, 33);
460 printf("%s%s%s ", on_circle, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_circle);
462 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
463 on_active, id_len, id, off_active,
464 on_loaded, load_len, u->load_state, off_loaded,
465 on_active, active_len, u->active_state,
466 sub_len, u->sub_state, off_active,
467 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
470 printf("%.*s\n", desc_len, u->description);
472 printf("%s\n", u->description);
475 if (!arg_no_legend) {
476 const char *on, *off;
480 "LOAD = Reflects whether the unit definition was properly loaded.\n"
481 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
482 "SUB = The low-level unit activation state, values depend on unit type.");
483 puts(job_count ? "JOB = Pending job for the unit.\n" : "");
484 on = ansi_highlight();
485 off = ansi_highlight_off();
487 on = ansi_highlight_red();
488 off = ansi_highlight_off();
492 printf("%s%u loaded units listed.%s\n"
493 "To show all installed unit files use 'systemctl list-unit-files'.\n",
496 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
497 "To show all installed unit files use 'systemctl list-unit-files'.\n",
504 static int get_unit_list(
508 UnitInfo **unit_infos,
510 sd_bus_message **_reply) {
512 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
513 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
514 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
523 r = sd_bus_message_new_method_call(
526 "org.freedesktop.systemd1",
527 "/org/freedesktop/systemd1",
528 "org.freedesktop.systemd1.Manager",
529 "ListUnitsFiltered");
532 return bus_log_create_error(r);
534 r = sd_bus_message_append_strv(m, arg_states);
536 return bus_log_create_error(r);
538 r = sd_bus_call(bus, m, 0, &error, &reply);
540 log_error("Failed to list units: %s", bus_error_message(&error, r));
544 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
546 return bus_log_parse_error(r);
548 while ((r = bus_parse_unit_info(reply, &u)) > 0) {
551 if (!output_show_unit(&u, patterns))
554 if (!GREEDY_REALLOC(*unit_infos, size, c+1))
557 (*unit_infos)[c++] = u;
560 return bus_log_parse_error(r);
562 r = sd_bus_message_exit_container(reply);
564 return bus_log_parse_error(r);
572 static void message_set_freep(Set **set) {
575 while ((m = set_steal_first(*set)))
576 sd_bus_message_unref(m);
581 static int get_unit_list_recursive(
584 UnitInfo **_unit_infos,
588 _cleanup_free_ UnitInfo *unit_infos = NULL;
589 _cleanup_(message_set_freep) Set *replies;
590 sd_bus_message *reply;
598 replies = set_new(NULL);
602 c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
606 r = set_put(replies, reply);
608 sd_bus_message_unref(reply);
613 _cleanup_strv_free_ char **machines = NULL;
616 r = sd_get_machine_names(&machines);
620 STRV_FOREACH(i, machines) {
621 _cleanup_bus_close_unref_ sd_bus *container = NULL;
624 r = sd_bus_open_system_container(&container, *i);
626 log_error_errno(r, "Failed to connect to container %s: %m", *i);
630 k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
636 r = set_put(replies, reply);
638 sd_bus_message_unref(reply);
643 *_machines = machines;
648 *_unit_infos = unit_infos;
657 static int list_units(sd_bus *bus, char **args) {
658 _cleanup_free_ UnitInfo *unit_infos = NULL;
659 _cleanup_(message_set_freep) Set *replies = NULL;
660 _cleanup_strv_free_ char **machines = NULL;
663 pager_open_if_enabled();
665 r = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
669 qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
670 return output_units_list(unit_infos, r);
673 static int get_triggered_units(
678 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
681 r = sd_bus_get_property_strv(
683 "org.freedesktop.systemd1",
685 "org.freedesktop.systemd1.Unit",
691 log_error("Failed to determine triggers: %s", bus_error_message(&error, r));
696 static int get_listening(
698 const char* unit_path,
701 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
702 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
703 const char *type, *path;
706 r = sd_bus_get_property(
708 "org.freedesktop.systemd1",
710 "org.freedesktop.systemd1.Socket",
716 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r));
720 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
722 return bus_log_parse_error(r);
724 while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
726 r = strv_extend(listening, type);
730 r = strv_extend(listening, path);
737 return bus_log_parse_error(r);
739 r = sd_bus_message_exit_container(reply);
741 return bus_log_parse_error(r);
753 /* Note: triggered is a list here, although it almost certainly
754 * will always be one unit. Nevertheless, dbus API allows for multiple
755 * values, so let's follow that. */
758 /* The strv above is shared. free is set only in the first one. */
762 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
768 if (!a->machine && b->machine)
770 if (a->machine && !b->machine)
772 if (a->machine && b->machine) {
773 o = strcasecmp(a->machine, b->machine);
778 o = strcmp(a->path, b->path);
780 o = strcmp(a->type, b->type);
785 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
786 struct socket_info *s;
787 unsigned pathlen = strlen("LISTEN"),
788 typelen = strlen("TYPE") * arg_show_types,
789 socklen = strlen("UNIT"),
790 servlen = strlen("ACTIVATES");
791 const char *on, *off;
793 for (s = socket_infos; s < socket_infos + cs; s++) {
797 socklen = MAX(socklen, strlen(s->id));
799 typelen = MAX(typelen, strlen(s->type));
800 pathlen = MAX(pathlen, strlen(s->path) + (s->machine ? strlen(s->machine)+1 : 0));
802 STRV_FOREACH(a, s->triggered)
803 tmp += strlen(*a) + 2*(a != s->triggered);
804 servlen = MAX(servlen, tmp);
809 printf("%-*s %-*.*s%-*s %s\n",
811 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
815 for (s = socket_infos; s < socket_infos + cs; s++) {
816 _cleanup_free_ char *j = NULL;
821 j = strjoin(s->machine, ":", s->path, NULL);
829 printf("%-*s %-*s %-*s",
830 pathlen, path, typelen, s->type, socklen, s->id);
833 pathlen, path, socklen, s->id);
834 STRV_FOREACH(a, s->triggered)
836 a == s->triggered ? "" : ",", *a);
840 on = ansi_highlight();
841 off = ansi_highlight_off();
845 on = ansi_highlight_red();
846 off = ansi_highlight_off();
849 if (!arg_no_legend) {
850 printf("%s%u sockets listed.%s\n", on, cs, off);
852 printf("Pass --all to see loaded but inactive sockets, too.\n");
858 static int list_sockets(sd_bus *bus, char **args) {
859 _cleanup_(message_set_freep) Set *replies = NULL;
860 _cleanup_strv_free_ char **machines = NULL;
861 _cleanup_free_ UnitInfo *unit_infos = NULL;
862 _cleanup_free_ struct socket_info *socket_infos = NULL;
864 struct socket_info *s;
869 pager_open_if_enabled();
871 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
875 for (u = unit_infos; u < unit_infos + n; u++) {
876 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
879 if (!endswith(u->id, ".socket"))
882 r = get_triggered_units(bus, u->unit_path, &triggered);
886 c = get_listening(bus, u->unit_path, &listening);
892 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
897 for (i = 0; i < c; i++)
898 socket_infos[cs + i] = (struct socket_info) {
899 .machine = u->machine,
901 .type = listening[i*2],
902 .path = listening[i*2 + 1],
903 .triggered = triggered,
904 .own_triggered = i==0,
907 /* from this point on we will cleanup those socket_infos */
910 listening = triggered = NULL; /* avoid cleanup */
913 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
914 (__compar_fn_t) socket_info_compare);
916 output_sockets_list(socket_infos, cs);
919 assert(cs == 0 || socket_infos);
920 for (s = socket_infos; s < socket_infos + cs; s++) {
923 if (s->own_triggered)
924 strv_free(s->triggered);
930 static int get_next_elapse(
933 dual_timestamp *next) {
935 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
943 r = sd_bus_get_property_trivial(
945 "org.freedesktop.systemd1",
947 "org.freedesktop.systemd1.Timer",
948 "NextElapseUSecMonotonic",
953 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
957 r = sd_bus_get_property_trivial(
959 "org.freedesktop.systemd1",
961 "org.freedesktop.systemd1.Timer",
962 "NextElapseUSecRealtime",
967 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
975 static int get_last_trigger(
980 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
987 r = sd_bus_get_property_trivial(
989 "org.freedesktop.systemd1",
991 "org.freedesktop.systemd1.Timer",
997 log_error("Failed to get last trigger time: %s", bus_error_message(&error, r));
1005 const char* machine;
1008 usec_t last_trigger;
1012 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
1018 if (!a->machine && b->machine)
1020 if (a->machine && !b->machine)
1022 if (a->machine && b->machine) {
1023 o = strcasecmp(a->machine, b->machine);
1028 if (a->next_elapse < b->next_elapse)
1030 if (a->next_elapse > b->next_elapse)
1033 return strcmp(a->id, b->id);
1036 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
1037 struct timer_info *t;
1039 nextlen = strlen("NEXT"),
1040 leftlen = strlen("LEFT"),
1041 lastlen = strlen("LAST"),
1042 passedlen = strlen("PASSED"),
1043 unitlen = strlen("UNIT"),
1044 activatelen = strlen("ACTIVATES");
1046 const char *on, *off;
1048 assert(timer_infos || n == 0);
1050 for (t = timer_infos; t < timer_infos + n; t++) {
1054 if (t->next_elapse > 0) {
1055 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1057 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
1058 nextlen = MAX(nextlen, strlen(tstamp) + 1);
1060 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
1061 leftlen = MAX(leftlen, strlen(trel));
1064 if (t->last_trigger > 0) {
1065 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1067 format_timestamp(tstamp, sizeof(tstamp), t->last_trigger);
1068 lastlen = MAX(lastlen, strlen(tstamp) + 1);
1070 format_timestamp_relative(trel, sizeof(trel), t->last_trigger);
1071 passedlen = MAX(passedlen, strlen(trel));
1074 unitlen = MAX(unitlen, strlen(t->id) + (t->machine ? strlen(t->machine)+1 : 0));
1076 STRV_FOREACH(a, t->triggered)
1077 ul += strlen(*a) + 2*(a != t->triggered);
1079 activatelen = MAX(activatelen, ul);
1084 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1088 passedlen, "PASSED",
1092 for (t = timer_infos; t < timer_infos + n; t++) {
1093 _cleanup_free_ char *j = NULL;
1095 char tstamp1[FORMAT_TIMESTAMP_MAX] = "n/a", trel1[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1096 char tstamp2[FORMAT_TIMESTAMP_MAX] = "n/a", trel2[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1099 format_timestamp(tstamp1, sizeof(tstamp1), t->next_elapse);
1100 format_timestamp_relative(trel1, sizeof(trel1), t->next_elapse);
1102 format_timestamp(tstamp2, sizeof(tstamp2), t->last_trigger);
1103 format_timestamp_relative(trel2, sizeof(trel2), t->last_trigger);
1106 j = strjoin(t->machine, ":", t->id, NULL);
1113 printf("%-*s %-*s %-*s %-*s %-*s",
1114 nextlen, tstamp1, leftlen, trel1, lastlen, tstamp2, passedlen, trel2, unitlen, unit);
1116 STRV_FOREACH(a, t->triggered)
1118 a == t->triggered ? "" : ",", *a);
1122 on = ansi_highlight();
1123 off = ansi_highlight_off();
1127 on = ansi_highlight_red();
1128 off = ansi_highlight_off();
1131 if (!arg_no_legend) {
1132 printf("%s%u timers listed.%s\n", on, n, off);
1134 printf("Pass --all to see loaded but inactive timers, too.\n");
1140 static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
1146 if (next->monotonic != USEC_INFINITY && next->monotonic > 0) {
1149 if (next->monotonic > nw->monotonic)
1150 converted = nw->realtime + (next->monotonic - nw->monotonic);
1152 converted = nw->realtime - (nw->monotonic - next->monotonic);
1154 if (next->realtime != USEC_INFINITY && next->realtime > 0)
1155 next_elapse = MIN(converted, next->realtime);
1157 next_elapse = converted;
1160 next_elapse = next->realtime;
1165 static int list_timers(sd_bus *bus, char **args) {
1166 _cleanup_(message_set_freep) Set *replies = NULL;
1167 _cleanup_strv_free_ char **machines = NULL;
1168 _cleanup_free_ struct timer_info *timer_infos = NULL;
1169 _cleanup_free_ UnitInfo *unit_infos = NULL;
1170 struct timer_info *t;
1177 pager_open_if_enabled();
1179 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
1183 dual_timestamp_get(&nw);
1185 for (u = unit_infos; u < unit_infos + n; u++) {
1186 _cleanup_strv_free_ char **triggered = NULL;
1187 dual_timestamp next = {};
1190 if (!endswith(u->id, ".timer"))
1193 r = get_triggered_units(bus, u->unit_path, &triggered);
1197 r = get_next_elapse(bus, u->unit_path, &next);
1201 get_last_trigger(bus, u->unit_path, &last);
1203 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
1208 m = calc_next_elapse(&nw, &next);
1210 timer_infos[c++] = (struct timer_info) {
1211 .machine = u->machine,
1214 .last_trigger = last,
1215 .triggered = triggered,
1218 triggered = NULL; /* avoid cleanup */
1221 qsort_safe(timer_infos, c, sizeof(struct timer_info),
1222 (__compar_fn_t) timer_info_compare);
1224 output_timers_list(timer_infos, c);
1227 for (t = timer_infos; t < timer_infos + c; t++)
1228 strv_free(t->triggered);
1233 static int compare_unit_file_list(const void *a, const void *b) {
1234 const char *d1, *d2;
1235 const UnitFileList *u = a, *v = b;
1237 d1 = strrchr(u->path, '.');
1238 d2 = strrchr(v->path, '.');
1243 r = strcasecmp(d1, d2);
1248 return strcasecmp(basename(u->path), basename(v->path));
1251 static bool output_show_unit_file(const UnitFileList *u, char **patterns) {
1252 if (!strv_isempty(patterns)) {
1255 STRV_FOREACH(pattern, patterns)
1256 if (fnmatch(*pattern, basename(u->path), FNM_NOESCAPE) == 0)
1262 if (!strv_isempty(arg_types)) {
1265 dot = strrchr(u->path, '.');
1269 if (!strv_find(arg_types, dot+1))
1273 if (!strv_isempty(arg_states)) {
1274 if (!strv_find(arg_states, unit_file_state_to_string(u->state)))
1281 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
1282 unsigned max_id_len, id_cols, state_cols;
1283 const UnitFileList *u;
1285 max_id_len = strlen("UNIT FILE");
1286 state_cols = strlen("STATE");
1288 for (u = units; u < units + c; u++) {
1289 max_id_len = MAX(max_id_len, strlen(basename(u->path)));
1290 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1294 unsigned basic_cols;
1296 id_cols = MIN(max_id_len, 25u);
1297 basic_cols = 1 + id_cols + state_cols;
1298 if (basic_cols < (unsigned) columns())
1299 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1301 id_cols = max_id_len;
1304 printf("%-*s %-*s\n",
1305 id_cols, "UNIT FILE",
1306 state_cols, "STATE");
1308 for (u = units; u < units + c; u++) {
1309 _cleanup_free_ char *e = NULL;
1310 const char *on, *off;
1313 if (u->state == UNIT_FILE_MASKED ||
1314 u->state == UNIT_FILE_MASKED_RUNTIME ||
1315 u->state == UNIT_FILE_DISABLED ||
1316 u->state == UNIT_FILE_INVALID) {
1317 on = ansi_highlight_red();
1318 off = ansi_highlight_off();
1319 } else if (u->state == UNIT_FILE_ENABLED) {
1320 on = ansi_highlight_green();
1321 off = ansi_highlight_off();
1325 id = basename(u->path);
1327 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1329 printf("%-*s %s%-*s%s\n",
1330 id_cols, e ? e : id,
1331 on, state_cols, unit_file_state_to_string(u->state), off);
1335 printf("\n%u unit files listed.\n", c);
1338 static int list_unit_files(sd_bus *bus, char **args) {
1339 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1340 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1341 _cleanup_free_ UnitFileList *units = NULL;
1349 pager_open_if_enabled();
1357 h = hashmap_new(&string_hash_ops);
1361 r = unit_file_get_list(arg_scope, arg_root, h);
1363 unit_file_list_free(h);
1364 log_error_errno(r, "Failed to get unit file list: %m");
1368 n_units = hashmap_size(h);
1370 units = new(UnitFileList, n_units);
1371 if (!units && n_units > 0) {
1372 unit_file_list_free(h);
1376 HASHMAP_FOREACH(u, h, i) {
1377 if (!output_show_unit_file(u, strv_skip_first(args)))
1384 assert(c <= n_units);
1387 r = sd_bus_call_method(
1389 "org.freedesktop.systemd1",
1390 "/org/freedesktop/systemd1",
1391 "org.freedesktop.systemd1.Manager",
1397 log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1401 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1403 return bus_log_parse_error(r);
1405 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1407 if (!GREEDY_REALLOC(units, size, c + 1))
1410 units[c] = (struct UnitFileList) {
1412 unit_file_state_from_string(state)
1415 if (output_show_unit_file(&units[c], strv_skip_first(args)))
1420 return bus_log_parse_error(r);
1422 r = sd_bus_message_exit_container(reply);
1424 return bus_log_parse_error(r);
1427 qsort_safe(units, c, sizeof(UnitFileList), compare_unit_file_list);
1428 output_unit_file_list(units, c);
1431 for (unit = units; unit < units + c; unit++)
1438 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1439 _cleanup_free_ char *n = NULL;
1440 size_t max_len = MAX(columns(),20u);
1446 for (i = level - 1; i >= 0; i--) {
1448 if (len > max_len - 3 && !arg_full) {
1449 printf("%s...\n",max_len % 2 ? "" : " ");
1452 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERTICAL : DRAW_TREE_SPACE));
1456 if (len > max_len - 3 && !arg_full) {
1457 printf("%s...\n",max_len % 2 ? "" : " ");
1461 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
1465 printf("%s\n", name);
1469 n = ellipsize(name, max_len-len, 100);
1477 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1479 static const char *dependencies[_DEPENDENCY_MAX] = {
1480 [DEPENDENCY_FORWARD] = "Requires\0"
1481 "RequiresOverridable\0"
1483 "RequisiteOverridable\0"
1486 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1487 "RequiredByOverridable\0"
1491 [DEPENDENCY_AFTER] = "After\0",
1492 [DEPENDENCY_BEFORE] = "Before\0",
1495 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1496 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1497 _cleanup_strv_free_ char **ret = NULL;
1498 _cleanup_free_ char *path = NULL;
1504 assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
1506 path = unit_dbus_path_from_name(name);
1510 r = sd_bus_call_method(
1512 "org.freedesktop.systemd1",
1514 "org.freedesktop.DBus.Properties",
1518 "s", "org.freedesktop.systemd1.Unit");
1520 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1524 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1526 return bus_log_parse_error(r);
1528 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1531 r = sd_bus_message_read(reply, "s", &prop);
1533 return bus_log_parse_error(r);
1535 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1536 r = sd_bus_message_skip(reply, "v");
1538 return bus_log_parse_error(r);
1541 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1543 return bus_log_parse_error(r);
1545 r = bus_message_read_strv_extend(reply, &ret);
1547 return bus_log_parse_error(r);
1549 r = sd_bus_message_exit_container(reply);
1551 return bus_log_parse_error(r);
1554 r = sd_bus_message_exit_container(reply);
1556 return bus_log_parse_error(r);
1560 return bus_log_parse_error(r);
1562 r = sd_bus_message_exit_container(reply);
1564 return bus_log_parse_error(r);
1572 static int list_dependencies_compare(const void *_a, const void *_b) {
1573 const char **a = (const char**) _a, **b = (const char**) _b;
1575 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1577 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1580 return strcasecmp(*a, *b);
1583 static int list_dependencies_one(
1588 unsigned int branches) {
1590 _cleanup_strv_free_ char **deps = NULL;
1598 r = strv_extend(units, name);
1602 r = list_dependencies_get_dependencies(bus, name, &deps);
1606 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1608 STRV_FOREACH(c, deps) {
1611 if (strv_contains(*units, *c)) {
1613 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1620 state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true);
1622 printf("%s%s%s ", ansi_highlight_green(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1624 printf("%s%s%s ", ansi_highlight_red(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1626 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1630 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1631 r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1638 strv_remove(*units, name);
1643 static int list_dependencies(sd_bus *bus, char **args) {
1644 _cleanup_strv_free_ char **units = NULL;
1645 _cleanup_free_ char *unit = NULL;
1651 unit = unit_name_mangle(args[1], MANGLE_NOGLOB);
1656 u = SPECIAL_DEFAULT_TARGET;
1658 pager_open_if_enabled();
1662 return list_dependencies_one(bus, u, 0, &units, 0);
1665 struct machine_info {
1669 char *control_group;
1670 uint32_t n_failed_units;
1675 static const struct bus_properties_map machine_info_property_map[] = {
1676 { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
1677 { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
1678 { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
1679 { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
1680 { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
1684 static void free_machines_list(struct machine_info *machine_infos, int n) {
1690 for (i = 0; i < n; i++) {
1691 free(machine_infos[i].name);
1692 free(machine_infos[i].state);
1693 free(machine_infos[i].control_group);
1696 free(machine_infos);
1699 static int compare_machine_info(const void *a, const void *b) {
1700 const struct machine_info *u = a, *v = b;
1702 if (u->is_host != v->is_host)
1703 return u->is_host > v->is_host ? -1 : 1;
1705 return strcasecmp(u->name, v->name);
1708 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1709 _cleanup_bus_close_unref_ sd_bus *container = NULL;
1715 r = sd_bus_open_system_container(&container, mi->name);
1722 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi);
1729 static bool output_show_machine(const char *name, char **patterns) {
1734 if (strv_isempty(patterns))
1737 STRV_FOREACH(i, patterns)
1738 if (fnmatch(*i, name, FNM_NOESCAPE) == 0)
1744 static int get_machine_list(
1746 struct machine_info **_machine_infos,
1749 struct machine_info *machine_infos = NULL;
1750 _cleanup_strv_free_ char **m = NULL;
1751 _cleanup_free_ char *hn = NULL;
1756 hn = gethostname_malloc();
1760 if (output_show_machine(hn, patterns)) {
1761 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1764 machine_infos[c].is_host = true;
1765 machine_infos[c].name = hn;
1768 get_machine_properties(bus, &machine_infos[c]);
1772 sd_get_machine_names(&m);
1773 STRV_FOREACH(i, m) {
1774 _cleanup_free_ char *class = NULL;
1776 if (!output_show_machine(*i, patterns))
1779 sd_machine_get_class(*i, &class);
1780 if (!streq_ptr(class, "container"))
1783 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1784 free_machines_list(machine_infos, c);
1788 machine_infos[c].is_host = false;
1789 machine_infos[c].name = strdup(*i);
1790 if (!machine_infos[c].name) {
1791 free_machines_list(machine_infos, c);
1795 get_machine_properties(NULL, &machine_infos[c]);
1799 *_machine_infos = machine_infos;
1803 static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1804 struct machine_info *m;
1807 namelen = sizeof("NAME") - 1,
1808 statelen = sizeof("STATE") - 1,
1809 failedlen = sizeof("FAILED") - 1,
1810 jobslen = sizeof("JOBS") - 1;
1812 assert(machine_infos || n == 0);
1814 for (m = machine_infos; m < machine_infos + n; m++) {
1815 namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
1816 statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
1817 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
1818 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
1820 if (!arg_no_legend && !streq_ptr(m->state, "running"))
1824 if (!arg_no_legend) {
1828 printf("%-*s %-*s %-*s %-*s\n",
1831 failedlen, "FAILED",
1835 for (m = machine_infos; m < machine_infos + n; m++) {
1836 const char *on_state = "", *off_state = "";
1837 const char *on_failed = "", *off_failed = "";
1838 bool circle = false;
1840 if (streq_ptr(m->state, "degraded")) {
1841 on_state = ansi_highlight_red();
1842 off_state = ansi_highlight_off();
1844 } else if (!streq_ptr(m->state, "running")) {
1845 on_state = ansi_highlight_yellow();
1846 off_state = ansi_highlight_off();
1850 if (m->n_failed_units > 0) {
1851 on_failed = ansi_highlight_red();
1852 off_failed = ansi_highlight_off();
1854 on_failed = off_failed = "";
1857 printf("%s%s%s ", on_state, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_state);
1860 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1861 (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
1862 on_state, statelen, strna(m->state), off_state,
1863 on_failed, failedlen, m->n_failed_units, off_failed,
1864 jobslen, m->n_jobs);
1866 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1867 namelen, strna(m->name),
1868 on_state, statelen, strna(m->state), off_state,
1869 on_failed, failedlen, m->n_failed_units, off_failed,
1870 jobslen, m->n_jobs);
1874 printf("\n%u machines listed.\n", n);
1877 static int list_machines(sd_bus *bus, char **args) {
1878 struct machine_info *machine_infos = NULL;
1883 if (geteuid() != 0) {
1884 log_error("Must be root.");
1888 pager_open_if_enabled();
1890 r = get_machine_list(bus, &machine_infos, strv_skip_first(args));
1894 qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
1895 output_machines_list(machine_infos, r);
1896 free_machines_list(machine_infos, r);
1901 static int get_default(sd_bus *bus, char **args) {
1902 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1903 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1904 _cleanup_free_ char *_path = NULL;
1908 if (!bus || avoid_bus()) {
1909 r = unit_file_get_default(arg_scope, arg_root, &_path);
1911 return log_error_errno(r, "Failed to get default target: %m");
1915 r = sd_bus_call_method(
1917 "org.freedesktop.systemd1",
1918 "/org/freedesktop/systemd1",
1919 "org.freedesktop.systemd1.Manager",
1925 log_error("Failed to get default target: %s", bus_error_message(&error, -r));
1929 r = sd_bus_message_read(reply, "s", &path);
1931 return bus_log_parse_error(r);
1935 printf("%s\n", path);
1940 static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) {
1943 assert(changes || n_changes == 0);
1945 for (i = 0; i < n_changes; i++) {
1946 if (changes[i].type == UNIT_FILE_SYMLINK)
1947 log_info("Created symlink from %s to %s.", changes[i].path, changes[i].source);
1949 log_info("Removed symlink %s.", changes[i].path);
1953 static int deserialize_and_dump_unit_file_changes(sd_bus_message *m) {
1954 const char *type, *path, *source;
1957 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1959 return bus_log_parse_error(r);
1961 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1963 if (streq(type, "symlink"))
1964 log_info("Created symlink from %s to %s.", path, source);
1966 log_info("Removed symlink %s.", path);
1970 return bus_log_parse_error(r);
1972 r = sd_bus_message_exit_container(m);
1974 return bus_log_parse_error(r);
1979 static int set_default(sd_bus *bus, char **args) {
1980 _cleanup_free_ char *unit = NULL;
1981 UnitFileChange *changes = NULL;
1982 unsigned n_changes = 0;
1985 unit = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
1989 if (!bus || avoid_bus()) {
1990 r = unit_file_set_default(arg_scope, arg_root, unit, true, &changes, &n_changes);
1992 return log_error_errno(r, "Failed to set default target: %m");
1995 dump_unit_file_changes(changes, n_changes);
1999 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
2000 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2002 r = sd_bus_message_new_method_call(
2005 "org.freedesktop.systemd1",
2006 "/org/freedesktop/systemd1",
2007 "org.freedesktop.systemd1.Manager",
2008 "SetDefaultTarget");
2010 return bus_log_create_error(r);
2012 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2014 return bus_log_create_error(r);
2016 r = sd_bus_message_append(m, "sb", unit, 1);
2018 return bus_log_create_error(r);
2020 r = sd_bus_call(bus, m, 0, &error, &reply);
2022 log_error("Failed to set default target: %s", bus_error_message(&error, -r));
2026 r = deserialize_and_dump_unit_file_changes(reply);
2030 /* Try to reload if enabled */
2032 r = daemon_reload(bus, args);
2037 unit_file_changes_free(changes, n_changes);
2044 const char *name, *type, *state;
2047 static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
2048 unsigned id_len, unit_len, type_len, state_len;
2049 const struct job_info *j;
2050 const char *on, *off;
2051 bool shorten = false;
2053 assert(n == 0 || jobs);
2056 on = ansi_highlight_green();
2057 off = ansi_highlight_off();
2059 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
2063 pager_open_if_enabled();
2065 id_len = strlen("JOB");
2066 unit_len = strlen("UNIT");
2067 type_len = strlen("TYPE");
2068 state_len = strlen("STATE");
2070 for (j = jobs; j < jobs + n; j++) {
2071 uint32_t id = j->id;
2072 assert(j->name && j->type && j->state);
2074 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
2075 unit_len = MAX(unit_len, strlen(j->name));
2076 type_len = MAX(type_len, strlen(j->type));
2077 state_len = MAX(state_len, strlen(j->state));
2080 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
2081 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
2086 printf("%*s %-*s %-*s %-*s\n",
2090 state_len, "STATE");
2092 for (j = jobs; j < jobs + n; j++) {
2093 _cleanup_free_ char *e = NULL;
2095 if (streq(j->state, "running")) {
2096 on = ansi_highlight();
2097 off = ansi_highlight_off();
2101 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
2102 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2104 on, unit_len, e ? e : j->name, off,
2106 on, state_len, j->state, off);
2109 if (!arg_no_legend) {
2110 on = ansi_highlight();
2111 off = ansi_highlight_off();
2113 printf("\n%s%u jobs listed%s.\n", on, n, off);
2117 static bool output_show_job(struct job_info *job, char **patterns) {
2122 if (strv_isempty(patterns))
2125 STRV_FOREACH(pattern, patterns)
2126 if (fnmatch(*pattern, job->name, FNM_NOESCAPE) == 0)
2131 static int list_jobs(sd_bus *bus, char **args) {
2132 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2133 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2134 const char *name, *type, *state, *job_path, *unit_path;
2135 _cleanup_free_ struct job_info *jobs = NULL;
2140 bool skipped = false;
2142 r = sd_bus_call_method(
2144 "org.freedesktop.systemd1",
2145 "/org/freedesktop/systemd1",
2146 "org.freedesktop.systemd1.Manager",
2152 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
2156 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2158 return bus_log_parse_error(r);
2160 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
2161 struct job_info job = { id, name, type, state };
2163 if (!output_show_job(&job, strv_skip_first(args))) {
2168 if (!GREEDY_REALLOC(jobs, size, c + 1))
2174 return bus_log_parse_error(r);
2176 r = sd_bus_message_exit_container(reply);
2178 return bus_log_parse_error(r);
2180 output_jobs_list(jobs, c, skipped);
2184 static int cancel_job(sd_bus *bus, char **args) {
2185 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2191 if (strv_length(args) <= 1)
2192 return daemon_reload(bus, args);
2194 STRV_FOREACH(name, args+1) {
2195 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2199 q = safe_atou32(*name, &id);
2201 return log_error_errno(q, "Failed to parse job id \"%s\": %m", *name);
2203 q = sd_bus_message_new_method_call(
2206 "org.freedesktop.systemd1",
2207 "/org/freedesktop/systemd1",
2208 "org.freedesktop.systemd1.Manager",
2211 return bus_log_create_error(q);
2213 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2215 return bus_log_create_error(1);
2217 q = sd_bus_message_append(m, "u", id);
2219 return bus_log_create_error(q);
2221 q = sd_bus_call(bus, m, 0, &error, NULL);
2223 log_error("Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, q));
2232 static int need_daemon_reload(sd_bus *bus, const char *unit) {
2233 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2237 /* We ignore all errors here, since this is used to show a
2240 /* We don't use unit_dbus_path_from_name() directly since we
2241 * don't want to load the unit if it isn't loaded. */
2243 r = sd_bus_call_method(
2245 "org.freedesktop.systemd1",
2246 "/org/freedesktop/systemd1",
2247 "org.freedesktop.systemd1.Manager",
2255 r = sd_bus_message_read(reply, "o", &path);
2259 r = sd_bus_get_property_trivial(
2261 "org.freedesktop.systemd1",
2263 "org.freedesktop.systemd1.Unit",
2273 static void warn_unit_file_changed(const char *name) {
2274 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2275 ansi_highlight_red(),
2276 ansi_highlight_off(),
2278 arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2281 typedef struct WaitData {
2288 static int wait_filter(sd_bus *bus, sd_bus_message *m, void *data, sd_bus_error *error) {
2295 log_debug("Got D-Bus request: %s.%s() on %s",
2296 sd_bus_message_get_interface(m),
2297 sd_bus_message_get_member(m),
2298 sd_bus_message_get_path(m));
2300 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
2301 log_error("Warning! D-Bus connection terminated.");
2303 } else if (sd_bus_message_is_signal(m, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
2305 const char *path, *result, *unit;
2309 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
2311 ret = set_remove(d->set, (char*) path);
2317 if (!isempty(result))
2318 d->result = strdup(result);
2321 d->name = strdup(unit);
2326 r = sd_bus_message_read(m, "uos", &id, &path, &result);
2328 ret = set_remove(d->set, (char*) path);
2335 d->result = strdup(result);
2341 bus_log_parse_error(r);
2347 static int enable_wait_for_jobs(sd_bus *bus) {
2352 r = sd_bus_add_match(
2356 "sender='org.freedesktop.systemd1',"
2357 "interface='org.freedesktop.systemd1.Manager',"
2358 "member='JobRemoved',"
2359 "path='/org/freedesktop/systemd1'",
2362 log_error("Failed to add match");
2366 /* This is slightly dirty, since we don't undo the match registrations. */
2370 static int bus_process_wait(sd_bus *bus) {
2374 r = sd_bus_process(bus, NULL);
2379 r = sd_bus_wait(bus, (uint64_t) -1);
2385 static int check_wait_response(WaitData *d) {
2391 if (streq(d->result, "canceled"))
2392 log_error("Job for %s canceled.", strna(d->name));
2393 else if (streq(d->result, "timeout"))
2394 log_error("Job for %s timed out.", strna(d->name));
2395 else if (streq(d->result, "dependency"))
2396 log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
2397 else if (streq(d->result, "invalid"))
2398 log_error("Job for %s invalid.", strna(d->name));
2399 else if (streq(d->result, "assert"))
2400 log_error("Assertion failed on job for %s.", strna(d->name));
2401 else if (streq(d->result, "unsupported"))
2402 log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
2403 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
2407 quotes = chars_intersect(d->name, SHELL_NEED_QUOTES);
2409 log_error("Job for %s failed. See \"systemctl status %s%s%s\" and \"journalctl -xe\" for details.",
2411 quotes ? "'" : "", d->name, quotes ? "'" : "");
2413 log_error("Job failed. See \"journalctl -xe\" for details.");
2417 if (streq(d->result, "canceled"))
2419 else if (streq(d->result, "timeout"))
2421 else if (streq(d->result, "dependency"))
2423 else if (streq(d->result, "invalid"))
2425 else if (streq(d->result, "assert"))
2427 else if (streq(d->result, "unsupported"))
2429 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2435 static int wait_for_jobs(sd_bus *bus, Set *s) {
2436 _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
2437 WaitData d = { .set = s };
2443 q = sd_bus_add_filter(bus, &slot, wait_filter, &d);
2447 while (!set_isempty(s)) {
2448 q = bus_process_wait(bus);
2450 return log_error_errno(q, "Failed to wait for response: %m");
2453 q = check_wait_response(&d);
2454 /* Return the first error as it is most likely to be
2456 if (q < 0 && r == 0)
2458 log_debug("Got result %s/%s for job %s",
2459 strna(d.result), strerror(-q), strna(d.name));
2472 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2473 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2474 _cleanup_free_ char *n = NULL, *state = NULL;
2480 n = unit_name_mangle(name, MANGLE_NOGLOB);
2484 /* We don't use unit_dbus_path_from_name() directly since we
2485 * don't want to load the unit if it isn't loaded. */
2487 r = sd_bus_call_method(
2489 "org.freedesktop.systemd1",
2490 "/org/freedesktop/systemd1",
2491 "org.freedesktop.systemd1.Manager",
2502 r = sd_bus_message_read(reply, "o", &path);
2504 return bus_log_parse_error(r);
2506 r = sd_bus_get_property_string(
2508 "org.freedesktop.systemd1",
2510 "org.freedesktop.systemd1.Unit",
2523 return nulstr_contains(good_states, state);
2526 static int check_triggering_units(
2530 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2531 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2532 _cleanup_strv_free_ char **triggered_by = NULL;
2533 bool print_warning_label = true;
2537 n = unit_name_mangle(name, MANGLE_NOGLOB);
2541 path = unit_dbus_path_from_name(n);
2545 r = sd_bus_get_property_string(
2547 "org.freedesktop.systemd1",
2549 "org.freedesktop.systemd1.Unit",
2554 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2558 if (streq(state, "masked"))
2561 r = sd_bus_get_property_strv(
2563 "org.freedesktop.systemd1",
2565 "org.freedesktop.systemd1.Unit",
2570 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2574 STRV_FOREACH(i, triggered_by) {
2575 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2577 return log_error_errno(r, "Failed to check unit: %m");
2582 if (print_warning_label) {
2583 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2584 print_warning_label = false;
2587 log_warning(" %s", *i);
2593 static const struct {
2596 } unit_actions[] = {
2597 { "start", "StartUnit" },
2598 { "stop", "StopUnit" },
2599 { "condstop", "StopUnit" },
2600 { "reload", "ReloadUnit" },
2601 { "restart", "RestartUnit" },
2602 { "try-restart", "TryRestartUnit" },
2603 { "condrestart", "TryRestartUnit" },
2604 { "reload-or-restart", "ReloadOrRestartUnit" },
2605 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2606 { "condreload", "ReloadOrTryRestartUnit" },
2607 { "force-reload", "ReloadOrTryRestartUnit" }
2610 static const char *verb_to_method(const char *verb) {
2613 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2614 if (streq_ptr(unit_actions[i].verb, verb))
2615 return unit_actions[i].method;
2620 static const char *method_to_verb(const char *method) {
2623 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2624 if (streq_ptr(unit_actions[i].method, method))
2625 return unit_actions[i].verb;
2630 static int start_unit_one(
2635 sd_bus_error *error,
2638 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2647 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2649 r = sd_bus_message_new_method_call(
2652 "org.freedesktop.systemd1",
2653 "/org/freedesktop/systemd1",
2654 "org.freedesktop.systemd1.Manager",
2657 return bus_log_create_error(r);
2659 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2661 return bus_log_create_error(r);
2663 r = sd_bus_message_append(m, "ss", name, mode);
2665 return bus_log_create_error(r);
2667 r = sd_bus_call(bus, m, 0, error, &reply);
2671 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2672 /* There's always a fallback possible for
2673 * legacy actions. */
2674 return -EADDRNOTAVAIL;
2676 verb = method_to_verb(method);
2678 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2682 r = sd_bus_message_read(reply, "o", &path);
2684 return bus_log_parse_error(r);
2686 if (need_daemon_reload(bus, name) > 0)
2687 warn_unit_file_changed(name);
2696 log_debug("Adding %s to the set", p);
2697 r = set_consume(s, p);
2705 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2707 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2711 STRV_FOREACH(name, names) {
2715 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2717 t = unit_name_mangle(*name, MANGLE_GLOB);
2721 if (string_is_glob(t))
2722 r = strv_consume(&globs, t);
2724 r = strv_consume(&mangled, t);
2729 /* Query the manager only if any of the names are a glob, since
2730 * this is fairly expensive */
2731 if (!strv_isempty(globs)) {
2732 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2733 _cleanup_free_ UnitInfo *unit_infos = NULL;
2735 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2739 for (i = 0; i < r; i++)
2740 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2745 mangled = NULL; /* do not free */
2750 static const struct {
2754 } action_table[_ACTION_MAX] = {
2755 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2756 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2757 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2758 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2759 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
2760 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
2761 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
2762 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
2763 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2764 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2765 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2766 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2767 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2768 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2769 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2772 static enum action verb_to_action(const char *verb) {
2775 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2776 if (streq_ptr(action_table[i].verb, verb))
2779 return _ACTION_INVALID;
2782 static int start_unit(sd_bus *bus, char **args) {
2783 _cleanup_set_free_free_ Set *s = NULL;
2784 _cleanup_strv_free_ char **names = NULL;
2785 const char *method, *mode, *one_name, *suffix = NULL;
2791 ask_password_agent_open_if_enabled();
2793 if (arg_action == ACTION_SYSTEMCTL) {
2795 method = verb_to_method(args[0]);
2796 action = verb_to_action(args[0]);
2798 if (streq(args[0], "isolate")) {
2802 mode = action_table[action].mode ?: arg_job_mode;
2804 one_name = action_table[action].target;
2806 assert(arg_action < ELEMENTSOF(action_table));
2807 assert(action_table[arg_action].target);
2809 method = "StartUnit";
2811 mode = action_table[arg_action].mode;
2812 one_name = action_table[arg_action].target;
2816 names = strv_new(one_name, NULL);
2818 r = expand_names(bus, args + 1, suffix, &names);
2820 log_error_errno(r, "Failed to expand names: %m");
2823 if (!arg_no_block) {
2824 r = enable_wait_for_jobs(bus);
2826 return log_error_errno(r, "Could not watch jobs: %m");
2828 s = set_new(&string_hash_ops);
2833 STRV_FOREACH(name, names) {
2834 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2837 q = start_unit_one(bus, method, *name, mode, &error, s);
2838 if (r >= 0 && q < 0)
2839 r = translate_bus_error_to_exit_status(q, &error);
2842 if (!arg_no_block) {
2845 q = wait_for_jobs(bus, s);
2849 /* When stopping units, warn if they can still be triggered by
2850 * another active unit (socket, path, timer) */
2851 if (!arg_quiet && streq(method, "StopUnit"))
2852 STRV_FOREACH(name, names)
2853 check_triggering_units(bus, *name);
2859 /* Ask systemd-logind, which might grant access to unprivileged users
2860 * through PolicyKit */
2861 static int reboot_with_logind(sd_bus *bus, enum action a) {
2863 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2870 polkit_agent_open_if_enabled();
2878 case ACTION_POWEROFF:
2879 method = "PowerOff";
2882 case ACTION_SUSPEND:
2886 case ACTION_HIBERNATE:
2887 method = "Hibernate";
2890 case ACTION_HYBRID_SLEEP:
2891 method = "HybridSleep";
2898 r = sd_bus_call_method(
2900 "org.freedesktop.login1",
2901 "/org/freedesktop/login1",
2902 "org.freedesktop.login1.Manager",
2906 "b", arg_ask_password);
2908 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2916 static int check_inhibitors(sd_bus *bus, enum action a) {
2918 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2919 _cleanup_strv_free_ char **sessions = NULL;
2920 const char *what, *who, *why, *mode;
2929 if (arg_ignore_inhibitors || arg_force > 0)
2941 r = sd_bus_call_method(
2943 "org.freedesktop.login1",
2944 "/org/freedesktop/login1",
2945 "org.freedesktop.login1.Manager",
2951 /* If logind is not around, then there are no inhibitors... */
2954 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2956 return bus_log_parse_error(r);
2958 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2959 _cleanup_free_ char *comm = NULL, *user = NULL;
2960 _cleanup_strv_free_ char **sv = NULL;
2962 if (!streq(mode, "block"))
2965 sv = strv_split(what, ":");
2969 if (!strv_contains(sv,
2971 a == ACTION_POWEROFF ||
2972 a == ACTION_REBOOT ||
2973 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2976 get_process_comm(pid, &comm);
2977 user = uid_to_name(uid);
2979 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
2980 who, pid, strna(comm), strna(user), why);
2985 return bus_log_parse_error(r);
2987 r = sd_bus_message_exit_container(reply);
2989 return bus_log_parse_error(r);
2991 /* Check for current sessions */
2992 sd_get_sessions(&sessions);
2993 STRV_FOREACH(s, sessions) {
2994 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2996 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2999 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
3002 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
3005 sd_session_get_tty(*s, &tty);
3006 sd_session_get_seat(*s, &seat);
3007 sd_session_get_service(*s, &service);
3008 user = uid_to_name(uid);
3010 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
3017 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3018 action_table[a].verb);
3026 static int start_special(sd_bus *bus, char **args) {
3032 a = verb_to_action(args[0]);
3034 r = check_inhibitors(bus, a);
3038 if (arg_force >= 2 && geteuid() != 0) {
3039 log_error("Must be root.");
3043 if (arg_force >= 2 &&
3044 (a == ACTION_HALT ||
3045 a == ACTION_POWEROFF ||
3046 a == ACTION_REBOOT))
3049 if (arg_force >= 1 &&
3050 (a == ACTION_HALT ||
3051 a == ACTION_POWEROFF ||
3052 a == ACTION_REBOOT ||
3053 a == ACTION_KEXEC ||
3055 return daemon_reload(bus, args);
3057 /* first try logind, to allow authentication with polkit */
3058 if (geteuid() != 0 &&
3059 (a == ACTION_POWEROFF ||
3060 a == ACTION_REBOOT ||
3061 a == ACTION_SUSPEND ||
3062 a == ACTION_HIBERNATE ||
3063 a == ACTION_HYBRID_SLEEP)) {
3064 r = reboot_with_logind(bus, a);
3069 r = start_unit(bus, args);
3070 if (r == EXIT_SUCCESS)
3076 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
3077 _cleanup_strv_free_ char **names = NULL;
3084 r = expand_names(bus, args, NULL, &names);
3086 return log_error_errno(r, "Failed to expand names: %m");
3088 STRV_FOREACH(name, names) {
3091 state = check_one_unit(bus, *name, good_states, arg_quiet);
3101 static int check_unit_active(sd_bus *bus, char **args) {
3102 /* According to LSB: 3, "program is not running" */
3103 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
3106 static int check_unit_failed(sd_bus *bus, char **args) {
3107 return check_unit_generic(bus, 1, "failed\0", args + 1);
3110 static int kill_unit(sd_bus *bus, char **args) {
3111 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3112 _cleanup_strv_free_ char **names = NULL;
3120 arg_kill_who = "all";
3122 r = expand_names(bus, args + 1, NULL, &names);
3124 log_error_errno(r, "Failed to expand names: %m");
3126 STRV_FOREACH(name, names) {
3127 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3129 q = sd_bus_message_new_method_call(
3132 "org.freedesktop.systemd1",
3133 "/org/freedesktop/systemd1",
3134 "org.freedesktop.systemd1.Manager",
3137 return bus_log_create_error(q);
3139 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
3141 return bus_log_create_error(q);
3143 q = sd_bus_message_append(m, "ssi", *names, arg_kill_who, arg_signal);
3145 return bus_log_create_error(q);
3147 q = sd_bus_call(bus, m, 0, &error, NULL);
3149 log_error("Failed to kill unit %s: %s", *names, bus_error_message(&error, q));
3158 typedef struct ExecStatusInfo {
3166 usec_t start_timestamp;
3167 usec_t exit_timestamp;
3172 LIST_FIELDS(struct ExecStatusInfo, exec);
3175 static void exec_status_info_free(ExecStatusInfo *i) {
3184 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3185 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3188 int32_t code, status;
3194 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3196 return bus_log_parse_error(r);
3200 r = sd_bus_message_read(m, "s", &path);
3202 return bus_log_parse_error(r);
3204 i->path = strdup(path);
3208 r = sd_bus_message_read_strv(m, &i->argv);
3210 return bus_log_parse_error(r);
3212 r = sd_bus_message_read(m,
3215 &start_timestamp, &start_timestamp_monotonic,
3216 &exit_timestamp, &exit_timestamp_monotonic,
3220 return bus_log_parse_error(r);
3223 i->start_timestamp = (usec_t) start_timestamp;
3224 i->exit_timestamp = (usec_t) exit_timestamp;
3225 i->pid = (pid_t) pid;
3229 r = sd_bus_message_exit_container(m);
3231 return bus_log_parse_error(r);
3236 typedef struct UnitStatusInfo {
3238 const char *load_state;
3239 const char *active_state;
3240 const char *sub_state;
3241 const char *unit_file_state;
3242 const char *unit_file_preset;
3244 const char *description;
3245 const char *following;
3247 char **documentation;
3249 const char *fragment_path;
3250 const char *source_path;
3251 const char *control_group;
3253 char **dropin_paths;
3255 const char *load_error;
3258 usec_t inactive_exit_timestamp;
3259 usec_t inactive_exit_timestamp_monotonic;
3260 usec_t active_enter_timestamp;
3261 usec_t active_exit_timestamp;
3262 usec_t inactive_enter_timestamp;
3264 bool need_daemon_reload;
3269 const char *status_text;
3270 const char *pid_file;
3274 usec_t start_timestamp;
3275 usec_t exit_timestamp;
3277 int exit_code, exit_status;
3279 usec_t condition_timestamp;
3280 bool condition_result;
3281 bool failed_condition_trigger;
3282 bool failed_condition_negate;
3283 const char *failed_condition;
3284 const char *failed_condition_parameter;
3286 usec_t assert_timestamp;
3288 bool failed_assert_trigger;
3289 bool failed_assert_negate;
3290 const char *failed_assert;
3291 const char *failed_assert_parameter;
3294 unsigned n_accepted;
3295 unsigned n_connections;
3298 /* Pairs of type, path */
3302 const char *sysfs_path;
3304 /* Mount, Automount */
3310 LIST_HEAD(ExecStatusInfo, exec);
3313 static void print_status_info(
3318 const char *active_on, *active_off, *on, *off, *ss;
3320 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3321 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3324 arg_all * OUTPUT_SHOW_ALL |
3325 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
3326 on_tty() * OUTPUT_COLOR |
3327 !arg_quiet * OUTPUT_WARN_CUTOFF |
3328 arg_full * OUTPUT_FULL_WIDTH;
3333 /* This shows pretty information about a unit. See
3334 * print_property() for a low-level property printer */
3336 if (streq_ptr(i->active_state, "failed")) {
3337 active_on = ansi_highlight_red();
3338 active_off = ansi_highlight_off();
3339 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3340 active_on = ansi_highlight_green();
3341 active_off = ansi_highlight_off();
3343 active_on = active_off = "";
3345 printf("%s%s%s %s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3347 if (i->description && !streq_ptr(i->id, i->description))
3348 printf(" - %s", i->description);
3353 printf(" Follow: unit currently follows state of %s\n", i->following);
3355 if (streq_ptr(i->load_state, "error")) {
3356 on = ansi_highlight_red();
3357 off = ansi_highlight_off();
3361 path = i->source_path ? i->source_path : i->fragment_path;
3364 printf(" Loaded: %s%s%s (Reason: %s)\n",
3365 on, strna(i->load_state), off, i->load_error);
3366 else if (path && !isempty(i->unit_file_state) && !isempty(i->unit_file_preset))
3367 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3368 on, strna(i->load_state), off, path, i->unit_file_state, i->unit_file_preset);
3369 else if (path && !isempty(i->unit_file_state))
3370 printf(" Loaded: %s%s%s (%s; %s)\n",
3371 on, strna(i->load_state), off, path, i->unit_file_state);
3373 printf(" Loaded: %s%s%s (%s)\n",
3374 on, strna(i->load_state), off, path);
3376 printf(" Loaded: %s%s%s\n",
3377 on, strna(i->load_state), off);
3379 if (!strv_isempty(i->dropin_paths)) {
3380 _cleanup_free_ char *dir = NULL;
3384 STRV_FOREACH(dropin, i->dropin_paths) {
3385 if (! dir || last) {
3386 printf(dir ? " " : " Drop-In: ");
3391 if (path_get_parent(*dropin, &dir) < 0) {
3396 printf("%s\n %s", dir,
3397 draw_special_char(DRAW_TREE_RIGHT));
3400 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3402 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3406 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3408 printf(" Active: %s%s (%s)%s",
3409 active_on, strna(i->active_state), ss, active_off);
3411 printf(" Active: %s%s%s",
3412 active_on, strna(i->active_state), active_off);
3414 if (!isempty(i->result) && !streq(i->result, "success"))
3415 printf(" (Result: %s)", i->result);
3417 timestamp = (streq_ptr(i->active_state, "active") ||
3418 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
3419 (streq_ptr(i->active_state, "inactive") ||
3420 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
3421 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
3422 i->active_exit_timestamp;
3424 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3425 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3428 printf(" since %s; %s\n", s2, s1);
3430 printf(" since %s\n", s2);
3434 if (!i->condition_result && i->condition_timestamp > 0) {
3435 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3436 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3438 printf("Condition: start %scondition failed%s at %s%s%s\n",
3439 ansi_highlight_yellow(), ansi_highlight_off(),
3440 s2, s1 ? "; " : "", s1 ? s1 : "");
3441 if (i->failed_condition_trigger)
3442 printf(" none of the trigger conditions were met\n");
3443 else if (i->failed_condition)
3444 printf(" %s=%s%s was not met\n",
3445 i->failed_condition,
3446 i->failed_condition_negate ? "!" : "",
3447 i->failed_condition_parameter);
3450 if (!i->assert_result && i->assert_timestamp > 0) {
3451 s1 = format_timestamp_relative(since1, sizeof(since1), i->assert_timestamp);
3452 s2 = format_timestamp(since2, sizeof(since2), i->assert_timestamp);
3454 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3455 ansi_highlight_red(), ansi_highlight_off(),
3456 s2, s1 ? "; " : "", s1 ? s1 : "");
3457 if (i->failed_assert_trigger)
3458 printf(" none of the trigger assertions were met\n");
3459 else if (i->failed_assert)
3460 printf(" %s=%s%s was not met\n",
3462 i->failed_assert_negate ? "!" : "",
3463 i->failed_assert_parameter);
3467 printf(" Device: %s\n", i->sysfs_path);
3469 printf(" Where: %s\n", i->where);
3471 printf(" What: %s\n", i->what);
3473 STRV_FOREACH(t, i->documentation)
3474 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3476 STRV_FOREACH_PAIR(t, t2, i->listen)
3477 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3480 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3482 LIST_FOREACH(exec, p, i->exec) {
3483 _cleanup_free_ char *argv = NULL;
3486 /* Only show exited processes here */
3490 argv = strv_join(p->argv, " ");
3491 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
3493 good = is_clean_exit_lsb(p->code, p->status, NULL);
3495 on = ansi_highlight_red();
3496 off = ansi_highlight_off();
3500 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3502 if (p->code == CLD_EXITED) {
3505 printf("status=%i", p->status);
3507 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3512 printf("signal=%s", signal_to_string(p->status));
3514 printf(")%s\n", off);
3516 if (i->main_pid == p->pid &&
3517 i->start_timestamp == p->start_timestamp &&
3518 i->exit_timestamp == p->start_timestamp)
3519 /* Let's not show this twice */
3522 if (p->pid == i->control_pid)
3526 if (i->main_pid > 0 || i->control_pid > 0) {
3527 if (i->main_pid > 0) {
3528 printf(" Main PID: "PID_FMT, i->main_pid);
3531 _cleanup_free_ char *comm = NULL;
3532 get_process_comm(i->main_pid, &comm);
3534 printf(" (%s)", comm);
3535 } else if (i->exit_code > 0) {
3536 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3538 if (i->exit_code == CLD_EXITED) {
3541 printf("status=%i", i->exit_status);
3543 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3548 printf("signal=%s", signal_to_string(i->exit_status));
3552 if (i->control_pid > 0)
3556 if (i->control_pid > 0) {
3557 _cleanup_free_ char *c = NULL;
3559 printf(" %8s: "PID_FMT, i->main_pid ? "" : " Control", i->control_pid);
3561 get_process_comm(i->control_pid, &c);
3570 printf(" Status: \"%s\"\n", i->status_text);
3571 if (i->status_errno > 0)
3572 printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
3574 if (i->control_group &&
3575 (i->main_pid > 0 || i->control_pid > 0 ||
3576 ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_CONTAINER) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3579 printf(" CGroup: %s\n", i->control_group);
3581 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
3584 static const char prefix[] = " ";
3587 if (c > sizeof(prefix) - 1)
3588 c -= sizeof(prefix) - 1;
3592 if (i->main_pid > 0)
3593 extra[k++] = i->main_pid;
3595 if (i->control_pid > 0)
3596 extra[k++] = i->control_pid;
3598 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, flags);
3602 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3603 show_journal_by_unit(stdout,
3607 i->inactive_exit_timestamp_monotonic,
3610 flags | OUTPUT_BEGIN_NEWLINE,
3611 arg_scope == UNIT_FILE_SYSTEM,
3615 if (i->need_daemon_reload)
3616 warn_unit_file_changed(i->id);
3619 static void show_unit_help(UnitStatusInfo *i) {
3624 if (!i->documentation) {
3625 log_info("Documentation for %s not known.", i->id);
3629 STRV_FOREACH(p, i->documentation)
3630 if (startswith(*p, "man:"))
3631 show_man_page(*p + 4, false);
3633 log_info("Can't show: %s", *p);
3636 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3643 switch (contents[0]) {
3645 case SD_BUS_TYPE_STRING: {
3648 r = sd_bus_message_read(m, "s", &s);
3650 return bus_log_parse_error(r);
3653 if (streq(name, "Id"))
3655 else if (streq(name, "LoadState"))
3657 else if (streq(name, "ActiveState"))
3658 i->active_state = s;
3659 else if (streq(name, "SubState"))
3661 else if (streq(name, "Description"))
3663 else if (streq(name, "FragmentPath"))
3664 i->fragment_path = s;
3665 else if (streq(name, "SourcePath"))
3668 else if (streq(name, "DefaultControlGroup")) {
3670 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3672 i->control_group = e;
3675 else if (streq(name, "ControlGroup"))
3676 i->control_group = s;
3677 else if (streq(name, "StatusText"))
3679 else if (streq(name, "PIDFile"))
3681 else if (streq(name, "SysFSPath"))
3683 else if (streq(name, "Where"))
3685 else if (streq(name, "What"))
3687 else if (streq(name, "Following"))
3689 else if (streq(name, "UnitFileState"))
3690 i->unit_file_state = s;
3691 else if (streq(name, "UnitFilePreset"))
3692 i->unit_file_preset = s;
3693 else if (streq(name, "Result"))
3700 case SD_BUS_TYPE_BOOLEAN: {
3703 r = sd_bus_message_read(m, "b", &b);
3705 return bus_log_parse_error(r);
3707 if (streq(name, "Accept"))
3709 else if (streq(name, "NeedDaemonReload"))
3710 i->need_daemon_reload = b;
3711 else if (streq(name, "ConditionResult"))
3712 i->condition_result = b;
3713 else if (streq(name, "AssertResult"))
3714 i->assert_result = b;
3719 case SD_BUS_TYPE_UINT32: {
3722 r = sd_bus_message_read(m, "u", &u);
3724 return bus_log_parse_error(r);
3726 if (streq(name, "MainPID")) {
3728 i->main_pid = (pid_t) u;
3731 } else if (streq(name, "ControlPID"))
3732 i->control_pid = (pid_t) u;
3733 else if (streq(name, "ExecMainPID")) {
3735 i->main_pid = (pid_t) u;
3736 } else if (streq(name, "NAccepted"))
3738 else if (streq(name, "NConnections"))
3739 i->n_connections = u;
3744 case SD_BUS_TYPE_INT32: {
3747 r = sd_bus_message_read(m, "i", &j);
3749 return bus_log_parse_error(r);
3751 if (streq(name, "ExecMainCode"))
3752 i->exit_code = (int) j;
3753 else if (streq(name, "ExecMainStatus"))
3754 i->exit_status = (int) j;
3755 else if (streq(name, "StatusErrno"))
3756 i->status_errno = (int) j;
3761 case SD_BUS_TYPE_UINT64: {
3764 r = sd_bus_message_read(m, "t", &u);
3766 return bus_log_parse_error(r);
3768 if (streq(name, "ExecMainStartTimestamp"))
3769 i->start_timestamp = (usec_t) u;
3770 else if (streq(name, "ExecMainExitTimestamp"))
3771 i->exit_timestamp = (usec_t) u;
3772 else if (streq(name, "ActiveEnterTimestamp"))
3773 i->active_enter_timestamp = (usec_t) u;
3774 else if (streq(name, "InactiveEnterTimestamp"))
3775 i->inactive_enter_timestamp = (usec_t) u;
3776 else if (streq(name, "InactiveExitTimestamp"))
3777 i->inactive_exit_timestamp = (usec_t) u;
3778 else if (streq(name, "InactiveExitTimestampMonotonic"))
3779 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3780 else if (streq(name, "ActiveExitTimestamp"))
3781 i->active_exit_timestamp = (usec_t) u;
3782 else if (streq(name, "ConditionTimestamp"))
3783 i->condition_timestamp = (usec_t) u;
3784 else if (streq(name, "AssertTimestamp"))
3785 i->assert_timestamp = (usec_t) u;
3790 case SD_BUS_TYPE_ARRAY:
3792 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3793 _cleanup_free_ ExecStatusInfo *info = NULL;
3795 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3797 return bus_log_parse_error(r);
3799 info = new0(ExecStatusInfo, 1);
3803 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3805 info->name = strdup(name);
3809 LIST_PREPEND(exec, i->exec, info);
3811 info = new0(ExecStatusInfo, 1);
3817 return bus_log_parse_error(r);
3819 r = sd_bus_message_exit_container(m);
3821 return bus_log_parse_error(r);
3825 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3826 const char *type, *path;
3828 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3830 return bus_log_parse_error(r);
3832 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3834 r = strv_extend(&i->listen, type);
3838 r = strv_extend(&i->listen, path);
3843 return bus_log_parse_error(r);
3845 r = sd_bus_message_exit_container(m);
3847 return bus_log_parse_error(r);
3851 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3853 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3855 return bus_log_parse_error(r);
3857 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3859 r = sd_bus_message_read_strv(m, &i->documentation);
3861 return bus_log_parse_error(r);
3863 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3864 const char *cond, *param;
3865 int trigger, negate;
3868 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3870 return bus_log_parse_error(r);
3872 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3873 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3874 if (state < 0 && (!trigger || !i->failed_condition)) {
3875 i->failed_condition = cond;
3876 i->failed_condition_trigger = trigger;
3877 i->failed_condition_negate = negate;
3878 i->failed_condition_parameter = param;
3882 return bus_log_parse_error(r);
3884 r = sd_bus_message_exit_container(m);
3886 return bus_log_parse_error(r);
3888 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Asserts")) {
3889 const char *cond, *param;
3890 int trigger, negate;
3893 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3895 return bus_log_parse_error(r);
3897 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3898 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3899 if (state < 0 && (!trigger || !i->failed_assert)) {
3900 i->failed_assert = cond;
3901 i->failed_assert_trigger = trigger;
3902 i->failed_assert_negate = negate;
3903 i->failed_assert_parameter = param;
3907 return bus_log_parse_error(r);
3909 r = sd_bus_message_exit_container(m);
3911 return bus_log_parse_error(r);
3918 case SD_BUS_TYPE_STRUCT_BEGIN:
3920 if (streq(name, "LoadError")) {
3921 const char *n, *message;
3923 r = sd_bus_message_read(m, "(ss)", &n, &message);
3925 return bus_log_parse_error(r);
3927 if (!isempty(message))
3928 i->load_error = message;
3941 r = sd_bus_message_skip(m, contents);
3943 return bus_log_parse_error(r);
3948 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3954 /* This is a low-level property printer, see
3955 * print_status_info() for the nicer output */
3957 if (arg_properties && !strv_find(arg_properties, name)) {
3958 /* skip what we didn't read */
3959 r = sd_bus_message_skip(m, contents);
3963 switch (contents[0]) {
3965 case SD_BUS_TYPE_STRUCT_BEGIN:
3967 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3970 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3972 return bus_log_parse_error(r);
3975 printf("%s=%"PRIu32"\n", name, u);
3977 printf("%s=\n", name);
3981 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3984 r = sd_bus_message_read(m, "(so)", &s, NULL);
3986 return bus_log_parse_error(r);
3988 if (arg_all || !isempty(s))
3989 printf("%s=%s\n", name, s);
3993 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3994 const char *a = NULL, *b = NULL;
3996 r = sd_bus_message_read(m, "(ss)", &a, &b);
3998 return bus_log_parse_error(r);
4000 if (arg_all || !isempty(a) || !isempty(b))
4001 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
4004 } else if (streq_ptr(name, "SystemCallFilter")) {
4005 _cleanup_strv_free_ char **l = NULL;
4008 r = sd_bus_message_enter_container(m, 'r', "bas");
4010 return bus_log_parse_error(r);
4012 r = sd_bus_message_read(m, "b", &whitelist);
4014 return bus_log_parse_error(r);
4016 r = sd_bus_message_read_strv(m, &l);
4018 return bus_log_parse_error(r);
4020 r = sd_bus_message_exit_container(m);
4022 return bus_log_parse_error(r);
4024 if (arg_all || whitelist || !strv_isempty(l)) {
4028 fputs(name, stdout);
4034 STRV_FOREACH(i, l) {
4042 fputc('\n', stdout);
4050 case SD_BUS_TYPE_ARRAY:
4052 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
4056 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
4058 return bus_log_parse_error(r);
4060 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
4061 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
4064 return bus_log_parse_error(r);
4066 r = sd_bus_message_exit_container(m);
4068 return bus_log_parse_error(r);
4072 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
4073 const char *type, *path;
4075 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4077 return bus_log_parse_error(r);
4079 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4080 printf("%s=%s\n", type, path);
4082 return bus_log_parse_error(r);
4084 r = sd_bus_message_exit_container(m);
4086 return bus_log_parse_error(r);
4090 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
4091 const char *type, *path;
4093 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4095 return bus_log_parse_error(r);
4097 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4098 printf("Listen%s=%s\n", type, path);
4100 return bus_log_parse_error(r);
4102 r = sd_bus_message_exit_container(m);
4104 return bus_log_parse_error(r);
4108 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
4110 uint64_t value, next_elapse;
4112 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
4114 return bus_log_parse_error(r);
4116 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
4117 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
4119 printf("%s={ value=%s ; next_elapse=%s }\n",
4121 format_timespan(timespan1, sizeof(timespan1), value, 0),
4122 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
4125 return bus_log_parse_error(r);
4127 r = sd_bus_message_exit_container(m);
4129 return bus_log_parse_error(r);
4133 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
4134 ExecStatusInfo info = {};
4136 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
4138 return bus_log_parse_error(r);
4140 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
4141 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
4142 _cleanup_free_ char *tt;
4144 tt = strv_join(info.argv, " ");
4146 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",
4150 yes_no(info.ignore),
4151 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
4152 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
4154 sigchld_code_to_string(info.code),
4156 info.code == CLD_EXITED ? "" : "/",
4157 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
4160 strv_free(info.argv);
4164 r = sd_bus_message_exit_container(m);
4166 return bus_log_parse_error(r);
4170 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
4171 const char *path, *rwm;
4173 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4175 return bus_log_parse_error(r);
4177 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
4178 printf("%s=%s %s\n", name, strna(path), strna(rwm));
4180 return bus_log_parse_error(r);
4182 r = sd_bus_message_exit_container(m);
4184 return bus_log_parse_error(r);
4188 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
4192 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4194 return bus_log_parse_error(r);
4196 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4197 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
4199 return bus_log_parse_error(r);
4201 r = sd_bus_message_exit_container(m);
4203 return bus_log_parse_error(r);
4207 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
4211 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4213 return bus_log_parse_error(r);
4215 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4216 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
4218 return bus_log_parse_error(r);
4220 r = sd_bus_message_exit_container(m);
4222 return bus_log_parse_error(r);
4230 r = bus_print_property(name, m, arg_all);
4232 return bus_log_parse_error(r);
4235 r = sd_bus_message_skip(m, contents);
4237 return bus_log_parse_error(r);
4240 printf("%s=[unprintable]\n", name);
4246 static int show_one(
4250 bool show_properties,
4254 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4255 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4256 UnitStatusInfo info = {};
4263 log_debug("Showing one %s", path);
4265 r = sd_bus_call_method(
4267 "org.freedesktop.systemd1",
4269 "org.freedesktop.DBus.Properties",
4275 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4279 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4281 return bus_log_parse_error(r);
4288 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4289 const char *name, *contents;
4291 r = sd_bus_message_read(reply, "s", &name);
4293 return bus_log_parse_error(r);
4295 r = sd_bus_message_peek_type(reply, NULL, &contents);
4297 return bus_log_parse_error(r);
4299 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4301 return bus_log_parse_error(r);
4303 if (show_properties)
4304 r = print_property(name, reply, contents);
4306 r = status_property(name, reply, &info, contents);
4310 r = sd_bus_message_exit_container(reply);
4312 return bus_log_parse_error(r);
4314 r = sd_bus_message_exit_container(reply);
4316 return bus_log_parse_error(r);
4319 return bus_log_parse_error(r);
4321 r = sd_bus_message_exit_container(reply);
4323 return bus_log_parse_error(r);
4327 if (!show_properties) {
4328 if (streq(verb, "help"))
4329 show_unit_help(&info);
4331 print_status_info(&info, ellipsized);
4334 strv_free(info.documentation);
4335 strv_free(info.dropin_paths);
4336 strv_free(info.listen);
4338 if (!streq_ptr(info.active_state, "active") &&
4339 !streq_ptr(info.active_state, "reloading") &&
4340 streq(verb, "status")) {
4341 /* According to LSB: "program not running" */
4342 /* 0: program is running or service is OK
4343 * 1: program is dead and /run PID file exists
4344 * 2: program is dead and /run/lock lock file exists
4345 * 3: program is not running
4346 * 4: program or service status is unknown
4348 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4354 while ((p = info.exec)) {
4355 LIST_REMOVE(exec, info.exec, p);
4356 exec_status_info_free(p);
4362 static int get_unit_dbus_path_by_pid(
4367 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4368 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4372 r = sd_bus_call_method(
4374 "org.freedesktop.systemd1",
4375 "/org/freedesktop/systemd1",
4376 "org.freedesktop.systemd1.Manager",
4382 log_error("Failed to get unit for PID "PID_FMT": %s", pid, bus_error_message(&error, r));
4386 r = sd_bus_message_read(reply, "o", &u);
4388 return bus_log_parse_error(r);
4398 static int show_all(
4401 bool show_properties,
4405 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4406 _cleanup_free_ UnitInfo *unit_infos = NULL;
4411 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4415 pager_open_if_enabled();
4419 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4421 for (u = unit_infos; u < unit_infos + c; u++) {
4422 _cleanup_free_ char *p = NULL;
4424 p = unit_dbus_path_from_name(u->id);
4428 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4431 else if (r > 0 && ret == 0)
4438 static int show_system_status(sd_bus *bus) {
4439 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4440 _cleanup_free_ char *hn = NULL;
4441 struct machine_info mi = {};
4442 const char *on, *off;
4445 hn = gethostname_malloc();
4449 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4451 return log_error_errno(r, "Failed to read server status: %m");
4453 if (streq_ptr(mi.state, "degraded")) {
4454 on = ansi_highlight_red();
4455 off = ansi_highlight_off();
4456 } else if (!streq_ptr(mi.state, "running")) {
4457 on = ansi_highlight_yellow();
4458 off = ansi_highlight_off();
4462 printf("%s%s%s %s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4464 printf(" State: %s%s%s\n",
4465 on, strna(mi.state), off);
4467 printf(" Jobs: %u queued\n", mi.n_jobs);
4468 printf(" Failed: %u units\n", mi.n_failed_units);
4470 printf(" Since: %s; %s\n",
4471 format_timestamp(since2, sizeof(since2), mi.timestamp),
4472 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4474 printf(" CGroup: %s\n", mi.control_group ?: "/");
4475 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
4477 arg_all * OUTPUT_SHOW_ALL |
4478 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
4479 on_tty() * OUTPUT_COLOR |
4480 !arg_quiet * OUTPUT_WARN_CUTOFF |
4481 arg_full * OUTPUT_FULL_WIDTH;
4483 static const char prefix[] = " ";
4487 if (c > sizeof(prefix) - 1)
4488 c -= sizeof(prefix) - 1;
4492 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
4496 free(mi.control_group);
4501 static int show(sd_bus *bus, char **args) {
4502 bool show_properties, show_status, new_line = false;
4503 bool ellipsized = false;
4509 show_properties = streq(args[0], "show");
4510 show_status = streq(args[0], "status");
4512 if (show_properties)
4513 pager_open_if_enabled();
4515 /* If no argument is specified inspect the manager itself */
4517 if (show_properties && strv_length(args) <= 1)
4518 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4520 if (show_status && strv_length(args) <= 1) {
4522 pager_open_if_enabled();
4523 show_system_status(bus);
4527 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4529 _cleanup_free_ char **patterns = NULL;
4532 STRV_FOREACH(name, args + 1) {
4533 _cleanup_free_ char *unit = NULL;
4536 if (safe_atou32(*name, &id) < 0) {
4537 if (strv_push(&patterns, *name) < 0)
4541 } else if (show_properties) {
4542 /* Interpret as job id */
4543 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4547 /* Interpret as PID */
4548 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4555 r = show_one(args[0], bus, unit, show_properties,
4556 &new_line, &ellipsized);
4559 else if (r > 0 && ret == 0)
4563 if (!strv_isempty(patterns)) {
4564 _cleanup_strv_free_ char **names = NULL;
4566 r = expand_names(bus, patterns, NULL, &names);
4568 log_error_errno(r, "Failed to expand names: %m");
4570 STRV_FOREACH(name, names) {
4571 _cleanup_free_ char *unit;
4573 unit = unit_dbus_path_from_name(*name);
4577 r = show_one(args[0], bus, unit, show_properties,
4578 &new_line, &ellipsized);
4581 else if (r > 0 && ret == 0)
4587 if (ellipsized && !arg_quiet)
4588 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4593 static int cat(sd_bus *bus, char **args) {
4594 _cleanup_strv_free_ char **names = NULL;
4602 r = expand_names(bus, args + 1, NULL, &names);
4604 log_error_errno(r, "Failed to expand names: %m");
4606 pager_open_if_enabled();
4608 STRV_FOREACH(name, names) {
4609 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4610 _cleanup_strv_free_ char **dropin_paths = NULL;
4611 _cleanup_free_ char *fragment_path = NULL, *unit = NULL;
4614 unit = unit_dbus_path_from_name(*name);
4618 if (need_daemon_reload(bus, *name) > 0)
4619 warn_unit_file_changed(*name);
4621 r = sd_bus_get_property_string(
4623 "org.freedesktop.systemd1",
4625 "org.freedesktop.systemd1.Unit",
4630 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
4634 r = sd_bus_get_property_strv(
4636 "org.freedesktop.systemd1",
4638 "org.freedesktop.systemd1.Unit",
4643 log_warning("Failed to get DropInPaths: %s", bus_error_message(&error, r));
4652 if (!isempty(fragment_path)) {
4653 printf("%s# %s%s\n",
4654 ansi_highlight_blue(),
4656 ansi_highlight_off());
4659 r = copy_file_fd(fragment_path, STDOUT_FILENO, false);
4661 log_warning_errno(r, "Failed to cat %s: %m", fragment_path);
4666 STRV_FOREACH(path, dropin_paths) {
4667 printf("%s%s# %s%s\n",
4668 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4669 ansi_highlight_blue(),
4671 ansi_highlight_off());
4674 r = copy_file_fd(*path, STDOUT_FILENO, false);
4676 log_warning_errno(r, "Failed to cat %s: %m", *path);
4682 return r < 0 ? r : 0;
4685 static int set_property(sd_bus *bus, char **args) {
4686 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4687 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4688 _cleanup_free_ char *n = NULL;
4692 r = sd_bus_message_new_method_call(
4695 "org.freedesktop.systemd1",
4696 "/org/freedesktop/systemd1",
4697 "org.freedesktop.systemd1.Manager",
4698 "SetUnitProperties");
4700 return bus_log_create_error(r);
4702 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4704 return bus_log_create_error(r);
4706 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4710 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4712 return bus_log_create_error(r);
4714 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4716 return bus_log_create_error(r);
4718 STRV_FOREACH(i, args + 2) {
4719 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4721 return bus_log_create_error(r);
4723 r = bus_append_unit_property_assignment(m, *i);
4727 r = sd_bus_message_close_container(m);
4729 return bus_log_create_error(r);
4732 r = sd_bus_message_close_container(m);
4734 return bus_log_create_error(r);
4736 r = sd_bus_call(bus, m, 0, &error, NULL);
4738 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4745 static int snapshot(sd_bus *bus, char **args) {
4746 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4747 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
4748 _cleanup_free_ char *n = NULL, *id = NULL;
4752 if (strv_length(args) > 1)
4753 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4759 r = sd_bus_message_new_method_call(
4762 "org.freedesktop.systemd1",
4763 "/org/freedesktop/systemd1",
4764 "org.freedesktop.systemd1.Manager",
4767 return bus_log_create_error(r);
4769 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4771 return bus_log_create_error(r);
4773 r = sd_bus_message_append(m, "sb", n, false);
4775 return bus_log_create_error(r);
4777 r = sd_bus_call(bus, m, 0, &error, &reply);
4779 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4783 r = sd_bus_message_read(reply, "o", &path);
4785 return bus_log_parse_error(r);
4787 r = sd_bus_get_property_string(
4789 "org.freedesktop.systemd1",
4791 "org.freedesktop.systemd1.Unit",
4796 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4806 static int delete_snapshot(sd_bus *bus, char **args) {
4807 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4808 _cleanup_strv_free_ char **names = NULL;
4814 r = expand_names(bus, args + 1, ".snapshot", &names);
4816 log_error_errno(r, "Failed to expand names: %m");
4818 STRV_FOREACH(name, names) {
4819 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4822 q = sd_bus_message_new_method_call(
4825 "org.freedesktop.systemd1",
4826 "/org/freedesktop/systemd1",
4827 "org.freedesktop.systemd1.Manager",
4830 return bus_log_create_error(q);
4832 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4834 return bus_log_create_error(q);
4836 q = sd_bus_message_append(m, "s", *name);
4838 return bus_log_create_error(q);
4840 q = sd_bus_call(bus, m, 0, &error, NULL);
4842 log_error("Failed to remove snapshot %s: %s", *name, bus_error_message(&error, q));
4851 static int daemon_reload(sd_bus *bus, char **args) {
4852 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4853 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4857 if (arg_action == ACTION_RELOAD)
4859 else if (arg_action == ACTION_REEXEC)
4860 method = "Reexecute";
4862 assert(arg_action == ACTION_SYSTEMCTL);
4865 streq(args[0], "clear-jobs") ||
4866 streq(args[0], "cancel") ? "ClearJobs" :
4867 streq(args[0], "daemon-reexec") ? "Reexecute" :
4868 streq(args[0], "reset-failed") ? "ResetFailed" :
4869 streq(args[0], "halt") ? "Halt" :
4870 streq(args[0], "poweroff") ? "PowerOff" :
4871 streq(args[0], "reboot") ? "Reboot" :
4872 streq(args[0], "kexec") ? "KExec" :
4873 streq(args[0], "exit") ? "Exit" :
4874 /* "daemon-reload" */ "Reload";
4877 r = sd_bus_message_new_method_call(
4880 "org.freedesktop.systemd1",
4881 "/org/freedesktop/systemd1",
4882 "org.freedesktop.systemd1.Manager",
4885 return bus_log_create_error(r);
4887 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4889 return bus_log_create_error(r);
4891 r = sd_bus_call(bus, m, 0, &error, NULL);
4892 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4893 /* There's always a fallback possible for
4894 * legacy actions. */
4896 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4897 /* On reexecution, we expect a disconnect, not a
4901 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4903 return r < 0 ? r : 0;
4906 static int reset_failed(sd_bus *bus, char **args) {
4907 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4908 _cleanup_strv_free_ char **names = NULL;
4912 if (strv_length(args) <= 1)
4913 return daemon_reload(bus, args);
4915 r = expand_names(bus, args + 1, NULL, &names);
4917 log_error_errno(r, "Failed to expand names: %m");
4919 STRV_FOREACH(name, names) {
4920 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4922 q = sd_bus_message_new_method_call(
4925 "org.freedesktop.systemd1",
4926 "/org/freedesktop/systemd1",
4927 "org.freedesktop.systemd1.Manager",
4930 return bus_log_create_error(q);
4932 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4934 return bus_log_create_error(q);
4936 q = sd_bus_message_append(m, "s", *name);
4938 return bus_log_create_error(q);
4940 q = sd_bus_call(bus, m, 0, &error, NULL);
4942 log_error("Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q));
4951 static int show_environment(sd_bus *bus, char **args) {
4952 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4953 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4957 pager_open_if_enabled();
4959 r = sd_bus_get_property(
4961 "org.freedesktop.systemd1",
4962 "/org/freedesktop/systemd1",
4963 "org.freedesktop.systemd1.Manager",
4969 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4973 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4975 return bus_log_parse_error(r);
4977 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4980 return bus_log_parse_error(r);
4982 r = sd_bus_message_exit_container(reply);
4984 return bus_log_parse_error(r);
4989 static int switch_root(sd_bus *bus, char **args) {
4990 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4991 _cleanup_free_ char *cmdline_init = NULL;
4992 const char *root, *init;
4996 l = strv_length(args);
4997 if (l < 2 || l > 3) {
4998 log_error("Wrong number of arguments.");
5007 r = parse_env_file("/proc/cmdline", WHITESPACE,
5008 "init", &cmdline_init,
5011 log_debug_errno(r, "Failed to parse /proc/cmdline: %m");
5013 init = cmdline_init;
5020 const char *root_systemd_path = NULL, *root_init_path = NULL;
5022 root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
5023 root_init_path = strappenda(root, "/", init);
5025 /* If the passed init is actually the same as the
5026 * systemd binary, then let's suppress it. */
5027 if (files_same(root_init_path, root_systemd_path) > 0)
5031 log_debug("Switching root - root: %s; init: %s", root, strna(init));
5033 r = sd_bus_call_method(
5035 "org.freedesktop.systemd1",
5036 "/org/freedesktop/systemd1",
5037 "org.freedesktop.systemd1.Manager",
5043 log_error("Failed to switch root: %s", bus_error_message(&error, r));
5050 static int set_environment(sd_bus *bus, char **args) {
5051 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5052 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
5059 method = streq(args[0], "set-environment")
5061 : "UnsetEnvironment";
5063 r = sd_bus_message_new_method_call(
5066 "org.freedesktop.systemd1",
5067 "/org/freedesktop/systemd1",
5068 "org.freedesktop.systemd1.Manager",
5071 return bus_log_create_error(r);
5073 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5075 return bus_log_create_error(r);
5077 r = sd_bus_message_append_strv(m, args + 1);
5079 return bus_log_create_error(r);
5081 r = sd_bus_call(bus, m, 0, &error, NULL);
5083 log_error("Failed to set environment: %s", bus_error_message(&error, r));
5090 static int import_environment(sd_bus *bus, char **args) {
5091 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5092 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
5098 r = sd_bus_message_new_method_call(
5101 "org.freedesktop.systemd1",
5102 "/org/freedesktop/systemd1",
5103 "org.freedesktop.systemd1.Manager",
5106 return bus_log_create_error(r);
5108 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5110 return bus_log_create_error(r);
5112 if (strv_isempty(args + 1))
5113 r = sd_bus_message_append_strv(m, environ);
5117 r = sd_bus_message_open_container(m, 'a', "s");
5119 return bus_log_create_error(r);
5121 STRV_FOREACH(a, args + 1) {
5123 if (!env_name_is_valid(*a)) {
5124 log_error("Not a valid environment variable name: %s", *a);
5128 STRV_FOREACH(b, environ) {
5131 eq = startswith(*b, *a);
5132 if (eq && *eq == '=') {
5134 r = sd_bus_message_append(m, "s", *b);
5136 return bus_log_create_error(r);
5143 r = sd_bus_message_close_container(m);
5146 return bus_log_create_error(r);
5148 r = sd_bus_call(bus, m, 0, &error, NULL);
5150 log_error("Failed to import environment: %s", bus_error_message(&error, r));
5157 static int enable_sysv_units(const char *verb, char **args) {
5160 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
5162 _cleanup_lookup_paths_free_ LookupPaths paths = {};
5164 if (arg_scope != UNIT_FILE_SYSTEM)
5167 if (!streq(verb, "enable") &&
5168 !streq(verb, "disable") &&
5169 !streq(verb, "is-enabled"))
5172 /* Processes all SysV units, and reshuffles the array so that
5173 * afterwards only the native units remain */
5175 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, arg_root, NULL, NULL, NULL);
5182 _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL;
5183 bool found_native = false, found_sysv;
5185 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
5193 if (!endswith(name, ".service"))
5196 if (path_is_absolute(name))
5199 STRV_FOREACH(k, paths.unit_path) {
5200 _cleanup_free_ char *path = NULL;
5202 path = path_join(arg_root, *k, name);
5206 found_native = access(path, F_OK) >= 0;
5214 p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name);
5218 p[strlen(p) - strlen(".service")] = 0;
5219 found_sysv = access(p, F_OK) >= 0;
5223 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
5225 if (!isempty(arg_root))
5226 argv[c++] = q = strappend("--root=", arg_root);
5228 argv[c++] = basename(p);
5230 streq(verb, "enable") ? "on" :
5231 streq(verb, "disable") ? "off" : "--level=5";
5234 l = strv_join((char**)argv, " ");
5238 log_info("Executing %s", l);
5242 return log_error_errno(errno, "Failed to fork: %m");
5243 else if (pid == 0) {
5246 execv(argv[0], (char**) argv);
5247 _exit(EXIT_FAILURE);
5250 j = wait_for_terminate(pid, &status);
5252 log_error_errno(r, "Failed to wait for child: %m");
5256 if (status.si_code == CLD_EXITED) {
5257 if (streq(verb, "is-enabled")) {
5258 if (status.si_status == 0) {
5267 } else if (status.si_status != 0)
5272 /* Remove this entry, so that we don't try enabling it as native unit */
5273 assert(f > 0 && streq(args[f-1], name));
5274 assert_se(strv_remove(args + f - 1, name));
5281 static int mangle_names(char **original_names, char ***mangled_names) {
5282 char **i, **l, **name;
5284 l = new(char*, strv_length(original_names) + 1);
5289 STRV_FOREACH(name, original_names) {
5291 /* When enabling units qualified path names are OK,
5292 * too, hence allow them explicitly. */
5297 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5313 static int enable_unit(sd_bus *bus, char **args) {
5314 _cleanup_strv_free_ char **names = NULL;
5315 const char *verb = args[0];
5316 UnitFileChange *changes = NULL;
5317 unsigned n_changes = 0;
5318 int carries_install_info = -1;
5324 r = mangle_names(args+1, &names);
5328 r = enable_sysv_units(verb, names);
5332 /* If the operation was fully executed by the SysV compat,
5333 * let's finish early */
5334 if (strv_isempty(names))
5337 if (!bus || avoid_bus()) {
5338 if (streq(verb, "enable")) {
5339 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5340 carries_install_info = r;
5341 } else if (streq(verb, "disable"))
5342 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5343 else if (streq(verb, "reenable")) {
5344 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5345 carries_install_info = r;
5346 } else if (streq(verb, "link"))
5347 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5348 else if (streq(verb, "preset")) {
5349 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_preset_mode, arg_force, &changes, &n_changes);
5350 carries_install_info = r;
5351 } else if (streq(verb, "mask"))
5352 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5353 else if (streq(verb, "unmask"))
5354 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5356 assert_not_reached("Unknown verb");
5359 log_error_errno(r, "Operation failed: %m");
5364 dump_unit_file_changes(changes, n_changes);
5368 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5369 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5370 int expect_carries_install_info = false;
5371 bool send_force = true, send_preset_mode = false;
5374 if (streq(verb, "enable")) {
5375 method = "EnableUnitFiles";
5376 expect_carries_install_info = true;
5377 } else if (streq(verb, "disable")) {
5378 method = "DisableUnitFiles";
5380 } else if (streq(verb, "reenable")) {
5381 method = "ReenableUnitFiles";
5382 expect_carries_install_info = true;
5383 } else if (streq(verb, "link"))
5384 method = "LinkUnitFiles";
5385 else if (streq(verb, "preset")) {
5387 if (arg_preset_mode != UNIT_FILE_PRESET_FULL) {
5388 method = "PresetUnitFilesWithMode";
5389 send_preset_mode = true;
5391 method = "PresetUnitFiles";
5393 expect_carries_install_info = true;
5394 } else if (streq(verb, "mask"))
5395 method = "MaskUnitFiles";
5396 else if (streq(verb, "unmask")) {
5397 method = "UnmaskUnitFiles";
5400 assert_not_reached("Unknown verb");
5402 r = sd_bus_message_new_method_call(
5405 "org.freedesktop.systemd1",
5406 "/org/freedesktop/systemd1",
5407 "org.freedesktop.systemd1.Manager",
5410 return bus_log_create_error(r);
5412 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5414 return bus_log_create_error(r);
5416 r = sd_bus_message_append_strv(m, names);
5418 return bus_log_create_error(r);
5420 if (send_preset_mode) {
5421 r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode));
5423 return bus_log_create_error(r);
5426 r = sd_bus_message_append(m, "b", arg_runtime);
5428 return bus_log_create_error(r);
5431 r = sd_bus_message_append(m, "b", arg_force);
5433 return bus_log_create_error(r);
5436 r = sd_bus_call(bus, m, 0, &error, &reply);
5438 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5442 if (expect_carries_install_info) {
5443 r = sd_bus_message_read(reply, "b", &carries_install_info);
5445 return bus_log_parse_error(r);
5448 r = deserialize_and_dump_unit_file_changes(reply);
5452 /* Try to reload if enabled */
5454 r = daemon_reload(bus, args);
5459 if (carries_install_info == 0)
5460 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5461 "using systemctl.\n"
5462 "Possible reasons for having this kind of units are:\n"
5463 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5464 " .wants/ or .requires/ directory.\n"
5465 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5466 " a requirement dependency on it.\n"
5467 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5468 " D-Bus, udev, scripted systemctl call, ...).\n");
5471 unit_file_changes_free(changes, n_changes);
5476 static int add_dependency(sd_bus *bus, char **args) {
5477 _cleanup_strv_free_ char **names = NULL;
5478 _cleanup_free_ char *target = NULL;
5479 const char *verb = args[0];
5486 target = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
5490 r = mangle_names(args+2, &names);
5494 if (streq(verb, "add-wants"))
5496 else if (streq(verb, "add-requires"))
5497 dep = UNIT_REQUIRES;
5499 assert_not_reached("Unknown verb");
5501 if (!bus || avoid_bus()) {
5502 UnitFileChange *changes = NULL;
5503 unsigned n_changes = 0;
5505 r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes);
5508 return log_error_errno(r, "Can't add dependency: %m");
5511 dump_unit_file_changes(changes, n_changes);
5513 unit_file_changes_free(changes, n_changes);
5516 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5517 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5519 r = sd_bus_message_new_method_call(
5522 "org.freedesktop.systemd1",
5523 "/org/freedesktop/systemd1",
5524 "org.freedesktop.systemd1.Manager",
5525 "AddDependencyUnitFiles");
5527 return bus_log_create_error(r);
5529 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5531 return bus_log_create_error(r);
5533 r = sd_bus_message_append_strv(m, names);
5535 return bus_log_create_error(r);
5537 r = sd_bus_message_append(m, "ssbb", target, unit_dependency_to_string(dep), arg_runtime, arg_force);
5539 return bus_log_create_error(r);
5541 r = sd_bus_call(bus, m, 0, &error, &reply);
5543 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5547 r = deserialize_and_dump_unit_file_changes(reply);
5552 r = daemon_reload(bus, args);
5560 static int preset_all(sd_bus *bus, char **args) {
5561 UnitFileChange *changes = NULL;
5562 unsigned n_changes = 0;
5565 if (!bus || avoid_bus()) {
5567 r = unit_file_preset_all(arg_scope, arg_runtime, arg_root, arg_preset_mode, arg_force, &changes, &n_changes);
5569 log_error_errno(r, "Operation failed: %m");
5574 dump_unit_file_changes(changes, n_changes);
5579 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
5580 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5582 r = sd_bus_message_new_method_call(
5585 "org.freedesktop.systemd1",
5586 "/org/freedesktop/systemd1",
5587 "org.freedesktop.systemd1.Manager",
5588 "PresetAllUnitFiles");
5590 return bus_log_create_error(r);
5592 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5594 return bus_log_create_error(r);
5596 r = sd_bus_message_append(
5599 unit_file_preset_mode_to_string(arg_preset_mode),
5603 return bus_log_create_error(r);
5605 r = sd_bus_call(bus, m, 0, &error, &reply);
5607 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5611 r = deserialize_and_dump_unit_file_changes(reply);
5616 r = daemon_reload(bus, args);
5622 unit_file_changes_free(changes, n_changes);
5627 static int unit_is_enabled(sd_bus *bus, char **args) {
5629 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5630 _cleanup_strv_free_ char **names = NULL;
5635 r = mangle_names(args+1, &names);
5639 r = enable_sysv_units(args[0], names);
5645 if (!bus || avoid_bus()) {
5647 STRV_FOREACH(name, names) {
5648 UnitFileState state;
5650 state = unit_file_get_state(arg_scope, arg_root, *name);
5652 return log_error_errno(state, "Failed to get unit file state for %s: %m", *name);
5654 if (state == UNIT_FILE_ENABLED ||
5655 state == UNIT_FILE_ENABLED_RUNTIME ||
5656 state == UNIT_FILE_STATIC ||
5657 state == UNIT_FILE_INDIRECT)
5661 puts(unit_file_state_to_string(state));
5665 STRV_FOREACH(name, names) {
5666 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5669 r = sd_bus_call_method(
5671 "org.freedesktop.systemd1",
5672 "/org/freedesktop/systemd1",
5673 "org.freedesktop.systemd1.Manager",
5679 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5683 r = sd_bus_message_read(reply, "s", &s);
5685 return bus_log_parse_error(r);
5687 if (STR_IN_SET(s, "enabled", "enabled-runtime", "static", "indirect"))
5698 static int is_system_running(sd_bus *bus, char **args) {
5699 _cleanup_free_ char *state = NULL;
5702 r = sd_bus_get_property_string(
5704 "org.freedesktop.systemd1",
5705 "/org/freedesktop/systemd1",
5706 "org.freedesktop.systemd1.Manager",
5719 return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE;
5722 static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **unit_path) {
5729 STRV_FOREACH(p, lp->unit_path) {
5732 path = path_join(arg_root, *p, unit_name);
5736 if (access(path, F_OK) == 0) {
5747 static int create_edit_temp_file(const char *new_path, const char *original_path, char **ret_tmp_fn) {
5752 assert(original_path);
5755 r = tempfn_random(new_path, &t);
5757 return log_error_errno(r, "Failed to determine temporary filename for %s: %m", new_path);
5759 r = mkdir_parents(new_path, 0755);
5761 log_error_errno(r, "Failed to create directories for %s: %m", new_path);
5766 r = copy_file(original_path, t, 0, 0644);
5770 log_error_errno(r, "Failed to create temporary file %s: %m", t);
5775 log_error_errno(r, "Failed to copy %s to %s: %m", original_path, t);
5785 static int get_drop_in_to_edit(const char *unit_name, const char *user_home, const char *user_runtime, char **ret_path) {
5792 switch (arg_scope) {
5793 case UNIT_FILE_SYSTEM:
5794 tmp = strappenda(arg_runtime ? "/run/systemd/system/" : SYSTEM_CONFIG_UNIT_PATH "/", unit_name, ".d/override.conf");
5796 case UNIT_FILE_GLOBAL:
5797 tmp = strappenda(arg_runtime ? "/run/systemd/user/" : USER_CONFIG_UNIT_PATH "/", unit_name, ".d/override.conf");
5799 case UNIT_FILE_USER:
5801 assert(user_runtime);
5803 tmp = strappenda(arg_runtime ? user_runtime : user_home, "/", unit_name, ".d/override.conf");
5806 assert_not_reached("Invalid scope");
5809 tmp_new_path = path_join(arg_root, tmp, NULL);
5813 *ret_path = tmp_new_path;
5818 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) {
5824 assert(ret_new_path);
5825 assert(ret_tmp_path);
5827 r = get_drop_in_to_edit(unit_name, user_home, user_runtime, &tmp_new_path);
5831 r = create_edit_temp_file(tmp_new_path, tmp_new_path, &tmp_tmp_path);
5837 *ret_new_path = tmp_new_path;
5838 *ret_tmp_path = tmp_tmp_path;
5843 static bool unit_is_editable(const char *unit_name, const char *fragment_path, const char *user_home) {
5844 bool editable = true;
5845 const char *invalid_path;
5852 switch (arg_scope) {
5853 case UNIT_FILE_SYSTEM:
5854 if (path_startswith(fragment_path, "/etc/systemd/system")) {
5856 invalid_path = "/etc/systemd/system";
5857 } else if (path_startswith(fragment_path, SYSTEM_CONFIG_UNIT_PATH)) {
5859 invalid_path = SYSTEM_CONFIG_UNIT_PATH;
5862 case UNIT_FILE_GLOBAL:
5863 if (path_startswith(fragment_path, "/etc/systemd/user")) {
5865 invalid_path = "/etc/systemd/user";
5866 } else if (path_startswith(fragment_path, USER_CONFIG_UNIT_PATH)) {
5868 invalid_path = USER_CONFIG_UNIT_PATH;
5871 case UNIT_FILE_USER:
5874 if (path_startswith(fragment_path, "/etc/systemd/user")) {
5876 invalid_path = "/etc/systemd/user";
5877 } else if (path_startswith(fragment_path, USER_CONFIG_UNIT_PATH)) {
5879 invalid_path = USER_CONFIG_UNIT_PATH;
5880 } else if (path_startswith(fragment_path, user_home)) {
5882 invalid_path = user_home;
5886 assert_not_reached("Invalid scope");
5890 log_error("%s ignored: cannot temporarily edit units from %s", unit_name, invalid_path);
5895 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) {
5901 if (!unit_is_editable(unit_name, fragment_path, user_home))
5904 switch (arg_scope) {
5905 case UNIT_FILE_SYSTEM:
5906 tmp_new_path = path_join(arg_root, arg_runtime ? "/run/systemd/system/" : SYSTEM_CONFIG_UNIT_PATH, unit_name);
5908 case UNIT_FILE_GLOBAL:
5909 tmp_new_path = path_join(arg_root, arg_runtime ? "/run/systemd/user/" : USER_CONFIG_UNIT_PATH, unit_name);
5911 case UNIT_FILE_USER:
5913 assert(user_runtime);
5915 tmp_new_path = path_join(arg_root, arg_runtime ? user_runtime : user_home, unit_name);
5918 assert_not_reached("Invalid scope");
5923 *ret_path = tmp_new_path;
5928 static int unit_file_create_copy(const char *unit_name,
5929 const char *fragment_path,
5930 const char *user_home,
5931 const char *user_runtime,
5932 char **ret_new_path,
5933 char **ret_tmp_path) {
5938 assert(fragment_path);
5940 assert(ret_new_path);
5941 assert(ret_tmp_path);
5943 r = get_copy_to_edit(unit_name, fragment_path, user_home, user_runtime, &tmp_new_path);
5947 if (!path_equal(fragment_path, tmp_new_path) && access(tmp_new_path, F_OK) == 0) {
5950 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);
5955 if (response != 'y') {
5956 log_warning("%s ignored", unit_name);
5962 r = create_edit_temp_file(tmp_new_path, fragment_path, &tmp_tmp_path);
5964 log_error_errno(r, "Failed to create temporary file for %s: %m", tmp_new_path);
5969 *ret_new_path = tmp_new_path;
5970 *ret_tmp_path = tmp_tmp_path;
5975 static int run_editor(char **paths) {
5983 log_error_errno(errno, "Failed to fork: %m");
5989 char **backup_editors = STRV_MAKE("nano", "vim", "vi");
5991 char **tmp_path, **original_path, **p;
5995 argc = strv_length(paths)/2 + 1;
5996 args = newa(const char*, argc + 1);
5999 STRV_FOREACH_PAIR(original_path, tmp_path, paths) {
6000 args[i] = *tmp_path;
6005 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
6006 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
6007 * we try to execute well known editors
6009 editor = getenv("SYSTEMD_EDITOR");
6011 editor = getenv("EDITOR");
6013 editor = getenv("VISUAL");
6015 if (!isempty(editor)) {
6017 execvp(editor, (char* const*) args);
6020 STRV_FOREACH(p, backup_editors) {
6022 execvp(*p, (char* const*) args);
6023 /* We do not fail if the editor doesn't exist
6024 * because we want to try each one of them before
6027 if (errno != ENOENT) {
6028 log_error("Failed to execute %s: %m", editor);
6029 _exit(EXIT_FAILURE);
6033 log_error("Cannot edit unit(s): No editor available. Please set either SYSTEMD_EDITOR or EDITOR or VISUAL environment variable");
6034 _exit(EXIT_FAILURE);
6037 r = wait_for_terminate_and_warn("editor", pid, true);
6039 return log_error_errno(r, "Failed to wait for child: %m");
6044 static int unit_find_path(sd_bus *bus, const char *unit_name, const char *template, bool avoid_bus_cache, LookupPaths *lp, char **path) {
6051 if (!avoid_bus_cache && !unit_name_is_template(unit_name)) {
6052 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
6053 _cleanup_free_ char *unit = NULL;
6054 _cleanup_free_ char *tmp_path = NULL;
6056 unit = unit_dbus_path_from_name(unit_name);
6060 if (need_daemon_reload(bus, unit_name) > 0) {
6061 warn_unit_file_changed(unit_name);
6065 r = sd_bus_get_property_string(
6067 "org.freedesktop.systemd1",
6069 "org.freedesktop.systemd1.Unit",
6074 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
6078 if (isempty(tmp_path)) {
6079 log_warning("%s ignored: not found", template);
6088 r = unit_file_find_path(lp, template, path);
6090 log_warning("%s ignored: not found", template);
6097 static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
6098 _cleanup_free_ char *user_home = NULL;
6099 _cleanup_free_ char *user_runtime = NULL;
6100 _cleanup_lookup_paths_free_ LookupPaths lp = {};
6101 bool avoid_bus_cache;
6108 if (arg_scope == UNIT_FILE_USER) {
6109 r = user_config_home(&user_home);
6111 return log_error_errno(r, "Failed to query XDG_CONFIG_HOME: %m");
6113 return log_error_errno(ENOTDIR, "Cannot edit units: $XDG_CONFIG_HOME and $HOME are not set.");
6115 r = user_runtime_dir(&user_runtime);
6117 return log_error_errno(r, "Failed to query XDG_CONFIG_HOME: %m");
6119 return log_error_errno(ENOTDIR, "Cannot edit units: $XDG_RUNTIME_DIR is not set.");
6122 r = lookup_paths_init(&lp,
6123 arg_scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
6124 arg_scope == UNIT_FILE_USER,
6128 return log_error_errno(r, "Failed get lookup paths: %m");
6130 avoid_bus_cache = !bus || avoid_bus();
6132 STRV_FOREACH(name, names) {
6133 _cleanup_free_ char *path = NULL;
6134 _cleanup_free_ char *template = NULL;
6135 char *new_path, *tmp_path;
6137 template = unit_name_template(*name);
6141 r = unit_find_path(bus, *name, template, avoid_bus_cache, &lp, &path);
6149 r = unit_file_create_copy(template, path, user_home, user_runtime, &new_path, &tmp_path);
6151 r = unit_file_create_drop_in(template, user_home, user_runtime, &new_path, &tmp_path);
6156 r = strv_push_pair(paths, new_path, tmp_path);
6164 static int edit(sd_bus *bus, char **args) {
6165 _cleanup_strv_free_ char **names = NULL;
6166 _cleanup_strv_free_ char **paths = NULL;
6167 char **original, **tmp;
6173 log_error("Cannot edit units if we are not on a tty");
6177 if (arg_transport != BUS_TRANSPORT_LOCAL) {
6178 log_error("Cannot remotely edit units");
6182 r = expand_names(bus, args + 1, NULL, &names);
6184 return log_error_errno(r, "Failed to expand names: %m");
6187 log_error("No unit name found by expanding names");
6191 r = find_paths_to_edit(bus, names, &paths);
6195 if (strv_isempty(paths)) {
6196 log_error("Cannot find any units to edit");
6200 r = run_editor(paths);
6204 STRV_FOREACH_PAIR(original, tmp, paths) {
6205 /* If the temporary file is empty we ignore it.
6206 * It's useful if the user wants to cancel its modification
6208 if (null_or_empty_path(*tmp)) {
6209 log_warning("Edition of %s canceled: temporary file empty", *original);
6212 r = rename(*tmp, *original);
6214 r = log_error_errno(errno, "Failed to rename %s to %s: %m", *tmp, *original);
6219 if (!arg_no_reload && bus && !avoid_bus())
6220 r = daemon_reload(bus, args);
6223 STRV_FOREACH_PAIR(original, tmp, paths)
6224 unlink_noerrno(*tmp);
6229 static void systemctl_help(void) {
6231 pager_open_if_enabled();
6233 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
6234 "Query or send control commands to the systemd manager.\n\n"
6235 " -h --help Show this help\n"
6236 " --version Show package version\n"
6237 " --system Connect to system manager\n"
6238 " --user Connect to user service manager\n"
6239 " -H --host=[USER@]HOST\n"
6240 " Operate on remote host\n"
6241 " -M --machine=CONTAINER\n"
6242 " Operate on local container\n"
6243 " -t --type=TYPE List only units of a particular type\n"
6244 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
6245 " -p --property=NAME Show only properties by this name\n"
6246 " -a --all Show all loaded units/properties, including dead/empty\n"
6247 " ones. To list all units installed on the system, use\n"
6248 " the 'list-unit-files' command instead.\n"
6249 " -l --full Don't ellipsize unit names on output\n"
6250 " -r --recursive Show unit list of host and local containers\n"
6251 " --reverse Show reverse dependencies with 'list-dependencies'\n"
6252 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
6253 " queueing a new job\n"
6254 " --show-types When showing sockets, explicitly show their type\n"
6255 " -i --ignore-inhibitors\n"
6256 " When shutting down or sleeping, ignore inhibitors\n"
6257 " --kill-who=WHO Who to send signal to\n"
6258 " -s --signal=SIGNAL Which signal to send\n"
6259 " -q --quiet Suppress output\n"
6260 " --no-block Do not wait until operation finished\n"
6261 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6262 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
6264 " --no-legend Do not print a legend (column headers and hints)\n"
6265 " --no-pager Do not pipe output into a pager\n"
6266 " --no-ask-password\n"
6267 " Do not ask for system passwords\n"
6268 " --global Enable/disable unit files globally\n"
6269 " --runtime Enable unit files only temporarily until next reboot\n"
6270 " -f --force When enabling unit files, override existing symlinks\n"
6271 " When shutting down, execute action immediately\n"
6272 " --preset-mode= Specifies whether fully apply presets, or only enable,\n"
6273 " or only disable\n"
6274 " --root=PATH Enable unit files in the specified root directory\n"
6275 " -n --lines=INTEGER Number of journal entries to show\n"
6276 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
6277 " verbose, export, json, json-pretty, json-sse, cat)\n"
6278 " --plain Print unit dependencies as a list instead of a tree\n\n"
6280 " list-units [PATTERN...] List loaded units\n"
6281 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
6282 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
6283 " start NAME... Start (activate) one or more units\n"
6284 " stop NAME... Stop (deactivate) one or more units\n"
6285 " reload NAME... Reload one or more units\n"
6286 " restart NAME... Start or restart one or more units\n"
6287 " try-restart NAME... Restart one or more units if active\n"
6288 " reload-or-restart NAME... Reload one or more units if possible,\n"
6289 " otherwise start or restart\n"
6290 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
6291 " otherwise restart if active\n"
6292 " isolate NAME Start one unit and stop all others\n"
6293 " kill NAME... Send signal to processes of a unit\n"
6294 " is-active PATTERN... Check whether units are active\n"
6295 " is-failed PATTERN... Check whether units are failed\n"
6296 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
6297 " show [PATTERN...|JOB...] Show properties of one or more\n"
6298 " units/jobs or the manager\n"
6299 " cat PATTERN... Show files and drop-ins of one or more units\n"
6300 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
6301 " help PATTERN...|PID... Show manual for one or more units\n"
6302 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
6304 " list-dependencies [NAME] Recursively show units which are required\n"
6305 " or wanted by this unit or by which this\n"
6306 " unit is required or wanted\n\n"
6307 "Unit File Commands:\n"
6308 " list-unit-files [PATTERN...] List installed unit files\n"
6309 " enable NAME... Enable one or more unit files\n"
6310 " disable NAME... Disable one or more unit files\n"
6311 " reenable NAME... Reenable one or more unit files\n"
6312 " preset NAME... Enable/disable one or more unit files\n"
6313 " based on preset configuration\n"
6314 " preset-all Enable/disable all unit files based on\n"
6315 " preset configuration\n"
6316 " is-enabled NAME... Check whether unit files are enabled\n\n"
6317 " mask NAME... Mask one or more units\n"
6318 " unmask NAME... Unmask one or more units\n"
6319 " link PATH... Link one or more units files into\n"
6320 " the search path\n"
6321 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6322 " on specified one or more units\n"
6323 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6324 " on specified one or more units\n"
6325 " get-default Get the name of the default target\n"
6326 " set-default NAME Set the default target\n"
6327 " edit NAME... Edit one or more unit files\n"
6329 "Machine Commands:\n"
6330 " list-machines [PATTERN...] List local containers and host\n\n"
6332 " list-jobs [PATTERN...] List jobs\n"
6333 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
6334 "Snapshot Commands:\n"
6335 " snapshot [NAME] Create a snapshot\n"
6336 " delete NAME... Remove one or more snapshots\n\n"
6337 "Environment Commands:\n"
6338 " show-environment Dump environment\n"
6339 " set-environment NAME=VALUE... Set one or more environment variables\n"
6340 " unset-environment NAME... Unset one or more environment variables\n"
6341 " import-environment NAME... Import all, one or more environment variables\n\n"
6342 "Manager Lifecycle Commands:\n"
6343 " daemon-reload Reload systemd manager configuration\n"
6344 " daemon-reexec Reexecute systemd manager\n\n"
6345 "System Commands:\n"
6346 " is-system-running Check whether system is fully running\n"
6347 " default Enter system default mode\n"
6348 " rescue Enter system rescue mode\n"
6349 " emergency Enter system emergency mode\n"
6350 " halt Shut down and halt the system\n"
6351 " poweroff Shut down and power-off the system\n"
6352 " reboot [ARG] Shut down and reboot the system\n"
6353 " kexec Shut down and reboot the system with kexec\n"
6354 " exit Request user instance exit\n"
6355 " switch-root ROOT [INIT] Change to a different root file system\n"
6356 " suspend Suspend the system\n"
6357 " hibernate Hibernate the system\n"
6358 " hybrid-sleep Hibernate and suspend the system\n",
6359 program_invocation_short_name);
6362 static void halt_help(void) {
6363 printf("%s [OPTIONS...]%s\n\n"
6364 "%s the system.\n\n"
6365 " --help Show this help\n"
6366 " --halt Halt the machine\n"
6367 " -p --poweroff Switch off the machine\n"
6368 " --reboot Reboot the machine\n"
6369 " -f --force Force immediate halt/power-off/reboot\n"
6370 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
6371 " -d --no-wtmp Don't write wtmp record\n"
6372 " --no-wall Don't send wall message before halt/power-off/reboot\n",
6373 program_invocation_short_name,
6374 arg_action == ACTION_REBOOT ? " [ARG]" : "",
6375 arg_action == ACTION_REBOOT ? "Reboot" :
6376 arg_action == ACTION_POWEROFF ? "Power off" :
6380 static void shutdown_help(void) {
6381 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
6382 "Shut down the system.\n\n"
6383 " --help Show this help\n"
6384 " -H --halt Halt the machine\n"
6385 " -P --poweroff Power-off the machine\n"
6386 " -r --reboot Reboot the machine\n"
6387 " -h Equivalent to --poweroff, overridden by --halt\n"
6388 " -k Don't halt/power-off/reboot, just send warnings\n"
6389 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6390 " -c Cancel a pending shutdown\n",
6391 program_invocation_short_name);
6394 static void telinit_help(void) {
6395 printf("%s [OPTIONS...] {COMMAND}\n\n"
6396 "Send control commands to the init daemon.\n\n"
6397 " --help Show this help\n"
6398 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
6400 " 0 Power-off the machine\n"
6401 " 6 Reboot the machine\n"
6402 " 2, 3, 4, 5 Start runlevelX.target unit\n"
6403 " 1, s, S Enter rescue mode\n"
6404 " q, Q Reload init daemon configuration\n"
6405 " u, U Reexecute init daemon\n",
6406 program_invocation_short_name);
6409 static void runlevel_help(void) {
6410 printf("%s [OPTIONS...]\n\n"
6411 "Prints the previous and current runlevel of the init system.\n\n"
6412 " --help Show this help\n",
6413 program_invocation_short_name);
6416 static void help_types(void) {
6421 puts("Available unit types:");
6422 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
6423 t = unit_type_to_string(i);
6429 static int systemctl_parse_argv(int argc, char *argv[]) {
6438 ARG_IGNORE_DEPENDENCIES,
6450 ARG_NO_ASK_PASSWORD,
6460 static const struct option options[] = {
6461 { "help", no_argument, NULL, 'h' },
6462 { "version", no_argument, NULL, ARG_VERSION },
6463 { "type", required_argument, NULL, 't' },
6464 { "property", required_argument, NULL, 'p' },
6465 { "all", no_argument, NULL, 'a' },
6466 { "reverse", no_argument, NULL, ARG_REVERSE },
6467 { "after", no_argument, NULL, ARG_AFTER },
6468 { "before", no_argument, NULL, ARG_BEFORE },
6469 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
6470 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
6471 { "full", no_argument, NULL, 'l' },
6472 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
6473 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
6474 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
6475 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
6476 { "ignore-inhibitors", no_argument, NULL, 'i' },
6477 { "user", no_argument, NULL, ARG_USER },
6478 { "system", no_argument, NULL, ARG_SYSTEM },
6479 { "global", no_argument, NULL, ARG_GLOBAL },
6480 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
6481 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
6482 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
6483 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6484 { "quiet", no_argument, NULL, 'q' },
6485 { "root", required_argument, NULL, ARG_ROOT },
6486 { "force", no_argument, NULL, ARG_FORCE },
6487 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
6488 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
6489 { "signal", required_argument, NULL, 's' },
6490 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
6491 { "host", required_argument, NULL, 'H' },
6492 { "machine", required_argument, NULL, 'M' },
6493 { "runtime", no_argument, NULL, ARG_RUNTIME },
6494 { "lines", required_argument, NULL, 'n' },
6495 { "output", required_argument, NULL, 'o' },
6496 { "plain", no_argument, NULL, ARG_PLAIN },
6497 { "state", required_argument, NULL, ARG_STATE },
6498 { "recursive", no_argument, NULL, 'r' },
6499 { "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
6508 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
6517 puts(PACKAGE_STRING);
6518 puts(SYSTEMD_FEATURES);
6522 const char *word, *state;
6525 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6526 _cleanup_free_ char *type;
6528 type = strndup(word, size);
6532 if (streq(type, "help")) {
6537 if (unit_type_from_string(type) >= 0) {
6538 if (strv_push(&arg_types, type))
6544 /* It's much nicer to use --state= for
6545 * load states, but let's support this
6546 * in --types= too for compatibility
6547 * with old versions */
6548 if (unit_load_state_from_string(optarg) >= 0) {
6549 if (strv_push(&arg_states, type) < 0)
6555 log_error("Unknown unit type or load state '%s'.", type);
6556 log_info("Use -t help to see a list of allowed values.");
6564 /* Make sure that if the empty property list
6565 was specified, we won't show any properties. */
6566 if (isempty(optarg) && !arg_properties) {
6567 arg_properties = new0(char*, 1);
6568 if (!arg_properties)
6571 const char *word, *state;
6574 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6577 prop = strndup(word, size);
6581 if (strv_consume(&arg_properties, prop) < 0)
6586 /* If the user asked for a particular
6587 * property, show it to him, even if it is
6599 arg_dependency = DEPENDENCY_REVERSE;
6603 arg_dependency = DEPENDENCY_AFTER;
6607 arg_dependency = DEPENDENCY_BEFORE;
6610 case ARG_SHOW_TYPES:
6611 arg_show_types = true;
6615 arg_job_mode = optarg;
6619 arg_job_mode = "fail";
6622 case ARG_IRREVERSIBLE:
6623 arg_job_mode = "replace-irreversibly";
6626 case ARG_IGNORE_DEPENDENCIES:
6627 arg_job_mode = "ignore-dependencies";
6631 arg_scope = UNIT_FILE_USER;
6635 arg_scope = UNIT_FILE_SYSTEM;
6639 arg_scope = UNIT_FILE_GLOBAL;
6643 arg_no_block = true;
6647 arg_no_legend = true;
6651 arg_no_pager = true;
6667 if (strv_extend(&arg_states, "failed") < 0)
6685 arg_no_reload = true;
6689 arg_kill_who = optarg;
6693 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
6694 log_error("Failed to parse signal string %s.", optarg);
6699 case ARG_NO_ASK_PASSWORD:
6700 arg_ask_password = false;
6704 arg_transport = BUS_TRANSPORT_REMOTE;
6709 arg_transport = BUS_TRANSPORT_CONTAINER;
6718 if (safe_atou(optarg, &arg_lines) < 0) {
6719 log_error("Failed to parse lines '%s'", optarg);
6725 arg_output = output_mode_from_string(optarg);
6726 if (arg_output < 0) {
6727 log_error("Unknown output '%s'.", optarg);
6733 arg_ignore_inhibitors = true;
6741 const char *word, *state;
6744 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6747 s = strndup(word, size);
6751 if (strv_consume(&arg_states, s) < 0)
6758 if (geteuid() != 0) {
6759 log_error("--recursive requires root privileges.");
6763 arg_recursive = true;
6766 case ARG_PRESET_MODE:
6768 arg_preset_mode = unit_file_preset_mode_from_string(optarg);
6769 if (arg_preset_mode < 0) {
6770 log_error("Failed to parse preset mode: %s.", optarg);
6780 assert_not_reached("Unhandled option");
6783 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
6784 log_error("Cannot access user instance remotely.");
6791 static int halt_parse_argv(int argc, char *argv[]) {
6800 static const struct option options[] = {
6801 { "help", no_argument, NULL, ARG_HELP },
6802 { "halt", no_argument, NULL, ARG_HALT },
6803 { "poweroff", no_argument, NULL, 'p' },
6804 { "reboot", no_argument, NULL, ARG_REBOOT },
6805 { "force", no_argument, NULL, 'f' },
6806 { "wtmp-only", no_argument, NULL, 'w' },
6807 { "no-wtmp", no_argument, NULL, 'd' },
6808 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6817 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
6818 if (runlevel == '0' || runlevel == '6')
6821 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
6829 arg_action = ACTION_HALT;
6833 if (arg_action != ACTION_REBOOT)
6834 arg_action = ACTION_POWEROFF;
6838 arg_action = ACTION_REBOOT;
6860 /* Compatibility nops */
6867 assert_not_reached("Unhandled option");
6870 if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
6871 r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL);
6874 } else if (optind < argc) {
6875 log_error("Too many arguments.");
6882 static int parse_time_spec(const char *t, usec_t *_u) {
6886 if (streq(t, "now"))
6888 else if (!strchr(t, ':')) {
6891 if (safe_atou64(t, &u) < 0)
6894 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
6903 hour = strtol(t, &e, 10);
6904 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
6907 minute = strtol(e+1, &e, 10);
6908 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
6911 n = now(CLOCK_REALTIME);
6912 s = (time_t) (n / USEC_PER_SEC);
6914 assert_se(localtime_r(&s, &tm));
6916 tm.tm_hour = (int) hour;
6917 tm.tm_min = (int) minute;
6920 assert_se(s = mktime(&tm));
6922 *_u = (usec_t) s * USEC_PER_SEC;
6925 *_u += USEC_PER_DAY;
6931 static int shutdown_parse_argv(int argc, char *argv[]) {
6938 static const struct option options[] = {
6939 { "help", no_argument, NULL, ARG_HELP },
6940 { "halt", no_argument, NULL, 'H' },
6941 { "poweroff", no_argument, NULL, 'P' },
6942 { "reboot", no_argument, NULL, 'r' },
6943 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
6944 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6953 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0)
6961 arg_action = ACTION_HALT;
6965 arg_action = ACTION_POWEROFF;
6970 arg_action = ACTION_KEXEC;
6972 arg_action = ACTION_REBOOT;
6976 arg_action = ACTION_KEXEC;
6980 if (arg_action != ACTION_HALT)
6981 arg_action = ACTION_POWEROFF;
6994 /* Compatibility nops */
6998 arg_action = ACTION_CANCEL_SHUTDOWN;
7005 assert_not_reached("Unhandled option");
7008 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
7009 r = parse_time_spec(argv[optind], &arg_when);
7011 log_error("Failed to parse time specification: %s", argv[optind]);
7015 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
7017 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
7018 /* No time argument for shutdown cancel */
7019 arg_wall = argv + optind;
7020 else if (argc > optind + 1)
7021 /* We skip the time argument */
7022 arg_wall = argv + optind + 1;
7029 static int telinit_parse_argv(int argc, char *argv[]) {
7036 static const struct option options[] = {
7037 { "help", no_argument, NULL, ARG_HELP },
7038 { "no-wall", no_argument, NULL, ARG_NO_WALL },
7042 static const struct {
7046 { '0', ACTION_POWEROFF },
7047 { '6', ACTION_REBOOT },
7048 { '1', ACTION_RESCUE },
7049 { '2', ACTION_RUNLEVEL2 },
7050 { '3', ACTION_RUNLEVEL3 },
7051 { '4', ACTION_RUNLEVEL4 },
7052 { '5', ACTION_RUNLEVEL5 },
7053 { 's', ACTION_RESCUE },
7054 { 'S', ACTION_RESCUE },
7055 { 'q', ACTION_RELOAD },
7056 { 'Q', ACTION_RELOAD },
7057 { 'u', ACTION_REEXEC },
7058 { 'U', ACTION_REEXEC }
7067 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
7082 assert_not_reached("Unhandled option");
7085 if (optind >= argc) {
7086 log_error("%s: required argument missing.",
7087 program_invocation_short_name);
7091 if (optind + 1 < argc) {
7092 log_error("Too many arguments.");
7096 if (strlen(argv[optind]) != 1) {
7097 log_error("Expected single character argument.");
7101 for (i = 0; i < ELEMENTSOF(table); i++)
7102 if (table[i].from == argv[optind][0])
7105 if (i >= ELEMENTSOF(table)) {
7106 log_error("Unknown command '%s'.", argv[optind]);
7110 arg_action = table[i].to;
7117 static int runlevel_parse_argv(int argc, char *argv[]) {
7123 static const struct option options[] = {
7124 { "help", no_argument, NULL, ARG_HELP },
7133 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
7144 assert_not_reached("Unhandled option");
7147 if (optind < argc) {
7148 log_error("Too many arguments.");
7155 static int parse_argv(int argc, char *argv[]) {
7159 if (program_invocation_short_name) {
7161 if (strstr(program_invocation_short_name, "halt")) {
7162 arg_action = ACTION_HALT;
7163 return halt_parse_argv(argc, argv);
7164 } else if (strstr(program_invocation_short_name, "poweroff")) {
7165 arg_action = ACTION_POWEROFF;
7166 return halt_parse_argv(argc, argv);
7167 } else if (strstr(program_invocation_short_name, "reboot")) {
7169 arg_action = ACTION_KEXEC;
7171 arg_action = ACTION_REBOOT;
7172 return halt_parse_argv(argc, argv);
7173 } else if (strstr(program_invocation_short_name, "shutdown")) {
7174 arg_action = ACTION_POWEROFF;
7175 return shutdown_parse_argv(argc, argv);
7176 } else if (strstr(program_invocation_short_name, "init")) {
7178 if (sd_booted() > 0) {
7179 arg_action = _ACTION_INVALID;
7180 return telinit_parse_argv(argc, argv);
7182 /* Hmm, so some other init system is
7183 * running, we need to forward this
7184 * request to it. For now we simply
7185 * guess that it is Upstart. */
7187 execv(TELINIT, argv);
7189 log_error("Couldn't find an alternative telinit implementation to spawn.");
7193 } else if (strstr(program_invocation_short_name, "runlevel")) {
7194 arg_action = ACTION_RUNLEVEL;
7195 return runlevel_parse_argv(argc, argv);
7199 arg_action = ACTION_SYSTEMCTL;
7200 return systemctl_parse_argv(argc, argv);
7203 _pure_ static int action_to_runlevel(void) {
7205 static const char table[_ACTION_MAX] = {
7206 [ACTION_HALT] = '0',
7207 [ACTION_POWEROFF] = '0',
7208 [ACTION_REBOOT] = '6',
7209 [ACTION_RUNLEVEL2] = '2',
7210 [ACTION_RUNLEVEL3] = '3',
7211 [ACTION_RUNLEVEL4] = '4',
7212 [ACTION_RUNLEVEL5] = '5',
7213 [ACTION_RESCUE] = '1'
7216 assert(arg_action < _ACTION_MAX);
7218 return table[arg_action];
7221 static int talk_initctl(void) {
7223 struct init_request request = {
7224 .magic = INIT_MAGIC,
7226 .cmd = INIT_CMD_RUNLVL
7229 _cleanup_close_ int fd = -1;
7233 rl = action_to_runlevel();
7237 request.runlevel = rl;
7239 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
7241 if (errno == ENOENT)
7244 log_error_errno(errno, "Failed to open "INIT_FIFO": %m");
7248 r = loop_write(fd, &request, sizeof(request), false);
7250 return log_error_errno(r, "Failed to write to "INIT_FIFO": %m");
7255 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
7257 static const struct {
7265 int (* const dispatch)(sd_bus *bus, char **args);
7271 { "list-units", MORE, 0, list_units },
7272 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
7273 { "list-sockets", MORE, 1, list_sockets },
7274 { "list-timers", MORE, 1, list_timers },
7275 { "list-jobs", MORE, 1, list_jobs },
7276 { "list-machines", MORE, 1, list_machines },
7277 { "clear-jobs", EQUAL, 1, daemon_reload },
7278 { "cancel", MORE, 2, cancel_job },
7279 { "start", MORE, 2, start_unit },
7280 { "stop", MORE, 2, start_unit },
7281 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
7282 { "reload", MORE, 2, start_unit },
7283 { "restart", MORE, 2, start_unit },
7284 { "try-restart", MORE, 2, start_unit },
7285 { "reload-or-restart", MORE, 2, start_unit },
7286 { "reload-or-try-restart", MORE, 2, start_unit },
7287 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
7288 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
7289 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
7290 { "isolate", EQUAL, 2, start_unit },
7291 { "kill", MORE, 2, kill_unit },
7292 { "is-active", MORE, 2, check_unit_active },
7293 { "check", MORE, 2, check_unit_active },
7294 { "is-failed", MORE, 2, check_unit_failed },
7295 { "show", MORE, 1, show },
7296 { "cat", MORE, 2, cat },
7297 { "status", MORE, 1, show },
7298 { "help", MORE, 2, show },
7299 { "snapshot", LESS, 2, snapshot },
7300 { "delete", MORE, 2, delete_snapshot },
7301 { "daemon-reload", EQUAL, 1, daemon_reload },
7302 { "daemon-reexec", EQUAL, 1, daemon_reload },
7303 { "show-environment", EQUAL, 1, show_environment },
7304 { "set-environment", MORE, 2, set_environment },
7305 { "unset-environment", MORE, 2, set_environment },
7306 { "import-environment", MORE, 1, import_environment},
7307 { "halt", EQUAL, 1, start_special, FORCE },
7308 { "poweroff", EQUAL, 1, start_special, FORCE },
7309 { "reboot", EQUAL, 1, start_special, FORCE },
7310 { "kexec", EQUAL, 1, start_special },
7311 { "suspend", EQUAL, 1, start_special },
7312 { "hibernate", EQUAL, 1, start_special },
7313 { "hybrid-sleep", EQUAL, 1, start_special },
7314 { "default", EQUAL, 1, start_special },
7315 { "rescue", EQUAL, 1, start_special },
7316 { "emergency", EQUAL, 1, start_special },
7317 { "exit", EQUAL, 1, start_special },
7318 { "reset-failed", MORE, 1, reset_failed },
7319 { "enable", MORE, 2, enable_unit, NOBUS },
7320 { "disable", MORE, 2, enable_unit, NOBUS },
7321 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
7322 { "reenable", MORE, 2, enable_unit, NOBUS },
7323 { "preset", MORE, 2, enable_unit, NOBUS },
7324 { "preset-all", EQUAL, 1, preset_all, NOBUS },
7325 { "mask", MORE, 2, enable_unit, NOBUS },
7326 { "unmask", MORE, 2, enable_unit, NOBUS },
7327 { "link", MORE, 2, enable_unit, NOBUS },
7328 { "switch-root", MORE, 2, switch_root },
7329 { "list-dependencies", LESS, 2, list_dependencies },
7330 { "set-default", EQUAL, 2, set_default, NOBUS },
7331 { "get-default", EQUAL, 1, get_default, NOBUS },
7332 { "set-property", MORE, 3, set_property },
7333 { "is-system-running", EQUAL, 1, is_system_running },
7334 { "add-wants", MORE, 3, add_dependency, NOBUS },
7335 { "add-requires", MORE, 3, add_dependency, NOBUS },
7336 { "edit", MORE, 2, edit, NOBUS },
7345 left = argc - optind;
7347 /* Special rule: no arguments (left == 0) means "list-units" */
7349 if (streq(argv[optind], "help") && !argv[optind+1]) {
7350 log_error("This command expects one or more "
7351 "unit names. Did you mean --help?");
7355 for (; verb->verb; verb++)
7356 if (streq(argv[optind], verb->verb))
7359 log_error("Unknown operation '%s'.", argv[optind]);
7364 switch (verb->argc_cmp) {
7367 if (left != verb->argc) {
7368 log_error("Invalid number of arguments.");
7375 if (left < verb->argc) {
7376 log_error("Too few arguments.");
7383 if (left > verb->argc) {
7384 log_error("Too many arguments.");
7391 assert_not_reached("Unknown comparison operator.");
7394 /* Require a bus connection for all operations but
7396 if (verb->bus == NOBUS) {
7397 if (!bus && !avoid_bus()) {
7398 log_error_errno(bus_error, "Failed to get D-Bus connection: %m");
7403 if (running_in_chroot() > 0) {
7404 log_info("Running in chroot, ignoring request.");
7408 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
7409 log_error_errno(bus_error, "Failed to get D-Bus connection: %m");
7414 return verb->dispatch(bus, argv + optind);
7417 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
7419 struct sd_shutdown_command c = {
7426 union sockaddr_union sockaddr = {
7427 .un.sun_family = AF_UNIX,
7428 .un.sun_path = "/run/systemd/shutdownd",
7431 struct iovec iovec[2] = {{
7432 .iov_base = (char*) &c,
7433 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
7436 struct msghdr msghdr = {
7437 .msg_name = &sockaddr,
7438 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
7439 + strlen("/run/systemd/shutdownd"),
7444 _cleanup_close_ int fd;
7446 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
7450 if (!isempty(message)) {
7451 iovec[1].iov_base = (char*) message;
7452 iovec[1].iov_len = strlen(message);
7453 msghdr.msg_iovlen++;
7456 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
7462 static int reload_with_fallback(sd_bus *bus) {
7465 /* First, try systemd via D-Bus. */
7466 if (daemon_reload(bus, NULL) >= 0)
7470 /* Nothing else worked, so let's try signals */
7471 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
7473 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0)
7474 return log_error_errno(errno, "kill() failed: %m");
7479 static int start_with_fallback(sd_bus *bus) {
7482 /* First, try systemd via D-Bus. */
7483 if (start_unit(bus, NULL) >= 0)
7487 /* Nothing else worked, so let's try
7489 if (talk_initctl() > 0)
7492 log_error("Failed to talk to init daemon.");
7496 warn_wall(arg_action);
7500 static int halt_now(enum action a) {
7502 /* The kernel will automaticall flush ATA disks and suchlike
7503 * on reboot(), but the file systems need to be synce'd
7504 * explicitly in advance. */
7507 /* Make sure C-A-D is handled by the kernel from this point
7509 reboot(RB_ENABLE_CAD);
7514 log_info("Halting.");
7515 reboot(RB_HALT_SYSTEM);
7518 case ACTION_POWEROFF:
7519 log_info("Powering off.");
7520 reboot(RB_POWER_OFF);
7523 case ACTION_REBOOT: {
7524 _cleanup_free_ char *param = NULL;
7526 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
7527 log_info("Rebooting with argument '%s'.", param);
7528 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
7529 LINUX_REBOOT_CMD_RESTART2, param);
7532 log_info("Rebooting.");
7533 reboot(RB_AUTOBOOT);
7538 assert_not_reached("Unknown action.");
7542 static int halt_main(sd_bus *bus) {
7545 r = check_inhibitors(bus, arg_action);
7549 if (geteuid() != 0) {
7550 /* Try logind if we are a normal user and no special
7551 * mode applies. Maybe PolicyKit allows us to shutdown
7554 if (arg_when <= 0 &&
7557 (arg_action == ACTION_POWEROFF ||
7558 arg_action == ACTION_REBOOT)) {
7559 r = reboot_with_logind(bus, arg_action);
7564 log_error("Must be root.");
7569 _cleanup_free_ char *m;
7571 m = strv_join(arg_wall, " ");
7575 r = send_shutdownd(arg_when,
7576 arg_action == ACTION_HALT ? 'H' :
7577 arg_action == ACTION_POWEROFF ? 'P' :
7578 arg_action == ACTION_KEXEC ? 'K' :
7585 log_warning_errno(r, "Failed to talk to shutdownd, proceeding with immediate shutdown: %m");
7587 char date[FORMAT_TIMESTAMP_MAX];
7589 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
7590 format_timestamp(date, sizeof(date), arg_when));
7595 if (!arg_dry && !arg_force)
7596 return start_with_fallback(bus);
7599 if (sd_booted() > 0)
7600 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7602 r = utmp_put_shutdown();
7604 log_warning_errno(r, "Failed to write utmp record: %m");
7611 r = halt_now(arg_action);
7612 log_error_errno(r, "Failed to reboot: %m");
7617 static int runlevel_main(void) {
7618 int r, runlevel, previous;
7620 r = utmp_get_runlevel(&runlevel, &previous);
7627 previous <= 0 ? 'N' : previous,
7628 runlevel <= 0 ? 'N' : runlevel);
7633 int main(int argc, char*argv[]) {
7634 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
7637 setlocale(LC_ALL, "");
7638 log_parse_environment();
7641 /* Explicitly not on_tty() to avoid setting cached value.
7642 * This becomes relevant for piping output which might be
7644 original_stdout_is_tty = isatty(STDOUT_FILENO);
7646 r = parse_argv(argc, argv);
7650 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
7651 * let's shortcut this */
7652 if (arg_action == ACTION_RUNLEVEL) {
7653 r = runlevel_main();
7657 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
7658 log_info("Running in chroot, ignoring request.");
7664 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
7666 /* systemctl_main() will print an error message for the bus
7667 * connection, but only if it needs to */
7669 switch (arg_action) {
7671 case ACTION_SYSTEMCTL:
7672 r = systemctl_main(bus, argc, argv, r);
7676 case ACTION_POWEROFF:
7682 case ACTION_RUNLEVEL2:
7683 case ACTION_RUNLEVEL3:
7684 case ACTION_RUNLEVEL4:
7685 case ACTION_RUNLEVEL5:
7687 case ACTION_EMERGENCY:
7688 case ACTION_DEFAULT:
7689 r = start_with_fallback(bus);
7694 r = reload_with_fallback(bus);
7697 case ACTION_CANCEL_SHUTDOWN: {
7698 _cleanup_free_ char *m = NULL;
7701 m = strv_join(arg_wall, " ");
7708 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
7710 log_warning_errno(r, "Failed to talk to shutdownd, shutdown hasn't been cancelled: %m");
7714 case ACTION_RUNLEVEL:
7715 case _ACTION_INVALID:
7717 assert_not_reached("Unknown action");
7722 ask_password_agent_close();
7723 polkit_agent_close();
7725 strv_free(arg_types);
7726 strv_free(arg_states);
7727 strv_free(arg_properties);
7729 return r < 0 ? EXIT_FAILURE : r;