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 static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **unit_path) {
2288 STRV_FOREACH(p, lp->unit_path) {
2291 path = path_join(arg_root, *p, unit_name);
2295 if (access(path, F_OK) == 0) {
2306 static int unit_find_path(sd_bus *bus, const char *unit_name, const char *template, bool avoid_bus_cache, LookupPaths *lp, char **path) {
2313 if (!avoid_bus_cache && !unit_name_is_template(unit_name)) {
2314 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2315 _cleanup_free_ char *unit = NULL;
2316 _cleanup_free_ char *tmp_path = NULL;
2318 unit = unit_dbus_path_from_name(unit_name);
2322 if (need_daemon_reload(bus, unit_name) > 0) {
2323 warn_unit_file_changed(unit_name);
2327 r = sd_bus_get_property_string(
2329 "org.freedesktop.systemd1",
2331 "org.freedesktop.systemd1.Unit",
2336 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
2340 if (isempty(tmp_path)) {
2341 log_warning("%s ignored: not found", template);
2350 r = unit_file_find_path(lp, template, path);
2352 log_warning("%s ignored: not found", template);
2359 typedef struct WaitData {
2366 static int wait_filter(sd_bus *bus, sd_bus_message *m, void *data, sd_bus_error *error) {
2373 log_debug("Got D-Bus request: %s.%s() on %s",
2374 sd_bus_message_get_interface(m),
2375 sd_bus_message_get_member(m),
2376 sd_bus_message_get_path(m));
2378 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
2379 log_error("Warning! D-Bus connection terminated.");
2381 } else if (sd_bus_message_is_signal(m, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
2383 const char *path, *result, *unit;
2387 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
2389 ret = set_remove(d->set, (char*) path);
2395 if (!isempty(result))
2396 d->result = strdup(result);
2399 d->name = strdup(unit);
2404 r = sd_bus_message_read(m, "uos", &id, &path, &result);
2406 ret = set_remove(d->set, (char*) path);
2413 d->result = strdup(result);
2419 bus_log_parse_error(r);
2425 static int enable_wait_for_jobs(sd_bus *bus) {
2430 r = sd_bus_add_match(
2434 "sender='org.freedesktop.systemd1',"
2435 "interface='org.freedesktop.systemd1.Manager',"
2436 "member='JobRemoved',"
2437 "path='/org/freedesktop/systemd1'",
2440 log_error("Failed to add match");
2444 /* This is slightly dirty, since we don't undo the match registrations. */
2448 static int bus_process_wait(sd_bus *bus) {
2452 r = sd_bus_process(bus, NULL);
2457 r = sd_bus_wait(bus, (uint64_t) -1);
2463 static int check_wait_response(WaitData *d) {
2469 if (streq(d->result, "canceled"))
2470 log_error("Job for %s canceled.", strna(d->name));
2471 else if (streq(d->result, "timeout"))
2472 log_error("Job for %s timed out.", strna(d->name));
2473 else if (streq(d->result, "dependency"))
2474 log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
2475 else if (streq(d->result, "invalid"))
2476 log_error("Job for %s invalid.", strna(d->name));
2477 else if (streq(d->result, "assert"))
2478 log_error("Assertion failed on job for %s.", strna(d->name));
2479 else if (streq(d->result, "unsupported"))
2480 log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
2481 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
2485 quotes = chars_intersect(d->name, SHELL_NEED_QUOTES);
2487 log_error("Job for %s failed. See \"systemctl status %s%s%s\" and \"journalctl -xe\" for details.",
2489 quotes ? "'" : "", d->name, quotes ? "'" : "");
2491 log_error("Job failed. See \"journalctl -xe\" for details.");
2495 if (streq(d->result, "canceled"))
2497 else if (streq(d->result, "timeout"))
2499 else if (streq(d->result, "dependency"))
2501 else if (streq(d->result, "invalid"))
2503 else if (streq(d->result, "assert"))
2505 else if (streq(d->result, "unsupported"))
2507 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2513 static int wait_for_jobs(sd_bus *bus, Set *s) {
2514 _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
2515 WaitData d = { .set = s };
2521 q = sd_bus_add_filter(bus, &slot, wait_filter, &d);
2525 while (!set_isempty(s)) {
2526 q = bus_process_wait(bus);
2528 return log_error_errno(q, "Failed to wait for response: %m");
2531 q = check_wait_response(&d);
2532 /* Return the first error as it is most likely to be
2534 if (q < 0 && r == 0)
2536 log_debug("Got result %s/%s for job %s",
2537 strna(d.result), strerror(-q), strna(d.name));
2550 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2551 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2552 _cleanup_free_ char *n = NULL, *state = NULL;
2558 n = unit_name_mangle(name, MANGLE_NOGLOB);
2562 /* We don't use unit_dbus_path_from_name() directly since we
2563 * don't want to load the unit if it isn't loaded. */
2565 r = sd_bus_call_method(
2567 "org.freedesktop.systemd1",
2568 "/org/freedesktop/systemd1",
2569 "org.freedesktop.systemd1.Manager",
2580 r = sd_bus_message_read(reply, "o", &path);
2582 return bus_log_parse_error(r);
2584 r = sd_bus_get_property_string(
2586 "org.freedesktop.systemd1",
2588 "org.freedesktop.systemd1.Unit",
2601 return nulstr_contains(good_states, state);
2604 static int check_triggering_units(
2608 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2609 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2610 _cleanup_strv_free_ char **triggered_by = NULL;
2611 bool print_warning_label = true;
2615 n = unit_name_mangle(name, MANGLE_NOGLOB);
2619 path = unit_dbus_path_from_name(n);
2623 r = sd_bus_get_property_string(
2625 "org.freedesktop.systemd1",
2627 "org.freedesktop.systemd1.Unit",
2632 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2636 if (streq(state, "masked"))
2639 r = sd_bus_get_property_strv(
2641 "org.freedesktop.systemd1",
2643 "org.freedesktop.systemd1.Unit",
2648 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2652 STRV_FOREACH(i, triggered_by) {
2653 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2655 return log_error_errno(r, "Failed to check unit: %m");
2660 if (print_warning_label) {
2661 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2662 print_warning_label = false;
2665 log_warning(" %s", *i);
2671 static const struct {
2674 } unit_actions[] = {
2675 { "start", "StartUnit" },
2676 { "stop", "StopUnit" },
2677 { "condstop", "StopUnit" },
2678 { "reload", "ReloadUnit" },
2679 { "restart", "RestartUnit" },
2680 { "try-restart", "TryRestartUnit" },
2681 { "condrestart", "TryRestartUnit" },
2682 { "reload-or-restart", "ReloadOrRestartUnit" },
2683 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2684 { "condreload", "ReloadOrTryRestartUnit" },
2685 { "force-reload", "ReloadOrTryRestartUnit" }
2688 static const char *verb_to_method(const char *verb) {
2691 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2692 if (streq_ptr(unit_actions[i].verb, verb))
2693 return unit_actions[i].method;
2698 static const char *method_to_verb(const char *method) {
2701 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2702 if (streq_ptr(unit_actions[i].method, method))
2703 return unit_actions[i].verb;
2708 static int start_unit_one(
2713 sd_bus_error *error,
2716 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2725 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2727 r = sd_bus_message_new_method_call(
2730 "org.freedesktop.systemd1",
2731 "/org/freedesktop/systemd1",
2732 "org.freedesktop.systemd1.Manager",
2735 return bus_log_create_error(r);
2737 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2739 return bus_log_create_error(r);
2741 r = sd_bus_message_append(m, "ss", name, mode);
2743 return bus_log_create_error(r);
2745 r = sd_bus_call(bus, m, 0, error, &reply);
2749 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2750 /* There's always a fallback possible for
2751 * legacy actions. */
2752 return -EADDRNOTAVAIL;
2754 verb = method_to_verb(method);
2756 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2760 r = sd_bus_message_read(reply, "o", &path);
2762 return bus_log_parse_error(r);
2764 if (need_daemon_reload(bus, name) > 0)
2765 warn_unit_file_changed(name);
2774 log_debug("Adding %s to the set", p);
2775 r = set_consume(s, p);
2783 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2785 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2789 STRV_FOREACH(name, names) {
2793 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2795 t = unit_name_mangle(*name, MANGLE_GLOB);
2799 if (string_is_glob(t))
2800 r = strv_consume(&globs, t);
2802 r = strv_consume(&mangled, t);
2807 /* Query the manager only if any of the names are a glob, since
2808 * this is fairly expensive */
2809 if (!strv_isempty(globs)) {
2810 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2811 _cleanup_free_ UnitInfo *unit_infos = NULL;
2813 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2817 for (i = 0; i < r; i++)
2818 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2823 mangled = NULL; /* do not free */
2828 static const struct {
2832 } action_table[_ACTION_MAX] = {
2833 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2834 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2835 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2836 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2837 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
2838 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
2839 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
2840 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
2841 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2842 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2843 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2844 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2845 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2846 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2847 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2850 static enum action verb_to_action(const char *verb) {
2853 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2854 if (streq_ptr(action_table[i].verb, verb))
2857 return _ACTION_INVALID;
2860 static int start_unit(sd_bus *bus, char **args) {
2861 _cleanup_set_free_free_ Set *s = NULL;
2862 _cleanup_strv_free_ char **names = NULL;
2863 const char *method, *mode, *one_name, *suffix = NULL;
2869 ask_password_agent_open_if_enabled();
2871 if (arg_action == ACTION_SYSTEMCTL) {
2873 method = verb_to_method(args[0]);
2874 action = verb_to_action(args[0]);
2876 if (streq(args[0], "isolate")) {
2880 mode = action_table[action].mode ?: arg_job_mode;
2882 one_name = action_table[action].target;
2884 assert(arg_action < ELEMENTSOF(action_table));
2885 assert(action_table[arg_action].target);
2887 method = "StartUnit";
2889 mode = action_table[arg_action].mode;
2890 one_name = action_table[arg_action].target;
2894 names = strv_new(one_name, NULL);
2896 r = expand_names(bus, args + 1, suffix, &names);
2898 log_error_errno(r, "Failed to expand names: %m");
2901 if (!arg_no_block) {
2902 r = enable_wait_for_jobs(bus);
2904 return log_error_errno(r, "Could not watch jobs: %m");
2906 s = set_new(&string_hash_ops);
2911 STRV_FOREACH(name, names) {
2912 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2915 q = start_unit_one(bus, method, *name, mode, &error, s);
2916 if (r >= 0 && q < 0)
2917 r = translate_bus_error_to_exit_status(q, &error);
2920 if (!arg_no_block) {
2923 q = wait_for_jobs(bus, s);
2927 /* When stopping units, warn if they can still be triggered by
2928 * another active unit (socket, path, timer) */
2929 if (!arg_quiet && streq(method, "StopUnit"))
2930 STRV_FOREACH(name, names)
2931 check_triggering_units(bus, *name);
2937 /* Ask systemd-logind, which might grant access to unprivileged users
2938 * through PolicyKit */
2939 static int reboot_with_logind(sd_bus *bus, enum action a) {
2941 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2948 polkit_agent_open_if_enabled();
2956 case ACTION_POWEROFF:
2957 method = "PowerOff";
2960 case ACTION_SUSPEND:
2964 case ACTION_HIBERNATE:
2965 method = "Hibernate";
2968 case ACTION_HYBRID_SLEEP:
2969 method = "HybridSleep";
2976 r = sd_bus_call_method(
2978 "org.freedesktop.login1",
2979 "/org/freedesktop/login1",
2980 "org.freedesktop.login1.Manager",
2984 "b", arg_ask_password);
2986 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2994 static int check_inhibitors(sd_bus *bus, enum action a) {
2996 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2997 _cleanup_strv_free_ char **sessions = NULL;
2998 const char *what, *who, *why, *mode;
3007 if (arg_ignore_inhibitors || arg_force > 0)
3019 r = sd_bus_call_method(
3021 "org.freedesktop.login1",
3022 "/org/freedesktop/login1",
3023 "org.freedesktop.login1.Manager",
3029 /* If logind is not around, then there are no inhibitors... */
3032 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
3034 return bus_log_parse_error(r);
3036 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
3037 _cleanup_free_ char *comm = NULL, *user = NULL;
3038 _cleanup_strv_free_ char **sv = NULL;
3040 if (!streq(mode, "block"))
3043 sv = strv_split(what, ":");
3047 if (!strv_contains(sv,
3049 a == ACTION_POWEROFF ||
3050 a == ACTION_REBOOT ||
3051 a == ACTION_KEXEC ? "shutdown" : "sleep"))
3054 get_process_comm(pid, &comm);
3055 user = uid_to_name(uid);
3057 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
3058 who, pid, strna(comm), strna(user), why);
3063 return bus_log_parse_error(r);
3065 r = sd_bus_message_exit_container(reply);
3067 return bus_log_parse_error(r);
3069 /* Check for current sessions */
3070 sd_get_sessions(&sessions);
3071 STRV_FOREACH(s, sessions) {
3072 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
3074 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
3077 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
3080 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
3083 sd_session_get_tty(*s, &tty);
3084 sd_session_get_seat(*s, &seat);
3085 sd_session_get_service(*s, &service);
3086 user = uid_to_name(uid);
3088 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
3095 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3096 action_table[a].verb);
3104 static int start_special(sd_bus *bus, char **args) {
3110 a = verb_to_action(args[0]);
3112 r = check_inhibitors(bus, a);
3116 if (arg_force >= 2 && geteuid() != 0) {
3117 log_error("Must be root.");
3121 if (arg_force >= 2 &&
3122 (a == ACTION_HALT ||
3123 a == ACTION_POWEROFF ||
3124 a == ACTION_REBOOT))
3127 if (arg_force >= 1 &&
3128 (a == ACTION_HALT ||
3129 a == ACTION_POWEROFF ||
3130 a == ACTION_REBOOT ||
3131 a == ACTION_KEXEC ||
3133 return daemon_reload(bus, args);
3135 /* first try logind, to allow authentication with polkit */
3136 if (geteuid() != 0 &&
3137 (a == ACTION_POWEROFF ||
3138 a == ACTION_REBOOT ||
3139 a == ACTION_SUSPEND ||
3140 a == ACTION_HIBERNATE ||
3141 a == ACTION_HYBRID_SLEEP)) {
3142 r = reboot_with_logind(bus, a);
3147 r = start_unit(bus, args);
3148 if (r == EXIT_SUCCESS)
3154 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
3155 _cleanup_strv_free_ char **names = NULL;
3162 r = expand_names(bus, args, NULL, &names);
3164 return log_error_errno(r, "Failed to expand names: %m");
3166 STRV_FOREACH(name, names) {
3169 state = check_one_unit(bus, *name, good_states, arg_quiet);
3179 static int check_unit_active(sd_bus *bus, char **args) {
3180 /* According to LSB: 3, "program is not running" */
3181 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
3184 static int check_unit_failed(sd_bus *bus, char **args) {
3185 return check_unit_generic(bus, 1, "failed\0", args + 1);
3188 static int kill_unit(sd_bus *bus, char **args) {
3189 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3190 _cleanup_strv_free_ char **names = NULL;
3198 arg_kill_who = "all";
3200 r = expand_names(bus, args + 1, NULL, &names);
3202 log_error_errno(r, "Failed to expand names: %m");
3204 STRV_FOREACH(name, names) {
3205 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3207 q = sd_bus_message_new_method_call(
3210 "org.freedesktop.systemd1",
3211 "/org/freedesktop/systemd1",
3212 "org.freedesktop.systemd1.Manager",
3215 return bus_log_create_error(q);
3217 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
3219 return bus_log_create_error(q);
3221 q = sd_bus_message_append(m, "ssi", *names, arg_kill_who, arg_signal);
3223 return bus_log_create_error(q);
3225 q = sd_bus_call(bus, m, 0, &error, NULL);
3227 log_error("Failed to kill unit %s: %s", *names, bus_error_message(&error, q));
3236 typedef struct ExecStatusInfo {
3244 usec_t start_timestamp;
3245 usec_t exit_timestamp;
3250 LIST_FIELDS(struct ExecStatusInfo, exec);
3253 static void exec_status_info_free(ExecStatusInfo *i) {
3262 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3263 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3266 int32_t code, status;
3272 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3274 return bus_log_parse_error(r);
3278 r = sd_bus_message_read(m, "s", &path);
3280 return bus_log_parse_error(r);
3282 i->path = strdup(path);
3286 r = sd_bus_message_read_strv(m, &i->argv);
3288 return bus_log_parse_error(r);
3290 r = sd_bus_message_read(m,
3293 &start_timestamp, &start_timestamp_monotonic,
3294 &exit_timestamp, &exit_timestamp_monotonic,
3298 return bus_log_parse_error(r);
3301 i->start_timestamp = (usec_t) start_timestamp;
3302 i->exit_timestamp = (usec_t) exit_timestamp;
3303 i->pid = (pid_t) pid;
3307 r = sd_bus_message_exit_container(m);
3309 return bus_log_parse_error(r);
3314 typedef struct UnitStatusInfo {
3316 const char *load_state;
3317 const char *active_state;
3318 const char *sub_state;
3319 const char *unit_file_state;
3320 const char *unit_file_preset;
3322 const char *description;
3323 const char *following;
3325 char **documentation;
3327 const char *fragment_path;
3328 const char *source_path;
3329 const char *control_group;
3331 char **dropin_paths;
3333 const char *load_error;
3336 usec_t inactive_exit_timestamp;
3337 usec_t inactive_exit_timestamp_monotonic;
3338 usec_t active_enter_timestamp;
3339 usec_t active_exit_timestamp;
3340 usec_t inactive_enter_timestamp;
3342 bool need_daemon_reload;
3347 const char *status_text;
3348 const char *pid_file;
3352 usec_t start_timestamp;
3353 usec_t exit_timestamp;
3355 int exit_code, exit_status;
3357 usec_t condition_timestamp;
3358 bool condition_result;
3359 bool failed_condition_trigger;
3360 bool failed_condition_negate;
3361 const char *failed_condition;
3362 const char *failed_condition_parameter;
3364 usec_t assert_timestamp;
3366 bool failed_assert_trigger;
3367 bool failed_assert_negate;
3368 const char *failed_assert;
3369 const char *failed_assert_parameter;
3372 unsigned n_accepted;
3373 unsigned n_connections;
3376 /* Pairs of type, path */
3380 const char *sysfs_path;
3382 /* Mount, Automount */
3388 LIST_HEAD(ExecStatusInfo, exec);
3391 static void print_status_info(
3396 const char *active_on, *active_off, *on, *off, *ss;
3398 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3399 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3402 arg_all * OUTPUT_SHOW_ALL |
3403 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
3404 on_tty() * OUTPUT_COLOR |
3405 !arg_quiet * OUTPUT_WARN_CUTOFF |
3406 arg_full * OUTPUT_FULL_WIDTH;
3411 /* This shows pretty information about a unit. See
3412 * print_property() for a low-level property printer */
3414 if (streq_ptr(i->active_state, "failed")) {
3415 active_on = ansi_highlight_red();
3416 active_off = ansi_highlight_off();
3417 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3418 active_on = ansi_highlight_green();
3419 active_off = ansi_highlight_off();
3421 active_on = active_off = "";
3423 printf("%s%s%s %s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3425 if (i->description && !streq_ptr(i->id, i->description))
3426 printf(" - %s", i->description);
3431 printf(" Follow: unit currently follows state of %s\n", i->following);
3433 if (streq_ptr(i->load_state, "error")) {
3434 on = ansi_highlight_red();
3435 off = ansi_highlight_off();
3439 path = i->source_path ? i->source_path : i->fragment_path;
3442 printf(" Loaded: %s%s%s (Reason: %s)\n",
3443 on, strna(i->load_state), off, i->load_error);
3444 else if (path && !isempty(i->unit_file_state) && !isempty(i->unit_file_preset))
3445 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3446 on, strna(i->load_state), off, path, i->unit_file_state, i->unit_file_preset);
3447 else if (path && !isempty(i->unit_file_state))
3448 printf(" Loaded: %s%s%s (%s; %s)\n",
3449 on, strna(i->load_state), off, path, i->unit_file_state);
3451 printf(" Loaded: %s%s%s (%s)\n",
3452 on, strna(i->load_state), off, path);
3454 printf(" Loaded: %s%s%s\n",
3455 on, strna(i->load_state), off);
3457 if (!strv_isempty(i->dropin_paths)) {
3458 _cleanup_free_ char *dir = NULL;
3462 STRV_FOREACH(dropin, i->dropin_paths) {
3463 if (! dir || last) {
3464 printf(dir ? " " : " Drop-In: ");
3469 if (path_get_parent(*dropin, &dir) < 0) {
3474 printf("%s\n %s", dir,
3475 draw_special_char(DRAW_TREE_RIGHT));
3478 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3480 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3484 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3486 printf(" Active: %s%s (%s)%s",
3487 active_on, strna(i->active_state), ss, active_off);
3489 printf(" Active: %s%s%s",
3490 active_on, strna(i->active_state), active_off);
3492 if (!isempty(i->result) && !streq(i->result, "success"))
3493 printf(" (Result: %s)", i->result);
3495 timestamp = (streq_ptr(i->active_state, "active") ||
3496 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
3497 (streq_ptr(i->active_state, "inactive") ||
3498 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
3499 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
3500 i->active_exit_timestamp;
3502 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3503 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3506 printf(" since %s; %s\n", s2, s1);
3508 printf(" since %s\n", s2);
3512 if (!i->condition_result && i->condition_timestamp > 0) {
3513 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3514 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3516 printf("Condition: start %scondition failed%s at %s%s%s\n",
3517 ansi_highlight_yellow(), ansi_highlight_off(),
3518 s2, s1 ? "; " : "", s1 ? s1 : "");
3519 if (i->failed_condition_trigger)
3520 printf(" none of the trigger conditions were met\n");
3521 else if (i->failed_condition)
3522 printf(" %s=%s%s was not met\n",
3523 i->failed_condition,
3524 i->failed_condition_negate ? "!" : "",
3525 i->failed_condition_parameter);
3528 if (!i->assert_result && i->assert_timestamp > 0) {
3529 s1 = format_timestamp_relative(since1, sizeof(since1), i->assert_timestamp);
3530 s2 = format_timestamp(since2, sizeof(since2), i->assert_timestamp);
3532 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3533 ansi_highlight_red(), ansi_highlight_off(),
3534 s2, s1 ? "; " : "", s1 ? s1 : "");
3535 if (i->failed_assert_trigger)
3536 printf(" none of the trigger assertions were met\n");
3537 else if (i->failed_assert)
3538 printf(" %s=%s%s was not met\n",
3540 i->failed_assert_negate ? "!" : "",
3541 i->failed_assert_parameter);
3545 printf(" Device: %s\n", i->sysfs_path);
3547 printf(" Where: %s\n", i->where);
3549 printf(" What: %s\n", i->what);
3551 STRV_FOREACH(t, i->documentation)
3552 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3554 STRV_FOREACH_PAIR(t, t2, i->listen)
3555 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3558 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3560 LIST_FOREACH(exec, p, i->exec) {
3561 _cleanup_free_ char *argv = NULL;
3564 /* Only show exited processes here */
3568 argv = strv_join(p->argv, " ");
3569 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
3571 good = is_clean_exit_lsb(p->code, p->status, NULL);
3573 on = ansi_highlight_red();
3574 off = ansi_highlight_off();
3578 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3580 if (p->code == CLD_EXITED) {
3583 printf("status=%i", p->status);
3585 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3590 printf("signal=%s", signal_to_string(p->status));
3592 printf(")%s\n", off);
3594 if (i->main_pid == p->pid &&
3595 i->start_timestamp == p->start_timestamp &&
3596 i->exit_timestamp == p->start_timestamp)
3597 /* Let's not show this twice */
3600 if (p->pid == i->control_pid)
3604 if (i->main_pid > 0 || i->control_pid > 0) {
3605 if (i->main_pid > 0) {
3606 printf(" Main PID: "PID_FMT, i->main_pid);
3609 _cleanup_free_ char *comm = NULL;
3610 get_process_comm(i->main_pid, &comm);
3612 printf(" (%s)", comm);
3613 } else if (i->exit_code > 0) {
3614 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3616 if (i->exit_code == CLD_EXITED) {
3619 printf("status=%i", i->exit_status);
3621 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3626 printf("signal=%s", signal_to_string(i->exit_status));
3630 if (i->control_pid > 0)
3634 if (i->control_pid > 0) {
3635 _cleanup_free_ char *c = NULL;
3637 printf(" %8s: "PID_FMT, i->main_pid ? "" : " Control", i->control_pid);
3639 get_process_comm(i->control_pid, &c);
3648 printf(" Status: \"%s\"\n", i->status_text);
3649 if (i->status_errno > 0)
3650 printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
3652 if (i->control_group &&
3653 (i->main_pid > 0 || i->control_pid > 0 ||
3654 ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_CONTAINER) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3657 printf(" CGroup: %s\n", i->control_group);
3659 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
3662 static const char prefix[] = " ";
3665 if (c > sizeof(prefix) - 1)
3666 c -= sizeof(prefix) - 1;
3670 if (i->main_pid > 0)
3671 extra[k++] = i->main_pid;
3673 if (i->control_pid > 0)
3674 extra[k++] = i->control_pid;
3676 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, flags);
3680 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3681 show_journal_by_unit(stdout,
3685 i->inactive_exit_timestamp_monotonic,
3688 flags | OUTPUT_BEGIN_NEWLINE,
3689 arg_scope == UNIT_FILE_SYSTEM,
3693 if (i->need_daemon_reload)
3694 warn_unit_file_changed(i->id);
3697 static void show_unit_help(UnitStatusInfo *i) {
3702 if (!i->documentation) {
3703 log_info("Documentation for %s not known.", i->id);
3707 STRV_FOREACH(p, i->documentation)
3708 if (startswith(*p, "man:"))
3709 show_man_page(*p + 4, false);
3711 log_info("Can't show: %s", *p);
3714 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3721 switch (contents[0]) {
3723 case SD_BUS_TYPE_STRING: {
3726 r = sd_bus_message_read(m, "s", &s);
3728 return bus_log_parse_error(r);
3731 if (streq(name, "Id"))
3733 else if (streq(name, "LoadState"))
3735 else if (streq(name, "ActiveState"))
3736 i->active_state = s;
3737 else if (streq(name, "SubState"))
3739 else if (streq(name, "Description"))
3741 else if (streq(name, "FragmentPath"))
3742 i->fragment_path = s;
3743 else if (streq(name, "SourcePath"))
3746 else if (streq(name, "DefaultControlGroup")) {
3748 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3750 i->control_group = e;
3753 else if (streq(name, "ControlGroup"))
3754 i->control_group = s;
3755 else if (streq(name, "StatusText"))
3757 else if (streq(name, "PIDFile"))
3759 else if (streq(name, "SysFSPath"))
3761 else if (streq(name, "Where"))
3763 else if (streq(name, "What"))
3765 else if (streq(name, "Following"))
3767 else if (streq(name, "UnitFileState"))
3768 i->unit_file_state = s;
3769 else if (streq(name, "UnitFilePreset"))
3770 i->unit_file_preset = s;
3771 else if (streq(name, "Result"))
3778 case SD_BUS_TYPE_BOOLEAN: {
3781 r = sd_bus_message_read(m, "b", &b);
3783 return bus_log_parse_error(r);
3785 if (streq(name, "Accept"))
3787 else if (streq(name, "NeedDaemonReload"))
3788 i->need_daemon_reload = b;
3789 else if (streq(name, "ConditionResult"))
3790 i->condition_result = b;
3791 else if (streq(name, "AssertResult"))
3792 i->assert_result = b;
3797 case SD_BUS_TYPE_UINT32: {
3800 r = sd_bus_message_read(m, "u", &u);
3802 return bus_log_parse_error(r);
3804 if (streq(name, "MainPID")) {
3806 i->main_pid = (pid_t) u;
3809 } else if (streq(name, "ControlPID"))
3810 i->control_pid = (pid_t) u;
3811 else if (streq(name, "ExecMainPID")) {
3813 i->main_pid = (pid_t) u;
3814 } else if (streq(name, "NAccepted"))
3816 else if (streq(name, "NConnections"))
3817 i->n_connections = u;
3822 case SD_BUS_TYPE_INT32: {
3825 r = sd_bus_message_read(m, "i", &j);
3827 return bus_log_parse_error(r);
3829 if (streq(name, "ExecMainCode"))
3830 i->exit_code = (int) j;
3831 else if (streq(name, "ExecMainStatus"))
3832 i->exit_status = (int) j;
3833 else if (streq(name, "StatusErrno"))
3834 i->status_errno = (int) j;
3839 case SD_BUS_TYPE_UINT64: {
3842 r = sd_bus_message_read(m, "t", &u);
3844 return bus_log_parse_error(r);
3846 if (streq(name, "ExecMainStartTimestamp"))
3847 i->start_timestamp = (usec_t) u;
3848 else if (streq(name, "ExecMainExitTimestamp"))
3849 i->exit_timestamp = (usec_t) u;
3850 else if (streq(name, "ActiveEnterTimestamp"))
3851 i->active_enter_timestamp = (usec_t) u;
3852 else if (streq(name, "InactiveEnterTimestamp"))
3853 i->inactive_enter_timestamp = (usec_t) u;
3854 else if (streq(name, "InactiveExitTimestamp"))
3855 i->inactive_exit_timestamp = (usec_t) u;
3856 else if (streq(name, "InactiveExitTimestampMonotonic"))
3857 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3858 else if (streq(name, "ActiveExitTimestamp"))
3859 i->active_exit_timestamp = (usec_t) u;
3860 else if (streq(name, "ConditionTimestamp"))
3861 i->condition_timestamp = (usec_t) u;
3862 else if (streq(name, "AssertTimestamp"))
3863 i->assert_timestamp = (usec_t) u;
3868 case SD_BUS_TYPE_ARRAY:
3870 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3871 _cleanup_free_ ExecStatusInfo *info = NULL;
3873 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3875 return bus_log_parse_error(r);
3877 info = new0(ExecStatusInfo, 1);
3881 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3883 info->name = strdup(name);
3887 LIST_PREPEND(exec, i->exec, info);
3889 info = new0(ExecStatusInfo, 1);
3895 return bus_log_parse_error(r);
3897 r = sd_bus_message_exit_container(m);
3899 return bus_log_parse_error(r);
3903 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3904 const char *type, *path;
3906 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3908 return bus_log_parse_error(r);
3910 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3912 r = strv_extend(&i->listen, type);
3916 r = strv_extend(&i->listen, path);
3921 return bus_log_parse_error(r);
3923 r = sd_bus_message_exit_container(m);
3925 return bus_log_parse_error(r);
3929 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3931 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3933 return bus_log_parse_error(r);
3935 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3937 r = sd_bus_message_read_strv(m, &i->documentation);
3939 return bus_log_parse_error(r);
3941 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3942 const char *cond, *param;
3943 int trigger, negate;
3946 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3948 return bus_log_parse_error(r);
3950 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3951 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3952 if (state < 0 && (!trigger || !i->failed_condition)) {
3953 i->failed_condition = cond;
3954 i->failed_condition_trigger = trigger;
3955 i->failed_condition_negate = negate;
3956 i->failed_condition_parameter = param;
3960 return bus_log_parse_error(r);
3962 r = sd_bus_message_exit_container(m);
3964 return bus_log_parse_error(r);
3966 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Asserts")) {
3967 const char *cond, *param;
3968 int trigger, negate;
3971 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3973 return bus_log_parse_error(r);
3975 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3976 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3977 if (state < 0 && (!trigger || !i->failed_assert)) {
3978 i->failed_assert = cond;
3979 i->failed_assert_trigger = trigger;
3980 i->failed_assert_negate = negate;
3981 i->failed_assert_parameter = param;
3985 return bus_log_parse_error(r);
3987 r = sd_bus_message_exit_container(m);
3989 return bus_log_parse_error(r);
3996 case SD_BUS_TYPE_STRUCT_BEGIN:
3998 if (streq(name, "LoadError")) {
3999 const char *n, *message;
4001 r = sd_bus_message_read(m, "(ss)", &n, &message);
4003 return bus_log_parse_error(r);
4005 if (!isempty(message))
4006 i->load_error = message;
4019 r = sd_bus_message_skip(m, contents);
4021 return bus_log_parse_error(r);
4026 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
4032 /* This is a low-level property printer, see
4033 * print_status_info() for the nicer output */
4035 if (arg_properties && !strv_find(arg_properties, name)) {
4036 /* skip what we didn't read */
4037 r = sd_bus_message_skip(m, contents);
4041 switch (contents[0]) {
4043 case SD_BUS_TYPE_STRUCT_BEGIN:
4045 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
4048 r = sd_bus_message_read(m, "(uo)", &u, NULL);
4050 return bus_log_parse_error(r);
4053 printf("%s=%"PRIu32"\n", name, u);
4055 printf("%s=\n", name);
4059 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
4062 r = sd_bus_message_read(m, "(so)", &s, NULL);
4064 return bus_log_parse_error(r);
4066 if (arg_all || !isempty(s))
4067 printf("%s=%s\n", name, s);
4071 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
4072 const char *a = NULL, *b = NULL;
4074 r = sd_bus_message_read(m, "(ss)", &a, &b);
4076 return bus_log_parse_error(r);
4078 if (arg_all || !isempty(a) || !isempty(b))
4079 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
4082 } else if (streq_ptr(name, "SystemCallFilter")) {
4083 _cleanup_strv_free_ char **l = NULL;
4086 r = sd_bus_message_enter_container(m, 'r', "bas");
4088 return bus_log_parse_error(r);
4090 r = sd_bus_message_read(m, "b", &whitelist);
4092 return bus_log_parse_error(r);
4094 r = sd_bus_message_read_strv(m, &l);
4096 return bus_log_parse_error(r);
4098 r = sd_bus_message_exit_container(m);
4100 return bus_log_parse_error(r);
4102 if (arg_all || whitelist || !strv_isempty(l)) {
4106 fputs(name, stdout);
4112 STRV_FOREACH(i, l) {
4120 fputc('\n', stdout);
4128 case SD_BUS_TYPE_ARRAY:
4130 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
4134 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
4136 return bus_log_parse_error(r);
4138 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
4139 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
4142 return bus_log_parse_error(r);
4144 r = sd_bus_message_exit_container(m);
4146 return bus_log_parse_error(r);
4150 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
4151 const char *type, *path;
4153 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4155 return bus_log_parse_error(r);
4157 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4158 printf("%s=%s\n", type, path);
4160 return bus_log_parse_error(r);
4162 r = sd_bus_message_exit_container(m);
4164 return bus_log_parse_error(r);
4168 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
4169 const char *type, *path;
4171 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4173 return bus_log_parse_error(r);
4175 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4176 printf("Listen%s=%s\n", type, path);
4178 return bus_log_parse_error(r);
4180 r = sd_bus_message_exit_container(m);
4182 return bus_log_parse_error(r);
4186 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
4188 uint64_t value, next_elapse;
4190 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
4192 return bus_log_parse_error(r);
4194 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
4195 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
4197 printf("%s={ value=%s ; next_elapse=%s }\n",
4199 format_timespan(timespan1, sizeof(timespan1), value, 0),
4200 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
4203 return bus_log_parse_error(r);
4205 r = sd_bus_message_exit_container(m);
4207 return bus_log_parse_error(r);
4211 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
4212 ExecStatusInfo info = {};
4214 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
4216 return bus_log_parse_error(r);
4218 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
4219 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
4220 _cleanup_free_ char *tt;
4222 tt = strv_join(info.argv, " ");
4224 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",
4228 yes_no(info.ignore),
4229 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
4230 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
4232 sigchld_code_to_string(info.code),
4234 info.code == CLD_EXITED ? "" : "/",
4235 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
4238 strv_free(info.argv);
4242 r = sd_bus_message_exit_container(m);
4244 return bus_log_parse_error(r);
4248 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
4249 const char *path, *rwm;
4251 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4253 return bus_log_parse_error(r);
4255 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
4256 printf("%s=%s %s\n", name, strna(path), strna(rwm));
4258 return bus_log_parse_error(r);
4260 r = sd_bus_message_exit_container(m);
4262 return bus_log_parse_error(r);
4266 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
4270 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4272 return bus_log_parse_error(r);
4274 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4275 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
4277 return bus_log_parse_error(r);
4279 r = sd_bus_message_exit_container(m);
4281 return bus_log_parse_error(r);
4285 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
4289 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4291 return bus_log_parse_error(r);
4293 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4294 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
4296 return bus_log_parse_error(r);
4298 r = sd_bus_message_exit_container(m);
4300 return bus_log_parse_error(r);
4308 r = bus_print_property(name, m, arg_all);
4310 return bus_log_parse_error(r);
4313 r = sd_bus_message_skip(m, contents);
4315 return bus_log_parse_error(r);
4318 printf("%s=[unprintable]\n", name);
4324 static int show_one(
4328 bool show_properties,
4332 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4333 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4334 UnitStatusInfo info = {};
4341 log_debug("Showing one %s", path);
4343 r = sd_bus_call_method(
4345 "org.freedesktop.systemd1",
4347 "org.freedesktop.DBus.Properties",
4353 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4357 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4359 return bus_log_parse_error(r);
4366 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4367 const char *name, *contents;
4369 r = sd_bus_message_read(reply, "s", &name);
4371 return bus_log_parse_error(r);
4373 r = sd_bus_message_peek_type(reply, NULL, &contents);
4375 return bus_log_parse_error(r);
4377 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4379 return bus_log_parse_error(r);
4381 if (show_properties)
4382 r = print_property(name, reply, contents);
4384 r = status_property(name, reply, &info, contents);
4388 r = sd_bus_message_exit_container(reply);
4390 return bus_log_parse_error(r);
4392 r = sd_bus_message_exit_container(reply);
4394 return bus_log_parse_error(r);
4397 return bus_log_parse_error(r);
4399 r = sd_bus_message_exit_container(reply);
4401 return bus_log_parse_error(r);
4405 if (!show_properties) {
4406 if (streq(verb, "help"))
4407 show_unit_help(&info);
4409 print_status_info(&info, ellipsized);
4412 strv_free(info.documentation);
4413 strv_free(info.dropin_paths);
4414 strv_free(info.listen);
4416 if (!streq_ptr(info.active_state, "active") &&
4417 !streq_ptr(info.active_state, "reloading") &&
4418 streq(verb, "status")) {
4419 /* According to LSB: "program not running" */
4420 /* 0: program is running or service is OK
4421 * 1: program is dead and /run PID file exists
4422 * 2: program is dead and /run/lock lock file exists
4423 * 3: program is not running
4424 * 4: program or service status is unknown
4426 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4432 while ((p = info.exec)) {
4433 LIST_REMOVE(exec, info.exec, p);
4434 exec_status_info_free(p);
4440 static int get_unit_dbus_path_by_pid(
4445 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4446 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4450 r = sd_bus_call_method(
4452 "org.freedesktop.systemd1",
4453 "/org/freedesktop/systemd1",
4454 "org.freedesktop.systemd1.Manager",
4460 log_error("Failed to get unit for PID "PID_FMT": %s", pid, bus_error_message(&error, r));
4464 r = sd_bus_message_read(reply, "o", &u);
4466 return bus_log_parse_error(r);
4476 static int show_all(
4479 bool show_properties,
4483 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4484 _cleanup_free_ UnitInfo *unit_infos = NULL;
4489 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4493 pager_open_if_enabled();
4497 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4499 for (u = unit_infos; u < unit_infos + c; u++) {
4500 _cleanup_free_ char *p = NULL;
4502 p = unit_dbus_path_from_name(u->id);
4506 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4509 else if (r > 0 && ret == 0)
4516 static int show_system_status(sd_bus *bus) {
4517 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4518 _cleanup_free_ char *hn = NULL;
4519 struct machine_info mi = {};
4520 const char *on, *off;
4523 hn = gethostname_malloc();
4527 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4529 return log_error_errno(r, "Failed to read server status: %m");
4531 if (streq_ptr(mi.state, "degraded")) {
4532 on = ansi_highlight_red();
4533 off = ansi_highlight_off();
4534 } else if (!streq_ptr(mi.state, "running")) {
4535 on = ansi_highlight_yellow();
4536 off = ansi_highlight_off();
4540 printf("%s%s%s %s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4542 printf(" State: %s%s%s\n",
4543 on, strna(mi.state), off);
4545 printf(" Jobs: %u queued\n", mi.n_jobs);
4546 printf(" Failed: %u units\n", mi.n_failed_units);
4548 printf(" Since: %s; %s\n",
4549 format_timestamp(since2, sizeof(since2), mi.timestamp),
4550 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4552 printf(" CGroup: %s\n", mi.control_group ?: "/");
4553 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
4555 arg_all * OUTPUT_SHOW_ALL |
4556 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
4557 on_tty() * OUTPUT_COLOR |
4558 !arg_quiet * OUTPUT_WARN_CUTOFF |
4559 arg_full * OUTPUT_FULL_WIDTH;
4561 static const char prefix[] = " ";
4565 if (c > sizeof(prefix) - 1)
4566 c -= sizeof(prefix) - 1;
4570 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
4574 free(mi.control_group);
4579 static int show(sd_bus *bus, char **args) {
4580 bool show_properties, show_status, new_line = false;
4581 bool ellipsized = false;
4587 show_properties = streq(args[0], "show");
4588 show_status = streq(args[0], "status");
4590 if (show_properties)
4591 pager_open_if_enabled();
4593 /* If no argument is specified inspect the manager itself */
4595 if (show_properties && strv_length(args) <= 1)
4596 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4598 if (show_status && strv_length(args) <= 1) {
4600 pager_open_if_enabled();
4601 show_system_status(bus);
4605 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4607 _cleanup_free_ char **patterns = NULL;
4610 STRV_FOREACH(name, args + 1) {
4611 _cleanup_free_ char *unit = NULL;
4614 if (safe_atou32(*name, &id) < 0) {
4615 if (strv_push(&patterns, *name) < 0)
4619 } else if (show_properties) {
4620 /* Interpret as job id */
4621 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4625 /* Interpret as PID */
4626 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4633 r = show_one(args[0], bus, unit, show_properties,
4634 &new_line, &ellipsized);
4637 else if (r > 0 && ret == 0)
4641 if (!strv_isempty(patterns)) {
4642 _cleanup_strv_free_ char **names = NULL;
4644 r = expand_names(bus, patterns, NULL, &names);
4646 log_error_errno(r, "Failed to expand names: %m");
4648 STRV_FOREACH(name, names) {
4649 _cleanup_free_ char *unit;
4651 unit = unit_dbus_path_from_name(*name);
4655 r = show_one(args[0], bus, unit, show_properties,
4656 &new_line, &ellipsized);
4659 else if (r > 0 && ret == 0)
4665 if (ellipsized && !arg_quiet)
4666 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4671 static int init_home_and_lookup_paths(char **user_home, char **user_runtime, LookupPaths *lp) {
4675 assert(user_runtime);
4678 if (arg_scope == UNIT_FILE_USER) {
4679 r = user_config_home(user_home);
4681 return log_error_errno(r, "Failed to query XDG_CONFIG_HOME: %m");
4683 return log_error_errno(ENOTDIR, "Cannot find units: $XDG_CONFIG_HOME and $HOME are not set.");
4685 r = user_runtime_dir(user_runtime);
4687 return log_error_errno(r, "Failed to query XDG_CONFIG_HOME: %m");
4689 return log_error_errno(ENOTDIR, "Cannot find units: $XDG_RUNTIME_DIR is not set.");
4692 r = lookup_paths_init(lp,
4693 arg_scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
4694 arg_scope == UNIT_FILE_USER,
4698 return log_error_errno(r, "Failed to lookup unit lookup paths: %m");
4703 static int cat(sd_bus *bus, char **args) {
4704 _cleanup_strv_free_ char **names = NULL;
4712 r = expand_names(bus, args + 1, NULL, &names);
4714 log_error_errno(r, "Failed to expand names: %m");
4716 pager_open_if_enabled();
4718 STRV_FOREACH(name, names) {
4719 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4720 _cleanup_strv_free_ char **dropin_paths = NULL;
4721 _cleanup_free_ char *fragment_path = NULL, *unit = NULL;
4724 unit = unit_dbus_path_from_name(*name);
4728 if (need_daemon_reload(bus, *name) > 0)
4729 warn_unit_file_changed(*name);
4731 r = sd_bus_get_property_string(
4733 "org.freedesktop.systemd1",
4735 "org.freedesktop.systemd1.Unit",
4740 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
4744 r = sd_bus_get_property_strv(
4746 "org.freedesktop.systemd1",
4748 "org.freedesktop.systemd1.Unit",
4753 log_warning("Failed to get DropInPaths: %s", bus_error_message(&error, r));
4762 if (!isempty(fragment_path)) {
4763 printf("%s# %s%s\n",
4764 ansi_highlight_blue(),
4766 ansi_highlight_off());
4769 r = copy_file_fd(fragment_path, STDOUT_FILENO, false);
4771 log_warning_errno(r, "Failed to cat %s: %m", fragment_path);
4776 STRV_FOREACH(path, dropin_paths) {
4777 printf("%s%s# %s%s\n",
4778 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4779 ansi_highlight_blue(),
4781 ansi_highlight_off());
4784 r = copy_file_fd(*path, STDOUT_FILENO, false);
4786 log_warning_errno(r, "Failed to cat %s: %m", *path);
4792 return r < 0 ? r : 0;
4795 static int set_property(sd_bus *bus, char **args) {
4796 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4797 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4798 _cleanup_free_ char *n = NULL;
4802 r = sd_bus_message_new_method_call(
4805 "org.freedesktop.systemd1",
4806 "/org/freedesktop/systemd1",
4807 "org.freedesktop.systemd1.Manager",
4808 "SetUnitProperties");
4810 return bus_log_create_error(r);
4812 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4814 return bus_log_create_error(r);
4816 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4820 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4822 return bus_log_create_error(r);
4824 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4826 return bus_log_create_error(r);
4828 STRV_FOREACH(i, args + 2) {
4829 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4831 return bus_log_create_error(r);
4833 r = bus_append_unit_property_assignment(m, *i);
4837 r = sd_bus_message_close_container(m);
4839 return bus_log_create_error(r);
4842 r = sd_bus_message_close_container(m);
4844 return bus_log_create_error(r);
4846 r = sd_bus_call(bus, m, 0, &error, NULL);
4848 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4855 static int snapshot(sd_bus *bus, char **args) {
4856 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4857 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
4858 _cleanup_free_ char *n = NULL, *id = NULL;
4862 if (strv_length(args) > 1)
4863 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4869 r = sd_bus_message_new_method_call(
4872 "org.freedesktop.systemd1",
4873 "/org/freedesktop/systemd1",
4874 "org.freedesktop.systemd1.Manager",
4877 return bus_log_create_error(r);
4879 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4881 return bus_log_create_error(r);
4883 r = sd_bus_message_append(m, "sb", n, false);
4885 return bus_log_create_error(r);
4887 r = sd_bus_call(bus, m, 0, &error, &reply);
4889 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4893 r = sd_bus_message_read(reply, "o", &path);
4895 return bus_log_parse_error(r);
4897 r = sd_bus_get_property_string(
4899 "org.freedesktop.systemd1",
4901 "org.freedesktop.systemd1.Unit",
4906 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4916 static int delete_snapshot(sd_bus *bus, char **args) {
4917 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4918 _cleanup_strv_free_ char **names = NULL;
4924 r = expand_names(bus, args + 1, ".snapshot", &names);
4926 log_error_errno(r, "Failed to expand names: %m");
4928 STRV_FOREACH(name, names) {
4929 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4932 q = sd_bus_message_new_method_call(
4935 "org.freedesktop.systemd1",
4936 "/org/freedesktop/systemd1",
4937 "org.freedesktop.systemd1.Manager",
4940 return bus_log_create_error(q);
4942 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4944 return bus_log_create_error(q);
4946 q = sd_bus_message_append(m, "s", *name);
4948 return bus_log_create_error(q);
4950 q = sd_bus_call(bus, m, 0, &error, NULL);
4952 log_error("Failed to remove snapshot %s: %s", *name, bus_error_message(&error, q));
4961 static int daemon_reload(sd_bus *bus, char **args) {
4962 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4963 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4967 if (arg_action == ACTION_RELOAD)
4969 else if (arg_action == ACTION_REEXEC)
4970 method = "Reexecute";
4972 assert(arg_action == ACTION_SYSTEMCTL);
4975 streq(args[0], "clear-jobs") ||
4976 streq(args[0], "cancel") ? "ClearJobs" :
4977 streq(args[0], "daemon-reexec") ? "Reexecute" :
4978 streq(args[0], "reset-failed") ? "ResetFailed" :
4979 streq(args[0], "halt") ? "Halt" :
4980 streq(args[0], "poweroff") ? "PowerOff" :
4981 streq(args[0], "reboot") ? "Reboot" :
4982 streq(args[0], "kexec") ? "KExec" :
4983 streq(args[0], "exit") ? "Exit" :
4984 /* "daemon-reload" */ "Reload";
4987 r = sd_bus_message_new_method_call(
4990 "org.freedesktop.systemd1",
4991 "/org/freedesktop/systemd1",
4992 "org.freedesktop.systemd1.Manager",
4995 return bus_log_create_error(r);
4997 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4999 return bus_log_create_error(r);
5001 r = sd_bus_call(bus, m, 0, &error, NULL);
5002 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
5003 /* There's always a fallback possible for
5004 * legacy actions. */
5006 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
5007 /* On reexecution, we expect a disconnect, not a
5011 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5013 return r < 0 ? r : 0;
5016 static int reset_failed(sd_bus *bus, char **args) {
5017 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5018 _cleanup_strv_free_ char **names = NULL;
5022 if (strv_length(args) <= 1)
5023 return daemon_reload(bus, args);
5025 r = expand_names(bus, args + 1, NULL, &names);
5027 log_error_errno(r, "Failed to expand names: %m");
5029 STRV_FOREACH(name, names) {
5030 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
5032 q = sd_bus_message_new_method_call(
5035 "org.freedesktop.systemd1",
5036 "/org/freedesktop/systemd1",
5037 "org.freedesktop.systemd1.Manager",
5040 return bus_log_create_error(q);
5042 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5044 return bus_log_create_error(q);
5046 q = sd_bus_message_append(m, "s", *name);
5048 return bus_log_create_error(q);
5050 q = sd_bus_call(bus, m, 0, &error, NULL);
5052 log_error("Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q));
5061 static int show_environment(sd_bus *bus, char **args) {
5062 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5063 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5067 pager_open_if_enabled();
5069 r = sd_bus_get_property(
5071 "org.freedesktop.systemd1",
5072 "/org/freedesktop/systemd1",
5073 "org.freedesktop.systemd1.Manager",
5079 log_error("Failed to get environment: %s", bus_error_message(&error, r));
5083 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
5085 return bus_log_parse_error(r);
5087 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
5090 return bus_log_parse_error(r);
5092 r = sd_bus_message_exit_container(reply);
5094 return bus_log_parse_error(r);
5099 static int switch_root(sd_bus *bus, char **args) {
5100 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5101 _cleanup_free_ char *cmdline_init = NULL;
5102 const char *root, *init;
5106 l = strv_length(args);
5107 if (l < 2 || l > 3) {
5108 log_error("Wrong number of arguments.");
5117 r = parse_env_file("/proc/cmdline", WHITESPACE,
5118 "init", &cmdline_init,
5121 log_debug_errno(r, "Failed to parse /proc/cmdline: %m");
5123 init = cmdline_init;
5130 const char *root_systemd_path = NULL, *root_init_path = NULL;
5132 root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
5133 root_init_path = strappenda(root, "/", init);
5135 /* If the passed init is actually the same as the
5136 * systemd binary, then let's suppress it. */
5137 if (files_same(root_init_path, root_systemd_path) > 0)
5141 log_debug("Switching root - root: %s; init: %s", root, strna(init));
5143 r = sd_bus_call_method(
5145 "org.freedesktop.systemd1",
5146 "/org/freedesktop/systemd1",
5147 "org.freedesktop.systemd1.Manager",
5153 log_error("Failed to switch root: %s", bus_error_message(&error, r));
5160 static int set_environment(sd_bus *bus, char **args) {
5161 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5162 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
5169 method = streq(args[0], "set-environment")
5171 : "UnsetEnvironment";
5173 r = sd_bus_message_new_method_call(
5176 "org.freedesktop.systemd1",
5177 "/org/freedesktop/systemd1",
5178 "org.freedesktop.systemd1.Manager",
5181 return bus_log_create_error(r);
5183 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5185 return bus_log_create_error(r);
5187 r = sd_bus_message_append_strv(m, args + 1);
5189 return bus_log_create_error(r);
5191 r = sd_bus_call(bus, m, 0, &error, NULL);
5193 log_error("Failed to set environment: %s", bus_error_message(&error, r));
5200 static int import_environment(sd_bus *bus, char **args) {
5201 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5202 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
5208 r = sd_bus_message_new_method_call(
5211 "org.freedesktop.systemd1",
5212 "/org/freedesktop/systemd1",
5213 "org.freedesktop.systemd1.Manager",
5216 return bus_log_create_error(r);
5218 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5220 return bus_log_create_error(r);
5222 if (strv_isempty(args + 1))
5223 r = sd_bus_message_append_strv(m, environ);
5227 r = sd_bus_message_open_container(m, 'a', "s");
5229 return bus_log_create_error(r);
5231 STRV_FOREACH(a, args + 1) {
5233 if (!env_name_is_valid(*a)) {
5234 log_error("Not a valid environment variable name: %s", *a);
5238 STRV_FOREACH(b, environ) {
5241 eq = startswith(*b, *a);
5242 if (eq && *eq == '=') {
5244 r = sd_bus_message_append(m, "s", *b);
5246 return bus_log_create_error(r);
5253 r = sd_bus_message_close_container(m);
5256 return bus_log_create_error(r);
5258 r = sd_bus_call(bus, m, 0, &error, NULL);
5260 log_error("Failed to import environment: %s", bus_error_message(&error, r));
5267 static int enable_sysv_units(const char *verb, char **args) {
5270 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
5272 _cleanup_lookup_paths_free_ LookupPaths paths = {};
5274 if (arg_scope != UNIT_FILE_SYSTEM)
5277 if (!streq(verb, "enable") &&
5278 !streq(verb, "disable") &&
5279 !streq(verb, "is-enabled"))
5282 /* Processes all SysV units, and reshuffles the array so that
5283 * afterwards only the native units remain */
5285 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, arg_root, NULL, NULL, NULL);
5292 _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL;
5293 bool found_native = false, found_sysv;
5295 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
5303 if (!endswith(name, ".service"))
5306 if (path_is_absolute(name))
5309 STRV_FOREACH(k, paths.unit_path) {
5310 _cleanup_free_ char *path = NULL;
5312 path = path_join(arg_root, *k, name);
5316 found_native = access(path, F_OK) >= 0;
5324 p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name);
5328 p[strlen(p) - strlen(".service")] = 0;
5329 found_sysv = access(p, F_OK) >= 0;
5333 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
5335 if (!isempty(arg_root))
5336 argv[c++] = q = strappend("--root=", arg_root);
5338 argv[c++] = basename(p);
5340 streq(verb, "enable") ? "on" :
5341 streq(verb, "disable") ? "off" : "--level=5";
5344 l = strv_join((char**)argv, " ");
5348 log_info("Executing %s", l);
5352 return log_error_errno(errno, "Failed to fork: %m");
5353 else if (pid == 0) {
5356 execv(argv[0], (char**) argv);
5357 _exit(EXIT_FAILURE);
5360 j = wait_for_terminate(pid, &status);
5362 log_error_errno(r, "Failed to wait for child: %m");
5366 if (status.si_code == CLD_EXITED) {
5367 if (streq(verb, "is-enabled")) {
5368 if (status.si_status == 0) {
5377 } else if (status.si_status != 0)
5382 /* Remove this entry, so that we don't try enabling it as native unit */
5383 assert(f > 0 && streq(args[f-1], name));
5384 assert_se(strv_remove(args + f - 1, name));
5391 static int mangle_names(char **original_names, char ***mangled_names) {
5392 char **i, **l, **name;
5394 l = new(char*, strv_length(original_names) + 1);
5399 STRV_FOREACH(name, original_names) {
5401 /* When enabling units qualified path names are OK,
5402 * too, hence allow them explicitly. */
5407 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5423 static int enable_unit(sd_bus *bus, char **args) {
5424 _cleanup_strv_free_ char **names = NULL;
5425 const char *verb = args[0];
5426 UnitFileChange *changes = NULL;
5427 unsigned n_changes = 0;
5428 int carries_install_info = -1;
5434 r = mangle_names(args+1, &names);
5438 r = enable_sysv_units(verb, names);
5442 /* If the operation was fully executed by the SysV compat,
5443 * let's finish early */
5444 if (strv_isempty(names))
5447 if (!bus || avoid_bus()) {
5448 if (streq(verb, "enable")) {
5449 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5450 carries_install_info = r;
5451 } else if (streq(verb, "disable"))
5452 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5453 else if (streq(verb, "reenable")) {
5454 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5455 carries_install_info = r;
5456 } else if (streq(verb, "link"))
5457 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5458 else if (streq(verb, "preset")) {
5459 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_preset_mode, arg_force, &changes, &n_changes);
5460 carries_install_info = r;
5461 } else if (streq(verb, "mask"))
5462 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5463 else if (streq(verb, "unmask"))
5464 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5466 assert_not_reached("Unknown verb");
5469 log_error_errno(r, "Operation failed: %m");
5474 dump_unit_file_changes(changes, n_changes);
5478 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5479 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5480 int expect_carries_install_info = false;
5481 bool send_force = true, send_preset_mode = false;
5484 if (streq(verb, "enable")) {
5485 method = "EnableUnitFiles";
5486 expect_carries_install_info = true;
5487 } else if (streq(verb, "disable")) {
5488 method = "DisableUnitFiles";
5490 } else if (streq(verb, "reenable")) {
5491 method = "ReenableUnitFiles";
5492 expect_carries_install_info = true;
5493 } else if (streq(verb, "link"))
5494 method = "LinkUnitFiles";
5495 else if (streq(verb, "preset")) {
5497 if (arg_preset_mode != UNIT_FILE_PRESET_FULL) {
5498 method = "PresetUnitFilesWithMode";
5499 send_preset_mode = true;
5501 method = "PresetUnitFiles";
5503 expect_carries_install_info = true;
5504 } else if (streq(verb, "mask"))
5505 method = "MaskUnitFiles";
5506 else if (streq(verb, "unmask")) {
5507 method = "UnmaskUnitFiles";
5510 assert_not_reached("Unknown verb");
5512 r = sd_bus_message_new_method_call(
5515 "org.freedesktop.systemd1",
5516 "/org/freedesktop/systemd1",
5517 "org.freedesktop.systemd1.Manager",
5520 return bus_log_create_error(r);
5522 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5524 return bus_log_create_error(r);
5526 r = sd_bus_message_append_strv(m, names);
5528 return bus_log_create_error(r);
5530 if (send_preset_mode) {
5531 r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode));
5533 return bus_log_create_error(r);
5536 r = sd_bus_message_append(m, "b", arg_runtime);
5538 return bus_log_create_error(r);
5541 r = sd_bus_message_append(m, "b", arg_force);
5543 return bus_log_create_error(r);
5546 r = sd_bus_call(bus, m, 0, &error, &reply);
5548 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5552 if (expect_carries_install_info) {
5553 r = sd_bus_message_read(reply, "b", &carries_install_info);
5555 return bus_log_parse_error(r);
5558 r = deserialize_and_dump_unit_file_changes(reply);
5562 /* Try to reload if enabled */
5564 r = daemon_reload(bus, args);
5569 if (carries_install_info == 0)
5570 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5571 "using systemctl.\n"
5572 "Possible reasons for having this kind of units are:\n"
5573 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5574 " .wants/ or .requires/ directory.\n"
5575 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5576 " a requirement dependency on it.\n"
5577 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5578 " D-Bus, udev, scripted systemctl call, ...).\n");
5581 unit_file_changes_free(changes, n_changes);
5586 static int add_dependency(sd_bus *bus, char **args) {
5587 _cleanup_strv_free_ char **names = NULL;
5588 _cleanup_free_ char *target = NULL;
5589 const char *verb = args[0];
5596 target = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
5600 r = mangle_names(args+2, &names);
5604 if (streq(verb, "add-wants"))
5606 else if (streq(verb, "add-requires"))
5607 dep = UNIT_REQUIRES;
5609 assert_not_reached("Unknown verb");
5611 if (!bus || avoid_bus()) {
5612 UnitFileChange *changes = NULL;
5613 unsigned n_changes = 0;
5615 r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes);
5618 return log_error_errno(r, "Can't add dependency: %m");
5621 dump_unit_file_changes(changes, n_changes);
5623 unit_file_changes_free(changes, n_changes);
5626 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5627 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5629 r = sd_bus_message_new_method_call(
5632 "org.freedesktop.systemd1",
5633 "/org/freedesktop/systemd1",
5634 "org.freedesktop.systemd1.Manager",
5635 "AddDependencyUnitFiles");
5637 return bus_log_create_error(r);
5639 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5641 return bus_log_create_error(r);
5643 r = sd_bus_message_append_strv(m, names);
5645 return bus_log_create_error(r);
5647 r = sd_bus_message_append(m, "ssbb", target, unit_dependency_to_string(dep), arg_runtime, arg_force);
5649 return bus_log_create_error(r);
5651 r = sd_bus_call(bus, m, 0, &error, &reply);
5653 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5657 r = deserialize_and_dump_unit_file_changes(reply);
5662 r = daemon_reload(bus, args);
5670 static int preset_all(sd_bus *bus, char **args) {
5671 UnitFileChange *changes = NULL;
5672 unsigned n_changes = 0;
5675 if (!bus || avoid_bus()) {
5677 r = unit_file_preset_all(arg_scope, arg_runtime, arg_root, arg_preset_mode, arg_force, &changes, &n_changes);
5679 log_error_errno(r, "Operation failed: %m");
5684 dump_unit_file_changes(changes, n_changes);
5689 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
5690 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5692 r = sd_bus_message_new_method_call(
5695 "org.freedesktop.systemd1",
5696 "/org/freedesktop/systemd1",
5697 "org.freedesktop.systemd1.Manager",
5698 "PresetAllUnitFiles");
5700 return bus_log_create_error(r);
5702 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5704 return bus_log_create_error(r);
5706 r = sd_bus_message_append(
5709 unit_file_preset_mode_to_string(arg_preset_mode),
5713 return bus_log_create_error(r);
5715 r = sd_bus_call(bus, m, 0, &error, &reply);
5717 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5721 r = deserialize_and_dump_unit_file_changes(reply);
5726 r = daemon_reload(bus, args);
5732 unit_file_changes_free(changes, n_changes);
5737 static int unit_is_enabled(sd_bus *bus, char **args) {
5739 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5740 _cleanup_strv_free_ char **names = NULL;
5745 r = mangle_names(args+1, &names);
5749 r = enable_sysv_units(args[0], names);
5755 if (!bus || avoid_bus()) {
5757 STRV_FOREACH(name, names) {
5758 UnitFileState state;
5760 state = unit_file_get_state(arg_scope, arg_root, *name);
5762 return log_error_errno(state, "Failed to get unit file state for %s: %m", *name);
5764 if (state == UNIT_FILE_ENABLED ||
5765 state == UNIT_FILE_ENABLED_RUNTIME ||
5766 state == UNIT_FILE_STATIC ||
5767 state == UNIT_FILE_INDIRECT)
5771 puts(unit_file_state_to_string(state));
5775 STRV_FOREACH(name, names) {
5776 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5779 r = sd_bus_call_method(
5781 "org.freedesktop.systemd1",
5782 "/org/freedesktop/systemd1",
5783 "org.freedesktop.systemd1.Manager",
5789 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5793 r = sd_bus_message_read(reply, "s", &s);
5795 return bus_log_parse_error(r);
5797 if (STR_IN_SET(s, "enabled", "enabled-runtime", "static", "indirect"))
5808 static int is_system_running(sd_bus *bus, char **args) {
5809 _cleanup_free_ char *state = NULL;
5812 r = sd_bus_get_property_string(
5814 "org.freedesktop.systemd1",
5815 "/org/freedesktop/systemd1",
5816 "org.freedesktop.systemd1.Manager",
5829 return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE;
5832 static int create_edit_temp_file(const char *new_path, const char *original_path, char **ret_tmp_fn) {
5837 assert(original_path);
5840 r = tempfn_random(new_path, &t);
5842 return log_error_errno(r, "Failed to determine temporary filename for %s: %m", new_path);
5844 r = mkdir_parents(new_path, 0755);
5846 log_error_errno(r, "Failed to create directories for %s: %m", new_path);
5851 r = copy_file(original_path, t, 0, 0644);
5855 log_error_errno(r, "Failed to create temporary file %s: %m", t);
5860 log_error_errno(r, "Failed to copy %s to %s: %m", original_path, t);
5870 static int get_drop_in_to_edit(const char *unit_name, const char *user_home, const char *user_runtime, char **ret_path) {
5877 switch (arg_scope) {
5878 case UNIT_FILE_SYSTEM:
5879 tmp = strappenda(arg_runtime ? "/run/systemd/system/" : SYSTEM_CONFIG_UNIT_PATH "/", unit_name, ".d/override.conf");
5881 case UNIT_FILE_GLOBAL:
5882 tmp = strappenda(arg_runtime ? "/run/systemd/user/" : USER_CONFIG_UNIT_PATH "/", unit_name, ".d/override.conf");
5884 case UNIT_FILE_USER:
5886 assert(user_runtime);
5888 tmp = strappenda(arg_runtime ? user_runtime : user_home, "/", unit_name, ".d/override.conf");
5891 assert_not_reached("Invalid scope");
5894 tmp_new_path = path_join(arg_root, tmp, NULL);
5898 *ret_path = tmp_new_path;
5903 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) {
5909 assert(ret_new_path);
5910 assert(ret_tmp_path);
5912 r = get_drop_in_to_edit(unit_name, user_home, user_runtime, &tmp_new_path);
5916 r = create_edit_temp_file(tmp_new_path, tmp_new_path, &tmp_tmp_path);
5922 *ret_new_path = tmp_new_path;
5923 *ret_tmp_path = tmp_tmp_path;
5928 static bool unit_is_editable(const char *unit_name, const char *fragment_path, const char *user_home) {
5929 bool editable = true;
5930 const char *invalid_path;
5937 switch (arg_scope) {
5938 case UNIT_FILE_SYSTEM:
5939 if (path_startswith(fragment_path, "/etc/systemd/system")) {
5941 invalid_path = "/etc/systemd/system";
5942 } else if (path_startswith(fragment_path, SYSTEM_CONFIG_UNIT_PATH)) {
5944 invalid_path = SYSTEM_CONFIG_UNIT_PATH;
5947 case UNIT_FILE_GLOBAL:
5948 if (path_startswith(fragment_path, "/etc/systemd/user")) {
5950 invalid_path = "/etc/systemd/user";
5951 } else if (path_startswith(fragment_path, USER_CONFIG_UNIT_PATH)) {
5953 invalid_path = USER_CONFIG_UNIT_PATH;
5956 case UNIT_FILE_USER:
5959 if (path_startswith(fragment_path, "/etc/systemd/user")) {
5961 invalid_path = "/etc/systemd/user";
5962 } else if (path_startswith(fragment_path, USER_CONFIG_UNIT_PATH)) {
5964 invalid_path = USER_CONFIG_UNIT_PATH;
5965 } else if (path_startswith(fragment_path, user_home)) {
5967 invalid_path = user_home;
5971 assert_not_reached("Invalid scope");
5975 log_error("%s ignored: cannot temporarily edit units from %s", unit_name, invalid_path);
5980 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) {
5986 if (!unit_is_editable(unit_name, fragment_path, user_home))
5989 switch (arg_scope) {
5990 case UNIT_FILE_SYSTEM:
5991 tmp_new_path = path_join(arg_root, arg_runtime ? "/run/systemd/system/" : SYSTEM_CONFIG_UNIT_PATH, unit_name);
5993 case UNIT_FILE_GLOBAL:
5994 tmp_new_path = path_join(arg_root, arg_runtime ? "/run/systemd/user/" : USER_CONFIG_UNIT_PATH, unit_name);
5996 case UNIT_FILE_USER:
5998 assert(user_runtime);
6000 tmp_new_path = path_join(arg_root, arg_runtime ? user_runtime : user_home, unit_name);
6003 assert_not_reached("Invalid scope");
6008 *ret_path = tmp_new_path;
6013 static int unit_file_create_copy(const char *unit_name,
6014 const char *fragment_path,
6015 const char *user_home,
6016 const char *user_runtime,
6017 char **ret_new_path,
6018 char **ret_tmp_path) {
6023 assert(fragment_path);
6025 assert(ret_new_path);
6026 assert(ret_tmp_path);
6028 r = get_copy_to_edit(unit_name, fragment_path, user_home, user_runtime, &tmp_new_path);
6032 if (!path_equal(fragment_path, tmp_new_path) && access(tmp_new_path, F_OK) == 0) {
6035 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);
6040 if (response != 'y') {
6041 log_warning("%s ignored", unit_name);
6047 r = create_edit_temp_file(tmp_new_path, fragment_path, &tmp_tmp_path);
6049 log_error_errno(r, "Failed to create temporary file for %s: %m", tmp_new_path);
6054 *ret_new_path = tmp_new_path;
6055 *ret_tmp_path = tmp_tmp_path;
6060 static int run_editor(char **paths) {
6068 log_error_errno(errno, "Failed to fork: %m");
6074 char **backup_editors = STRV_MAKE("nano", "vim", "vi");
6076 char **tmp_path, **original_path, **p;
6080 argc = strv_length(paths)/2 + 1;
6081 args = newa(const char*, argc + 1);
6084 STRV_FOREACH_PAIR(original_path, tmp_path, paths) {
6085 args[i] = *tmp_path;
6090 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
6091 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
6092 * we try to execute well known editors
6094 editor = getenv("SYSTEMD_EDITOR");
6096 editor = getenv("EDITOR");
6098 editor = getenv("VISUAL");
6100 if (!isempty(editor)) {
6102 execvp(editor, (char* const*) args);
6105 STRV_FOREACH(p, backup_editors) {
6107 execvp(*p, (char* const*) args);
6108 /* We do not fail if the editor doesn't exist
6109 * because we want to try each one of them before
6112 if (errno != ENOENT) {
6113 log_error("Failed to execute %s: %m", editor);
6114 _exit(EXIT_FAILURE);
6118 log_error("Cannot edit unit(s): No editor available. Please set either SYSTEMD_EDITOR or EDITOR or VISUAL environment variable");
6119 _exit(EXIT_FAILURE);
6122 r = wait_for_terminate_and_warn("editor", pid, true);
6124 return log_error_errno(r, "Failed to wait for child: %m");
6129 static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
6130 _cleanup_free_ char *user_home = NULL;
6131 _cleanup_free_ char *user_runtime = NULL;
6132 _cleanup_lookup_paths_free_ LookupPaths lp = {};
6133 bool avoid_bus_cache;
6140 r = init_home_and_lookup_paths(&user_home, &user_runtime, &lp);
6144 avoid_bus_cache = !bus || avoid_bus();
6146 STRV_FOREACH(name, names) {
6147 _cleanup_free_ char *path = NULL;
6148 _cleanup_free_ char *template = NULL;
6149 char *new_path, *tmp_path;
6151 template = unit_name_template(*name);
6155 r = unit_find_path(bus, *name, template, avoid_bus_cache, &lp, &path);
6163 r = unit_file_create_copy(template, path, user_home, user_runtime, &new_path, &tmp_path);
6165 r = unit_file_create_drop_in(template, user_home, user_runtime, &new_path, &tmp_path);
6170 r = strv_push_pair(paths, new_path, tmp_path);
6178 static int edit(sd_bus *bus, char **args) {
6179 _cleanup_strv_free_ char **names = NULL;
6180 _cleanup_strv_free_ char **paths = NULL;
6181 char **original, **tmp;
6187 log_error("Cannot edit units if we are not on a tty");
6191 if (arg_transport != BUS_TRANSPORT_LOCAL) {
6192 log_error("Cannot remotely edit units");
6196 r = expand_names(bus, args + 1, NULL, &names);
6198 return log_error_errno(r, "Failed to expand names: %m");
6201 log_error("No unit name found by expanding names");
6205 r = find_paths_to_edit(bus, names, &paths);
6209 if (strv_isempty(paths)) {
6210 log_error("Cannot find any units to edit");
6214 r = run_editor(paths);
6218 STRV_FOREACH_PAIR(original, tmp, paths) {
6219 /* If the temporary file is empty we ignore it.
6220 * It's useful if the user wants to cancel its modification
6222 if (null_or_empty_path(*tmp)) {
6223 log_warning("Edition of %s canceled: temporary file empty", *original);
6226 r = rename(*tmp, *original);
6228 r = log_error_errno(errno, "Failed to rename %s to %s: %m", *tmp, *original);
6233 if (!arg_no_reload && bus && !avoid_bus())
6234 r = daemon_reload(bus, args);
6237 STRV_FOREACH_PAIR(original, tmp, paths)
6238 unlink_noerrno(*tmp);
6243 static void systemctl_help(void) {
6245 pager_open_if_enabled();
6247 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
6248 "Query or send control commands to the systemd manager.\n\n"
6249 " -h --help Show this help\n"
6250 " --version Show package version\n"
6251 " --system Connect to system manager\n"
6252 " --user Connect to user service manager\n"
6253 " -H --host=[USER@]HOST\n"
6254 " Operate on remote host\n"
6255 " -M --machine=CONTAINER\n"
6256 " Operate on local container\n"
6257 " -t --type=TYPE List only units of a particular type\n"
6258 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
6259 " -p --property=NAME Show only properties by this name\n"
6260 " -a --all Show all loaded units/properties, including dead/empty\n"
6261 " ones. To list all units installed on the system, use\n"
6262 " the 'list-unit-files' command instead.\n"
6263 " -l --full Don't ellipsize unit names on output\n"
6264 " -r --recursive Show unit list of host and local containers\n"
6265 " --reverse Show reverse dependencies with 'list-dependencies'\n"
6266 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
6267 " queueing a new job\n"
6268 " --show-types When showing sockets, explicitly show their type\n"
6269 " -i --ignore-inhibitors\n"
6270 " When shutting down or sleeping, ignore inhibitors\n"
6271 " --kill-who=WHO Who to send signal to\n"
6272 " -s --signal=SIGNAL Which signal to send\n"
6273 " -q --quiet Suppress output\n"
6274 " --no-block Do not wait until operation finished\n"
6275 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6276 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
6278 " --no-legend Do not print a legend (column headers and hints)\n"
6279 " --no-pager Do not pipe output into a pager\n"
6280 " --no-ask-password\n"
6281 " Do not ask for system passwords\n"
6282 " --global Enable/disable unit files globally\n"
6283 " --runtime Enable unit files only temporarily until next reboot\n"
6284 " -f --force When enabling unit files, override existing symlinks\n"
6285 " When shutting down, execute action immediately\n"
6286 " --preset-mode= Specifies whether fully apply presets, or only enable,\n"
6287 " or only disable\n"
6288 " --root=PATH Enable unit files in the specified root directory\n"
6289 " -n --lines=INTEGER Number of journal entries to show\n"
6290 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
6291 " verbose, export, json, json-pretty, json-sse, cat)\n"
6292 " --plain Print unit dependencies as a list instead of a tree\n\n"
6294 " list-units [PATTERN...] List loaded units\n"
6295 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
6296 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
6297 " start NAME... Start (activate) one or more units\n"
6298 " stop NAME... Stop (deactivate) one or more units\n"
6299 " reload NAME... Reload one or more units\n"
6300 " restart NAME... Start or restart one or more units\n"
6301 " try-restart NAME... Restart one or more units if active\n"
6302 " reload-or-restart NAME... Reload one or more units if possible,\n"
6303 " otherwise start or restart\n"
6304 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
6305 " otherwise restart if active\n"
6306 " isolate NAME Start one unit and stop all others\n"
6307 " kill NAME... Send signal to processes of a unit\n"
6308 " is-active PATTERN... Check whether units are active\n"
6309 " is-failed PATTERN... Check whether units are failed\n"
6310 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
6311 " show [PATTERN...|JOB...] Show properties of one or more\n"
6312 " units/jobs or the manager\n"
6313 " cat PATTERN... Show files and drop-ins of one or more units\n"
6314 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
6315 " help PATTERN...|PID... Show manual for one or more units\n"
6316 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
6318 " list-dependencies [NAME] Recursively show units which are required\n"
6319 " or wanted by this unit or by which this\n"
6320 " unit is required or wanted\n\n"
6321 "Unit File Commands:\n"
6322 " list-unit-files [PATTERN...] List installed unit files\n"
6323 " enable NAME... Enable one or more unit files\n"
6324 " disable NAME... Disable one or more unit files\n"
6325 " reenable NAME... Reenable one or more unit files\n"
6326 " preset NAME... Enable/disable one or more unit files\n"
6327 " based on preset configuration\n"
6328 " preset-all Enable/disable all unit files based on\n"
6329 " preset configuration\n"
6330 " is-enabled NAME... Check whether unit files are enabled\n\n"
6331 " mask NAME... Mask one or more units\n"
6332 " unmask NAME... Unmask one or more units\n"
6333 " link PATH... Link one or more units files into\n"
6334 " the search path\n"
6335 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6336 " on specified one or more units\n"
6337 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6338 " on specified one or more units\n"
6339 " get-default Get the name of the default target\n"
6340 " set-default NAME Set the default target\n"
6341 " edit NAME... Edit one or more unit files\n"
6343 "Machine Commands:\n"
6344 " list-machines [PATTERN...] List local containers and host\n\n"
6346 " list-jobs [PATTERN...] List jobs\n"
6347 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
6348 "Snapshot Commands:\n"
6349 " snapshot [NAME] Create a snapshot\n"
6350 " delete NAME... Remove one or more snapshots\n\n"
6351 "Environment Commands:\n"
6352 " show-environment Dump environment\n"
6353 " set-environment NAME=VALUE... Set one or more environment variables\n"
6354 " unset-environment NAME... Unset one or more environment variables\n"
6355 " import-environment NAME... Import all, one or more environment variables\n\n"
6356 "Manager Lifecycle Commands:\n"
6357 " daemon-reload Reload systemd manager configuration\n"
6358 " daemon-reexec Reexecute systemd manager\n\n"
6359 "System Commands:\n"
6360 " is-system-running Check whether system is fully running\n"
6361 " default Enter system default mode\n"
6362 " rescue Enter system rescue mode\n"
6363 " emergency Enter system emergency mode\n"
6364 " halt Shut down and halt the system\n"
6365 " poweroff Shut down and power-off the system\n"
6366 " reboot [ARG] Shut down and reboot the system\n"
6367 " kexec Shut down and reboot the system with kexec\n"
6368 " exit Request user instance exit\n"
6369 " switch-root ROOT [INIT] Change to a different root file system\n"
6370 " suspend Suspend the system\n"
6371 " hibernate Hibernate the system\n"
6372 " hybrid-sleep Hibernate and suspend the system\n",
6373 program_invocation_short_name);
6376 static void halt_help(void) {
6377 printf("%s [OPTIONS...]%s\n\n"
6378 "%s the system.\n\n"
6379 " --help Show this help\n"
6380 " --halt Halt the machine\n"
6381 " -p --poweroff Switch off the machine\n"
6382 " --reboot Reboot the machine\n"
6383 " -f --force Force immediate halt/power-off/reboot\n"
6384 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
6385 " -d --no-wtmp Don't write wtmp record\n"
6386 " --no-wall Don't send wall message before halt/power-off/reboot\n",
6387 program_invocation_short_name,
6388 arg_action == ACTION_REBOOT ? " [ARG]" : "",
6389 arg_action == ACTION_REBOOT ? "Reboot" :
6390 arg_action == ACTION_POWEROFF ? "Power off" :
6394 static void shutdown_help(void) {
6395 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
6396 "Shut down the system.\n\n"
6397 " --help Show this help\n"
6398 " -H --halt Halt the machine\n"
6399 " -P --poweroff Power-off the machine\n"
6400 " -r --reboot Reboot the machine\n"
6401 " -h Equivalent to --poweroff, overridden by --halt\n"
6402 " -k Don't halt/power-off/reboot, just send warnings\n"
6403 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6404 " -c Cancel a pending shutdown\n",
6405 program_invocation_short_name);
6408 static void telinit_help(void) {
6409 printf("%s [OPTIONS...] {COMMAND}\n\n"
6410 "Send control commands to the init daemon.\n\n"
6411 " --help Show this help\n"
6412 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
6414 " 0 Power-off the machine\n"
6415 " 6 Reboot the machine\n"
6416 " 2, 3, 4, 5 Start runlevelX.target unit\n"
6417 " 1, s, S Enter rescue mode\n"
6418 " q, Q Reload init daemon configuration\n"
6419 " u, U Reexecute init daemon\n",
6420 program_invocation_short_name);
6423 static void runlevel_help(void) {
6424 printf("%s [OPTIONS...]\n\n"
6425 "Prints the previous and current runlevel of the init system.\n\n"
6426 " --help Show this help\n",
6427 program_invocation_short_name);
6430 static void help_types(void) {
6435 puts("Available unit types:");
6436 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
6437 t = unit_type_to_string(i);
6443 static int systemctl_parse_argv(int argc, char *argv[]) {
6452 ARG_IGNORE_DEPENDENCIES,
6464 ARG_NO_ASK_PASSWORD,
6474 static const struct option options[] = {
6475 { "help", no_argument, NULL, 'h' },
6476 { "version", no_argument, NULL, ARG_VERSION },
6477 { "type", required_argument, NULL, 't' },
6478 { "property", required_argument, NULL, 'p' },
6479 { "all", no_argument, NULL, 'a' },
6480 { "reverse", no_argument, NULL, ARG_REVERSE },
6481 { "after", no_argument, NULL, ARG_AFTER },
6482 { "before", no_argument, NULL, ARG_BEFORE },
6483 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
6484 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
6485 { "full", no_argument, NULL, 'l' },
6486 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
6487 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
6488 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
6489 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
6490 { "ignore-inhibitors", no_argument, NULL, 'i' },
6491 { "user", no_argument, NULL, ARG_USER },
6492 { "system", no_argument, NULL, ARG_SYSTEM },
6493 { "global", no_argument, NULL, ARG_GLOBAL },
6494 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
6495 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
6496 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
6497 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6498 { "quiet", no_argument, NULL, 'q' },
6499 { "root", required_argument, NULL, ARG_ROOT },
6500 { "force", no_argument, NULL, ARG_FORCE },
6501 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
6502 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
6503 { "signal", required_argument, NULL, 's' },
6504 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
6505 { "host", required_argument, NULL, 'H' },
6506 { "machine", required_argument, NULL, 'M' },
6507 { "runtime", no_argument, NULL, ARG_RUNTIME },
6508 { "lines", required_argument, NULL, 'n' },
6509 { "output", required_argument, NULL, 'o' },
6510 { "plain", no_argument, NULL, ARG_PLAIN },
6511 { "state", required_argument, NULL, ARG_STATE },
6512 { "recursive", no_argument, NULL, 'r' },
6513 { "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
6522 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
6531 puts(PACKAGE_STRING);
6532 puts(SYSTEMD_FEATURES);
6536 const char *word, *state;
6539 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6540 _cleanup_free_ char *type;
6542 type = strndup(word, size);
6546 if (streq(type, "help")) {
6551 if (unit_type_from_string(type) >= 0) {
6552 if (strv_push(&arg_types, type))
6558 /* It's much nicer to use --state= for
6559 * load states, but let's support this
6560 * in --types= too for compatibility
6561 * with old versions */
6562 if (unit_load_state_from_string(optarg) >= 0) {
6563 if (strv_push(&arg_states, type) < 0)
6569 log_error("Unknown unit type or load state '%s'.", type);
6570 log_info("Use -t help to see a list of allowed values.");
6578 /* Make sure that if the empty property list
6579 was specified, we won't show any properties. */
6580 if (isempty(optarg) && !arg_properties) {
6581 arg_properties = new0(char*, 1);
6582 if (!arg_properties)
6585 const char *word, *state;
6588 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6591 prop = strndup(word, size);
6595 if (strv_consume(&arg_properties, prop) < 0)
6600 /* If the user asked for a particular
6601 * property, show it to him, even if it is
6613 arg_dependency = DEPENDENCY_REVERSE;
6617 arg_dependency = DEPENDENCY_AFTER;
6621 arg_dependency = DEPENDENCY_BEFORE;
6624 case ARG_SHOW_TYPES:
6625 arg_show_types = true;
6629 arg_job_mode = optarg;
6633 arg_job_mode = "fail";
6636 case ARG_IRREVERSIBLE:
6637 arg_job_mode = "replace-irreversibly";
6640 case ARG_IGNORE_DEPENDENCIES:
6641 arg_job_mode = "ignore-dependencies";
6645 arg_scope = UNIT_FILE_USER;
6649 arg_scope = UNIT_FILE_SYSTEM;
6653 arg_scope = UNIT_FILE_GLOBAL;
6657 arg_no_block = true;
6661 arg_no_legend = true;
6665 arg_no_pager = true;
6681 if (strv_extend(&arg_states, "failed") < 0)
6699 arg_no_reload = true;
6703 arg_kill_who = optarg;
6707 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
6708 log_error("Failed to parse signal string %s.", optarg);
6713 case ARG_NO_ASK_PASSWORD:
6714 arg_ask_password = false;
6718 arg_transport = BUS_TRANSPORT_REMOTE;
6723 arg_transport = BUS_TRANSPORT_CONTAINER;
6732 if (safe_atou(optarg, &arg_lines) < 0) {
6733 log_error("Failed to parse lines '%s'", optarg);
6739 arg_output = output_mode_from_string(optarg);
6740 if (arg_output < 0) {
6741 log_error("Unknown output '%s'.", optarg);
6747 arg_ignore_inhibitors = true;
6755 const char *word, *state;
6758 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6761 s = strndup(word, size);
6765 if (strv_consume(&arg_states, s) < 0)
6772 if (geteuid() != 0) {
6773 log_error("--recursive requires root privileges.");
6777 arg_recursive = true;
6780 case ARG_PRESET_MODE:
6782 arg_preset_mode = unit_file_preset_mode_from_string(optarg);
6783 if (arg_preset_mode < 0) {
6784 log_error("Failed to parse preset mode: %s.", optarg);
6794 assert_not_reached("Unhandled option");
6797 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
6798 log_error("Cannot access user instance remotely.");
6805 static int halt_parse_argv(int argc, char *argv[]) {
6814 static const struct option options[] = {
6815 { "help", no_argument, NULL, ARG_HELP },
6816 { "halt", no_argument, NULL, ARG_HALT },
6817 { "poweroff", no_argument, NULL, 'p' },
6818 { "reboot", no_argument, NULL, ARG_REBOOT },
6819 { "force", no_argument, NULL, 'f' },
6820 { "wtmp-only", no_argument, NULL, 'w' },
6821 { "no-wtmp", no_argument, NULL, 'd' },
6822 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6831 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
6832 if (runlevel == '0' || runlevel == '6')
6835 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
6843 arg_action = ACTION_HALT;
6847 if (arg_action != ACTION_REBOOT)
6848 arg_action = ACTION_POWEROFF;
6852 arg_action = ACTION_REBOOT;
6874 /* Compatibility nops */
6881 assert_not_reached("Unhandled option");
6884 if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
6885 r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL);
6888 } else if (optind < argc) {
6889 log_error("Too many arguments.");
6896 static int parse_time_spec(const char *t, usec_t *_u) {
6900 if (streq(t, "now"))
6902 else if (!strchr(t, ':')) {
6905 if (safe_atou64(t, &u) < 0)
6908 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
6917 hour = strtol(t, &e, 10);
6918 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
6921 minute = strtol(e+1, &e, 10);
6922 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
6925 n = now(CLOCK_REALTIME);
6926 s = (time_t) (n / USEC_PER_SEC);
6928 assert_se(localtime_r(&s, &tm));
6930 tm.tm_hour = (int) hour;
6931 tm.tm_min = (int) minute;
6934 assert_se(s = mktime(&tm));
6936 *_u = (usec_t) s * USEC_PER_SEC;
6939 *_u += USEC_PER_DAY;
6945 static int shutdown_parse_argv(int argc, char *argv[]) {
6952 static const struct option options[] = {
6953 { "help", no_argument, NULL, ARG_HELP },
6954 { "halt", no_argument, NULL, 'H' },
6955 { "poweroff", no_argument, NULL, 'P' },
6956 { "reboot", no_argument, NULL, 'r' },
6957 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
6958 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6967 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0)
6975 arg_action = ACTION_HALT;
6979 arg_action = ACTION_POWEROFF;
6984 arg_action = ACTION_KEXEC;
6986 arg_action = ACTION_REBOOT;
6990 arg_action = ACTION_KEXEC;
6994 if (arg_action != ACTION_HALT)
6995 arg_action = ACTION_POWEROFF;
7008 /* Compatibility nops */
7012 arg_action = ACTION_CANCEL_SHUTDOWN;
7019 assert_not_reached("Unhandled option");
7022 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
7023 r = parse_time_spec(argv[optind], &arg_when);
7025 log_error("Failed to parse time specification: %s", argv[optind]);
7029 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
7031 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
7032 /* No time argument for shutdown cancel */
7033 arg_wall = argv + optind;
7034 else if (argc > optind + 1)
7035 /* We skip the time argument */
7036 arg_wall = argv + optind + 1;
7043 static int telinit_parse_argv(int argc, char *argv[]) {
7050 static const struct option options[] = {
7051 { "help", no_argument, NULL, ARG_HELP },
7052 { "no-wall", no_argument, NULL, ARG_NO_WALL },
7056 static const struct {
7060 { '0', ACTION_POWEROFF },
7061 { '6', ACTION_REBOOT },
7062 { '1', ACTION_RESCUE },
7063 { '2', ACTION_RUNLEVEL2 },
7064 { '3', ACTION_RUNLEVEL3 },
7065 { '4', ACTION_RUNLEVEL4 },
7066 { '5', ACTION_RUNLEVEL5 },
7067 { 's', ACTION_RESCUE },
7068 { 'S', ACTION_RESCUE },
7069 { 'q', ACTION_RELOAD },
7070 { 'Q', ACTION_RELOAD },
7071 { 'u', ACTION_REEXEC },
7072 { 'U', ACTION_REEXEC }
7081 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
7096 assert_not_reached("Unhandled option");
7099 if (optind >= argc) {
7100 log_error("%s: required argument missing.",
7101 program_invocation_short_name);
7105 if (optind + 1 < argc) {
7106 log_error("Too many arguments.");
7110 if (strlen(argv[optind]) != 1) {
7111 log_error("Expected single character argument.");
7115 for (i = 0; i < ELEMENTSOF(table); i++)
7116 if (table[i].from == argv[optind][0])
7119 if (i >= ELEMENTSOF(table)) {
7120 log_error("Unknown command '%s'.", argv[optind]);
7124 arg_action = table[i].to;
7131 static int runlevel_parse_argv(int argc, char *argv[]) {
7137 static const struct option options[] = {
7138 { "help", no_argument, NULL, ARG_HELP },
7147 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
7158 assert_not_reached("Unhandled option");
7161 if (optind < argc) {
7162 log_error("Too many arguments.");
7169 static int parse_argv(int argc, char *argv[]) {
7173 if (program_invocation_short_name) {
7175 if (strstr(program_invocation_short_name, "halt")) {
7176 arg_action = ACTION_HALT;
7177 return halt_parse_argv(argc, argv);
7178 } else if (strstr(program_invocation_short_name, "poweroff")) {
7179 arg_action = ACTION_POWEROFF;
7180 return halt_parse_argv(argc, argv);
7181 } else if (strstr(program_invocation_short_name, "reboot")) {
7183 arg_action = ACTION_KEXEC;
7185 arg_action = ACTION_REBOOT;
7186 return halt_parse_argv(argc, argv);
7187 } else if (strstr(program_invocation_short_name, "shutdown")) {
7188 arg_action = ACTION_POWEROFF;
7189 return shutdown_parse_argv(argc, argv);
7190 } else if (strstr(program_invocation_short_name, "init")) {
7192 if (sd_booted() > 0) {
7193 arg_action = _ACTION_INVALID;
7194 return telinit_parse_argv(argc, argv);
7196 /* Hmm, so some other init system is
7197 * running, we need to forward this
7198 * request to it. For now we simply
7199 * guess that it is Upstart. */
7201 execv(TELINIT, argv);
7203 log_error("Couldn't find an alternative telinit implementation to spawn.");
7207 } else if (strstr(program_invocation_short_name, "runlevel")) {
7208 arg_action = ACTION_RUNLEVEL;
7209 return runlevel_parse_argv(argc, argv);
7213 arg_action = ACTION_SYSTEMCTL;
7214 return systemctl_parse_argv(argc, argv);
7217 _pure_ static int action_to_runlevel(void) {
7219 static const char table[_ACTION_MAX] = {
7220 [ACTION_HALT] = '0',
7221 [ACTION_POWEROFF] = '0',
7222 [ACTION_REBOOT] = '6',
7223 [ACTION_RUNLEVEL2] = '2',
7224 [ACTION_RUNLEVEL3] = '3',
7225 [ACTION_RUNLEVEL4] = '4',
7226 [ACTION_RUNLEVEL5] = '5',
7227 [ACTION_RESCUE] = '1'
7230 assert(arg_action < _ACTION_MAX);
7232 return table[arg_action];
7235 static int talk_initctl(void) {
7237 struct init_request request = {
7238 .magic = INIT_MAGIC,
7240 .cmd = INIT_CMD_RUNLVL
7243 _cleanup_close_ int fd = -1;
7247 rl = action_to_runlevel();
7251 request.runlevel = rl;
7253 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
7255 if (errno == ENOENT)
7258 log_error_errno(errno, "Failed to open "INIT_FIFO": %m");
7262 r = loop_write(fd, &request, sizeof(request), false);
7264 return log_error_errno(r, "Failed to write to "INIT_FIFO": %m");
7269 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
7271 static const struct {
7279 int (* const dispatch)(sd_bus *bus, char **args);
7285 { "list-units", MORE, 0, list_units },
7286 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
7287 { "list-sockets", MORE, 1, list_sockets },
7288 { "list-timers", MORE, 1, list_timers },
7289 { "list-jobs", MORE, 1, list_jobs },
7290 { "list-machines", MORE, 1, list_machines },
7291 { "clear-jobs", EQUAL, 1, daemon_reload },
7292 { "cancel", MORE, 2, cancel_job },
7293 { "start", MORE, 2, start_unit },
7294 { "stop", MORE, 2, start_unit },
7295 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
7296 { "reload", MORE, 2, start_unit },
7297 { "restart", MORE, 2, start_unit },
7298 { "try-restart", MORE, 2, start_unit },
7299 { "reload-or-restart", MORE, 2, start_unit },
7300 { "reload-or-try-restart", MORE, 2, start_unit },
7301 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
7302 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
7303 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
7304 { "isolate", EQUAL, 2, start_unit },
7305 { "kill", MORE, 2, kill_unit },
7306 { "is-active", MORE, 2, check_unit_active },
7307 { "check", MORE, 2, check_unit_active },
7308 { "is-failed", MORE, 2, check_unit_failed },
7309 { "show", MORE, 1, show },
7310 { "cat", MORE, 2, cat },
7311 { "status", MORE, 1, show },
7312 { "help", MORE, 2, show },
7313 { "snapshot", LESS, 2, snapshot },
7314 { "delete", MORE, 2, delete_snapshot },
7315 { "daemon-reload", EQUAL, 1, daemon_reload },
7316 { "daemon-reexec", EQUAL, 1, daemon_reload },
7317 { "show-environment", EQUAL, 1, show_environment },
7318 { "set-environment", MORE, 2, set_environment },
7319 { "unset-environment", MORE, 2, set_environment },
7320 { "import-environment", MORE, 1, import_environment},
7321 { "halt", EQUAL, 1, start_special, FORCE },
7322 { "poweroff", EQUAL, 1, start_special, FORCE },
7323 { "reboot", EQUAL, 1, start_special, FORCE },
7324 { "kexec", EQUAL, 1, start_special },
7325 { "suspend", EQUAL, 1, start_special },
7326 { "hibernate", EQUAL, 1, start_special },
7327 { "hybrid-sleep", EQUAL, 1, start_special },
7328 { "default", EQUAL, 1, start_special },
7329 { "rescue", EQUAL, 1, start_special },
7330 { "emergency", EQUAL, 1, start_special },
7331 { "exit", EQUAL, 1, start_special },
7332 { "reset-failed", MORE, 1, reset_failed },
7333 { "enable", MORE, 2, enable_unit, NOBUS },
7334 { "disable", MORE, 2, enable_unit, NOBUS },
7335 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
7336 { "reenable", MORE, 2, enable_unit, NOBUS },
7337 { "preset", MORE, 2, enable_unit, NOBUS },
7338 { "preset-all", EQUAL, 1, preset_all, NOBUS },
7339 { "mask", MORE, 2, enable_unit, NOBUS },
7340 { "unmask", MORE, 2, enable_unit, NOBUS },
7341 { "link", MORE, 2, enable_unit, NOBUS },
7342 { "switch-root", MORE, 2, switch_root },
7343 { "list-dependencies", LESS, 2, list_dependencies },
7344 { "set-default", EQUAL, 2, set_default, NOBUS },
7345 { "get-default", EQUAL, 1, get_default, NOBUS },
7346 { "set-property", MORE, 3, set_property },
7347 { "is-system-running", EQUAL, 1, is_system_running },
7348 { "add-wants", MORE, 3, add_dependency, NOBUS },
7349 { "add-requires", MORE, 3, add_dependency, NOBUS },
7350 { "edit", MORE, 2, edit, NOBUS },
7359 left = argc - optind;
7361 /* Special rule: no arguments (left == 0) means "list-units" */
7363 if (streq(argv[optind], "help") && !argv[optind+1]) {
7364 log_error("This command expects one or more "
7365 "unit names. Did you mean --help?");
7369 for (; verb->verb; verb++)
7370 if (streq(argv[optind], verb->verb))
7373 log_error("Unknown operation '%s'.", argv[optind]);
7378 switch (verb->argc_cmp) {
7381 if (left != verb->argc) {
7382 log_error("Invalid number of arguments.");
7389 if (left < verb->argc) {
7390 log_error("Too few arguments.");
7397 if (left > verb->argc) {
7398 log_error("Too many arguments.");
7405 assert_not_reached("Unknown comparison operator.");
7408 /* Require a bus connection for all operations but
7410 if (verb->bus == NOBUS) {
7411 if (!bus && !avoid_bus()) {
7412 log_error_errno(bus_error, "Failed to get D-Bus connection: %m");
7417 if (running_in_chroot() > 0) {
7418 log_info("Running in chroot, ignoring request.");
7422 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
7423 log_error_errno(bus_error, "Failed to get D-Bus connection: %m");
7428 return verb->dispatch(bus, argv + optind);
7431 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
7433 struct sd_shutdown_command c = {
7440 union sockaddr_union sockaddr = {
7441 .un.sun_family = AF_UNIX,
7442 .un.sun_path = "/run/systemd/shutdownd",
7445 struct iovec iovec[2] = {{
7446 .iov_base = (char*) &c,
7447 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
7450 struct msghdr msghdr = {
7451 .msg_name = &sockaddr,
7452 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
7453 + strlen("/run/systemd/shutdownd"),
7458 _cleanup_close_ int fd;
7460 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
7464 if (!isempty(message)) {
7465 iovec[1].iov_base = (char*) message;
7466 iovec[1].iov_len = strlen(message);
7467 msghdr.msg_iovlen++;
7470 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
7476 static int reload_with_fallback(sd_bus *bus) {
7479 /* First, try systemd via D-Bus. */
7480 if (daemon_reload(bus, NULL) >= 0)
7484 /* Nothing else worked, so let's try signals */
7485 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
7487 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0)
7488 return log_error_errno(errno, "kill() failed: %m");
7493 static int start_with_fallback(sd_bus *bus) {
7496 /* First, try systemd via D-Bus. */
7497 if (start_unit(bus, NULL) >= 0)
7501 /* Nothing else worked, so let's try
7503 if (talk_initctl() > 0)
7506 log_error("Failed to talk to init daemon.");
7510 warn_wall(arg_action);
7514 static int halt_now(enum action a) {
7516 /* The kernel will automaticall flush ATA disks and suchlike
7517 * on reboot(), but the file systems need to be synce'd
7518 * explicitly in advance. */
7521 /* Make sure C-A-D is handled by the kernel from this point
7523 reboot(RB_ENABLE_CAD);
7528 log_info("Halting.");
7529 reboot(RB_HALT_SYSTEM);
7532 case ACTION_POWEROFF:
7533 log_info("Powering off.");
7534 reboot(RB_POWER_OFF);
7537 case ACTION_REBOOT: {
7538 _cleanup_free_ char *param = NULL;
7540 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
7541 log_info("Rebooting with argument '%s'.", param);
7542 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
7543 LINUX_REBOOT_CMD_RESTART2, param);
7546 log_info("Rebooting.");
7547 reboot(RB_AUTOBOOT);
7552 assert_not_reached("Unknown action.");
7556 static int halt_main(sd_bus *bus) {
7559 r = check_inhibitors(bus, arg_action);
7563 if (geteuid() != 0) {
7564 /* Try logind if we are a normal user and no special
7565 * mode applies. Maybe PolicyKit allows us to shutdown
7568 if (arg_when <= 0 &&
7571 (arg_action == ACTION_POWEROFF ||
7572 arg_action == ACTION_REBOOT)) {
7573 r = reboot_with_logind(bus, arg_action);
7578 log_error("Must be root.");
7583 _cleanup_free_ char *m;
7585 m = strv_join(arg_wall, " ");
7589 r = send_shutdownd(arg_when,
7590 arg_action == ACTION_HALT ? 'H' :
7591 arg_action == ACTION_POWEROFF ? 'P' :
7592 arg_action == ACTION_KEXEC ? 'K' :
7599 log_warning_errno(r, "Failed to talk to shutdownd, proceeding with immediate shutdown: %m");
7601 char date[FORMAT_TIMESTAMP_MAX];
7603 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
7604 format_timestamp(date, sizeof(date), arg_when));
7609 if (!arg_dry && !arg_force)
7610 return start_with_fallback(bus);
7613 if (sd_booted() > 0)
7614 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7616 r = utmp_put_shutdown();
7618 log_warning_errno(r, "Failed to write utmp record: %m");
7625 r = halt_now(arg_action);
7626 log_error_errno(r, "Failed to reboot: %m");
7631 static int runlevel_main(void) {
7632 int r, runlevel, previous;
7634 r = utmp_get_runlevel(&runlevel, &previous);
7641 previous <= 0 ? 'N' : previous,
7642 runlevel <= 0 ? 'N' : runlevel);
7647 int main(int argc, char*argv[]) {
7648 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
7651 setlocale(LC_ALL, "");
7652 log_parse_environment();
7655 /* Explicitly not on_tty() to avoid setting cached value.
7656 * This becomes relevant for piping output which might be
7658 original_stdout_is_tty = isatty(STDOUT_FILENO);
7660 r = parse_argv(argc, argv);
7664 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
7665 * let's shortcut this */
7666 if (arg_action == ACTION_RUNLEVEL) {
7667 r = runlevel_main();
7671 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
7672 log_info("Running in chroot, ignoring request.");
7678 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
7680 /* systemctl_main() will print an error message for the bus
7681 * connection, but only if it needs to */
7683 switch (arg_action) {
7685 case ACTION_SYSTEMCTL:
7686 r = systemctl_main(bus, argc, argv, r);
7690 case ACTION_POWEROFF:
7696 case ACTION_RUNLEVEL2:
7697 case ACTION_RUNLEVEL3:
7698 case ACTION_RUNLEVEL4:
7699 case ACTION_RUNLEVEL5:
7701 case ACTION_EMERGENCY:
7702 case ACTION_DEFAULT:
7703 r = start_with_fallback(bus);
7708 r = reload_with_fallback(bus);
7711 case ACTION_CANCEL_SHUTDOWN: {
7712 _cleanup_free_ char *m = NULL;
7715 m = strv_join(arg_wall, " ");
7722 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
7724 log_warning_errno(r, "Failed to talk to shutdownd, shutdown hasn't been cancelled: %m");
7728 case ACTION_RUNLEVEL:
7729 case _ACTION_INVALID:
7731 assert_not_reached("Unknown action");
7736 ask_password_agent_close();
7737 polkit_agent_close();
7739 strv_free(arg_types);
7740 strv_free(arg_states);
7741 strv_free(arg_properties);
7743 return r < 0 ? EXIT_FAILURE : r;