1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Marc-Antoine Perennou
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/reboot.h>
24 #include <linux/reboot.h>
25 #include <sys/syscall.h>
32 #include <sys/ioctl.h>
36 #include <sys/socket.h>
39 #include <sys/prctl.h>
42 #include "sd-daemon.h"
43 #include "sd-shutdown.h"
50 #include "utmp-wtmp.h"
53 #include "path-util.h"
55 #include "cgroup-show.h"
56 #include "cgroup-util.h"
58 #include "path-lookup.h"
59 #include "conf-parser.h"
60 #include "exit-status.h"
62 #include "unit-name.h"
64 #include "spawn-ask-password-agent.h"
65 #include "spawn-polkit-agent.h"
67 #include "logs-show.h"
68 #include "socket-util.h"
73 #include "bus-message.h"
74 #include "bus-error.h"
75 #include "bus-errors.h"
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 typedef struct WaitData {
2280 static int wait_filter(sd_bus *bus, sd_bus_message *m, void *data, sd_bus_error *error) {
2287 log_debug("Got D-Bus request: %s.%s() on %s",
2288 sd_bus_message_get_interface(m),
2289 sd_bus_message_get_member(m),
2290 sd_bus_message_get_path(m));
2292 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
2293 log_error("Warning! D-Bus connection terminated.");
2295 } else if (sd_bus_message_is_signal(m, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
2297 const char *path, *result, *unit;
2301 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
2303 ret = set_remove(d->set, (char*) path);
2309 if (!isempty(result))
2310 d->result = strdup(result);
2313 d->name = strdup(unit);
2318 r = sd_bus_message_read(m, "uos", &id, &path, &result);
2320 ret = set_remove(d->set, (char*) path);
2327 d->result = strdup(result);
2333 bus_log_parse_error(r);
2339 static int enable_wait_for_jobs(sd_bus *bus) {
2344 r = sd_bus_add_match(
2348 "sender='org.freedesktop.systemd1',"
2349 "interface='org.freedesktop.systemd1.Manager',"
2350 "member='JobRemoved',"
2351 "path='/org/freedesktop/systemd1'",
2354 log_error("Failed to add match");
2358 /* This is slightly dirty, since we don't undo the match registrations. */
2362 static int bus_process_wait(sd_bus *bus) {
2366 r = sd_bus_process(bus, NULL);
2371 r = sd_bus_wait(bus, (uint64_t) -1);
2377 static int check_wait_response(WaitData *d) {
2383 if (streq(d->result, "timeout"))
2384 log_error("Job for %s timed out.", strna(d->name));
2385 else if (streq(d->result, "canceled"))
2386 log_error("Job for %s canceled.", strna(d->name));
2387 else if (streq(d->result, "dependency"))
2388 log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
2389 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
2393 quotes = chars_intersect(d->name, SHELL_NEED_QUOTES);
2395 log_error("Job for %s failed. See \"systemctl status %s%s%s\" and \"journalctl -xe\" for details.",
2397 quotes ? "'" : "", d->name, quotes ? "'" : "");
2399 log_error("Job failed. See \"journalctl -xe\" for details.");
2403 if (streq(d->result, "timeout"))
2405 else if (streq(d->result, "canceled"))
2407 else if (streq(d->result, "dependency"))
2409 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2415 static int wait_for_jobs(sd_bus *bus, Set *s) {
2416 _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
2417 WaitData d = { .set = s };
2423 q = sd_bus_add_filter(bus, &slot, wait_filter, &d);
2427 while (!set_isempty(s)) {
2428 q = bus_process_wait(bus);
2430 return log_error_errno(q, "Failed to wait for response: %m");
2433 q = check_wait_response(&d);
2434 /* Return the first error as it is most likely to be
2436 if (q < 0 && r == 0)
2438 log_debug("Got result %s/%s for job %s",
2439 strna(d.result), strerror(-q), strna(d.name));
2452 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2453 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2454 _cleanup_free_ char *n = NULL, *state = NULL;
2460 n = unit_name_mangle(name, MANGLE_NOGLOB);
2464 /* We don't use unit_dbus_path_from_name() directly since we
2465 * don't want to load the unit if it isn't loaded. */
2467 r = sd_bus_call_method(
2469 "org.freedesktop.systemd1",
2470 "/org/freedesktop/systemd1",
2471 "org.freedesktop.systemd1.Manager",
2482 r = sd_bus_message_read(reply, "o", &path);
2484 return bus_log_parse_error(r);
2486 r = sd_bus_get_property_string(
2488 "org.freedesktop.systemd1",
2490 "org.freedesktop.systemd1.Unit",
2503 return nulstr_contains(good_states, state);
2506 static int check_triggering_units(
2510 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2511 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2512 _cleanup_strv_free_ char **triggered_by = NULL;
2513 bool print_warning_label = true;
2517 n = unit_name_mangle(name, MANGLE_NOGLOB);
2521 path = unit_dbus_path_from_name(n);
2525 r = sd_bus_get_property_string(
2527 "org.freedesktop.systemd1",
2529 "org.freedesktop.systemd1.Unit",
2534 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2538 if (streq(state, "masked"))
2541 r = sd_bus_get_property_strv(
2543 "org.freedesktop.systemd1",
2545 "org.freedesktop.systemd1.Unit",
2550 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2554 STRV_FOREACH(i, triggered_by) {
2555 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2557 return log_error_errno(r, "Failed to check unit: %m");
2562 if (print_warning_label) {
2563 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2564 print_warning_label = false;
2567 log_warning(" %s", *i);
2573 static const struct {
2576 } unit_actions[] = {
2577 { "start", "StartUnit" },
2578 { "stop", "StopUnit" },
2579 { "condstop", "StopUnit" },
2580 { "reload", "ReloadUnit" },
2581 { "restart", "RestartUnit" },
2582 { "try-restart", "TryRestartUnit" },
2583 { "condrestart", "TryRestartUnit" },
2584 { "reload-or-restart", "ReloadOrRestartUnit" },
2585 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2586 { "condreload", "ReloadOrTryRestartUnit" },
2587 { "force-reload", "ReloadOrTryRestartUnit" }
2590 static const char *verb_to_method(const char *verb) {
2593 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2594 if (streq_ptr(unit_actions[i].verb, verb))
2595 return unit_actions[i].method;
2600 static const char *method_to_verb(const char *method) {
2603 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2604 if (streq_ptr(unit_actions[i].method, method))
2605 return unit_actions[i].verb;
2610 static int start_unit_one(
2615 sd_bus_error *error,
2618 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2627 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2629 r = sd_bus_message_new_method_call(
2632 "org.freedesktop.systemd1",
2633 "/org/freedesktop/systemd1",
2634 "org.freedesktop.systemd1.Manager",
2637 return bus_log_create_error(r);
2639 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2641 return bus_log_create_error(r);
2643 r = sd_bus_message_append(m, "ss", name, mode);
2645 return bus_log_create_error(r);
2647 r = sd_bus_call(bus, m, 0, error, &reply);
2651 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2652 /* There's always a fallback possible for
2653 * legacy actions. */
2654 return -EADDRNOTAVAIL;
2656 verb = method_to_verb(method);
2658 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2662 r = sd_bus_message_read(reply, "o", &path);
2664 return bus_log_parse_error(r);
2666 if (need_daemon_reload(bus, name) > 0)
2667 log_warning("Warning: Unit file of %s changed on disk, 'systemctl%s daemon-reload' recommended.",
2668 name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2677 log_debug("Adding %s to the set", p);
2678 r = set_consume(s, p);
2686 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2688 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2692 STRV_FOREACH(name, names) {
2696 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2698 t = unit_name_mangle(*name, MANGLE_GLOB);
2702 if (string_is_glob(t))
2703 r = strv_consume(&globs, t);
2705 r = strv_consume(&mangled, t);
2710 /* Query the manager only if any of the names are a glob, since
2711 * this is fairly expensive */
2712 if (!strv_isempty(globs)) {
2713 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2714 _cleanup_free_ UnitInfo *unit_infos = NULL;
2716 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2720 for (i = 0; i < r; i++)
2721 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2726 mangled = NULL; /* do not free */
2731 static const struct {
2735 } action_table[_ACTION_MAX] = {
2736 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2737 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2738 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2739 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2740 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
2741 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
2742 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
2743 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
2744 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2745 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2746 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2747 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2748 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2749 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2750 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2753 static enum action verb_to_action(const char *verb) {
2756 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2757 if (streq_ptr(action_table[i].verb, verb))
2760 return _ACTION_INVALID;
2763 static int start_unit(sd_bus *bus, char **args) {
2764 _cleanup_set_free_free_ Set *s = NULL;
2765 _cleanup_strv_free_ char **names = NULL;
2766 const char *method, *mode, *one_name, *suffix = NULL;
2772 ask_password_agent_open_if_enabled();
2774 if (arg_action == ACTION_SYSTEMCTL) {
2776 method = verb_to_method(args[0]);
2777 action = verb_to_action(args[0]);
2779 if (streq(args[0], "isolate")) {
2783 mode = action_table[action].mode ?: arg_job_mode;
2785 one_name = action_table[action].target;
2787 assert(arg_action < ELEMENTSOF(action_table));
2788 assert(action_table[arg_action].target);
2790 method = "StartUnit";
2792 mode = action_table[arg_action].mode;
2793 one_name = action_table[arg_action].target;
2797 names = strv_new(one_name, NULL);
2799 r = expand_names(bus, args + 1, suffix, &names);
2801 log_error_errno(r, "Failed to expand names: %m");
2804 if (!arg_no_block) {
2805 r = enable_wait_for_jobs(bus);
2807 return log_error_errno(r, "Could not watch jobs: %m");
2809 s = set_new(&string_hash_ops);
2814 STRV_FOREACH(name, names) {
2815 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2818 q = start_unit_one(bus, method, *name, mode, &error, s);
2819 if (r >= 0 && q < 0)
2820 r = translate_bus_error_to_exit_status(q, &error);
2823 if (!arg_no_block) {
2826 q = wait_for_jobs(bus, s);
2830 /* When stopping units, warn if they can still be triggered by
2831 * another active unit (socket, path, timer) */
2832 if (!arg_quiet && streq(method, "StopUnit"))
2833 STRV_FOREACH(name, names)
2834 check_triggering_units(bus, *name);
2840 /* Ask systemd-logind, which might grant access to unprivileged users
2841 * through PolicyKit */
2842 static int reboot_with_logind(sd_bus *bus, enum action a) {
2844 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2851 polkit_agent_open_if_enabled();
2859 case ACTION_POWEROFF:
2860 method = "PowerOff";
2863 case ACTION_SUSPEND:
2867 case ACTION_HIBERNATE:
2868 method = "Hibernate";
2871 case ACTION_HYBRID_SLEEP:
2872 method = "HybridSleep";
2879 r = sd_bus_call_method(
2881 "org.freedesktop.login1",
2882 "/org/freedesktop/login1",
2883 "org.freedesktop.login1.Manager",
2887 "b", arg_ask_password);
2889 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2897 static int check_inhibitors(sd_bus *bus, enum action a) {
2899 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2900 _cleanup_strv_free_ char **sessions = NULL;
2901 const char *what, *who, *why, *mode;
2910 if (arg_ignore_inhibitors || arg_force > 0)
2922 r = sd_bus_call_method(
2924 "org.freedesktop.login1",
2925 "/org/freedesktop/login1",
2926 "org.freedesktop.login1.Manager",
2932 /* If logind is not around, then there are no inhibitors... */
2935 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2937 return bus_log_parse_error(r);
2939 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2940 _cleanup_free_ char *comm = NULL, *user = NULL;
2941 _cleanup_strv_free_ char **sv = NULL;
2943 if (!streq(mode, "block"))
2946 sv = strv_split(what, ":");
2950 if (!strv_contains(sv,
2952 a == ACTION_POWEROFF ||
2953 a == ACTION_REBOOT ||
2954 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2957 get_process_comm(pid, &comm);
2958 user = uid_to_name(uid);
2960 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
2961 who, pid, strna(comm), strna(user), why);
2966 return bus_log_parse_error(r);
2968 r = sd_bus_message_exit_container(reply);
2970 return bus_log_parse_error(r);
2972 /* Check for current sessions */
2973 sd_get_sessions(&sessions);
2974 STRV_FOREACH(s, sessions) {
2975 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2977 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2980 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2983 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2986 sd_session_get_tty(*s, &tty);
2987 sd_session_get_seat(*s, &seat);
2988 sd_session_get_service(*s, &service);
2989 user = uid_to_name(uid);
2991 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2998 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2999 action_table[a].verb);
3007 static int start_special(sd_bus *bus, char **args) {
3013 a = verb_to_action(args[0]);
3015 r = check_inhibitors(bus, a);
3019 if (arg_force >= 2 && geteuid() != 0) {
3020 log_error("Must be root.");
3024 if (arg_force >= 2 &&
3025 (a == ACTION_HALT ||
3026 a == ACTION_POWEROFF ||
3027 a == ACTION_REBOOT))
3030 if (arg_force >= 1 &&
3031 (a == ACTION_HALT ||
3032 a == ACTION_POWEROFF ||
3033 a == ACTION_REBOOT ||
3034 a == ACTION_KEXEC ||
3036 return daemon_reload(bus, args);
3038 /* first try logind, to allow authentication with polkit */
3039 if (geteuid() != 0 &&
3040 (a == ACTION_POWEROFF ||
3041 a == ACTION_REBOOT ||
3042 a == ACTION_SUSPEND ||
3043 a == ACTION_HIBERNATE ||
3044 a == ACTION_HYBRID_SLEEP)) {
3045 r = reboot_with_logind(bus, a);
3050 r = start_unit(bus, args);
3051 if (r == EXIT_SUCCESS)
3057 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
3058 _cleanup_strv_free_ char **names = NULL;
3065 r = expand_names(bus, args, NULL, &names);
3067 return log_error_errno(r, "Failed to expand names: %m");
3069 STRV_FOREACH(name, names) {
3072 state = check_one_unit(bus, *name, good_states, arg_quiet);
3082 static int check_unit_active(sd_bus *bus, char **args) {
3083 /* According to LSB: 3, "program is not running" */
3084 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
3087 static int check_unit_failed(sd_bus *bus, char **args) {
3088 return check_unit_generic(bus, 1, "failed\0", args + 1);
3091 static int kill_unit(sd_bus *bus, char **args) {
3092 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3093 _cleanup_strv_free_ char **names = NULL;
3101 arg_kill_who = "all";
3103 r = expand_names(bus, args + 1, NULL, &names);
3105 log_error_errno(r, "Failed to expand names: %m");
3107 STRV_FOREACH(name, names) {
3108 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3110 q = sd_bus_message_new_method_call(
3113 "org.freedesktop.systemd1",
3114 "/org/freedesktop/systemd1",
3115 "org.freedesktop.systemd1.Manager",
3118 return bus_log_create_error(q);
3120 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
3122 return bus_log_create_error(q);
3124 q = sd_bus_message_append(m, "ssi", *names, arg_kill_who, arg_signal);
3126 return bus_log_create_error(q);
3128 q = sd_bus_call(bus, m, 0, &error, NULL);
3130 log_error("Failed to kill unit %s: %s", *names, bus_error_message(&error, q));
3139 typedef struct ExecStatusInfo {
3147 usec_t start_timestamp;
3148 usec_t exit_timestamp;
3153 LIST_FIELDS(struct ExecStatusInfo, exec);
3156 static void exec_status_info_free(ExecStatusInfo *i) {
3165 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3166 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3169 int32_t code, status;
3175 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3177 return bus_log_parse_error(r);
3181 r = sd_bus_message_read(m, "s", &path);
3183 return bus_log_parse_error(r);
3185 i->path = strdup(path);
3189 r = sd_bus_message_read_strv(m, &i->argv);
3191 return bus_log_parse_error(r);
3193 r = sd_bus_message_read(m,
3196 &start_timestamp, &start_timestamp_monotonic,
3197 &exit_timestamp, &exit_timestamp_monotonic,
3201 return bus_log_parse_error(r);
3204 i->start_timestamp = (usec_t) start_timestamp;
3205 i->exit_timestamp = (usec_t) exit_timestamp;
3206 i->pid = (pid_t) pid;
3210 r = sd_bus_message_exit_container(m);
3212 return bus_log_parse_error(r);
3217 typedef struct UnitStatusInfo {
3219 const char *load_state;
3220 const char *active_state;
3221 const char *sub_state;
3222 const char *unit_file_state;
3223 const char *unit_file_preset;
3225 const char *description;
3226 const char *following;
3228 char **documentation;
3230 const char *fragment_path;
3231 const char *source_path;
3232 const char *control_group;
3234 char **dropin_paths;
3236 const char *load_error;
3239 usec_t inactive_exit_timestamp;
3240 usec_t inactive_exit_timestamp_monotonic;
3241 usec_t active_enter_timestamp;
3242 usec_t active_exit_timestamp;
3243 usec_t inactive_enter_timestamp;
3245 bool need_daemon_reload;
3250 const char *status_text;
3251 const char *pid_file;
3255 usec_t start_timestamp;
3256 usec_t exit_timestamp;
3258 int exit_code, exit_status;
3260 usec_t condition_timestamp;
3261 bool condition_result;
3262 bool failed_condition_trigger;
3263 bool failed_condition_negate;
3264 const char *failed_condition;
3265 const char *failed_condition_parameter;
3267 usec_t assert_timestamp;
3269 bool failed_assert_trigger;
3270 bool failed_assert_negate;
3271 const char *failed_assert;
3272 const char *failed_assert_parameter;
3275 unsigned n_accepted;
3276 unsigned n_connections;
3279 /* Pairs of type, path */
3283 const char *sysfs_path;
3285 /* Mount, Automount */
3291 LIST_HEAD(ExecStatusInfo, exec);
3294 static void print_status_info(
3299 const char *active_on, *active_off, *on, *off, *ss;
3301 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3302 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3305 arg_all * OUTPUT_SHOW_ALL |
3306 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
3307 on_tty() * OUTPUT_COLOR |
3308 !arg_quiet * OUTPUT_WARN_CUTOFF |
3309 arg_full * OUTPUT_FULL_WIDTH;
3314 /* This shows pretty information about a unit. See
3315 * print_property() for a low-level property printer */
3317 if (streq_ptr(i->active_state, "failed")) {
3318 active_on = ansi_highlight_red();
3319 active_off = ansi_highlight_off();
3320 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3321 active_on = ansi_highlight_green();
3322 active_off = ansi_highlight_off();
3324 active_on = active_off = "";
3326 printf("%s%s%s %s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3328 if (i->description && !streq_ptr(i->id, i->description))
3329 printf(" - %s", i->description);
3334 printf(" Follow: unit currently follows state of %s\n", i->following);
3336 if (streq_ptr(i->load_state, "error")) {
3337 on = ansi_highlight_red();
3338 off = ansi_highlight_off();
3342 path = i->source_path ? i->source_path : i->fragment_path;
3345 printf(" Loaded: %s%s%s (Reason: %s)\n",
3346 on, strna(i->load_state), off, i->load_error);
3347 else if (path && !isempty(i->unit_file_state) && !isempty(i->unit_file_preset))
3348 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3349 on, strna(i->load_state), off, path, i->unit_file_state, i->unit_file_preset);
3350 else if (path && !isempty(i->unit_file_state))
3351 printf(" Loaded: %s%s%s (%s; %s)\n",
3352 on, strna(i->load_state), off, path, i->unit_file_state);
3354 printf(" Loaded: %s%s%s (%s)\n",
3355 on, strna(i->load_state), off, path);
3357 printf(" Loaded: %s%s%s\n",
3358 on, strna(i->load_state), off);
3360 if (!strv_isempty(i->dropin_paths)) {
3361 _cleanup_free_ char *dir = NULL;
3365 STRV_FOREACH(dropin, i->dropin_paths) {
3366 if (! dir || last) {
3367 printf(dir ? " " : " Drop-In: ");
3372 if (path_get_parent(*dropin, &dir) < 0) {
3377 printf("%s\n %s", dir,
3378 draw_special_char(DRAW_TREE_RIGHT));
3381 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3383 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3387 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3389 printf(" Active: %s%s (%s)%s",
3390 active_on, strna(i->active_state), ss, active_off);
3392 printf(" Active: %s%s%s",
3393 active_on, strna(i->active_state), active_off);
3395 if (!isempty(i->result) && !streq(i->result, "success"))
3396 printf(" (Result: %s)", i->result);
3398 timestamp = (streq_ptr(i->active_state, "active") ||
3399 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
3400 (streq_ptr(i->active_state, "inactive") ||
3401 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
3402 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
3403 i->active_exit_timestamp;
3405 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3406 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3409 printf(" since %s; %s\n", s2, s1);
3411 printf(" since %s\n", s2);
3415 if (!i->condition_result && i->condition_timestamp > 0) {
3416 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3417 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3419 printf("Condition: start %scondition failed%s at %s%s%s\n",
3420 ansi_highlight_yellow(), ansi_highlight_off(),
3421 s2, s1 ? "; " : "", s1 ? s1 : "");
3422 if (i->failed_condition_trigger)
3423 printf(" none of the trigger conditions were met\n");
3424 else if (i->failed_condition)
3425 printf(" %s=%s%s was not met\n",
3426 i->failed_condition,
3427 i->failed_condition_negate ? "!" : "",
3428 i->failed_condition_parameter);
3431 if (!i->assert_result && i->assert_timestamp > 0) {
3432 s1 = format_timestamp_relative(since1, sizeof(since1), i->assert_timestamp);
3433 s2 = format_timestamp(since2, sizeof(since2), i->assert_timestamp);
3435 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3436 ansi_highlight_red(), ansi_highlight_off(),
3437 s2, s1 ? "; " : "", s1 ? s1 : "");
3438 if (i->failed_assert_trigger)
3439 printf(" none of the trigger assertions were met\n");
3440 else if (i->failed_assert)
3441 printf(" %s=%s%s was not met\n",
3443 i->failed_assert_negate ? "!" : "",
3444 i->failed_assert_parameter);
3448 printf(" Device: %s\n", i->sysfs_path);
3450 printf(" Where: %s\n", i->where);
3452 printf(" What: %s\n", i->what);
3454 STRV_FOREACH(t, i->documentation)
3455 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3457 STRV_FOREACH_PAIR(t, t2, i->listen)
3458 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3461 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3463 LIST_FOREACH(exec, p, i->exec) {
3464 _cleanup_free_ char *argv = NULL;
3467 /* Only show exited processes here */
3471 argv = strv_join(p->argv, " ");
3472 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
3474 good = is_clean_exit_lsb(p->code, p->status, NULL);
3476 on = ansi_highlight_red();
3477 off = ansi_highlight_off();
3481 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3483 if (p->code == CLD_EXITED) {
3486 printf("status=%i", p->status);
3488 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3493 printf("signal=%s", signal_to_string(p->status));
3495 printf(")%s\n", off);
3497 if (i->main_pid == p->pid &&
3498 i->start_timestamp == p->start_timestamp &&
3499 i->exit_timestamp == p->start_timestamp)
3500 /* Let's not show this twice */
3503 if (p->pid == i->control_pid)
3507 if (i->main_pid > 0 || i->control_pid > 0) {
3508 if (i->main_pid > 0) {
3509 printf(" Main PID: "PID_FMT, i->main_pid);
3512 _cleanup_free_ char *comm = NULL;
3513 get_process_comm(i->main_pid, &comm);
3515 printf(" (%s)", comm);
3516 } else if (i->exit_code > 0) {
3517 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3519 if (i->exit_code == CLD_EXITED) {
3522 printf("status=%i", i->exit_status);
3524 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3529 printf("signal=%s", signal_to_string(i->exit_status));
3533 if (i->control_pid > 0)
3537 if (i->control_pid > 0) {
3538 _cleanup_free_ char *c = NULL;
3540 printf(" %8s: "PID_FMT, i->main_pid ? "" : " Control", i->control_pid);
3542 get_process_comm(i->control_pid, &c);
3551 printf(" Status: \"%s\"\n", i->status_text);
3552 if (i->status_errno > 0)
3553 printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
3555 if (i->control_group &&
3556 (i->main_pid > 0 || i->control_pid > 0 ||
3557 ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_CONTAINER) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3560 printf(" CGroup: %s\n", i->control_group);
3562 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
3565 static const char prefix[] = " ";
3568 if (c > sizeof(prefix) - 1)
3569 c -= sizeof(prefix) - 1;
3573 if (i->main_pid > 0)
3574 extra[k++] = i->main_pid;
3576 if (i->control_pid > 0)
3577 extra[k++] = i->control_pid;
3579 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, flags);
3583 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3584 show_journal_by_unit(stdout,
3588 i->inactive_exit_timestamp_monotonic,
3591 flags | OUTPUT_BEGIN_NEWLINE,
3592 arg_scope == UNIT_FILE_SYSTEM,
3596 if (i->need_daemon_reload)
3597 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
3598 ansi_highlight_red(),
3599 ansi_highlight_off(),
3600 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
3603 static void show_unit_help(UnitStatusInfo *i) {
3608 if (!i->documentation) {
3609 log_info("Documentation for %s not known.", i->id);
3613 STRV_FOREACH(p, i->documentation)
3614 if (startswith(*p, "man:"))
3615 show_man_page(*p + 4, false);
3617 log_info("Can't show: %s", *p);
3620 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3627 switch (contents[0]) {
3629 case SD_BUS_TYPE_STRING: {
3632 r = sd_bus_message_read(m, "s", &s);
3634 return bus_log_parse_error(r);
3637 if (streq(name, "Id"))
3639 else if (streq(name, "LoadState"))
3641 else if (streq(name, "ActiveState"))
3642 i->active_state = s;
3643 else if (streq(name, "SubState"))
3645 else if (streq(name, "Description"))
3647 else if (streq(name, "FragmentPath"))
3648 i->fragment_path = s;
3649 else if (streq(name, "SourcePath"))
3652 else if (streq(name, "DefaultControlGroup")) {
3654 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3656 i->control_group = e;
3659 else if (streq(name, "ControlGroup"))
3660 i->control_group = s;
3661 else if (streq(name, "StatusText"))
3663 else if (streq(name, "PIDFile"))
3665 else if (streq(name, "SysFSPath"))
3667 else if (streq(name, "Where"))
3669 else if (streq(name, "What"))
3671 else if (streq(name, "Following"))
3673 else if (streq(name, "UnitFileState"))
3674 i->unit_file_state = s;
3675 else if (streq(name, "UnitFilePreset"))
3676 i->unit_file_preset = s;
3677 else if (streq(name, "Result"))
3684 case SD_BUS_TYPE_BOOLEAN: {
3687 r = sd_bus_message_read(m, "b", &b);
3689 return bus_log_parse_error(r);
3691 if (streq(name, "Accept"))
3693 else if (streq(name, "NeedDaemonReload"))
3694 i->need_daemon_reload = b;
3695 else if (streq(name, "ConditionResult"))
3696 i->condition_result = b;
3697 else if (streq(name, "AssertResult"))
3698 i->assert_result = b;
3703 case SD_BUS_TYPE_UINT32: {
3706 r = sd_bus_message_read(m, "u", &u);
3708 return bus_log_parse_error(r);
3710 if (streq(name, "MainPID")) {
3712 i->main_pid = (pid_t) u;
3715 } else if (streq(name, "ControlPID"))
3716 i->control_pid = (pid_t) u;
3717 else if (streq(name, "ExecMainPID")) {
3719 i->main_pid = (pid_t) u;
3720 } else if (streq(name, "NAccepted"))
3722 else if (streq(name, "NConnections"))
3723 i->n_connections = u;
3728 case SD_BUS_TYPE_INT32: {
3731 r = sd_bus_message_read(m, "i", &j);
3733 return bus_log_parse_error(r);
3735 if (streq(name, "ExecMainCode"))
3736 i->exit_code = (int) j;
3737 else if (streq(name, "ExecMainStatus"))
3738 i->exit_status = (int) j;
3739 else if (streq(name, "StatusErrno"))
3740 i->status_errno = (int) j;
3745 case SD_BUS_TYPE_UINT64: {
3748 r = sd_bus_message_read(m, "t", &u);
3750 return bus_log_parse_error(r);
3752 if (streq(name, "ExecMainStartTimestamp"))
3753 i->start_timestamp = (usec_t) u;
3754 else if (streq(name, "ExecMainExitTimestamp"))
3755 i->exit_timestamp = (usec_t) u;
3756 else if (streq(name, "ActiveEnterTimestamp"))
3757 i->active_enter_timestamp = (usec_t) u;
3758 else if (streq(name, "InactiveEnterTimestamp"))
3759 i->inactive_enter_timestamp = (usec_t) u;
3760 else if (streq(name, "InactiveExitTimestamp"))
3761 i->inactive_exit_timestamp = (usec_t) u;
3762 else if (streq(name, "InactiveExitTimestampMonotonic"))
3763 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3764 else if (streq(name, "ActiveExitTimestamp"))
3765 i->active_exit_timestamp = (usec_t) u;
3766 else if (streq(name, "ConditionTimestamp"))
3767 i->condition_timestamp = (usec_t) u;
3768 else if (streq(name, "AssertTimestamp"))
3769 i->assert_timestamp = (usec_t) u;
3774 case SD_BUS_TYPE_ARRAY:
3776 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3777 _cleanup_free_ ExecStatusInfo *info = NULL;
3779 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3781 return bus_log_parse_error(r);
3783 info = new0(ExecStatusInfo, 1);
3787 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3789 info->name = strdup(name);
3793 LIST_PREPEND(exec, i->exec, info);
3795 info = new0(ExecStatusInfo, 1);
3801 return bus_log_parse_error(r);
3803 r = sd_bus_message_exit_container(m);
3805 return bus_log_parse_error(r);
3809 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3810 const char *type, *path;
3812 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3814 return bus_log_parse_error(r);
3816 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3818 r = strv_extend(&i->listen, type);
3822 r = strv_extend(&i->listen, path);
3827 return bus_log_parse_error(r);
3829 r = sd_bus_message_exit_container(m);
3831 return bus_log_parse_error(r);
3835 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3837 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3839 return bus_log_parse_error(r);
3841 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3843 r = sd_bus_message_read_strv(m, &i->documentation);
3845 return bus_log_parse_error(r);
3847 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3848 const char *cond, *param;
3849 int trigger, negate;
3852 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3854 return bus_log_parse_error(r);
3856 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3857 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3858 if (state < 0 && (!trigger || !i->failed_condition)) {
3859 i->failed_condition = cond;
3860 i->failed_condition_trigger = trigger;
3861 i->failed_condition_negate = negate;
3862 i->failed_condition_parameter = param;
3866 return bus_log_parse_error(r);
3868 r = sd_bus_message_exit_container(m);
3870 return bus_log_parse_error(r);
3872 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Asserts")) {
3873 const char *cond, *param;
3874 int trigger, negate;
3877 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3879 return bus_log_parse_error(r);
3881 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3882 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3883 if (state < 0 && (!trigger || !i->failed_assert)) {
3884 i->failed_assert = cond;
3885 i->failed_assert_trigger = trigger;
3886 i->failed_assert_negate = negate;
3887 i->failed_assert_parameter = param;
3891 return bus_log_parse_error(r);
3893 r = sd_bus_message_exit_container(m);
3895 return bus_log_parse_error(r);
3902 case SD_BUS_TYPE_STRUCT_BEGIN:
3904 if (streq(name, "LoadError")) {
3905 const char *n, *message;
3907 r = sd_bus_message_read(m, "(ss)", &n, &message);
3909 return bus_log_parse_error(r);
3911 if (!isempty(message))
3912 i->load_error = message;
3925 r = sd_bus_message_skip(m, contents);
3927 return bus_log_parse_error(r);
3932 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3938 /* This is a low-level property printer, see
3939 * print_status_info() for the nicer output */
3941 if (arg_properties && !strv_find(arg_properties, name)) {
3942 /* skip what we didn't read */
3943 r = sd_bus_message_skip(m, contents);
3947 switch (contents[0]) {
3949 case SD_BUS_TYPE_STRUCT_BEGIN:
3951 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3954 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3956 return bus_log_parse_error(r);
3959 printf("%s=%"PRIu32"\n", name, u);
3961 printf("%s=\n", name);
3965 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3968 r = sd_bus_message_read(m, "(so)", &s, NULL);
3970 return bus_log_parse_error(r);
3972 if (arg_all || !isempty(s))
3973 printf("%s=%s\n", name, s);
3977 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3978 const char *a = NULL, *b = NULL;
3980 r = sd_bus_message_read(m, "(ss)", &a, &b);
3982 return bus_log_parse_error(r);
3984 if (arg_all || !isempty(a) || !isempty(b))
3985 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3988 } else if (streq_ptr(name, "SystemCallFilter")) {
3989 _cleanup_strv_free_ char **l = NULL;
3992 r = sd_bus_message_enter_container(m, 'r', "bas");
3994 return bus_log_parse_error(r);
3996 r = sd_bus_message_read(m, "b", &whitelist);
3998 return bus_log_parse_error(r);
4000 r = sd_bus_message_read_strv(m, &l);
4002 return bus_log_parse_error(r);
4004 r = sd_bus_message_exit_container(m);
4006 return bus_log_parse_error(r);
4008 if (arg_all || whitelist || !strv_isempty(l)) {
4012 fputs(name, stdout);
4018 STRV_FOREACH(i, l) {
4026 fputc('\n', stdout);
4034 case SD_BUS_TYPE_ARRAY:
4036 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
4040 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
4042 return bus_log_parse_error(r);
4044 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
4045 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
4048 return bus_log_parse_error(r);
4050 r = sd_bus_message_exit_container(m);
4052 return bus_log_parse_error(r);
4056 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
4057 const char *type, *path;
4059 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4061 return bus_log_parse_error(r);
4063 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4064 printf("%s=%s\n", type, path);
4066 return bus_log_parse_error(r);
4068 r = sd_bus_message_exit_container(m);
4070 return bus_log_parse_error(r);
4074 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
4075 const char *type, *path;
4077 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4079 return bus_log_parse_error(r);
4081 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4082 printf("Listen%s=%s\n", type, path);
4084 return bus_log_parse_error(r);
4086 r = sd_bus_message_exit_container(m);
4088 return bus_log_parse_error(r);
4092 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
4094 uint64_t value, next_elapse;
4096 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
4098 return bus_log_parse_error(r);
4100 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
4101 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
4103 printf("%s={ value=%s ; next_elapse=%s }\n",
4105 format_timespan(timespan1, sizeof(timespan1), value, 0),
4106 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
4109 return bus_log_parse_error(r);
4111 r = sd_bus_message_exit_container(m);
4113 return bus_log_parse_error(r);
4117 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
4118 ExecStatusInfo info = {};
4120 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
4122 return bus_log_parse_error(r);
4124 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
4125 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
4126 _cleanup_free_ char *tt;
4128 tt = strv_join(info.argv, " ");
4130 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",
4134 yes_no(info.ignore),
4135 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
4136 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
4138 sigchld_code_to_string(info.code),
4140 info.code == CLD_EXITED ? "" : "/",
4141 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
4144 strv_free(info.argv);
4148 r = sd_bus_message_exit_container(m);
4150 return bus_log_parse_error(r);
4154 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
4155 const char *path, *rwm;
4157 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4159 return bus_log_parse_error(r);
4161 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
4162 printf("%s=%s %s\n", name, strna(path), strna(rwm));
4164 return bus_log_parse_error(r);
4166 r = sd_bus_message_exit_container(m);
4168 return bus_log_parse_error(r);
4172 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
4176 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4178 return bus_log_parse_error(r);
4180 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4181 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
4183 return bus_log_parse_error(r);
4185 r = sd_bus_message_exit_container(m);
4187 return bus_log_parse_error(r);
4191 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
4195 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4197 return bus_log_parse_error(r);
4199 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4200 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
4202 return bus_log_parse_error(r);
4204 r = sd_bus_message_exit_container(m);
4206 return bus_log_parse_error(r);
4214 r = bus_print_property(name, m, arg_all);
4216 return bus_log_parse_error(r);
4219 r = sd_bus_message_skip(m, contents);
4221 return bus_log_parse_error(r);
4224 printf("%s=[unprintable]\n", name);
4230 static int show_one(
4234 bool show_properties,
4238 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4239 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4240 UnitStatusInfo info = {};
4247 log_debug("Showing one %s", path);
4249 r = sd_bus_call_method(
4251 "org.freedesktop.systemd1",
4253 "org.freedesktop.DBus.Properties",
4259 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4263 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4265 return bus_log_parse_error(r);
4272 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4273 const char *name, *contents;
4275 r = sd_bus_message_read(reply, "s", &name);
4277 return bus_log_parse_error(r);
4279 r = sd_bus_message_peek_type(reply, NULL, &contents);
4281 return bus_log_parse_error(r);
4283 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4285 return bus_log_parse_error(r);
4287 if (show_properties)
4288 r = print_property(name, reply, contents);
4290 r = status_property(name, reply, &info, contents);
4294 r = sd_bus_message_exit_container(reply);
4296 return bus_log_parse_error(r);
4298 r = sd_bus_message_exit_container(reply);
4300 return bus_log_parse_error(r);
4303 return bus_log_parse_error(r);
4305 r = sd_bus_message_exit_container(reply);
4307 return bus_log_parse_error(r);
4311 if (!show_properties) {
4312 if (streq(verb, "help"))
4313 show_unit_help(&info);
4315 print_status_info(&info, ellipsized);
4318 strv_free(info.documentation);
4319 strv_free(info.dropin_paths);
4320 strv_free(info.listen);
4322 if (!streq_ptr(info.active_state, "active") &&
4323 !streq_ptr(info.active_state, "reloading") &&
4324 streq(verb, "status")) {
4325 /* According to LSB: "program not running" */
4326 /* 0: program is running or service is OK
4327 * 1: program is dead and /run PID file exists
4328 * 2: program is dead and /run/lock lock file exists
4329 * 3: program is not running
4330 * 4: program or service status is unknown
4332 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4338 while ((p = info.exec)) {
4339 LIST_REMOVE(exec, info.exec, p);
4340 exec_status_info_free(p);
4346 static int get_unit_dbus_path_by_pid(
4351 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4352 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4356 r = sd_bus_call_method(
4358 "org.freedesktop.systemd1",
4359 "/org/freedesktop/systemd1",
4360 "org.freedesktop.systemd1.Manager",
4366 log_error("Failed to get unit for PID "PID_FMT": %s", pid, bus_error_message(&error, r));
4370 r = sd_bus_message_read(reply, "o", &u);
4372 return bus_log_parse_error(r);
4382 static int show_all(
4385 bool show_properties,
4389 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4390 _cleanup_free_ UnitInfo *unit_infos = NULL;
4395 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4399 pager_open_if_enabled();
4403 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4405 for (u = unit_infos; u < unit_infos + c; u++) {
4406 _cleanup_free_ char *p = NULL;
4408 p = unit_dbus_path_from_name(u->id);
4412 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4415 else if (r > 0 && ret == 0)
4422 static int show_system_status(sd_bus *bus) {
4423 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4424 _cleanup_free_ char *hn = NULL;
4425 struct machine_info mi = {};
4426 const char *on, *off;
4429 hn = gethostname_malloc();
4433 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4435 return log_error_errno(r, "Failed to read server status: %m");
4437 if (streq_ptr(mi.state, "degraded")) {
4438 on = ansi_highlight_red();
4439 off = ansi_highlight_off();
4440 } else if (!streq_ptr(mi.state, "running")) {
4441 on = ansi_highlight_yellow();
4442 off = ansi_highlight_off();
4446 printf("%s%s%s %s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4448 printf(" State: %s%s%s\n",
4449 on, strna(mi.state), off);
4451 printf(" Jobs: %u queued\n", mi.n_jobs);
4452 printf(" Failed: %u units\n", mi.n_failed_units);
4454 printf(" Since: %s; %s\n",
4455 format_timestamp(since2, sizeof(since2), mi.timestamp),
4456 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4458 printf(" CGroup: %s\n", mi.control_group ?: "/");
4459 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
4461 arg_all * OUTPUT_SHOW_ALL |
4462 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
4463 on_tty() * OUTPUT_COLOR |
4464 !arg_quiet * OUTPUT_WARN_CUTOFF |
4465 arg_full * OUTPUT_FULL_WIDTH;
4467 static const char prefix[] = " ";
4471 if (c > sizeof(prefix) - 1)
4472 c -= sizeof(prefix) - 1;
4476 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
4480 free(mi.control_group);
4485 static int show(sd_bus *bus, char **args) {
4486 bool show_properties, show_status, new_line = false;
4487 bool ellipsized = false;
4493 show_properties = streq(args[0], "show");
4494 show_status = streq(args[0], "status");
4496 if (show_properties)
4497 pager_open_if_enabled();
4499 /* If no argument is specified inspect the manager itself */
4501 if (show_properties && strv_length(args) <= 1)
4502 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4504 if (show_status && strv_length(args) <= 1) {
4506 pager_open_if_enabled();
4507 show_system_status(bus);
4511 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4513 _cleanup_free_ char **patterns = NULL;
4516 STRV_FOREACH(name, args + 1) {
4517 _cleanup_free_ char *unit = NULL;
4520 if (safe_atou32(*name, &id) < 0) {
4521 if (strv_push(&patterns, *name) < 0)
4525 } else if (show_properties) {
4526 /* Interpret as job id */
4527 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4531 /* Interpret as PID */
4532 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4539 r = show_one(args[0], bus, unit, show_properties,
4540 &new_line, &ellipsized);
4543 else if (r > 0 && ret == 0)
4547 if (!strv_isempty(patterns)) {
4548 _cleanup_strv_free_ char **names = NULL;
4550 r = expand_names(bus, patterns, NULL, &names);
4552 log_error_errno(r, "Failed to expand names: %m");
4554 STRV_FOREACH(name, names) {
4555 _cleanup_free_ char *unit;
4557 unit = unit_dbus_path_from_name(*name);
4561 r = show_one(args[0], bus, unit, show_properties,
4562 &new_line, &ellipsized);
4565 else if (r > 0 && ret == 0)
4571 if (ellipsized && !arg_quiet)
4572 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4577 static int cat(sd_bus *bus, char **args) {
4578 _cleanup_strv_free_ char **names = NULL;
4586 r = expand_names(bus, args + 1, NULL, &names);
4588 log_error_errno(r, "Failed to expand names: %m");
4590 pager_open_if_enabled();
4592 STRV_FOREACH(name, names) {
4593 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4594 _cleanup_strv_free_ char **dropin_paths = NULL;
4595 _cleanup_free_ char *fragment_path = NULL, *unit = NULL;
4598 unit = unit_dbus_path_from_name(*name);
4602 if (need_daemon_reload(bus, *name) > 0)
4603 log_warning("Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'.",
4604 *name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
4606 r = sd_bus_get_property_string(
4608 "org.freedesktop.systemd1",
4610 "org.freedesktop.systemd1.Unit",
4615 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
4619 r = sd_bus_get_property_strv(
4621 "org.freedesktop.systemd1",
4623 "org.freedesktop.systemd1.Unit",
4628 log_warning("Failed to get DropInPaths: %s", bus_error_message(&error, r));
4637 if (!isempty(fragment_path)) {
4638 printf("%s# %s%s\n",
4639 ansi_highlight_blue(),
4641 ansi_highlight_off());
4644 r = copy_file_fd(fragment_path, STDOUT_FILENO);
4646 log_warning_errno(r, "Failed to cat %s: %m", fragment_path);
4651 STRV_FOREACH(path, dropin_paths) {
4652 printf("%s%s# %s%s\n",
4653 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4654 ansi_highlight_blue(),
4656 ansi_highlight_off());
4659 r = copy_file_fd(*path, STDOUT_FILENO);
4661 log_warning_errno(r, "Failed to cat %s: %m", *path);
4667 return r < 0 ? r : 0;
4670 static int set_property(sd_bus *bus, char **args) {
4671 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4672 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4673 _cleanup_free_ char *n = NULL;
4677 r = sd_bus_message_new_method_call(
4680 "org.freedesktop.systemd1",
4681 "/org/freedesktop/systemd1",
4682 "org.freedesktop.systemd1.Manager",
4683 "SetUnitProperties");
4685 return bus_log_create_error(r);
4687 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4689 return bus_log_create_error(r);
4691 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4695 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4697 return bus_log_create_error(r);
4699 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4701 return bus_log_create_error(r);
4703 STRV_FOREACH(i, args + 2) {
4704 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4706 return bus_log_create_error(r);
4708 r = bus_append_unit_property_assignment(m, *i);
4712 r = sd_bus_message_close_container(m);
4714 return bus_log_create_error(r);
4717 r = sd_bus_message_close_container(m);
4719 return bus_log_create_error(r);
4721 r = sd_bus_call(bus, m, 0, &error, NULL);
4723 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4730 static int snapshot(sd_bus *bus, char **args) {
4731 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4732 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
4733 _cleanup_free_ char *n = NULL, *id = NULL;
4737 if (strv_length(args) > 1)
4738 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4744 r = sd_bus_message_new_method_call(
4747 "org.freedesktop.systemd1",
4748 "/org/freedesktop/systemd1",
4749 "org.freedesktop.systemd1.Manager",
4752 return bus_log_create_error(r);
4754 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4756 return bus_log_create_error(r);
4758 r = sd_bus_message_append(m, "sb", n, false);
4760 return bus_log_create_error(r);
4762 r = sd_bus_call(bus, m, 0, &error, &reply);
4764 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4768 r = sd_bus_message_read(reply, "o", &path);
4770 return bus_log_parse_error(r);
4772 r = sd_bus_get_property_string(
4774 "org.freedesktop.systemd1",
4776 "org.freedesktop.systemd1.Unit",
4781 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4791 static int delete_snapshot(sd_bus *bus, char **args) {
4792 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4793 _cleanup_strv_free_ char **names = NULL;
4799 r = expand_names(bus, args + 1, ".snapshot", &names);
4801 log_error_errno(r, "Failed to expand names: %m");
4803 STRV_FOREACH(name, names) {
4804 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4807 q = sd_bus_message_new_method_call(
4810 "org.freedesktop.systemd1",
4811 "/org/freedesktop/systemd1",
4812 "org.freedesktop.systemd1.Manager",
4815 return bus_log_create_error(q);
4817 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4819 return bus_log_create_error(q);
4821 q = sd_bus_message_append(m, "s", *name);
4823 return bus_log_create_error(q);
4825 q = sd_bus_call(bus, m, 0, &error, NULL);
4827 log_error("Failed to remove snapshot %s: %s", *name, bus_error_message(&error, q));
4836 static int daemon_reload(sd_bus *bus, char **args) {
4837 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4838 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4842 if (arg_action == ACTION_RELOAD)
4844 else if (arg_action == ACTION_REEXEC)
4845 method = "Reexecute";
4847 assert(arg_action == ACTION_SYSTEMCTL);
4850 streq(args[0], "clear-jobs") ||
4851 streq(args[0], "cancel") ? "ClearJobs" :
4852 streq(args[0], "daemon-reexec") ? "Reexecute" :
4853 streq(args[0], "reset-failed") ? "ResetFailed" :
4854 streq(args[0], "halt") ? "Halt" :
4855 streq(args[0], "poweroff") ? "PowerOff" :
4856 streq(args[0], "reboot") ? "Reboot" :
4857 streq(args[0], "kexec") ? "KExec" :
4858 streq(args[0], "exit") ? "Exit" :
4859 /* "daemon-reload" */ "Reload";
4862 r = sd_bus_message_new_method_call(
4865 "org.freedesktop.systemd1",
4866 "/org/freedesktop/systemd1",
4867 "org.freedesktop.systemd1.Manager",
4870 return bus_log_create_error(r);
4872 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4874 return bus_log_create_error(r);
4876 r = sd_bus_call(bus, m, 0, &error, NULL);
4877 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4878 /* There's always a fallback possible for
4879 * legacy actions. */
4881 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4882 /* On reexecution, we expect a disconnect, not a
4886 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4888 return r < 0 ? r : 0;
4891 static int reset_failed(sd_bus *bus, char **args) {
4892 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4893 _cleanup_strv_free_ char **names = NULL;
4897 if (strv_length(args) <= 1)
4898 return daemon_reload(bus, args);
4900 r = expand_names(bus, args + 1, NULL, &names);
4902 log_error_errno(r, "Failed to expand names: %m");
4904 STRV_FOREACH(name, names) {
4905 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4907 q = sd_bus_message_new_method_call(
4910 "org.freedesktop.systemd1",
4911 "/org/freedesktop/systemd1",
4912 "org.freedesktop.systemd1.Manager",
4915 return bus_log_create_error(q);
4917 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4919 return bus_log_create_error(q);
4921 q = sd_bus_message_append(m, "s", *name);
4923 return bus_log_create_error(q);
4925 q = sd_bus_call(bus, m, 0, &error, NULL);
4927 log_error("Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q));
4936 static int show_environment(sd_bus *bus, char **args) {
4937 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4938 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4942 pager_open_if_enabled();
4944 r = sd_bus_get_property(
4946 "org.freedesktop.systemd1",
4947 "/org/freedesktop/systemd1",
4948 "org.freedesktop.systemd1.Manager",
4954 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4958 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4960 return bus_log_parse_error(r);
4962 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4965 return bus_log_parse_error(r);
4967 r = sd_bus_message_exit_container(reply);
4969 return bus_log_parse_error(r);
4974 static int switch_root(sd_bus *bus, char **args) {
4975 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4976 _cleanup_free_ char *cmdline_init = NULL;
4977 const char *root, *init;
4981 l = strv_length(args);
4982 if (l < 2 || l > 3) {
4983 log_error("Wrong number of arguments.");
4992 r = parse_env_file("/proc/cmdline", WHITESPACE,
4993 "init", &cmdline_init,
4996 log_debug_errno(r, "Failed to parse /proc/cmdline: %m");
4998 init = cmdline_init;
5005 const char *root_systemd_path = NULL, *root_init_path = NULL;
5007 root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
5008 root_init_path = strappenda(root, "/", init);
5010 /* If the passed init is actually the same as the
5011 * systemd binary, then let's suppress it. */
5012 if (files_same(root_init_path, root_systemd_path) > 0)
5016 log_debug("Switching root - root: %s; init: %s", root, strna(init));
5018 r = sd_bus_call_method(
5020 "org.freedesktop.systemd1",
5021 "/org/freedesktop/systemd1",
5022 "org.freedesktop.systemd1.Manager",
5028 log_error("Failed to switch root: %s", bus_error_message(&error, r));
5035 static int set_environment(sd_bus *bus, char **args) {
5036 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5037 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
5044 method = streq(args[0], "set-environment")
5046 : "UnsetEnvironment";
5048 r = sd_bus_message_new_method_call(
5051 "org.freedesktop.systemd1",
5052 "/org/freedesktop/systemd1",
5053 "org.freedesktop.systemd1.Manager",
5056 return bus_log_create_error(r);
5058 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5060 return bus_log_create_error(r);
5062 r = sd_bus_message_append_strv(m, args + 1);
5064 return bus_log_create_error(r);
5066 r = sd_bus_call(bus, m, 0, &error, NULL);
5068 log_error("Failed to set environment: %s", bus_error_message(&error, r));
5075 static int import_environment(sd_bus *bus, char **args) {
5076 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5077 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
5083 r = sd_bus_message_new_method_call(
5086 "org.freedesktop.systemd1",
5087 "/org/freedesktop/systemd1",
5088 "org.freedesktop.systemd1.Manager",
5091 return bus_log_create_error(r);
5093 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5095 return bus_log_create_error(r);
5097 if (strv_isempty(args + 1))
5098 r = sd_bus_message_append_strv(m, environ);
5102 r = sd_bus_message_open_container(m, 'a', "s");
5104 return bus_log_create_error(r);
5106 STRV_FOREACH(a, args + 1) {
5108 if (!env_name_is_valid(*a)) {
5109 log_error("Not a valid environment variable name: %s", *a);
5113 STRV_FOREACH(b, environ) {
5116 eq = startswith(*b, *a);
5117 if (eq && *eq == '=') {
5119 r = sd_bus_message_append(m, "s", *b);
5121 return bus_log_create_error(r);
5128 r = sd_bus_message_close_container(m);
5131 return bus_log_create_error(r);
5133 r = sd_bus_call(bus, m, 0, &error, NULL);
5135 log_error("Failed to import environment: %s", bus_error_message(&error, r));
5142 static int enable_sysv_units(const char *verb, char **args) {
5145 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
5146 unsigned f = 1, t = 1;
5147 _cleanup_lookup_paths_free_ LookupPaths paths = {};
5149 if (arg_scope != UNIT_FILE_SYSTEM)
5152 if (!streq(verb, "enable") &&
5153 !streq(verb, "disable") &&
5154 !streq(verb, "is-enabled"))
5157 /* Processes all SysV units, and reshuffles the array so that
5158 * afterwards only the native units remain */
5160 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, arg_root, NULL, NULL, NULL);
5165 for (f = 0; args[f]; f++) {
5167 _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL;
5168 bool found_native = false, found_sysv;
5170 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
5178 if (!endswith(name, ".service"))
5181 if (path_is_absolute(name))
5184 STRV_FOREACH(k, paths.unit_path) {
5185 _cleanup_free_ char *path = NULL;
5187 path = path_join(arg_root, *k, name);
5191 found_native = access(path, F_OK) >= 0;
5199 p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name);
5203 p[strlen(p) - strlen(".service")] = 0;
5204 found_sysv = access(p, F_OK) >= 0;
5208 /* Mark this entry, so that we don't try enabling it as native unit */
5209 args[f] = (char*) "";
5211 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
5213 if (!isempty(arg_root))
5214 argv[c++] = q = strappend("--root=", arg_root);
5216 argv[c++] = basename(p);
5218 streq(verb, "enable") ? "on" :
5219 streq(verb, "disable") ? "off" : "--level=5";
5222 l = strv_join((char**)argv, " ");
5226 log_info("Executing %s", l);
5230 return log_error_errno(errno, "Failed to fork: %m");
5231 else if (pid == 0) {
5234 execv(argv[0], (char**) argv);
5235 _exit(EXIT_FAILURE);
5238 j = wait_for_terminate(pid, &status);
5240 log_error_errno(r, "Failed to wait for child: %m");
5244 if (status.si_code == CLD_EXITED) {
5245 if (streq(verb, "is-enabled")) {
5246 if (status.si_status == 0) {
5255 } else if (status.si_status != 0)
5261 /* Drop all SysV units */
5262 for (f = 0, t = 0; args[f]; f++) {
5264 if (isempty(args[f]))
5267 args[t++] = args[f];
5276 static int mangle_names(char **original_names, char ***mangled_names) {
5277 char **i, **l, **name;
5279 l = new(char*, strv_length(original_names) + 1);
5284 STRV_FOREACH(name, original_names) {
5286 /* When enabling units qualified path names are OK,
5287 * too, hence allow them explicitly. */
5292 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5308 static int enable_unit(sd_bus *bus, char **args) {
5309 _cleanup_strv_free_ char **names = NULL;
5310 const char *verb = args[0];
5311 UnitFileChange *changes = NULL;
5312 unsigned n_changes = 0;
5313 int carries_install_info = -1;
5319 r = mangle_names(args+1, &names);
5323 r = enable_sysv_units(verb, names);
5327 /* If the operation was fully executed by the SysV compat,
5328 * let's finish early */
5329 if (strv_isempty(names))
5332 if (!bus || avoid_bus()) {
5333 if (streq(verb, "enable")) {
5334 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5335 carries_install_info = r;
5336 } else if (streq(verb, "disable"))
5337 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5338 else if (streq(verb, "reenable")) {
5339 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5340 carries_install_info = r;
5341 } else if (streq(verb, "link"))
5342 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5343 else if (streq(verb, "preset")) {
5344 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_preset_mode, arg_force, &changes, &n_changes);
5345 carries_install_info = r;
5346 } else if (streq(verb, "mask"))
5347 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5348 else if (streq(verb, "unmask"))
5349 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5351 assert_not_reached("Unknown verb");
5354 log_error_errno(r, "Operation failed: %m");
5359 dump_unit_file_changes(changes, n_changes);
5363 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5364 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5365 int expect_carries_install_info = false;
5366 bool send_force = true, send_preset_mode = false;
5369 if (streq(verb, "enable")) {
5370 method = "EnableUnitFiles";
5371 expect_carries_install_info = true;
5372 } else if (streq(verb, "disable")) {
5373 method = "DisableUnitFiles";
5375 } else if (streq(verb, "reenable")) {
5376 method = "ReenableUnitFiles";
5377 expect_carries_install_info = true;
5378 } else if (streq(verb, "link"))
5379 method = "LinkUnitFiles";
5380 else if (streq(verb, "preset")) {
5382 if (arg_preset_mode != UNIT_FILE_PRESET_FULL) {
5383 method = "PresetUnitFilesWithMode";
5384 send_preset_mode = true;
5386 method = "PresetUnitFiles";
5388 expect_carries_install_info = true;
5389 } else if (streq(verb, "mask"))
5390 method = "MaskUnitFiles";
5391 else if (streq(verb, "unmask")) {
5392 method = "UnmaskUnitFiles";
5395 assert_not_reached("Unknown verb");
5397 r = sd_bus_message_new_method_call(
5400 "org.freedesktop.systemd1",
5401 "/org/freedesktop/systemd1",
5402 "org.freedesktop.systemd1.Manager",
5405 return bus_log_create_error(r);
5407 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5409 return bus_log_create_error(r);
5411 r = sd_bus_message_append_strv(m, names);
5413 return bus_log_create_error(r);
5415 if (send_preset_mode) {
5416 r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode));
5418 return bus_log_create_error(r);
5421 r = sd_bus_message_append(m, "b", arg_runtime);
5423 return bus_log_create_error(r);
5426 r = sd_bus_message_append(m, "b", arg_force);
5428 return bus_log_create_error(r);
5431 r = sd_bus_call(bus, m, 0, &error, &reply);
5433 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5437 if (expect_carries_install_info) {
5438 r = sd_bus_message_read(reply, "b", &carries_install_info);
5440 return bus_log_parse_error(r);
5443 r = deserialize_and_dump_unit_file_changes(reply);
5447 /* Try to reload if enabled */
5449 r = daemon_reload(bus, args);
5454 if (carries_install_info == 0)
5455 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5456 "using systemctl.\n"
5457 "Possible reasons for having this kind of units are:\n"
5458 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5459 " .wants/ or .requires/ directory.\n"
5460 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5461 " a requirement dependency on it.\n"
5462 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5463 " D-Bus, udev, scripted systemctl call, ...).\n");
5466 unit_file_changes_free(changes, n_changes);
5471 static int add_dependency(sd_bus *bus, char **args) {
5472 _cleanup_strv_free_ char **names = NULL;
5473 _cleanup_free_ char *target = NULL;
5474 const char *verb = args[0];
5481 target = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
5485 r = mangle_names(args+2, &names);
5489 if (streq(verb, "add-wants"))
5491 else if (streq(verb, "add-requires"))
5492 dep = UNIT_REQUIRES;
5494 assert_not_reached("Unknown verb");
5496 if (!bus || avoid_bus()) {
5497 UnitFileChange *changes = NULL;
5498 unsigned n_changes = 0;
5500 r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes);
5503 return log_error_errno(r, "Can't add dependency: %m");
5506 dump_unit_file_changes(changes, n_changes);
5508 unit_file_changes_free(changes, n_changes);
5511 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5512 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5514 r = sd_bus_message_new_method_call(
5517 "org.freedesktop.systemd1",
5518 "/org/freedesktop/systemd1",
5519 "org.freedesktop.systemd1.Manager",
5520 "AddDependencyUnitFiles");
5522 return bus_log_create_error(r);
5524 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5526 return bus_log_create_error(r);
5528 r = sd_bus_message_append_strv(m, names);
5530 return bus_log_create_error(r);
5532 r = sd_bus_message_append(m, "ssbb", target, unit_dependency_to_string(dep), arg_runtime, arg_force);
5534 return bus_log_create_error(r);
5536 r = sd_bus_call(bus, m, 0, &error, &reply);
5538 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5542 r = deserialize_and_dump_unit_file_changes(reply);
5547 r = daemon_reload(bus, args);
5555 static int preset_all(sd_bus *bus, char **args) {
5556 UnitFileChange *changes = NULL;
5557 unsigned n_changes = 0;
5560 if (!bus || avoid_bus()) {
5562 r = unit_file_preset_all(arg_scope, arg_runtime, arg_root, arg_preset_mode, arg_force, &changes, &n_changes);
5564 log_error_errno(r, "Operation failed: %m");
5569 dump_unit_file_changes(changes, n_changes);
5574 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
5575 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5577 r = sd_bus_message_new_method_call(
5580 "org.freedesktop.systemd1",
5581 "/org/freedesktop/systemd1",
5582 "org.freedesktop.systemd1.Manager",
5583 "PresetAllUnitFiles");
5585 return bus_log_create_error(r);
5587 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5589 return bus_log_create_error(r);
5591 r = sd_bus_message_append(
5594 unit_file_preset_mode_to_string(arg_preset_mode),
5598 return bus_log_create_error(r);
5600 r = sd_bus_call(bus, m, 0, &error, &reply);
5602 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5606 r = deserialize_and_dump_unit_file_changes(reply);
5611 r = daemon_reload(bus, args);
5617 unit_file_changes_free(changes, n_changes);
5622 static int unit_is_enabled(sd_bus *bus, char **args) {
5624 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5625 _cleanup_strv_free_ char **names = NULL;
5630 r = mangle_names(args+1, &names);
5634 r = enable_sysv_units(args[0], names);
5640 if (!bus || avoid_bus()) {
5642 STRV_FOREACH(name, names) {
5643 UnitFileState state;
5645 state = unit_file_get_state(arg_scope, arg_root, *name);
5647 return log_error_errno(state, "Failed to get unit file state for %s: %m", *name);
5649 if (state == UNIT_FILE_ENABLED ||
5650 state == UNIT_FILE_ENABLED_RUNTIME ||
5651 state == UNIT_FILE_STATIC ||
5652 state == UNIT_FILE_INDIRECT)
5656 puts(unit_file_state_to_string(state));
5660 STRV_FOREACH(name, names) {
5661 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5664 r = sd_bus_call_method(
5666 "org.freedesktop.systemd1",
5667 "/org/freedesktop/systemd1",
5668 "org.freedesktop.systemd1.Manager",
5674 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5678 r = sd_bus_message_read(reply, "s", &s);
5680 return bus_log_parse_error(r);
5682 if (STR_IN_SET(s, "enabled", "enabled-runtime", "static", "indirect"))
5693 static int is_system_running(sd_bus *bus, char **args) {
5694 _cleanup_free_ char *state = NULL;
5697 r = sd_bus_get_property_string(
5699 "org.freedesktop.systemd1",
5700 "/org/freedesktop/systemd1",
5701 "org.freedesktop.systemd1.Manager",
5714 return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE;
5717 static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **unit_path) {
5724 STRV_FOREACH(p, lp->unit_path) {
5727 path = path_join(arg_root, *p, unit_name);
5731 if (access(path, F_OK) == 0) {
5742 static int create_edit_temp_file(const char *new_path, const char *original_path, char **ret_tmp_fn) {
5747 assert(original_path);
5750 t = tempfn_random(new_path);
5754 r = mkdir_parents(new_path, 0755);
5756 log_error_errno(r, "Failed to create directories for %s: %m", new_path);
5761 r = copy_file(original_path, t, 0, 0644);
5765 log_error_errno(r, "Failed to create temporary file %s: %m", t);
5770 log_error_errno(r, "Failed to copy %s to %s: %m", original_path, t);
5780 static int get_drop_in_to_edit(const char *unit_name, const char *user_home, const char *user_runtime, char **ret_path) {
5787 switch (arg_scope) {
5788 case UNIT_FILE_SYSTEM:
5789 tmp = strappenda(arg_runtime ? "/run/systemd/system/" : SYSTEM_CONFIG_UNIT_PATH "/", unit_name, ".d/override.conf");
5791 case UNIT_FILE_GLOBAL:
5792 tmp = strappenda(arg_runtime ? "/run/systemd/user/" : USER_CONFIG_UNIT_PATH "/", unit_name, ".d/override.conf");
5794 case UNIT_FILE_USER:
5796 assert(user_runtime);
5798 tmp = strappenda(arg_runtime ? user_runtime : user_home, "/", unit_name, ".d/override.conf");
5801 assert_not_reached("Invalid scope");
5804 tmp_new_path = path_join(arg_root, tmp, NULL);
5808 *ret_path = tmp_new_path;
5813 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) {
5819 assert(ret_new_path);
5820 assert(ret_tmp_path);
5822 r = get_drop_in_to_edit(unit_name, user_home, user_runtime, &tmp_new_path);
5826 r = create_edit_temp_file(tmp_new_path, tmp_new_path, &tmp_tmp_path);
5832 *ret_new_path = tmp_new_path;
5833 *ret_tmp_path = tmp_tmp_path;
5838 static bool unit_is_editable(const char *unit_name, const char *fragment_path, const char *user_home) {
5839 bool editable = true;
5840 const char *invalid_path;
5847 switch (arg_scope) {
5848 case UNIT_FILE_SYSTEM:
5849 if (path_startswith(fragment_path, "/etc/systemd/system")) {
5851 invalid_path = "/etc/systemd/system";
5852 } else if (path_startswith(fragment_path, SYSTEM_CONFIG_UNIT_PATH)) {
5854 invalid_path = SYSTEM_CONFIG_UNIT_PATH;
5857 case UNIT_FILE_GLOBAL:
5858 if (path_startswith(fragment_path, "/etc/systemd/user")) {
5860 invalid_path = "/etc/systemd/user";
5861 } else if (path_startswith(fragment_path, USER_CONFIG_UNIT_PATH)) {
5863 invalid_path = USER_CONFIG_UNIT_PATH;
5866 case UNIT_FILE_USER:
5869 if (path_startswith(fragment_path, "/etc/systemd/user")) {
5871 invalid_path = "/etc/systemd/user";
5872 } else if (path_startswith(fragment_path, USER_CONFIG_UNIT_PATH)) {
5874 invalid_path = USER_CONFIG_UNIT_PATH;
5875 } else if (path_startswith(fragment_path, user_home)) {
5877 invalid_path = user_home;
5881 assert_not_reached("Invalid scope");
5885 log_error("%s ignored: cannot temporarily edit units from %s", unit_name, invalid_path);
5890 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) {
5896 if (!unit_is_editable(unit_name, fragment_path, user_home))
5899 switch (arg_scope) {
5900 case UNIT_FILE_SYSTEM:
5901 tmp_new_path = path_join(arg_root, arg_runtime ? "/run/systemd/system/" : SYSTEM_CONFIG_UNIT_PATH, unit_name);
5903 case UNIT_FILE_GLOBAL:
5904 tmp_new_path = path_join(arg_root, arg_runtime ? "/run/systemd/user/" : USER_CONFIG_UNIT_PATH, unit_name);
5906 case UNIT_FILE_USER:
5908 assert(user_runtime);
5910 tmp_new_path = path_join(arg_root, arg_runtime ? user_runtime : user_home, unit_name);
5913 assert_not_reached("Invalid scope");
5918 *ret_path = tmp_new_path;
5923 static int unit_file_create_copy(const char *unit_name,
5924 const char *fragment_path,
5925 const char *user_home,
5926 const char *user_runtime,
5927 char **ret_new_path,
5928 char **ret_tmp_path) {
5933 assert(fragment_path);
5935 assert(ret_new_path);
5936 assert(ret_tmp_path);
5938 r = get_copy_to_edit(unit_name, fragment_path, user_home, user_runtime, &tmp_new_path);
5942 if (!path_equal(fragment_path, tmp_new_path) && access(tmp_new_path, F_OK) == 0) {
5945 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);
5950 if (response != 'y') {
5951 log_warning("%s ignored", unit_name);
5957 r = create_edit_temp_file(tmp_new_path, fragment_path, &tmp_tmp_path);
5959 log_error_errno(r, "Failed to create temporary file for %s: %m", tmp_new_path);
5964 *ret_new_path = tmp_new_path;
5965 *ret_tmp_path = tmp_tmp_path;
5970 static int run_editor(char **paths) {
5978 log_error_errno(errno, "Failed to fork: %m");
5984 char **backup_editors = STRV_MAKE("nano", "vim", "vi");
5986 char **tmp_path, **original_path, **p;
5990 argc = strv_length(paths)/2 + 1;
5991 args = newa(const char*, argc + 1);
5994 STRV_FOREACH_PAIR(original_path, tmp_path, paths) {
5995 args[i] = *tmp_path;
6000 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
6001 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
6002 * we try to execute well known editors
6004 editor = getenv("SYSTEMD_EDITOR");
6006 editor = getenv("EDITOR");
6008 editor = getenv("VISUAL");
6010 if (!isempty(editor)) {
6012 execvp(editor, (char* const*) args);
6015 STRV_FOREACH(p, backup_editors) {
6017 execvp(*p, (char* const*) args);
6018 /* We do not fail if the editor doesn't exist
6019 * because we want to try each one of them before
6022 if (errno != ENOENT) {
6023 log_error("Failed to execute %s: %m", editor);
6024 _exit(EXIT_FAILURE);
6028 log_error("Cannot edit unit(s): No editor available. Please set either SYSTEMD_EDITOR or EDITOR or VISUAL environment variable");
6029 _exit(EXIT_FAILURE);
6032 r = wait_for_terminate_and_warn("editor", pid, true);
6034 return log_error_errno(r, "Failed to wait for child: %m");
6039 static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
6040 _cleanup_free_ char *user_home = NULL;
6041 _cleanup_free_ char *user_runtime = NULL;
6048 if (arg_scope == UNIT_FILE_USER) {
6049 r = user_config_home(&user_home);
6053 log_error("Cannot edit units for the user instance: home directory unknown");
6057 r = user_runtime_dir(&user_runtime);
6061 log_error("Cannot edit units for the user instance: runtime directory unknown");
6066 if (!bus || avoid_bus()) {
6067 _cleanup_lookup_paths_free_ LookupPaths lp = {};
6069 /* If there is no bus, we try to find the units by testing each available directory
6070 * according to the scope.
6072 r = lookup_paths_init(&lp,
6073 arg_scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
6074 arg_scope == UNIT_FILE_USER,
6078 log_error_errno(r, "Failed get lookup paths: %m");
6082 STRV_FOREACH(name, names) {
6083 _cleanup_free_ char *path = NULL;
6084 char *new_path, *tmp_path;
6086 r = unit_file_find_path(&lp, *name, &path);
6090 log_warning("%s ignored: not found", *name);
6095 r = unit_file_create_copy(*name, path, user_home, user_runtime, &new_path, &tmp_path);
6097 r = unit_file_create_drop_in(*name, user_home, user_runtime, &new_path, &tmp_path);
6102 r = strv_push(paths, new_path);
6106 r = strv_push(paths, tmp_path);
6111 STRV_FOREACH(name, names) {
6112 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
6113 _cleanup_free_ char *fragment_path = NULL;
6114 _cleanup_free_ char *unit = NULL;
6115 char *new_path, *tmp_path;
6117 unit = unit_dbus_path_from_name(*name);
6121 if (need_daemon_reload(bus, *name) > 0) {
6122 log_warning("%s ignored: unit file changed on disk. Run 'systemctl%s daemon-reload'.",
6123 *name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
6127 r = sd_bus_get_property_string(
6129 "org.freedesktop.systemd1",
6131 "org.freedesktop.systemd1.Unit",
6136 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
6140 if (isempty(fragment_path)) {
6141 log_warning("%s ignored: not found", *name);
6146 r = unit_file_create_copy(*name, fragment_path, user_home, user_runtime, &new_path, &tmp_path);
6148 r = unit_file_create_drop_in(*name, user_home, user_runtime, &new_path, &tmp_path);
6152 r = strv_push(paths, new_path);
6156 r = strv_push(paths, tmp_path);
6165 static int edit(sd_bus *bus, char **args) {
6166 _cleanup_strv_free_ char **names = NULL;
6167 _cleanup_strv_free_ char **paths = NULL;
6168 char **original, **tmp;
6174 log_error("Cannot edit units if we are not on a tty");
6178 if (arg_transport != BUS_TRANSPORT_LOCAL) {
6179 log_error("Cannot remotely edit units");
6183 r = expand_names(bus, args + 1, NULL, &names);
6185 return log_error_errno(r, "Failed to expand names: %m");
6188 log_error("No unit name found by expanding names");
6192 r = find_paths_to_edit(bus, names, &paths);
6196 if (strv_isempty(paths)) {
6197 log_error("Cannot find any units to edit");
6201 r = run_editor(paths);
6205 STRV_FOREACH_PAIR(original, tmp, paths) {
6206 /* If the temporary file is empty we ignore it.
6207 * It's useful if the user wants to cancel its modification
6209 if (null_or_empty_path(*tmp)) {
6210 log_warning("Edition of %s canceled: temporary file empty", *original);
6213 r = rename(*tmp, *original);
6215 r = log_error_errno(errno, "Failed to rename %s to %s: %m", *tmp, *original);
6220 if (!arg_no_reload && bus && !avoid_bus())
6221 r = daemon_reload(bus, args);
6224 STRV_FOREACH_PAIR(original, tmp, paths)
6225 unlink_noerrno(*tmp);
6230 static void systemctl_help(void) {
6232 pager_open_if_enabled();
6234 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
6235 "Query or send control commands to the systemd manager.\n\n"
6236 " -h --help Show this help\n"
6237 " --version Show package version\n"
6238 " --system Connect to system manager\n"
6239 " --user Connect to user service manager\n"
6240 " -H --host=[USER@]HOST\n"
6241 " Operate on remote host\n"
6242 " -M --machine=CONTAINER\n"
6243 " Operate on local container\n"
6244 " -t --type=TYPE List only units of a particular type\n"
6245 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
6246 " -p --property=NAME Show only properties by this name\n"
6247 " -a --all Show all loaded units/properties, including dead/empty\n"
6248 " ones. To list all units installed on the system, use\n"
6249 " the 'list-unit-files' command instead.\n"
6250 " -l --full Don't ellipsize unit names on output\n"
6251 " -r --recursive Show unit list of host and local containers\n"
6252 " --reverse Show reverse dependencies with 'list-dependencies'\n"
6253 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
6254 " queueing a new job\n"
6255 " --show-types When showing sockets, explicitly show their type\n"
6256 " -i --ignore-inhibitors\n"
6257 " When shutting down or sleeping, ignore inhibitors\n"
6258 " --kill-who=WHO Who to send signal to\n"
6259 " -s --signal=SIGNAL Which signal to send\n"
6260 " -q --quiet Suppress output\n"
6261 " --no-block Do not wait until operation finished\n"
6262 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6263 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
6265 " --no-legend Do not print a legend (column headers and hints)\n"
6266 " --no-pager Do not pipe output into a pager\n"
6267 " --no-ask-password\n"
6268 " Do not ask for system passwords\n"
6269 " --global Enable/disable unit files globally\n"
6270 " --runtime Enable unit files only temporarily until next reboot\n"
6271 " -f --force When enabling unit files, override existing symlinks\n"
6272 " When shutting down, execute action immediately\n"
6273 " --preset-mode= Specifies whether fully apply presets, or only enable,\n"
6274 " or only disable\n"
6275 " --root=PATH Enable unit files in the specified root directory\n"
6276 " -n --lines=INTEGER Number of journal entries to show\n"
6277 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
6278 " verbose, export, json, json-pretty, json-sse, cat)\n"
6279 " --plain Print unit dependencies as a list instead of a tree\n\n"
6281 " list-units [PATTERN...] List loaded units\n"
6282 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
6283 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
6284 " start NAME... Start (activate) one or more units\n"
6285 " stop NAME... Stop (deactivate) one or more units\n"
6286 " reload NAME... Reload one or more units\n"
6287 " restart NAME... Start or restart one or more units\n"
6288 " try-restart NAME... Restart one or more units if active\n"
6289 " reload-or-restart NAME... Reload one or more units if possible,\n"
6290 " otherwise start or restart\n"
6291 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
6292 " otherwise restart if active\n"
6293 " isolate NAME Start one unit and stop all others\n"
6294 " kill NAME... Send signal to processes of a unit\n"
6295 " is-active PATTERN... Check whether units are active\n"
6296 " is-failed PATTERN... Check whether units are failed\n"
6297 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
6298 " show [PATTERN...|JOB...] Show properties of one or more\n"
6299 " units/jobs or the manager\n"
6300 " cat PATTERN... Show files and drop-ins of one or more units\n"
6301 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
6302 " help PATTERN...|PID... Show manual for one or more units\n"
6303 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
6305 " list-dependencies [NAME] Recursively show units which are required\n"
6306 " or wanted by this unit or by which this\n"
6307 " unit is required or wanted\n\n"
6308 "Unit File Commands:\n"
6309 " list-unit-files [PATTERN...] List installed unit files\n"
6310 " enable NAME... Enable one or more unit files\n"
6311 " disable NAME... Disable one or more unit files\n"
6312 " reenable NAME... Reenable one or more unit files\n"
6313 " preset NAME... Enable/disable one or more unit files\n"
6314 " based on preset configuration\n"
6315 " preset-all Enable/disable all unit files based on\n"
6316 " preset configuration\n"
6317 " is-enabled NAME... Check whether unit files are enabled\n\n"
6318 " mask NAME... Mask one or more units\n"
6319 " unmask NAME... Unmask one or more units\n"
6320 " link PATH... Link one or more units files into\n"
6321 " the search path\n"
6322 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6323 " on specified one or more units\n"
6324 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6325 " on specified one or more units\n"
6326 " get-default Get the name of the default target\n"
6327 " set-default NAME Set the default target\n"
6328 " edit NAME... Edit one or more unit files\n"
6330 "Machine Commands:\n"
6331 " list-machines [PATTERN...] List local containers and host\n\n"
6333 " list-jobs [PATTERN...] List jobs\n"
6334 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
6335 "Snapshot Commands:\n"
6336 " snapshot [NAME] Create a snapshot\n"
6337 " delete NAME... Remove one or more snapshots\n\n"
6338 "Environment Commands:\n"
6339 " show-environment Dump environment\n"
6340 " set-environment NAME=VALUE... Set one or more environment variables\n"
6341 " unset-environment NAME... Unset one or more environment variables\n"
6342 " import-environment NAME... Import all, one or more environment variables\n\n"
6343 "Manager Lifecycle Commands:\n"
6344 " daemon-reload Reload systemd manager configuration\n"
6345 " daemon-reexec Reexecute systemd manager\n\n"
6346 "System Commands:\n"
6347 " is-system-running Check whether system is fully running\n"
6348 " default Enter system default mode\n"
6349 " rescue Enter system rescue mode\n"
6350 " emergency Enter system emergency mode\n"
6351 " halt Shut down and halt the system\n"
6352 " poweroff Shut down and power-off the system\n"
6353 " reboot [ARG] Shut down and reboot the system\n"
6354 " kexec Shut down and reboot the system with kexec\n"
6355 " exit Request user instance exit\n"
6356 " switch-root ROOT [INIT] Change to a different root file system\n"
6357 " suspend Suspend the system\n"
6358 " hibernate Hibernate the system\n"
6359 " hybrid-sleep Hibernate and suspend the system\n",
6360 program_invocation_short_name);
6363 static void halt_help(void) {
6364 printf("%s [OPTIONS...]%s\n\n"
6365 "%s the system.\n\n"
6366 " --help Show this help\n"
6367 " --halt Halt the machine\n"
6368 " -p --poweroff Switch off the machine\n"
6369 " --reboot Reboot the machine\n"
6370 " -f --force Force immediate halt/power-off/reboot\n"
6371 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
6372 " -d --no-wtmp Don't write wtmp record\n"
6373 " --no-wall Don't send wall message before halt/power-off/reboot\n",
6374 program_invocation_short_name,
6375 arg_action == ACTION_REBOOT ? " [ARG]" : "",
6376 arg_action == ACTION_REBOOT ? "Reboot" :
6377 arg_action == ACTION_POWEROFF ? "Power off" :
6381 static void shutdown_help(void) {
6382 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
6383 "Shut down the system.\n\n"
6384 " --help Show this help\n"
6385 " -H --halt Halt the machine\n"
6386 " -P --poweroff Power-off the machine\n"
6387 " -r --reboot Reboot the machine\n"
6388 " -h Equivalent to --poweroff, overridden by --halt\n"
6389 " -k Don't halt/power-off/reboot, just send warnings\n"
6390 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6391 " -c Cancel a pending shutdown\n",
6392 program_invocation_short_name);
6395 static void telinit_help(void) {
6396 printf("%s [OPTIONS...] {COMMAND}\n\n"
6397 "Send control commands to the init daemon.\n\n"
6398 " --help Show this help\n"
6399 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
6401 " 0 Power-off the machine\n"
6402 " 6 Reboot the machine\n"
6403 " 2, 3, 4, 5 Start runlevelX.target unit\n"
6404 " 1, s, S Enter rescue mode\n"
6405 " q, Q Reload init daemon configuration\n"
6406 " u, U Reexecute init daemon\n",
6407 program_invocation_short_name);
6410 static void runlevel_help(void) {
6411 printf("%s [OPTIONS...]\n\n"
6412 "Prints the previous and current runlevel of the init system.\n\n"
6413 " --help Show this help\n",
6414 program_invocation_short_name);
6417 static void help_types(void) {
6422 puts("Available unit types:");
6423 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
6424 t = unit_type_to_string(i);
6430 static int systemctl_parse_argv(int argc, char *argv[]) {
6439 ARG_IGNORE_DEPENDENCIES,
6451 ARG_NO_ASK_PASSWORD,
6461 static const struct option options[] = {
6462 { "help", no_argument, NULL, 'h' },
6463 { "version", no_argument, NULL, ARG_VERSION },
6464 { "type", required_argument, NULL, 't' },
6465 { "property", required_argument, NULL, 'p' },
6466 { "all", no_argument, NULL, 'a' },
6467 { "reverse", no_argument, NULL, ARG_REVERSE },
6468 { "after", no_argument, NULL, ARG_AFTER },
6469 { "before", no_argument, NULL, ARG_BEFORE },
6470 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
6471 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
6472 { "full", no_argument, NULL, 'l' },
6473 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
6474 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
6475 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
6476 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
6477 { "ignore-inhibitors", no_argument, NULL, 'i' },
6478 { "user", no_argument, NULL, ARG_USER },
6479 { "system", no_argument, NULL, ARG_SYSTEM },
6480 { "global", no_argument, NULL, ARG_GLOBAL },
6481 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
6482 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
6483 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
6484 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6485 { "quiet", no_argument, NULL, 'q' },
6486 { "root", required_argument, NULL, ARG_ROOT },
6487 { "force", no_argument, NULL, ARG_FORCE },
6488 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
6489 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
6490 { "signal", required_argument, NULL, 's' },
6491 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
6492 { "host", required_argument, NULL, 'H' },
6493 { "machine", required_argument, NULL, 'M' },
6494 { "runtime", no_argument, NULL, ARG_RUNTIME },
6495 { "lines", required_argument, NULL, 'n' },
6496 { "output", required_argument, NULL, 'o' },
6497 { "plain", no_argument, NULL, ARG_PLAIN },
6498 { "state", required_argument, NULL, ARG_STATE },
6499 { "recursive", no_argument, NULL, 'r' },
6500 { "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
6509 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
6518 puts(PACKAGE_STRING);
6519 puts(SYSTEMD_FEATURES);
6523 const char *word, *state;
6526 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6527 _cleanup_free_ char *type;
6529 type = strndup(word, size);
6533 if (streq(type, "help")) {
6538 if (unit_type_from_string(type) >= 0) {
6539 if (strv_push(&arg_types, type))
6545 /* It's much nicer to use --state= for
6546 * load states, but let's support this
6547 * in --types= too for compatibility
6548 * with old versions */
6549 if (unit_load_state_from_string(optarg) >= 0) {
6550 if (strv_push(&arg_states, type) < 0)
6556 log_error("Unknown unit type or load state '%s'.", type);
6557 log_info("Use -t help to see a list of allowed values.");
6565 /* Make sure that if the empty property list
6566 was specified, we won't show any properties. */
6567 if (isempty(optarg) && !arg_properties) {
6568 arg_properties = new0(char*, 1);
6569 if (!arg_properties)
6572 const char *word, *state;
6575 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6578 prop = strndup(word, size);
6582 if (strv_consume(&arg_properties, prop) < 0)
6587 /* If the user asked for a particular
6588 * property, show it to him, even if it is
6600 arg_dependency = DEPENDENCY_REVERSE;
6604 arg_dependency = DEPENDENCY_AFTER;
6608 arg_dependency = DEPENDENCY_BEFORE;
6611 case ARG_SHOW_TYPES:
6612 arg_show_types = true;
6616 arg_job_mode = optarg;
6620 arg_job_mode = "fail";
6623 case ARG_IRREVERSIBLE:
6624 arg_job_mode = "replace-irreversibly";
6627 case ARG_IGNORE_DEPENDENCIES:
6628 arg_job_mode = "ignore-dependencies";
6632 arg_scope = UNIT_FILE_USER;
6636 arg_scope = UNIT_FILE_SYSTEM;
6640 arg_scope = UNIT_FILE_GLOBAL;
6644 arg_no_block = true;
6648 arg_no_legend = true;
6652 arg_no_pager = true;
6668 if (strv_extend(&arg_states, "failed") < 0)
6686 arg_no_reload = true;
6690 arg_kill_who = optarg;
6694 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
6695 log_error("Failed to parse signal string %s.", optarg);
6700 case ARG_NO_ASK_PASSWORD:
6701 arg_ask_password = false;
6705 arg_transport = BUS_TRANSPORT_REMOTE;
6710 arg_transport = BUS_TRANSPORT_CONTAINER;
6719 if (safe_atou(optarg, &arg_lines) < 0) {
6720 log_error("Failed to parse lines '%s'", optarg);
6726 arg_output = output_mode_from_string(optarg);
6727 if (arg_output < 0) {
6728 log_error("Unknown output '%s'.", optarg);
6734 arg_ignore_inhibitors = true;
6742 const char *word, *state;
6745 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6748 s = strndup(word, size);
6752 if (strv_consume(&arg_states, s) < 0)
6759 if (geteuid() != 0) {
6760 log_error("--recursive requires root privileges.");
6764 arg_recursive = true;
6767 case ARG_PRESET_MODE:
6769 arg_preset_mode = unit_file_preset_mode_from_string(optarg);
6770 if (arg_preset_mode < 0) {
6771 log_error("Failed to parse preset mode: %s.", optarg);
6781 assert_not_reached("Unhandled option");
6784 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
6785 log_error("Cannot access user instance remotely.");
6792 static int halt_parse_argv(int argc, char *argv[]) {
6801 static const struct option options[] = {
6802 { "help", no_argument, NULL, ARG_HELP },
6803 { "halt", no_argument, NULL, ARG_HALT },
6804 { "poweroff", no_argument, NULL, 'p' },
6805 { "reboot", no_argument, NULL, ARG_REBOOT },
6806 { "force", no_argument, NULL, 'f' },
6807 { "wtmp-only", no_argument, NULL, 'w' },
6808 { "no-wtmp", no_argument, NULL, 'd' },
6809 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6818 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
6819 if (runlevel == '0' || runlevel == '6')
6822 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
6830 arg_action = ACTION_HALT;
6834 if (arg_action != ACTION_REBOOT)
6835 arg_action = ACTION_POWEROFF;
6839 arg_action = ACTION_REBOOT;
6861 /* Compatibility nops */
6868 assert_not_reached("Unhandled option");
6871 if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
6872 r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL);
6875 } else if (optind < argc) {
6876 log_error("Too many arguments.");
6883 static int parse_time_spec(const char *t, usec_t *_u) {
6887 if (streq(t, "now"))
6889 else if (!strchr(t, ':')) {
6892 if (safe_atou64(t, &u) < 0)
6895 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
6904 hour = strtol(t, &e, 10);
6905 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
6908 minute = strtol(e+1, &e, 10);
6909 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
6912 n = now(CLOCK_REALTIME);
6913 s = (time_t) (n / USEC_PER_SEC);
6915 assert_se(localtime_r(&s, &tm));
6917 tm.tm_hour = (int) hour;
6918 tm.tm_min = (int) minute;
6921 assert_se(s = mktime(&tm));
6923 *_u = (usec_t) s * USEC_PER_SEC;
6926 *_u += USEC_PER_DAY;
6932 static int shutdown_parse_argv(int argc, char *argv[]) {
6939 static const struct option options[] = {
6940 { "help", no_argument, NULL, ARG_HELP },
6941 { "halt", no_argument, NULL, 'H' },
6942 { "poweroff", no_argument, NULL, 'P' },
6943 { "reboot", no_argument, NULL, 'r' },
6944 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
6945 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6954 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0)
6962 arg_action = ACTION_HALT;
6966 arg_action = ACTION_POWEROFF;
6971 arg_action = ACTION_KEXEC;
6973 arg_action = ACTION_REBOOT;
6977 arg_action = ACTION_KEXEC;
6981 if (arg_action != ACTION_HALT)
6982 arg_action = ACTION_POWEROFF;
6995 /* Compatibility nops */
6999 arg_action = ACTION_CANCEL_SHUTDOWN;
7006 assert_not_reached("Unhandled option");
7009 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
7010 r = parse_time_spec(argv[optind], &arg_when);
7012 log_error("Failed to parse time specification: %s", argv[optind]);
7016 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
7018 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
7019 /* No time argument for shutdown cancel */
7020 arg_wall = argv + optind;
7021 else if (argc > optind + 1)
7022 /* We skip the time argument */
7023 arg_wall = argv + optind + 1;
7030 static int telinit_parse_argv(int argc, char *argv[]) {
7037 static const struct option options[] = {
7038 { "help", no_argument, NULL, ARG_HELP },
7039 { "no-wall", no_argument, NULL, ARG_NO_WALL },
7043 static const struct {
7047 { '0', ACTION_POWEROFF },
7048 { '6', ACTION_REBOOT },
7049 { '1', ACTION_RESCUE },
7050 { '2', ACTION_RUNLEVEL2 },
7051 { '3', ACTION_RUNLEVEL3 },
7052 { '4', ACTION_RUNLEVEL4 },
7053 { '5', ACTION_RUNLEVEL5 },
7054 { 's', ACTION_RESCUE },
7055 { 'S', ACTION_RESCUE },
7056 { 'q', ACTION_RELOAD },
7057 { 'Q', ACTION_RELOAD },
7058 { 'u', ACTION_REEXEC },
7059 { 'U', ACTION_REEXEC }
7068 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
7083 assert_not_reached("Unhandled option");
7086 if (optind >= argc) {
7087 log_error("%s: required argument missing.",
7088 program_invocation_short_name);
7092 if (optind + 1 < argc) {
7093 log_error("Too many arguments.");
7097 if (strlen(argv[optind]) != 1) {
7098 log_error("Expected single character argument.");
7102 for (i = 0; i < ELEMENTSOF(table); i++)
7103 if (table[i].from == argv[optind][0])
7106 if (i >= ELEMENTSOF(table)) {
7107 log_error("Unknown command '%s'.", argv[optind]);
7111 arg_action = table[i].to;
7118 static int runlevel_parse_argv(int argc, char *argv[]) {
7124 static const struct option options[] = {
7125 { "help", no_argument, NULL, ARG_HELP },
7134 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
7145 assert_not_reached("Unhandled option");
7148 if (optind < argc) {
7149 log_error("Too many arguments.");
7156 static int parse_argv(int argc, char *argv[]) {
7160 if (program_invocation_short_name) {
7162 if (strstr(program_invocation_short_name, "halt")) {
7163 arg_action = ACTION_HALT;
7164 return halt_parse_argv(argc, argv);
7165 } else if (strstr(program_invocation_short_name, "poweroff")) {
7166 arg_action = ACTION_POWEROFF;
7167 return halt_parse_argv(argc, argv);
7168 } else if (strstr(program_invocation_short_name, "reboot")) {
7170 arg_action = ACTION_KEXEC;
7172 arg_action = ACTION_REBOOT;
7173 return halt_parse_argv(argc, argv);
7174 } else if (strstr(program_invocation_short_name, "shutdown")) {
7175 arg_action = ACTION_POWEROFF;
7176 return shutdown_parse_argv(argc, argv);
7177 } else if (strstr(program_invocation_short_name, "init")) {
7179 if (sd_booted() > 0) {
7180 arg_action = _ACTION_INVALID;
7181 return telinit_parse_argv(argc, argv);
7183 /* Hmm, so some other init system is
7184 * running, we need to forward this
7185 * request to it. For now we simply
7186 * guess that it is Upstart. */
7188 execv(TELINIT, argv);
7190 log_error("Couldn't find an alternative telinit implementation to spawn.");
7194 } else if (strstr(program_invocation_short_name, "runlevel")) {
7195 arg_action = ACTION_RUNLEVEL;
7196 return runlevel_parse_argv(argc, argv);
7200 arg_action = ACTION_SYSTEMCTL;
7201 return systemctl_parse_argv(argc, argv);
7204 _pure_ static int action_to_runlevel(void) {
7206 static const char table[_ACTION_MAX] = {
7207 [ACTION_HALT] = '0',
7208 [ACTION_POWEROFF] = '0',
7209 [ACTION_REBOOT] = '6',
7210 [ACTION_RUNLEVEL2] = '2',
7211 [ACTION_RUNLEVEL3] = '3',
7212 [ACTION_RUNLEVEL4] = '4',
7213 [ACTION_RUNLEVEL5] = '5',
7214 [ACTION_RESCUE] = '1'
7217 assert(arg_action < _ACTION_MAX);
7219 return table[arg_action];
7222 static int talk_initctl(void) {
7224 struct init_request request = {
7225 .magic = INIT_MAGIC,
7227 .cmd = INIT_CMD_RUNLVL
7230 _cleanup_close_ int fd = -1;
7234 rl = action_to_runlevel();
7238 request.runlevel = rl;
7240 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
7242 if (errno == ENOENT)
7245 log_error_errno(errno, "Failed to open "INIT_FIFO": %m");
7250 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
7252 log_error_errno(errno, "Failed to write to "INIT_FIFO": %m");
7253 return errno > 0 ? -errno : -EIO;
7259 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
7261 static const struct {
7269 int (* const dispatch)(sd_bus *bus, char **args);
7275 { "list-units", MORE, 0, list_units },
7276 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
7277 { "list-sockets", MORE, 1, list_sockets },
7278 { "list-timers", MORE, 1, list_timers },
7279 { "list-jobs", MORE, 1, list_jobs },
7280 { "list-machines", MORE, 1, list_machines },
7281 { "clear-jobs", EQUAL, 1, daemon_reload },
7282 { "cancel", MORE, 2, cancel_job },
7283 { "start", MORE, 2, start_unit },
7284 { "stop", MORE, 2, start_unit },
7285 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
7286 { "reload", MORE, 2, start_unit },
7287 { "restart", MORE, 2, start_unit },
7288 { "try-restart", MORE, 2, start_unit },
7289 { "reload-or-restart", MORE, 2, start_unit },
7290 { "reload-or-try-restart", MORE, 2, start_unit },
7291 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
7292 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
7293 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
7294 { "isolate", EQUAL, 2, start_unit },
7295 { "kill", MORE, 2, kill_unit },
7296 { "is-active", MORE, 2, check_unit_active },
7297 { "check", MORE, 2, check_unit_active },
7298 { "is-failed", MORE, 2, check_unit_failed },
7299 { "show", MORE, 1, show },
7300 { "cat", MORE, 2, cat },
7301 { "status", MORE, 1, show },
7302 { "help", MORE, 2, show },
7303 { "snapshot", LESS, 2, snapshot },
7304 { "delete", MORE, 2, delete_snapshot },
7305 { "daemon-reload", EQUAL, 1, daemon_reload },
7306 { "daemon-reexec", EQUAL, 1, daemon_reload },
7307 { "show-environment", EQUAL, 1, show_environment },
7308 { "set-environment", MORE, 2, set_environment },
7309 { "unset-environment", MORE, 2, set_environment },
7310 { "import-environment", MORE, 1, import_environment},
7311 { "halt", EQUAL, 1, start_special, FORCE },
7312 { "poweroff", EQUAL, 1, start_special, FORCE },
7313 { "reboot", EQUAL, 1, start_special, FORCE },
7314 { "kexec", EQUAL, 1, start_special },
7315 { "suspend", EQUAL, 1, start_special },
7316 { "hibernate", EQUAL, 1, start_special },
7317 { "hybrid-sleep", EQUAL, 1, start_special },
7318 { "default", EQUAL, 1, start_special },
7319 { "rescue", EQUAL, 1, start_special },
7320 { "emergency", EQUAL, 1, start_special },
7321 { "exit", EQUAL, 1, start_special },
7322 { "reset-failed", MORE, 1, reset_failed },
7323 { "enable", MORE, 2, enable_unit, NOBUS },
7324 { "disable", MORE, 2, enable_unit, NOBUS },
7325 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
7326 { "reenable", MORE, 2, enable_unit, NOBUS },
7327 { "preset", MORE, 2, enable_unit, NOBUS },
7328 { "preset-all", EQUAL, 1, preset_all, NOBUS },
7329 { "mask", MORE, 2, enable_unit, NOBUS },
7330 { "unmask", MORE, 2, enable_unit, NOBUS },
7331 { "link", MORE, 2, enable_unit, NOBUS },
7332 { "switch-root", MORE, 2, switch_root },
7333 { "list-dependencies", LESS, 2, list_dependencies },
7334 { "set-default", EQUAL, 2, set_default, NOBUS },
7335 { "get-default", EQUAL, 1, get_default, NOBUS },
7336 { "set-property", MORE, 3, set_property },
7337 { "is-system-running", EQUAL, 1, is_system_running },
7338 { "add-wants", MORE, 3, add_dependency, NOBUS },
7339 { "add-requires", MORE, 3, add_dependency, NOBUS },
7340 { "edit", MORE, 2, edit, NOBUS },
7349 left = argc - optind;
7351 /* Special rule: no arguments (left == 0) means "list-units" */
7353 if (streq(argv[optind], "help") && !argv[optind+1]) {
7354 log_error("This command expects one or more "
7355 "unit names. Did you mean --help?");
7359 for (; verb->verb; verb++)
7360 if (streq(argv[optind], verb->verb))
7363 log_error("Unknown operation '%s'.", argv[optind]);
7368 switch (verb->argc_cmp) {
7371 if (left != verb->argc) {
7372 log_error("Invalid number of arguments.");
7379 if (left < verb->argc) {
7380 log_error("Too few arguments.");
7387 if (left > verb->argc) {
7388 log_error("Too many arguments.");
7395 assert_not_reached("Unknown comparison operator.");
7398 /* Require a bus connection for all operations but
7400 if (verb->bus == NOBUS) {
7401 if (!bus && !avoid_bus()) {
7402 log_error_errno(bus_error, "Failed to get D-Bus connection: %m");
7407 if (running_in_chroot() > 0) {
7408 log_info("Running in chroot, ignoring request.");
7412 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
7413 log_error_errno(bus_error, "Failed to get D-Bus connection: %m");
7418 return verb->dispatch(bus, argv + optind);
7421 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
7423 struct sd_shutdown_command c = {
7430 union sockaddr_union sockaddr = {
7431 .un.sun_family = AF_UNIX,
7432 .un.sun_path = "/run/systemd/shutdownd",
7435 struct iovec iovec[2] = {{
7436 .iov_base = (char*) &c,
7437 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
7440 struct msghdr msghdr = {
7441 .msg_name = &sockaddr,
7442 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
7443 + strlen("/run/systemd/shutdownd"),
7448 _cleanup_close_ int fd;
7450 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
7454 if (!isempty(message)) {
7455 iovec[1].iov_base = (char*) message;
7456 iovec[1].iov_len = strlen(message);
7457 msghdr.msg_iovlen++;
7460 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
7466 static int reload_with_fallback(sd_bus *bus) {
7469 /* First, try systemd via D-Bus. */
7470 if (daemon_reload(bus, NULL) >= 0)
7474 /* Nothing else worked, so let's try signals */
7475 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
7477 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0)
7478 return log_error_errno(errno, "kill() failed: %m");
7483 static int start_with_fallback(sd_bus *bus) {
7486 /* First, try systemd via D-Bus. */
7487 if (start_unit(bus, NULL) >= 0)
7491 /* Nothing else worked, so let's try
7493 if (talk_initctl() > 0)
7496 log_error("Failed to talk to init daemon.");
7500 warn_wall(arg_action);
7504 static int halt_now(enum action a) {
7506 /* The kernel will automaticall flush ATA disks and suchlike
7507 * on reboot(), but the file systems need to be synce'd
7508 * explicitly in advance. */
7511 /* Make sure C-A-D is handled by the kernel from this point
7513 reboot(RB_ENABLE_CAD);
7518 log_info("Halting.");
7519 reboot(RB_HALT_SYSTEM);
7522 case ACTION_POWEROFF:
7523 log_info("Powering off.");
7524 reboot(RB_POWER_OFF);
7527 case ACTION_REBOOT: {
7528 _cleanup_free_ char *param = NULL;
7530 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
7531 log_info("Rebooting with argument '%s'.", param);
7532 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
7533 LINUX_REBOOT_CMD_RESTART2, param);
7536 log_info("Rebooting.");
7537 reboot(RB_AUTOBOOT);
7542 assert_not_reached("Unknown action.");
7546 static int halt_main(sd_bus *bus) {
7549 r = check_inhibitors(bus, arg_action);
7553 if (geteuid() != 0) {
7554 /* Try logind if we are a normal user and no special
7555 * mode applies. Maybe PolicyKit allows us to shutdown
7558 if (arg_when <= 0 &&
7561 (arg_action == ACTION_POWEROFF ||
7562 arg_action == ACTION_REBOOT)) {
7563 r = reboot_with_logind(bus, arg_action);
7568 log_error("Must be root.");
7573 _cleanup_free_ char *m;
7575 m = strv_join(arg_wall, " ");
7579 r = send_shutdownd(arg_when,
7580 arg_action == ACTION_HALT ? 'H' :
7581 arg_action == ACTION_POWEROFF ? 'P' :
7582 arg_action == ACTION_KEXEC ? 'K' :
7589 log_warning_errno(r, "Failed to talk to shutdownd, proceeding with immediate shutdown: %m");
7591 char date[FORMAT_TIMESTAMP_MAX];
7593 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
7594 format_timestamp(date, sizeof(date), arg_when));
7599 if (!arg_dry && !arg_force)
7600 return start_with_fallback(bus);
7603 if (sd_booted() > 0)
7604 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7606 r = utmp_put_shutdown();
7608 log_warning_errno(r, "Failed to write utmp record: %m");
7615 r = halt_now(arg_action);
7616 log_error_errno(r, "Failed to reboot: %m");
7621 static int runlevel_main(void) {
7622 int r, runlevel, previous;
7624 r = utmp_get_runlevel(&runlevel, &previous);
7631 previous <= 0 ? 'N' : previous,
7632 runlevel <= 0 ? 'N' : runlevel);
7637 int main(int argc, char*argv[]) {
7638 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
7641 setlocale(LC_ALL, "");
7642 log_parse_environment();
7645 /* Explicitly not on_tty() to avoid setting cached value.
7646 * This becomes relevant for piping output which might be
7648 original_stdout_is_tty = isatty(STDOUT_FILENO);
7650 r = parse_argv(argc, argv);
7654 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
7655 * let's shortcut this */
7656 if (arg_action == ACTION_RUNLEVEL) {
7657 r = runlevel_main();
7661 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
7662 log_info("Running in chroot, ignoring request.");
7668 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
7670 /* systemctl_main() will print an error message for the bus
7671 * connection, but only if it needs to */
7673 switch (arg_action) {
7675 case ACTION_SYSTEMCTL:
7676 r = systemctl_main(bus, argc, argv, r);
7680 case ACTION_POWEROFF:
7686 case ACTION_RUNLEVEL2:
7687 case ACTION_RUNLEVEL3:
7688 case ACTION_RUNLEVEL4:
7689 case ACTION_RUNLEVEL5:
7691 case ACTION_EMERGENCY:
7692 case ACTION_DEFAULT:
7693 r = start_with_fallback(bus);
7698 r = reload_with_fallback(bus);
7701 case ACTION_CANCEL_SHUTDOWN: {
7702 _cleanup_free_ char *m = NULL;
7705 m = strv_join(arg_wall, " ");
7712 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
7714 log_warning_errno(r, "Failed to talk to shutdownd, shutdown hasn't been cancelled: %m");
7718 case ACTION_RUNLEVEL:
7719 case _ACTION_INVALID:
7721 assert_not_reached("Unknown action");
7726 ask_password_agent_close();
7727 polkit_agent_close();
7729 strv_free(arg_types);
7730 strv_free(arg_states);
7731 strv_free(arg_properties);
7733 return r < 0 ? EXIT_FAILURE : r;