1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Marc-Antoine Perennou
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/reboot.h>
24 #include <linux/reboot.h>
25 #include <sys/syscall.h>
32 #include <sys/ioctl.h>
36 #include <sys/socket.h>
39 #include <sys/prctl.h>
42 #include "sd-daemon.h"
43 #include "sd-shutdown.h"
50 #include "utmp-wtmp.h"
53 #include "path-util.h"
55 #include "cgroup-show.h"
56 #include "cgroup-util.h"
58 #include "path-lookup.h"
59 #include "conf-parser.h"
60 #include "exit-status.h"
62 #include "unit-name.h"
64 #include "spawn-ask-password-agent.h"
65 #include "spawn-polkit-agent.h"
67 #include "logs-show.h"
68 #include "socket-util.h"
73 #include "bus-message.h"
74 #include "bus-error.h"
75 #include "bus-common-errors.h"
78 static char **arg_types = NULL;
79 static char **arg_states = NULL;
80 static char **arg_properties = NULL;
81 static bool arg_all = false;
82 static enum dependency {
88 } arg_dependency = DEPENDENCY_FORWARD;
89 static const char *arg_job_mode = "replace";
90 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
91 static bool arg_no_block = false;
92 static bool arg_no_legend = false;
93 static bool arg_no_pager = false;
94 static bool arg_no_wtmp = false;
95 static bool arg_no_wall = false;
96 static bool arg_no_reload = false;
97 static bool arg_show_types = false;
98 static bool arg_ignore_inhibitors = false;
99 static bool arg_dry = false;
100 static bool arg_quiet = false;
101 static bool arg_full = false;
102 static bool arg_recursive = false;
103 static int arg_force = 0;
104 static bool arg_ask_password = true;
105 static bool arg_runtime = false;
106 static UnitFilePresetMode arg_preset_mode = UNIT_FILE_PRESET_FULL;
107 static char **arg_wall = NULL;
108 static const char *arg_kill_who = NULL;
109 static int arg_signal = SIGTERM;
110 static const char *arg_root = NULL;
111 static usec_t arg_when = 0;
133 ACTION_CANCEL_SHUTDOWN,
135 } arg_action = ACTION_SYSTEMCTL;
136 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
137 static char *arg_host = NULL;
138 static unsigned arg_lines = 10;
139 static OutputMode arg_output = OUTPUT_SHORT;
140 static bool arg_plain = false;
142 static bool original_stdout_is_tty;
144 static int daemon_reload(sd_bus *bus, char **args);
145 static int halt_now(enum action a);
146 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet);
148 static char** strv_skip_first(char **strv) {
149 if (strv_length(strv) > 0)
154 static void pager_open_if_enabled(void) {
162 static void ask_password_agent_open_if_enabled(void) {
164 /* Open the password agent as a child process if necessary */
166 if (!arg_ask_password)
169 if (arg_scope != UNIT_FILE_SYSTEM)
172 if (arg_transport != BUS_TRANSPORT_LOCAL)
175 ask_password_agent_open();
179 static void polkit_agent_open_if_enabled(void) {
181 /* Open the polkit agent as a child process if necessary */
183 if (!arg_ask_password)
186 if (arg_scope != UNIT_FILE_SYSTEM)
189 if (arg_transport != BUS_TRANSPORT_LOCAL)
196 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
199 if (!sd_bus_error_is_set(error))
202 if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) ||
203 sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
204 sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
205 sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
206 return EXIT_NOPERMISSION;
208 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
209 return EXIT_NOTINSTALLED;
211 if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
212 sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED))
213 return EXIT_NOTIMPLEMENTED;
215 if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
216 return EXIT_NOTCONFIGURED;
224 static void warn_wall(enum action a) {
225 static const char *table[_ACTION_MAX] = {
226 [ACTION_HALT] = "The system is going down for system halt NOW!",
227 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
228 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
229 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
230 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
231 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
232 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
239 _cleanup_free_ char *p;
241 p = strv_join(arg_wall, " ");
248 utmp_wall(p, NULL, NULL);
256 utmp_wall(table[a], NULL, NULL);
259 static bool avoid_bus(void) {
261 if (running_in_chroot() > 0)
264 if (sd_booted() <= 0)
267 if (!isempty(arg_root))
270 if (arg_scope == UNIT_FILE_GLOBAL)
276 static int compare_unit_info(const void *a, const void *b) {
277 const UnitInfo *u = a, *v = b;
281 /* First, order by machine */
282 if (!u->machine && v->machine)
284 if (u->machine && !v->machine)
286 if (u->machine && v->machine) {
287 r = strcasecmp(u->machine, v->machine);
292 /* Second, order by unit type */
293 d1 = strrchr(u->id, '.');
294 d2 = strrchr(v->id, '.');
296 r = strcasecmp(d1, d2);
301 /* Third, order by name */
302 return strcasecmp(u->id, v->id);
305 static bool output_show_unit(const UnitInfo *u, char **patterns) {
306 if (!strv_isempty(patterns)) {
309 STRV_FOREACH(pattern, patterns)
310 if (fnmatch(*pattern, u->id, FNM_NOESCAPE) == 0)
319 dot = strrchr(u->id, '.');
323 if (!strv_find(arg_types, dot+1))
333 if (streq(u->active_state, "inactive") || u->following[0])
339 static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
340 unsigned circle_len = 0, id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
342 unsigned n_shown = 0;
345 max_id_len = strlen("UNIT");
346 load_len = strlen("LOAD");
347 active_len = strlen("ACTIVE");
348 sub_len = strlen("SUB");
349 job_len = strlen("JOB");
352 for (u = unit_infos; u < unit_infos + c; u++) {
353 max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0));
354 load_len = MAX(load_len, strlen(u->load_state));
355 active_len = MAX(active_len, strlen(u->active_state));
356 sub_len = MAX(sub_len, strlen(u->sub_state));
358 if (u->job_id != 0) {
359 job_len = MAX(job_len, strlen(u->job_type));
363 if (!arg_no_legend &&
364 (streq(u->active_state, "failed") ||
365 STR_IN_SET(u->load_state, "error", "not-found", "masked")))
369 if (!arg_full && original_stdout_is_tty) {
372 id_len = MIN(max_id_len, 25u);
373 basic_len = circle_len + 5 + id_len + 5 + active_len + sub_len;
376 basic_len += job_len + 1;
378 if (basic_len < (unsigned) columns()) {
379 unsigned extra_len, incr;
380 extra_len = columns() - basic_len;
382 /* Either UNIT already got 25, or is fully satisfied.
383 * Grant up to 25 to DESC now. */
384 incr = MIN(extra_len, 25u);
388 /* split the remaining space between UNIT and DESC,
389 * but do not give UNIT more than it needs. */
391 incr = MIN(extra_len / 2, max_id_len - id_len);
393 desc_len += extra_len - incr;
399 for (u = unit_infos; u < unit_infos + c; u++) {
400 _cleanup_free_ char *e = NULL, *j = NULL;
401 const char *on_loaded = "", *off_loaded = "";
402 const char *on_active = "", *off_active = "";
403 const char *on_circle = "", *off_circle = "";
407 if (!n_shown && !arg_no_legend) {
412 printf("%-*s %-*s %-*s %-*s ",
415 active_len, "ACTIVE",
419 printf("%-*s ", job_len, "JOB");
421 if (!arg_full && arg_no_pager)
422 printf("%.*s\n", desc_len, "DESCRIPTION");
424 printf("%s\n", "DESCRIPTION");
429 if (STR_IN_SET(u->load_state, "error", "not-found", "masked")) {
430 on_loaded = ansi_highlight_red();
431 on_circle = ansi_highlight_yellow();
432 off_loaded = off_circle = ansi_highlight_off();
436 if (streq(u->active_state, "failed")) {
437 on_circle = on_active = ansi_highlight_red();
438 off_circle = off_active = ansi_highlight_off();
443 j = strjoin(u->machine, ":", u->id, NULL);
452 e = ellipsize(id, id_len, 33);
460 printf("%s%s%s ", on_circle, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_circle);
462 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
463 on_active, id_len, id, off_active,
464 on_loaded, load_len, u->load_state, off_loaded,
465 on_active, active_len, u->active_state,
466 sub_len, u->sub_state, off_active,
467 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
470 printf("%.*s\n", desc_len, u->description);
472 printf("%s\n", u->description);
475 if (!arg_no_legend) {
476 const char *on, *off;
480 "LOAD = Reflects whether the unit definition was properly loaded.\n"
481 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
482 "SUB = The low-level unit activation state, values depend on unit type.");
483 puts(job_count ? "JOB = Pending job for the unit.\n" : "");
484 on = ansi_highlight();
485 off = ansi_highlight_off();
487 on = ansi_highlight_red();
488 off = ansi_highlight_off();
492 printf("%s%u loaded units listed.%s\n"
493 "To show all installed unit files use 'systemctl list-unit-files'.\n",
496 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
497 "To show all installed unit files use 'systemctl list-unit-files'.\n",
504 static int get_unit_list(
508 UnitInfo **unit_infos,
510 sd_bus_message **_reply) {
512 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
513 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
514 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
523 r = sd_bus_message_new_method_call(
526 "org.freedesktop.systemd1",
527 "/org/freedesktop/systemd1",
528 "org.freedesktop.systemd1.Manager",
529 "ListUnitsFiltered");
532 return bus_log_create_error(r);
534 r = sd_bus_message_append_strv(m, arg_states);
536 return bus_log_create_error(r);
538 r = sd_bus_call(bus, m, 0, &error, &reply);
540 log_error("Failed to list units: %s", bus_error_message(&error, r));
544 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
546 return bus_log_parse_error(r);
548 while ((r = bus_parse_unit_info(reply, &u)) > 0) {
551 if (!output_show_unit(&u, patterns))
554 if (!GREEDY_REALLOC(*unit_infos, size, c+1))
557 (*unit_infos)[c++] = u;
560 return bus_log_parse_error(r);
562 r = sd_bus_message_exit_container(reply);
564 return bus_log_parse_error(r);
572 static void message_set_freep(Set **set) {
575 while ((m = set_steal_first(*set)))
576 sd_bus_message_unref(m);
581 static int get_unit_list_recursive(
584 UnitInfo **_unit_infos,
588 _cleanup_free_ UnitInfo *unit_infos = NULL;
589 _cleanup_(message_set_freep) Set *replies;
590 sd_bus_message *reply;
598 replies = set_new(NULL);
602 c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
606 r = set_put(replies, reply);
608 sd_bus_message_unref(reply);
613 _cleanup_strv_free_ char **machines = NULL;
616 r = sd_get_machine_names(&machines);
620 STRV_FOREACH(i, machines) {
621 _cleanup_bus_close_unref_ sd_bus *container = NULL;
624 r = sd_bus_open_system_container(&container, *i);
626 log_error_errno(r, "Failed to connect to container %s: %m", *i);
630 k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
636 r = set_put(replies, reply);
638 sd_bus_message_unref(reply);
643 *_machines = machines;
648 *_unit_infos = unit_infos;
657 static int list_units(sd_bus *bus, char **args) {
658 _cleanup_free_ UnitInfo *unit_infos = NULL;
659 _cleanup_(message_set_freep) Set *replies = NULL;
660 _cleanup_strv_free_ char **machines = NULL;
663 pager_open_if_enabled();
665 r = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
669 qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
670 return output_units_list(unit_infos, r);
673 static int get_triggered_units(
678 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
681 r = sd_bus_get_property_strv(
683 "org.freedesktop.systemd1",
685 "org.freedesktop.systemd1.Unit",
691 log_error("Failed to determine triggers: %s", bus_error_message(&error, r));
696 static int get_listening(
698 const char* unit_path,
701 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
702 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
703 const char *type, *path;
706 r = sd_bus_get_property(
708 "org.freedesktop.systemd1",
710 "org.freedesktop.systemd1.Socket",
716 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r));
720 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
722 return bus_log_parse_error(r);
724 while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
726 r = strv_extend(listening, type);
730 r = strv_extend(listening, path);
737 return bus_log_parse_error(r);
739 r = sd_bus_message_exit_container(reply);
741 return bus_log_parse_error(r);
753 /* Note: triggered is a list here, although it almost certainly
754 * will always be one unit. Nevertheless, dbus API allows for multiple
755 * values, so let's follow that. */
758 /* The strv above is shared. free is set only in the first one. */
762 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
768 if (!a->machine && b->machine)
770 if (a->machine && !b->machine)
772 if (a->machine && b->machine) {
773 o = strcasecmp(a->machine, b->machine);
778 o = strcmp(a->path, b->path);
780 o = strcmp(a->type, b->type);
785 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
786 struct socket_info *s;
787 unsigned pathlen = strlen("LISTEN"),
788 typelen = strlen("TYPE") * arg_show_types,
789 socklen = strlen("UNIT"),
790 servlen = strlen("ACTIVATES");
791 const char *on, *off;
793 for (s = socket_infos; s < socket_infos + cs; s++) {
797 socklen = MAX(socklen, strlen(s->id));
799 typelen = MAX(typelen, strlen(s->type));
800 pathlen = MAX(pathlen, strlen(s->path) + (s->machine ? strlen(s->machine)+1 : 0));
802 STRV_FOREACH(a, s->triggered)
803 tmp += strlen(*a) + 2*(a != s->triggered);
804 servlen = MAX(servlen, tmp);
809 printf("%-*s %-*.*s%-*s %s\n",
811 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
815 for (s = socket_infos; s < socket_infos + cs; s++) {
816 _cleanup_free_ char *j = NULL;
821 j = strjoin(s->machine, ":", s->path, NULL);
829 printf("%-*s %-*s %-*s",
830 pathlen, path, typelen, s->type, socklen, s->id);
833 pathlen, path, socklen, s->id);
834 STRV_FOREACH(a, s->triggered)
836 a == s->triggered ? "" : ",", *a);
840 on = ansi_highlight();
841 off = ansi_highlight_off();
845 on = ansi_highlight_red();
846 off = ansi_highlight_off();
849 if (!arg_no_legend) {
850 printf("%s%u sockets listed.%s\n", on, cs, off);
852 printf("Pass --all to see loaded but inactive sockets, too.\n");
858 static int list_sockets(sd_bus *bus, char **args) {
859 _cleanup_(message_set_freep) Set *replies = NULL;
860 _cleanup_strv_free_ char **machines = NULL;
861 _cleanup_free_ UnitInfo *unit_infos = NULL;
862 _cleanup_free_ struct socket_info *socket_infos = NULL;
864 struct socket_info *s;
869 pager_open_if_enabled();
871 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
875 for (u = unit_infos; u < unit_infos + n; u++) {
876 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
879 if (!endswith(u->id, ".socket"))
882 r = get_triggered_units(bus, u->unit_path, &triggered);
886 c = get_listening(bus, u->unit_path, &listening);
892 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
897 for (i = 0; i < c; i++)
898 socket_infos[cs + i] = (struct socket_info) {
899 .machine = u->machine,
901 .type = listening[i*2],
902 .path = listening[i*2 + 1],
903 .triggered = triggered,
904 .own_triggered = i==0,
907 /* from this point on we will cleanup those socket_infos */
910 listening = triggered = NULL; /* avoid cleanup */
913 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
914 (__compar_fn_t) socket_info_compare);
916 output_sockets_list(socket_infos, cs);
919 assert(cs == 0 || socket_infos);
920 for (s = socket_infos; s < socket_infos + cs; s++) {
923 if (s->own_triggered)
924 strv_free(s->triggered);
930 static int get_next_elapse(
933 dual_timestamp *next) {
935 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
943 r = sd_bus_get_property_trivial(
945 "org.freedesktop.systemd1",
947 "org.freedesktop.systemd1.Timer",
948 "NextElapseUSecMonotonic",
953 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
957 r = sd_bus_get_property_trivial(
959 "org.freedesktop.systemd1",
961 "org.freedesktop.systemd1.Timer",
962 "NextElapseUSecRealtime",
967 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
975 static int get_last_trigger(
980 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
987 r = sd_bus_get_property_trivial(
989 "org.freedesktop.systemd1",
991 "org.freedesktop.systemd1.Timer",
997 log_error("Failed to get last trigger time: %s", bus_error_message(&error, r));
1005 const char* machine;
1008 usec_t last_trigger;
1012 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
1018 if (!a->machine && b->machine)
1020 if (a->machine && !b->machine)
1022 if (a->machine && b->machine) {
1023 o = strcasecmp(a->machine, b->machine);
1028 if (a->next_elapse < b->next_elapse)
1030 if (a->next_elapse > b->next_elapse)
1033 return strcmp(a->id, b->id);
1036 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
1037 struct timer_info *t;
1039 nextlen = strlen("NEXT"),
1040 leftlen = strlen("LEFT"),
1041 lastlen = strlen("LAST"),
1042 passedlen = strlen("PASSED"),
1043 unitlen = strlen("UNIT"),
1044 activatelen = strlen("ACTIVATES");
1046 const char *on, *off;
1048 assert(timer_infos || n == 0);
1050 for (t = timer_infos; t < timer_infos + n; t++) {
1054 if (t->next_elapse > 0) {
1055 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1057 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
1058 nextlen = MAX(nextlen, strlen(tstamp) + 1);
1060 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
1061 leftlen = MAX(leftlen, strlen(trel));
1064 if (t->last_trigger > 0) {
1065 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1067 format_timestamp(tstamp, sizeof(tstamp), t->last_trigger);
1068 lastlen = MAX(lastlen, strlen(tstamp) + 1);
1070 format_timestamp_relative(trel, sizeof(trel), t->last_trigger);
1071 passedlen = MAX(passedlen, strlen(trel));
1074 unitlen = MAX(unitlen, strlen(t->id) + (t->machine ? strlen(t->machine)+1 : 0));
1076 STRV_FOREACH(a, t->triggered)
1077 ul += strlen(*a) + 2*(a != t->triggered);
1079 activatelen = MAX(activatelen, ul);
1084 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1088 passedlen, "PASSED",
1092 for (t = timer_infos; t < timer_infos + n; t++) {
1093 _cleanup_free_ char *j = NULL;
1095 char tstamp1[FORMAT_TIMESTAMP_MAX] = "n/a", trel1[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1096 char tstamp2[FORMAT_TIMESTAMP_MAX] = "n/a", trel2[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1099 format_timestamp(tstamp1, sizeof(tstamp1), t->next_elapse);
1100 format_timestamp_relative(trel1, sizeof(trel1), t->next_elapse);
1102 format_timestamp(tstamp2, sizeof(tstamp2), t->last_trigger);
1103 format_timestamp_relative(trel2, sizeof(trel2), t->last_trigger);
1106 j = strjoin(t->machine, ":", t->id, NULL);
1113 printf("%-*s %-*s %-*s %-*s %-*s",
1114 nextlen, tstamp1, leftlen, trel1, lastlen, tstamp2, passedlen, trel2, unitlen, unit);
1116 STRV_FOREACH(a, t->triggered)
1118 a == t->triggered ? "" : ",", *a);
1122 on = ansi_highlight();
1123 off = ansi_highlight_off();
1127 on = ansi_highlight_red();
1128 off = ansi_highlight_off();
1131 if (!arg_no_legend) {
1132 printf("%s%u timers listed.%s\n", on, n, off);
1134 printf("Pass --all to see loaded but inactive timers, too.\n");
1140 static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
1146 if (next->monotonic != USEC_INFINITY && next->monotonic > 0) {
1149 if (next->monotonic > nw->monotonic)
1150 converted = nw->realtime + (next->monotonic - nw->monotonic);
1152 converted = nw->realtime - (nw->monotonic - next->monotonic);
1154 if (next->realtime != USEC_INFINITY && next->realtime > 0)
1155 next_elapse = MIN(converted, next->realtime);
1157 next_elapse = converted;
1160 next_elapse = next->realtime;
1165 static int list_timers(sd_bus *bus, char **args) {
1166 _cleanup_(message_set_freep) Set *replies = NULL;
1167 _cleanup_strv_free_ char **machines = NULL;
1168 _cleanup_free_ struct timer_info *timer_infos = NULL;
1169 _cleanup_free_ UnitInfo *unit_infos = NULL;
1170 struct timer_info *t;
1177 pager_open_if_enabled();
1179 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
1183 dual_timestamp_get(&nw);
1185 for (u = unit_infos; u < unit_infos + n; u++) {
1186 _cleanup_strv_free_ char **triggered = NULL;
1187 dual_timestamp next = {};
1190 if (!endswith(u->id, ".timer"))
1193 r = get_triggered_units(bus, u->unit_path, &triggered);
1197 r = get_next_elapse(bus, u->unit_path, &next);
1201 get_last_trigger(bus, u->unit_path, &last);
1203 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
1208 m = calc_next_elapse(&nw, &next);
1210 timer_infos[c++] = (struct timer_info) {
1211 .machine = u->machine,
1214 .last_trigger = last,
1215 .triggered = triggered,
1218 triggered = NULL; /* avoid cleanup */
1221 qsort_safe(timer_infos, c, sizeof(struct timer_info),
1222 (__compar_fn_t) timer_info_compare);
1224 output_timers_list(timer_infos, c);
1227 for (t = timer_infos; t < timer_infos + c; t++)
1228 strv_free(t->triggered);
1233 static int compare_unit_file_list(const void *a, const void *b) {
1234 const char *d1, *d2;
1235 const UnitFileList *u = a, *v = b;
1237 d1 = strrchr(u->path, '.');
1238 d2 = strrchr(v->path, '.');
1243 r = strcasecmp(d1, d2);
1248 return strcasecmp(basename(u->path), basename(v->path));
1251 static bool output_show_unit_file(const UnitFileList *u, char **patterns) {
1252 if (!strv_isempty(patterns)) {
1255 STRV_FOREACH(pattern, patterns)
1256 if (fnmatch(*pattern, basename(u->path), FNM_NOESCAPE) == 0)
1262 if (!strv_isempty(arg_types)) {
1265 dot = strrchr(u->path, '.');
1269 if (!strv_find(arg_types, dot+1))
1273 if (!strv_isempty(arg_states)) {
1274 if (!strv_find(arg_states, unit_file_state_to_string(u->state)))
1281 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
1282 unsigned max_id_len, id_cols, state_cols;
1283 const UnitFileList *u;
1285 max_id_len = strlen("UNIT FILE");
1286 state_cols = strlen("STATE");
1288 for (u = units; u < units + c; u++) {
1289 max_id_len = MAX(max_id_len, strlen(basename(u->path)));
1290 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1294 unsigned basic_cols;
1296 id_cols = MIN(max_id_len, 25u);
1297 basic_cols = 1 + id_cols + state_cols;
1298 if (basic_cols < (unsigned) columns())
1299 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1301 id_cols = max_id_len;
1304 printf("%-*s %-*s\n",
1305 id_cols, "UNIT FILE",
1306 state_cols, "STATE");
1308 for (u = units; u < units + c; u++) {
1309 _cleanup_free_ char *e = NULL;
1310 const char *on, *off;
1313 if (u->state == UNIT_FILE_MASKED ||
1314 u->state == UNIT_FILE_MASKED_RUNTIME ||
1315 u->state == UNIT_FILE_DISABLED ||
1316 u->state == UNIT_FILE_INVALID) {
1317 on = ansi_highlight_red();
1318 off = ansi_highlight_off();
1319 } else if (u->state == UNIT_FILE_ENABLED) {
1320 on = ansi_highlight_green();
1321 off = ansi_highlight_off();
1325 id = basename(u->path);
1327 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1329 printf("%-*s %s%-*s%s\n",
1330 id_cols, e ? e : id,
1331 on, state_cols, unit_file_state_to_string(u->state), off);
1335 printf("\n%u unit files listed.\n", c);
1338 static int list_unit_files(sd_bus *bus, char **args) {
1339 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1340 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1341 _cleanup_free_ UnitFileList *units = NULL;
1349 pager_open_if_enabled();
1357 h = hashmap_new(&string_hash_ops);
1361 r = unit_file_get_list(arg_scope, arg_root, h);
1363 unit_file_list_free(h);
1364 log_error_errno(r, "Failed to get unit file list: %m");
1368 n_units = hashmap_size(h);
1370 units = new(UnitFileList, n_units);
1371 if (!units && n_units > 0) {
1372 unit_file_list_free(h);
1376 HASHMAP_FOREACH(u, h, i) {
1377 if (!output_show_unit_file(u, strv_skip_first(args)))
1384 assert(c <= n_units);
1387 r = sd_bus_call_method(
1389 "org.freedesktop.systemd1",
1390 "/org/freedesktop/systemd1",
1391 "org.freedesktop.systemd1.Manager",
1397 log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1401 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1403 return bus_log_parse_error(r);
1405 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1407 if (!GREEDY_REALLOC(units, size, c + 1))
1410 units[c] = (struct UnitFileList) {
1412 unit_file_state_from_string(state)
1415 if (output_show_unit_file(&units[c], strv_skip_first(args)))
1420 return bus_log_parse_error(r);
1422 r = sd_bus_message_exit_container(reply);
1424 return bus_log_parse_error(r);
1427 qsort_safe(units, c, sizeof(UnitFileList), compare_unit_file_list);
1428 output_unit_file_list(units, c);
1431 for (unit = units; unit < units + c; unit++)
1438 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1439 _cleanup_free_ char *n = NULL;
1440 size_t max_len = MAX(columns(),20u);
1446 for (i = level - 1; i >= 0; i--) {
1448 if (len > max_len - 3 && !arg_full) {
1449 printf("%s...\n",max_len % 2 ? "" : " ");
1452 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERTICAL : DRAW_TREE_SPACE));
1456 if (len > max_len - 3 && !arg_full) {
1457 printf("%s...\n",max_len % 2 ? "" : " ");
1461 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
1465 printf("%s\n", name);
1469 n = ellipsize(name, max_len-len, 100);
1477 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1479 static const char *dependencies[_DEPENDENCY_MAX] = {
1480 [DEPENDENCY_FORWARD] = "Requires\0"
1481 "RequiresOverridable\0"
1483 "RequisiteOverridable\0"
1486 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1487 "RequiredByOverridable\0"
1491 [DEPENDENCY_AFTER] = "After\0",
1492 [DEPENDENCY_BEFORE] = "Before\0",
1495 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1496 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1497 _cleanup_strv_free_ char **ret = NULL;
1498 _cleanup_free_ char *path = NULL;
1504 assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
1506 path = unit_dbus_path_from_name(name);
1510 r = sd_bus_call_method(
1512 "org.freedesktop.systemd1",
1514 "org.freedesktop.DBus.Properties",
1518 "s", "org.freedesktop.systemd1.Unit");
1520 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1524 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1526 return bus_log_parse_error(r);
1528 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1531 r = sd_bus_message_read(reply, "s", &prop);
1533 return bus_log_parse_error(r);
1535 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1536 r = sd_bus_message_skip(reply, "v");
1538 return bus_log_parse_error(r);
1541 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1543 return bus_log_parse_error(r);
1545 r = bus_message_read_strv_extend(reply, &ret);
1547 return bus_log_parse_error(r);
1549 r = sd_bus_message_exit_container(reply);
1551 return bus_log_parse_error(r);
1554 r = sd_bus_message_exit_container(reply);
1556 return bus_log_parse_error(r);
1560 return bus_log_parse_error(r);
1562 r = sd_bus_message_exit_container(reply);
1564 return bus_log_parse_error(r);
1572 static int list_dependencies_compare(const void *_a, const void *_b) {
1573 const char **a = (const char**) _a, **b = (const char**) _b;
1575 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1577 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1580 return strcasecmp(*a, *b);
1583 static int list_dependencies_one(
1588 unsigned int branches) {
1590 _cleanup_strv_free_ char **deps = NULL;
1598 r = strv_extend(units, name);
1602 r = list_dependencies_get_dependencies(bus, name, &deps);
1606 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1608 STRV_FOREACH(c, deps) {
1611 if (strv_contains(*units, *c)) {
1613 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1620 state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true);
1622 printf("%s%s%s ", ansi_highlight_green(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1624 printf("%s%s%s ", ansi_highlight_red(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1626 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1630 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1631 r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1638 strv_remove(*units, name);
1643 static int list_dependencies(sd_bus *bus, char **args) {
1644 _cleanup_strv_free_ char **units = NULL;
1645 _cleanup_free_ char *unit = NULL;
1651 unit = unit_name_mangle(args[1], MANGLE_NOGLOB);
1656 u = SPECIAL_DEFAULT_TARGET;
1658 pager_open_if_enabled();
1662 return list_dependencies_one(bus, u, 0, &units, 0);
1665 struct machine_info {
1669 char *control_group;
1670 uint32_t n_failed_units;
1675 static const struct bus_properties_map machine_info_property_map[] = {
1676 { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
1677 { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
1678 { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
1679 { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
1680 { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
1684 static void free_machines_list(struct machine_info *machine_infos, int n) {
1690 for (i = 0; i < n; i++) {
1691 free(machine_infos[i].name);
1692 free(machine_infos[i].state);
1693 free(machine_infos[i].control_group);
1696 free(machine_infos);
1699 static int compare_machine_info(const void *a, const void *b) {
1700 const struct machine_info *u = a, *v = b;
1702 if (u->is_host != v->is_host)
1703 return u->is_host > v->is_host ? -1 : 1;
1705 return strcasecmp(u->name, v->name);
1708 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1709 _cleanup_bus_close_unref_ sd_bus *container = NULL;
1715 r = sd_bus_open_system_container(&container, mi->name);
1722 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi);
1729 static bool output_show_machine(const char *name, char **patterns) {
1734 if (strv_isempty(patterns))
1737 STRV_FOREACH(i, patterns)
1738 if (fnmatch(*i, name, FNM_NOESCAPE) == 0)
1744 static int get_machine_list(
1746 struct machine_info **_machine_infos,
1749 struct machine_info *machine_infos = NULL;
1750 _cleanup_strv_free_ char **m = NULL;
1751 _cleanup_free_ char *hn = NULL;
1756 hn = gethostname_malloc();
1760 if (output_show_machine(hn, patterns)) {
1761 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1764 machine_infos[c].is_host = true;
1765 machine_infos[c].name = hn;
1768 get_machine_properties(bus, &machine_infos[c]);
1772 sd_get_machine_names(&m);
1773 STRV_FOREACH(i, m) {
1774 _cleanup_free_ char *class = NULL;
1776 if (!output_show_machine(*i, patterns))
1779 sd_machine_get_class(*i, &class);
1780 if (!streq_ptr(class, "container"))
1783 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1784 free_machines_list(machine_infos, c);
1788 machine_infos[c].is_host = false;
1789 machine_infos[c].name = strdup(*i);
1790 if (!machine_infos[c].name) {
1791 free_machines_list(machine_infos, c);
1795 get_machine_properties(NULL, &machine_infos[c]);
1799 *_machine_infos = machine_infos;
1803 static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1804 struct machine_info *m;
1807 namelen = sizeof("NAME") - 1,
1808 statelen = sizeof("STATE") - 1,
1809 failedlen = sizeof("FAILED") - 1,
1810 jobslen = sizeof("JOBS") - 1;
1812 assert(machine_infos || n == 0);
1814 for (m = machine_infos; m < machine_infos + n; m++) {
1815 namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
1816 statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
1817 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
1818 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
1820 if (!arg_no_legend && !streq_ptr(m->state, "running"))
1824 if (!arg_no_legend) {
1828 printf("%-*s %-*s %-*s %-*s\n",
1831 failedlen, "FAILED",
1835 for (m = machine_infos; m < machine_infos + n; m++) {
1836 const char *on_state = "", *off_state = "";
1837 const char *on_failed = "", *off_failed = "";
1838 bool circle = false;
1840 if (streq_ptr(m->state, "degraded")) {
1841 on_state = ansi_highlight_red();
1842 off_state = ansi_highlight_off();
1844 } else if (!streq_ptr(m->state, "running")) {
1845 on_state = ansi_highlight_yellow();
1846 off_state = ansi_highlight_off();
1850 if (m->n_failed_units > 0) {
1851 on_failed = ansi_highlight_red();
1852 off_failed = ansi_highlight_off();
1854 on_failed = off_failed = "";
1857 printf("%s%s%s ", on_state, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_state);
1860 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1861 (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
1862 on_state, statelen, strna(m->state), off_state,
1863 on_failed, failedlen, m->n_failed_units, off_failed,
1864 jobslen, m->n_jobs);
1866 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1867 namelen, strna(m->name),
1868 on_state, statelen, strna(m->state), off_state,
1869 on_failed, failedlen, m->n_failed_units, off_failed,
1870 jobslen, m->n_jobs);
1874 printf("\n%u machines listed.\n", n);
1877 static int list_machines(sd_bus *bus, char **args) {
1878 struct machine_info *machine_infos = NULL;
1883 if (geteuid() != 0) {
1884 log_error("Must be root.");
1888 pager_open_if_enabled();
1890 r = get_machine_list(bus, &machine_infos, strv_skip_first(args));
1894 qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
1895 output_machines_list(machine_infos, r);
1896 free_machines_list(machine_infos, r);
1901 static int get_default(sd_bus *bus, char **args) {
1902 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1903 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1904 _cleanup_free_ char *_path = NULL;
1908 if (!bus || avoid_bus()) {
1909 r = unit_file_get_default(arg_scope, arg_root, &_path);
1911 return log_error_errno(r, "Failed to get default target: %m");
1915 r = sd_bus_call_method(
1917 "org.freedesktop.systemd1",
1918 "/org/freedesktop/systemd1",
1919 "org.freedesktop.systemd1.Manager",
1925 log_error("Failed to get default target: %s", bus_error_message(&error, -r));
1929 r = sd_bus_message_read(reply, "s", &path);
1931 return bus_log_parse_error(r);
1935 printf("%s\n", path);
1940 static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) {
1943 assert(changes || n_changes == 0);
1945 for (i = 0; i < n_changes; i++) {
1946 if (changes[i].type == UNIT_FILE_SYMLINK)
1947 log_info("Created symlink from %s to %s.", changes[i].path, changes[i].source);
1949 log_info("Removed symlink %s.", changes[i].path);
1953 static int deserialize_and_dump_unit_file_changes(sd_bus_message *m) {
1954 const char *type, *path, *source;
1957 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1959 return bus_log_parse_error(r);
1961 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1963 if (streq(type, "symlink"))
1964 log_info("Created symlink from %s to %s.", path, source);
1966 log_info("Removed symlink %s.", path);
1970 return bus_log_parse_error(r);
1972 r = sd_bus_message_exit_container(m);
1974 return bus_log_parse_error(r);
1979 static int set_default(sd_bus *bus, char **args) {
1980 _cleanup_free_ char *unit = NULL;
1981 UnitFileChange *changes = NULL;
1982 unsigned n_changes = 0;
1985 unit = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
1989 if (!bus || avoid_bus()) {
1990 r = unit_file_set_default(arg_scope, arg_root, unit, true, &changes, &n_changes);
1992 return log_error_errno(r, "Failed to set default target: %m");
1995 dump_unit_file_changes(changes, n_changes);
1999 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
2000 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2002 r = sd_bus_message_new_method_call(
2005 "org.freedesktop.systemd1",
2006 "/org/freedesktop/systemd1",
2007 "org.freedesktop.systemd1.Manager",
2008 "SetDefaultTarget");
2010 return bus_log_create_error(r);
2012 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2014 return bus_log_create_error(r);
2016 r = sd_bus_message_append(m, "sb", unit, 1);
2018 return bus_log_create_error(r);
2020 r = sd_bus_call(bus, m, 0, &error, &reply);
2022 log_error("Failed to set default target: %s", bus_error_message(&error, -r));
2026 r = deserialize_and_dump_unit_file_changes(reply);
2030 /* Try to reload if enabled */
2032 r = daemon_reload(bus, args);
2037 unit_file_changes_free(changes, n_changes);
2044 const char *name, *type, *state;
2047 static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
2048 unsigned id_len, unit_len, type_len, state_len;
2049 const struct job_info *j;
2050 const char *on, *off;
2051 bool shorten = false;
2053 assert(n == 0 || jobs);
2056 on = ansi_highlight_green();
2057 off = ansi_highlight_off();
2059 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
2063 pager_open_if_enabled();
2065 id_len = strlen("JOB");
2066 unit_len = strlen("UNIT");
2067 type_len = strlen("TYPE");
2068 state_len = strlen("STATE");
2070 for (j = jobs; j < jobs + n; j++) {
2071 uint32_t id = j->id;
2072 assert(j->name && j->type && j->state);
2074 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
2075 unit_len = MAX(unit_len, strlen(j->name));
2076 type_len = MAX(type_len, strlen(j->type));
2077 state_len = MAX(state_len, strlen(j->state));
2080 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
2081 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
2086 printf("%*s %-*s %-*s %-*s\n",
2090 state_len, "STATE");
2092 for (j = jobs; j < jobs + n; j++) {
2093 _cleanup_free_ char *e = NULL;
2095 if (streq(j->state, "running")) {
2096 on = ansi_highlight();
2097 off = ansi_highlight_off();
2101 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
2102 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2104 on, unit_len, e ? e : j->name, off,
2106 on, state_len, j->state, off);
2109 if (!arg_no_legend) {
2110 on = ansi_highlight();
2111 off = ansi_highlight_off();
2113 printf("\n%s%u jobs listed%s.\n", on, n, off);
2117 static bool output_show_job(struct job_info *job, char **patterns) {
2122 if (strv_isempty(patterns))
2125 STRV_FOREACH(pattern, patterns)
2126 if (fnmatch(*pattern, job->name, FNM_NOESCAPE) == 0)
2131 static int list_jobs(sd_bus *bus, char **args) {
2132 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2133 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2134 const char *name, *type, *state, *job_path, *unit_path;
2135 _cleanup_free_ struct job_info *jobs = NULL;
2140 bool skipped = false;
2142 r = sd_bus_call_method(
2144 "org.freedesktop.systemd1",
2145 "/org/freedesktop/systemd1",
2146 "org.freedesktop.systemd1.Manager",
2152 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
2156 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2158 return bus_log_parse_error(r);
2160 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
2161 struct job_info job = { id, name, type, state };
2163 if (!output_show_job(&job, strv_skip_first(args))) {
2168 if (!GREEDY_REALLOC(jobs, size, c + 1))
2174 return bus_log_parse_error(r);
2176 r = sd_bus_message_exit_container(reply);
2178 return bus_log_parse_error(r);
2180 output_jobs_list(jobs, c, skipped);
2184 static int cancel_job(sd_bus *bus, char **args) {
2185 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2191 if (strv_length(args) <= 1)
2192 return daemon_reload(bus, args);
2194 STRV_FOREACH(name, args+1) {
2195 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2199 q = safe_atou32(*name, &id);
2201 return log_error_errno(q, "Failed to parse job id \"%s\": %m", *name);
2203 q = sd_bus_message_new_method_call(
2206 "org.freedesktop.systemd1",
2207 "/org/freedesktop/systemd1",
2208 "org.freedesktop.systemd1.Manager",
2211 return bus_log_create_error(q);
2213 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2215 return bus_log_create_error(1);
2217 q = sd_bus_message_append(m, "u", id);
2219 return bus_log_create_error(q);
2221 q = sd_bus_call(bus, m, 0, &error, NULL);
2223 log_error("Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, q));
2232 static int need_daemon_reload(sd_bus *bus, const char *unit) {
2233 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2237 /* We ignore all errors here, since this is used to show a
2240 /* We don't use unit_dbus_path_from_name() directly since we
2241 * don't want to load the unit if it isn't loaded. */
2243 r = sd_bus_call_method(
2245 "org.freedesktop.systemd1",
2246 "/org/freedesktop/systemd1",
2247 "org.freedesktop.systemd1.Manager",
2255 r = sd_bus_message_read(reply, "o", &path);
2259 r = sd_bus_get_property_trivial(
2261 "org.freedesktop.systemd1",
2263 "org.freedesktop.systemd1.Unit",
2273 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, "canceled"))
2384 log_error("Job for %s canceled.", strna(d->name));
2385 else if (streq(d->result, "timeout"))
2386 log_error("Job for %s timed out.", 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, "invalid"))
2390 log_error("Job for %s invalid.", strna(d->name));
2391 else if (streq(d->result, "assert"))
2392 log_error("Assertion failed on job for %s.", strna(d->name));
2393 else if (streq(d->result, "unsupported"))
2394 log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
2395 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
2399 quotes = chars_intersect(d->name, SHELL_NEED_QUOTES);
2401 log_error("Job for %s failed. See \"systemctl status %s%s%s\" and \"journalctl -xe\" for details.",
2403 quotes ? "'" : "", d->name, quotes ? "'" : "");
2405 log_error("Job failed. See \"journalctl -xe\" for details.");
2409 if (streq(d->result, "canceled"))
2411 else if (streq(d->result, "timeout"))
2413 else if (streq(d->result, "dependency"))
2415 else if (streq(d->result, "invalid"))
2417 else if (streq(d->result, "assert"))
2419 else if (streq(d->result, "unsupported"))
2421 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2427 static int wait_for_jobs(sd_bus *bus, Set *s) {
2428 _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
2429 WaitData d = { .set = s };
2435 q = sd_bus_add_filter(bus, &slot, wait_filter, &d);
2439 while (!set_isempty(s)) {
2440 q = bus_process_wait(bus);
2442 return log_error_errno(q, "Failed to wait for response: %m");
2445 q = check_wait_response(&d);
2446 /* Return the first error as it is most likely to be
2448 if (q < 0 && r == 0)
2450 log_debug("Got result %s/%s for job %s",
2451 strna(d.result), strerror(-q), strna(d.name));
2464 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2465 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2466 _cleanup_free_ char *n = NULL, *state = NULL;
2472 n = unit_name_mangle(name, MANGLE_NOGLOB);
2476 /* We don't use unit_dbus_path_from_name() directly since we
2477 * don't want to load the unit if it isn't loaded. */
2479 r = sd_bus_call_method(
2481 "org.freedesktop.systemd1",
2482 "/org/freedesktop/systemd1",
2483 "org.freedesktop.systemd1.Manager",
2494 r = sd_bus_message_read(reply, "o", &path);
2496 return bus_log_parse_error(r);
2498 r = sd_bus_get_property_string(
2500 "org.freedesktop.systemd1",
2502 "org.freedesktop.systemd1.Unit",
2515 return nulstr_contains(good_states, state);
2518 static int check_triggering_units(
2522 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2523 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2524 _cleanup_strv_free_ char **triggered_by = NULL;
2525 bool print_warning_label = true;
2529 n = unit_name_mangle(name, MANGLE_NOGLOB);
2533 path = unit_dbus_path_from_name(n);
2537 r = sd_bus_get_property_string(
2539 "org.freedesktop.systemd1",
2541 "org.freedesktop.systemd1.Unit",
2546 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2550 if (streq(state, "masked"))
2553 r = sd_bus_get_property_strv(
2555 "org.freedesktop.systemd1",
2557 "org.freedesktop.systemd1.Unit",
2562 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2566 STRV_FOREACH(i, triggered_by) {
2567 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2569 return log_error_errno(r, "Failed to check unit: %m");
2574 if (print_warning_label) {
2575 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2576 print_warning_label = false;
2579 log_warning(" %s", *i);
2585 static const struct {
2588 } unit_actions[] = {
2589 { "start", "StartUnit" },
2590 { "stop", "StopUnit" },
2591 { "condstop", "StopUnit" },
2592 { "reload", "ReloadUnit" },
2593 { "restart", "RestartUnit" },
2594 { "try-restart", "TryRestartUnit" },
2595 { "condrestart", "TryRestartUnit" },
2596 { "reload-or-restart", "ReloadOrRestartUnit" },
2597 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2598 { "condreload", "ReloadOrTryRestartUnit" },
2599 { "force-reload", "ReloadOrTryRestartUnit" }
2602 static const char *verb_to_method(const char *verb) {
2605 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2606 if (streq_ptr(unit_actions[i].verb, verb))
2607 return unit_actions[i].method;
2612 static const char *method_to_verb(const char *method) {
2615 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2616 if (streq_ptr(unit_actions[i].method, method))
2617 return unit_actions[i].verb;
2622 static int start_unit_one(
2627 sd_bus_error *error,
2630 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
2639 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2641 r = sd_bus_message_new_method_call(
2644 "org.freedesktop.systemd1",
2645 "/org/freedesktop/systemd1",
2646 "org.freedesktop.systemd1.Manager",
2649 return bus_log_create_error(r);
2651 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
2653 return bus_log_create_error(r);
2655 r = sd_bus_message_append(m, "ss", name, mode);
2657 return bus_log_create_error(r);
2659 r = sd_bus_call(bus, m, 0, error, &reply);
2663 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2664 /* There's always a fallback possible for
2665 * legacy actions. */
2666 return -EADDRNOTAVAIL;
2668 verb = method_to_verb(method);
2670 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2674 r = sd_bus_message_read(reply, "o", &path);
2676 return bus_log_parse_error(r);
2678 if (need_daemon_reload(bus, name) > 0)
2679 log_warning("Warning: Unit file of %s changed on disk, 'systemctl%s daemon-reload' recommended.",
2680 name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2689 log_debug("Adding %s to the set", p);
2690 r = set_consume(s, p);
2698 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2700 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2704 STRV_FOREACH(name, names) {
2708 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2710 t = unit_name_mangle(*name, MANGLE_GLOB);
2714 if (string_is_glob(t))
2715 r = strv_consume(&globs, t);
2717 r = strv_consume(&mangled, t);
2722 /* Query the manager only if any of the names are a glob, since
2723 * this is fairly expensive */
2724 if (!strv_isempty(globs)) {
2725 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2726 _cleanup_free_ UnitInfo *unit_infos = NULL;
2728 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2732 for (i = 0; i < r; i++)
2733 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2738 mangled = NULL; /* do not free */
2743 static const struct {
2747 } action_table[_ACTION_MAX] = {
2748 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2749 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2750 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2751 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2752 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
2753 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
2754 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
2755 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
2756 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2757 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2758 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2759 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2760 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2761 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2762 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2765 static enum action verb_to_action(const char *verb) {
2768 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2769 if (streq_ptr(action_table[i].verb, verb))
2772 return _ACTION_INVALID;
2775 static int start_unit(sd_bus *bus, char **args) {
2776 _cleanup_set_free_free_ Set *s = NULL;
2777 _cleanup_strv_free_ char **names = NULL;
2778 const char *method, *mode, *one_name, *suffix = NULL;
2784 ask_password_agent_open_if_enabled();
2786 if (arg_action == ACTION_SYSTEMCTL) {
2788 method = verb_to_method(args[0]);
2789 action = verb_to_action(args[0]);
2791 if (streq(args[0], "isolate")) {
2795 mode = action_table[action].mode ?: arg_job_mode;
2797 one_name = action_table[action].target;
2799 assert(arg_action < ELEMENTSOF(action_table));
2800 assert(action_table[arg_action].target);
2802 method = "StartUnit";
2804 mode = action_table[arg_action].mode;
2805 one_name = action_table[arg_action].target;
2809 names = strv_new(one_name, NULL);
2811 r = expand_names(bus, args + 1, suffix, &names);
2813 log_error_errno(r, "Failed to expand names: %m");
2816 if (!arg_no_block) {
2817 r = enable_wait_for_jobs(bus);
2819 return log_error_errno(r, "Could not watch jobs: %m");
2821 s = set_new(&string_hash_ops);
2826 STRV_FOREACH(name, names) {
2827 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2830 q = start_unit_one(bus, method, *name, mode, &error, s);
2831 if (r >= 0 && q < 0)
2832 r = translate_bus_error_to_exit_status(q, &error);
2835 if (!arg_no_block) {
2838 q = wait_for_jobs(bus, s);
2842 /* When stopping units, warn if they can still be triggered by
2843 * another active unit (socket, path, timer) */
2844 if (!arg_quiet && streq(method, "StopUnit"))
2845 STRV_FOREACH(name, names)
2846 check_triggering_units(bus, *name);
2852 /* Ask systemd-logind, which might grant access to unprivileged users
2853 * through PolicyKit */
2854 static int reboot_with_logind(sd_bus *bus, enum action a) {
2856 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2863 polkit_agent_open_if_enabled();
2871 case ACTION_POWEROFF:
2872 method = "PowerOff";
2875 case ACTION_SUSPEND:
2879 case ACTION_HIBERNATE:
2880 method = "Hibernate";
2883 case ACTION_HYBRID_SLEEP:
2884 method = "HybridSleep";
2891 r = sd_bus_call_method(
2893 "org.freedesktop.login1",
2894 "/org/freedesktop/login1",
2895 "org.freedesktop.login1.Manager",
2899 "b", arg_ask_password);
2901 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2909 static int check_inhibitors(sd_bus *bus, enum action a) {
2911 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2912 _cleanup_strv_free_ char **sessions = NULL;
2913 const char *what, *who, *why, *mode;
2922 if (arg_ignore_inhibitors || arg_force > 0)
2934 r = sd_bus_call_method(
2936 "org.freedesktop.login1",
2937 "/org/freedesktop/login1",
2938 "org.freedesktop.login1.Manager",
2944 /* If logind is not around, then there are no inhibitors... */
2947 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2949 return bus_log_parse_error(r);
2951 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2952 _cleanup_free_ char *comm = NULL, *user = NULL;
2953 _cleanup_strv_free_ char **sv = NULL;
2955 if (!streq(mode, "block"))
2958 sv = strv_split(what, ":");
2962 if (!strv_contains(sv,
2964 a == ACTION_POWEROFF ||
2965 a == ACTION_REBOOT ||
2966 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2969 get_process_comm(pid, &comm);
2970 user = uid_to_name(uid);
2972 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
2973 who, pid, strna(comm), strna(user), why);
2978 return bus_log_parse_error(r);
2980 r = sd_bus_message_exit_container(reply);
2982 return bus_log_parse_error(r);
2984 /* Check for current sessions */
2985 sd_get_sessions(&sessions);
2986 STRV_FOREACH(s, sessions) {
2987 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2989 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2992 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2995 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2998 sd_session_get_tty(*s, &tty);
2999 sd_session_get_seat(*s, &seat);
3000 sd_session_get_service(*s, &service);
3001 user = uid_to_name(uid);
3003 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
3010 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
3011 action_table[a].verb);
3019 static int start_special(sd_bus *bus, char **args) {
3025 a = verb_to_action(args[0]);
3027 r = check_inhibitors(bus, a);
3031 if (arg_force >= 2 && geteuid() != 0) {
3032 log_error("Must be root.");
3036 if (arg_force >= 2 &&
3037 (a == ACTION_HALT ||
3038 a == ACTION_POWEROFF ||
3039 a == ACTION_REBOOT))
3042 if (arg_force >= 1 &&
3043 (a == ACTION_HALT ||
3044 a == ACTION_POWEROFF ||
3045 a == ACTION_REBOOT ||
3046 a == ACTION_KEXEC ||
3048 return daemon_reload(bus, args);
3050 /* first try logind, to allow authentication with polkit */
3051 if (geteuid() != 0 &&
3052 (a == ACTION_POWEROFF ||
3053 a == ACTION_REBOOT ||
3054 a == ACTION_SUSPEND ||
3055 a == ACTION_HIBERNATE ||
3056 a == ACTION_HYBRID_SLEEP)) {
3057 r = reboot_with_logind(bus, a);
3062 r = start_unit(bus, args);
3063 if (r == EXIT_SUCCESS)
3069 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
3070 _cleanup_strv_free_ char **names = NULL;
3077 r = expand_names(bus, args, NULL, &names);
3079 return log_error_errno(r, "Failed to expand names: %m");
3081 STRV_FOREACH(name, names) {
3084 state = check_one_unit(bus, *name, good_states, arg_quiet);
3094 static int check_unit_active(sd_bus *bus, char **args) {
3095 /* According to LSB: 3, "program is not running" */
3096 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
3099 static int check_unit_failed(sd_bus *bus, char **args) {
3100 return check_unit_generic(bus, 1, "failed\0", args + 1);
3103 static int kill_unit(sd_bus *bus, char **args) {
3104 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3105 _cleanup_strv_free_ char **names = NULL;
3113 arg_kill_who = "all";
3115 r = expand_names(bus, args + 1, NULL, &names);
3117 log_error_errno(r, "Failed to expand names: %m");
3119 STRV_FOREACH(name, names) {
3120 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
3122 q = sd_bus_message_new_method_call(
3125 "org.freedesktop.systemd1",
3126 "/org/freedesktop/systemd1",
3127 "org.freedesktop.systemd1.Manager",
3130 return bus_log_create_error(q);
3132 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
3134 return bus_log_create_error(q);
3136 q = sd_bus_message_append(m, "ssi", *names, arg_kill_who, arg_signal);
3138 return bus_log_create_error(q);
3140 q = sd_bus_call(bus, m, 0, &error, NULL);
3142 log_error("Failed to kill unit %s: %s", *names, bus_error_message(&error, q));
3151 typedef struct ExecStatusInfo {
3159 usec_t start_timestamp;
3160 usec_t exit_timestamp;
3165 LIST_FIELDS(struct ExecStatusInfo, exec);
3168 static void exec_status_info_free(ExecStatusInfo *i) {
3177 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3178 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3181 int32_t code, status;
3187 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3189 return bus_log_parse_error(r);
3193 r = sd_bus_message_read(m, "s", &path);
3195 return bus_log_parse_error(r);
3197 i->path = strdup(path);
3201 r = sd_bus_message_read_strv(m, &i->argv);
3203 return bus_log_parse_error(r);
3205 r = sd_bus_message_read(m,
3208 &start_timestamp, &start_timestamp_monotonic,
3209 &exit_timestamp, &exit_timestamp_monotonic,
3213 return bus_log_parse_error(r);
3216 i->start_timestamp = (usec_t) start_timestamp;
3217 i->exit_timestamp = (usec_t) exit_timestamp;
3218 i->pid = (pid_t) pid;
3222 r = sd_bus_message_exit_container(m);
3224 return bus_log_parse_error(r);
3229 typedef struct UnitStatusInfo {
3231 const char *load_state;
3232 const char *active_state;
3233 const char *sub_state;
3234 const char *unit_file_state;
3235 const char *unit_file_preset;
3237 const char *description;
3238 const char *following;
3240 char **documentation;
3242 const char *fragment_path;
3243 const char *source_path;
3244 const char *control_group;
3246 char **dropin_paths;
3248 const char *load_error;
3251 usec_t inactive_exit_timestamp;
3252 usec_t inactive_exit_timestamp_monotonic;
3253 usec_t active_enter_timestamp;
3254 usec_t active_exit_timestamp;
3255 usec_t inactive_enter_timestamp;
3257 bool need_daemon_reload;
3262 const char *status_text;
3263 const char *pid_file;
3267 usec_t start_timestamp;
3268 usec_t exit_timestamp;
3270 int exit_code, exit_status;
3272 usec_t condition_timestamp;
3273 bool condition_result;
3274 bool failed_condition_trigger;
3275 bool failed_condition_negate;
3276 const char *failed_condition;
3277 const char *failed_condition_parameter;
3279 usec_t assert_timestamp;
3281 bool failed_assert_trigger;
3282 bool failed_assert_negate;
3283 const char *failed_assert;
3284 const char *failed_assert_parameter;
3287 unsigned n_accepted;
3288 unsigned n_connections;
3291 /* Pairs of type, path */
3295 const char *sysfs_path;
3297 /* Mount, Automount */
3303 LIST_HEAD(ExecStatusInfo, exec);
3306 static void print_status_info(
3311 const char *active_on, *active_off, *on, *off, *ss;
3313 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3314 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3317 arg_all * OUTPUT_SHOW_ALL |
3318 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
3319 on_tty() * OUTPUT_COLOR |
3320 !arg_quiet * OUTPUT_WARN_CUTOFF |
3321 arg_full * OUTPUT_FULL_WIDTH;
3326 /* This shows pretty information about a unit. See
3327 * print_property() for a low-level property printer */
3329 if (streq_ptr(i->active_state, "failed")) {
3330 active_on = ansi_highlight_red();
3331 active_off = ansi_highlight_off();
3332 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3333 active_on = ansi_highlight_green();
3334 active_off = ansi_highlight_off();
3336 active_on = active_off = "";
3338 printf("%s%s%s %s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3340 if (i->description && !streq_ptr(i->id, i->description))
3341 printf(" - %s", i->description);
3346 printf(" Follow: unit currently follows state of %s\n", i->following);
3348 if (streq_ptr(i->load_state, "error")) {
3349 on = ansi_highlight_red();
3350 off = ansi_highlight_off();
3354 path = i->source_path ? i->source_path : i->fragment_path;
3357 printf(" Loaded: %s%s%s (Reason: %s)\n",
3358 on, strna(i->load_state), off, i->load_error);
3359 else if (path && !isempty(i->unit_file_state) && !isempty(i->unit_file_preset))
3360 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3361 on, strna(i->load_state), off, path, i->unit_file_state, i->unit_file_preset);
3362 else if (path && !isempty(i->unit_file_state))
3363 printf(" Loaded: %s%s%s (%s; %s)\n",
3364 on, strna(i->load_state), off, path, i->unit_file_state);
3366 printf(" Loaded: %s%s%s (%s)\n",
3367 on, strna(i->load_state), off, path);
3369 printf(" Loaded: %s%s%s\n",
3370 on, strna(i->load_state), off);
3372 if (!strv_isempty(i->dropin_paths)) {
3373 _cleanup_free_ char *dir = NULL;
3377 STRV_FOREACH(dropin, i->dropin_paths) {
3378 if (! dir || last) {
3379 printf(dir ? " " : " Drop-In: ");
3384 if (path_get_parent(*dropin, &dir) < 0) {
3389 printf("%s\n %s", dir,
3390 draw_special_char(DRAW_TREE_RIGHT));
3393 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3395 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3399 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3401 printf(" Active: %s%s (%s)%s",
3402 active_on, strna(i->active_state), ss, active_off);
3404 printf(" Active: %s%s%s",
3405 active_on, strna(i->active_state), active_off);
3407 if (!isempty(i->result) && !streq(i->result, "success"))
3408 printf(" (Result: %s)", i->result);
3410 timestamp = (streq_ptr(i->active_state, "active") ||
3411 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
3412 (streq_ptr(i->active_state, "inactive") ||
3413 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
3414 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
3415 i->active_exit_timestamp;
3417 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3418 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3421 printf(" since %s; %s\n", s2, s1);
3423 printf(" since %s\n", s2);
3427 if (!i->condition_result && i->condition_timestamp > 0) {
3428 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3429 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3431 printf("Condition: start %scondition failed%s at %s%s%s\n",
3432 ansi_highlight_yellow(), ansi_highlight_off(),
3433 s2, s1 ? "; " : "", s1 ? s1 : "");
3434 if (i->failed_condition_trigger)
3435 printf(" none of the trigger conditions were met\n");
3436 else if (i->failed_condition)
3437 printf(" %s=%s%s was not met\n",
3438 i->failed_condition,
3439 i->failed_condition_negate ? "!" : "",
3440 i->failed_condition_parameter);
3443 if (!i->assert_result && i->assert_timestamp > 0) {
3444 s1 = format_timestamp_relative(since1, sizeof(since1), i->assert_timestamp);
3445 s2 = format_timestamp(since2, sizeof(since2), i->assert_timestamp);
3447 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3448 ansi_highlight_red(), ansi_highlight_off(),
3449 s2, s1 ? "; " : "", s1 ? s1 : "");
3450 if (i->failed_assert_trigger)
3451 printf(" none of the trigger assertions were met\n");
3452 else if (i->failed_assert)
3453 printf(" %s=%s%s was not met\n",
3455 i->failed_assert_negate ? "!" : "",
3456 i->failed_assert_parameter);
3460 printf(" Device: %s\n", i->sysfs_path);
3462 printf(" Where: %s\n", i->where);
3464 printf(" What: %s\n", i->what);
3466 STRV_FOREACH(t, i->documentation)
3467 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3469 STRV_FOREACH_PAIR(t, t2, i->listen)
3470 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3473 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3475 LIST_FOREACH(exec, p, i->exec) {
3476 _cleanup_free_ char *argv = NULL;
3479 /* Only show exited processes here */
3483 argv = strv_join(p->argv, " ");
3484 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
3486 good = is_clean_exit_lsb(p->code, p->status, NULL);
3488 on = ansi_highlight_red();
3489 off = ansi_highlight_off();
3493 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3495 if (p->code == CLD_EXITED) {
3498 printf("status=%i", p->status);
3500 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3505 printf("signal=%s", signal_to_string(p->status));
3507 printf(")%s\n", off);
3509 if (i->main_pid == p->pid &&
3510 i->start_timestamp == p->start_timestamp &&
3511 i->exit_timestamp == p->start_timestamp)
3512 /* Let's not show this twice */
3515 if (p->pid == i->control_pid)
3519 if (i->main_pid > 0 || i->control_pid > 0) {
3520 if (i->main_pid > 0) {
3521 printf(" Main PID: "PID_FMT, i->main_pid);
3524 _cleanup_free_ char *comm = NULL;
3525 get_process_comm(i->main_pid, &comm);
3527 printf(" (%s)", comm);
3528 } else if (i->exit_code > 0) {
3529 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3531 if (i->exit_code == CLD_EXITED) {
3534 printf("status=%i", i->exit_status);
3536 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3541 printf("signal=%s", signal_to_string(i->exit_status));
3545 if (i->control_pid > 0)
3549 if (i->control_pid > 0) {
3550 _cleanup_free_ char *c = NULL;
3552 printf(" %8s: "PID_FMT, i->main_pid ? "" : " Control", i->control_pid);
3554 get_process_comm(i->control_pid, &c);
3563 printf(" Status: \"%s\"\n", i->status_text);
3564 if (i->status_errno > 0)
3565 printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
3567 if (i->control_group &&
3568 (i->main_pid > 0 || i->control_pid > 0 ||
3569 ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_CONTAINER) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3572 printf(" CGroup: %s\n", i->control_group);
3574 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
3577 static const char prefix[] = " ";
3580 if (c > sizeof(prefix) - 1)
3581 c -= sizeof(prefix) - 1;
3585 if (i->main_pid > 0)
3586 extra[k++] = i->main_pid;
3588 if (i->control_pid > 0)
3589 extra[k++] = i->control_pid;
3591 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, flags);
3595 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3596 show_journal_by_unit(stdout,
3600 i->inactive_exit_timestamp_monotonic,
3603 flags | OUTPUT_BEGIN_NEWLINE,
3604 arg_scope == UNIT_FILE_SYSTEM,
3608 if (i->need_daemon_reload)
3609 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
3610 ansi_highlight_red(),
3611 ansi_highlight_off(),
3612 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
3615 static void show_unit_help(UnitStatusInfo *i) {
3620 if (!i->documentation) {
3621 log_info("Documentation for %s not known.", i->id);
3625 STRV_FOREACH(p, i->documentation)
3626 if (startswith(*p, "man:"))
3627 show_man_page(*p + 4, false);
3629 log_info("Can't show: %s", *p);
3632 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3639 switch (contents[0]) {
3641 case SD_BUS_TYPE_STRING: {
3644 r = sd_bus_message_read(m, "s", &s);
3646 return bus_log_parse_error(r);
3649 if (streq(name, "Id"))
3651 else if (streq(name, "LoadState"))
3653 else if (streq(name, "ActiveState"))
3654 i->active_state = s;
3655 else if (streq(name, "SubState"))
3657 else if (streq(name, "Description"))
3659 else if (streq(name, "FragmentPath"))
3660 i->fragment_path = s;
3661 else if (streq(name, "SourcePath"))
3664 else if (streq(name, "DefaultControlGroup")) {
3666 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3668 i->control_group = e;
3671 else if (streq(name, "ControlGroup"))
3672 i->control_group = s;
3673 else if (streq(name, "StatusText"))
3675 else if (streq(name, "PIDFile"))
3677 else if (streq(name, "SysFSPath"))
3679 else if (streq(name, "Where"))
3681 else if (streq(name, "What"))
3683 else if (streq(name, "Following"))
3685 else if (streq(name, "UnitFileState"))
3686 i->unit_file_state = s;
3687 else if (streq(name, "UnitFilePreset"))
3688 i->unit_file_preset = s;
3689 else if (streq(name, "Result"))
3696 case SD_BUS_TYPE_BOOLEAN: {
3699 r = sd_bus_message_read(m, "b", &b);
3701 return bus_log_parse_error(r);
3703 if (streq(name, "Accept"))
3705 else if (streq(name, "NeedDaemonReload"))
3706 i->need_daemon_reload = b;
3707 else if (streq(name, "ConditionResult"))
3708 i->condition_result = b;
3709 else if (streq(name, "AssertResult"))
3710 i->assert_result = b;
3715 case SD_BUS_TYPE_UINT32: {
3718 r = sd_bus_message_read(m, "u", &u);
3720 return bus_log_parse_error(r);
3722 if (streq(name, "MainPID")) {
3724 i->main_pid = (pid_t) u;
3727 } else if (streq(name, "ControlPID"))
3728 i->control_pid = (pid_t) u;
3729 else if (streq(name, "ExecMainPID")) {
3731 i->main_pid = (pid_t) u;
3732 } else if (streq(name, "NAccepted"))
3734 else if (streq(name, "NConnections"))
3735 i->n_connections = u;
3740 case SD_BUS_TYPE_INT32: {
3743 r = sd_bus_message_read(m, "i", &j);
3745 return bus_log_parse_error(r);
3747 if (streq(name, "ExecMainCode"))
3748 i->exit_code = (int) j;
3749 else if (streq(name, "ExecMainStatus"))
3750 i->exit_status = (int) j;
3751 else if (streq(name, "StatusErrno"))
3752 i->status_errno = (int) j;
3757 case SD_BUS_TYPE_UINT64: {
3760 r = sd_bus_message_read(m, "t", &u);
3762 return bus_log_parse_error(r);
3764 if (streq(name, "ExecMainStartTimestamp"))
3765 i->start_timestamp = (usec_t) u;
3766 else if (streq(name, "ExecMainExitTimestamp"))
3767 i->exit_timestamp = (usec_t) u;
3768 else if (streq(name, "ActiveEnterTimestamp"))
3769 i->active_enter_timestamp = (usec_t) u;
3770 else if (streq(name, "InactiveEnterTimestamp"))
3771 i->inactive_enter_timestamp = (usec_t) u;
3772 else if (streq(name, "InactiveExitTimestamp"))
3773 i->inactive_exit_timestamp = (usec_t) u;
3774 else if (streq(name, "InactiveExitTimestampMonotonic"))
3775 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3776 else if (streq(name, "ActiveExitTimestamp"))
3777 i->active_exit_timestamp = (usec_t) u;
3778 else if (streq(name, "ConditionTimestamp"))
3779 i->condition_timestamp = (usec_t) u;
3780 else if (streq(name, "AssertTimestamp"))
3781 i->assert_timestamp = (usec_t) u;
3786 case SD_BUS_TYPE_ARRAY:
3788 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3789 _cleanup_free_ ExecStatusInfo *info = NULL;
3791 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3793 return bus_log_parse_error(r);
3795 info = new0(ExecStatusInfo, 1);
3799 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3801 info->name = strdup(name);
3805 LIST_PREPEND(exec, i->exec, info);
3807 info = new0(ExecStatusInfo, 1);
3813 return bus_log_parse_error(r);
3815 r = sd_bus_message_exit_container(m);
3817 return bus_log_parse_error(r);
3821 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3822 const char *type, *path;
3824 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3826 return bus_log_parse_error(r);
3828 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3830 r = strv_extend(&i->listen, type);
3834 r = strv_extend(&i->listen, path);
3839 return bus_log_parse_error(r);
3841 r = sd_bus_message_exit_container(m);
3843 return bus_log_parse_error(r);
3847 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3849 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3851 return bus_log_parse_error(r);
3853 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3855 r = sd_bus_message_read_strv(m, &i->documentation);
3857 return bus_log_parse_error(r);
3859 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3860 const char *cond, *param;
3861 int trigger, negate;
3864 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3866 return bus_log_parse_error(r);
3868 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3869 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3870 if (state < 0 && (!trigger || !i->failed_condition)) {
3871 i->failed_condition = cond;
3872 i->failed_condition_trigger = trigger;
3873 i->failed_condition_negate = negate;
3874 i->failed_condition_parameter = param;
3878 return bus_log_parse_error(r);
3880 r = sd_bus_message_exit_container(m);
3882 return bus_log_parse_error(r);
3884 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Asserts")) {
3885 const char *cond, *param;
3886 int trigger, negate;
3889 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3891 return bus_log_parse_error(r);
3893 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3894 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3895 if (state < 0 && (!trigger || !i->failed_assert)) {
3896 i->failed_assert = cond;
3897 i->failed_assert_trigger = trigger;
3898 i->failed_assert_negate = negate;
3899 i->failed_assert_parameter = param;
3903 return bus_log_parse_error(r);
3905 r = sd_bus_message_exit_container(m);
3907 return bus_log_parse_error(r);
3914 case SD_BUS_TYPE_STRUCT_BEGIN:
3916 if (streq(name, "LoadError")) {
3917 const char *n, *message;
3919 r = sd_bus_message_read(m, "(ss)", &n, &message);
3921 return bus_log_parse_error(r);
3923 if (!isempty(message))
3924 i->load_error = message;
3937 r = sd_bus_message_skip(m, contents);
3939 return bus_log_parse_error(r);
3944 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3950 /* This is a low-level property printer, see
3951 * print_status_info() for the nicer output */
3953 if (arg_properties && !strv_find(arg_properties, name)) {
3954 /* skip what we didn't read */
3955 r = sd_bus_message_skip(m, contents);
3959 switch (contents[0]) {
3961 case SD_BUS_TYPE_STRUCT_BEGIN:
3963 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3966 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3968 return bus_log_parse_error(r);
3971 printf("%s=%"PRIu32"\n", name, u);
3973 printf("%s=\n", name);
3977 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3980 r = sd_bus_message_read(m, "(so)", &s, NULL);
3982 return bus_log_parse_error(r);
3984 if (arg_all || !isempty(s))
3985 printf("%s=%s\n", name, s);
3989 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3990 const char *a = NULL, *b = NULL;
3992 r = sd_bus_message_read(m, "(ss)", &a, &b);
3994 return bus_log_parse_error(r);
3996 if (arg_all || !isempty(a) || !isempty(b))
3997 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
4000 } else if (streq_ptr(name, "SystemCallFilter")) {
4001 _cleanup_strv_free_ char **l = NULL;
4004 r = sd_bus_message_enter_container(m, 'r', "bas");
4006 return bus_log_parse_error(r);
4008 r = sd_bus_message_read(m, "b", &whitelist);
4010 return bus_log_parse_error(r);
4012 r = sd_bus_message_read_strv(m, &l);
4014 return bus_log_parse_error(r);
4016 r = sd_bus_message_exit_container(m);
4018 return bus_log_parse_error(r);
4020 if (arg_all || whitelist || !strv_isempty(l)) {
4024 fputs(name, stdout);
4030 STRV_FOREACH(i, l) {
4038 fputc('\n', stdout);
4046 case SD_BUS_TYPE_ARRAY:
4048 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
4052 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
4054 return bus_log_parse_error(r);
4056 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
4057 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
4060 return bus_log_parse_error(r);
4062 r = sd_bus_message_exit_container(m);
4064 return bus_log_parse_error(r);
4068 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
4069 const char *type, *path;
4071 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4073 return bus_log_parse_error(r);
4075 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4076 printf("%s=%s\n", type, path);
4078 return bus_log_parse_error(r);
4080 r = sd_bus_message_exit_container(m);
4082 return bus_log_parse_error(r);
4086 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
4087 const char *type, *path;
4089 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4091 return bus_log_parse_error(r);
4093 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4094 printf("Listen%s=%s\n", type, path);
4096 return bus_log_parse_error(r);
4098 r = sd_bus_message_exit_container(m);
4100 return bus_log_parse_error(r);
4104 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
4106 uint64_t value, next_elapse;
4108 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
4110 return bus_log_parse_error(r);
4112 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
4113 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
4115 printf("%s={ value=%s ; next_elapse=%s }\n",
4117 format_timespan(timespan1, sizeof(timespan1), value, 0),
4118 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
4121 return bus_log_parse_error(r);
4123 r = sd_bus_message_exit_container(m);
4125 return bus_log_parse_error(r);
4129 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
4130 ExecStatusInfo info = {};
4132 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
4134 return bus_log_parse_error(r);
4136 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
4137 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
4138 _cleanup_free_ char *tt;
4140 tt = strv_join(info.argv, " ");
4142 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",
4146 yes_no(info.ignore),
4147 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
4148 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
4150 sigchld_code_to_string(info.code),
4152 info.code == CLD_EXITED ? "" : "/",
4153 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
4156 strv_free(info.argv);
4160 r = sd_bus_message_exit_container(m);
4162 return bus_log_parse_error(r);
4166 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
4167 const char *path, *rwm;
4169 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4171 return bus_log_parse_error(r);
4173 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
4174 printf("%s=%s %s\n", name, strna(path), strna(rwm));
4176 return bus_log_parse_error(r);
4178 r = sd_bus_message_exit_container(m);
4180 return bus_log_parse_error(r);
4184 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
4188 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4190 return bus_log_parse_error(r);
4192 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4193 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
4195 return bus_log_parse_error(r);
4197 r = sd_bus_message_exit_container(m);
4199 return bus_log_parse_error(r);
4203 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
4207 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4209 return bus_log_parse_error(r);
4211 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4212 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
4214 return bus_log_parse_error(r);
4216 r = sd_bus_message_exit_container(m);
4218 return bus_log_parse_error(r);
4226 r = bus_print_property(name, m, arg_all);
4228 return bus_log_parse_error(r);
4231 r = sd_bus_message_skip(m, contents);
4233 return bus_log_parse_error(r);
4236 printf("%s=[unprintable]\n", name);
4242 static int show_one(
4246 bool show_properties,
4250 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4251 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4252 UnitStatusInfo info = {};
4259 log_debug("Showing one %s", path);
4261 r = sd_bus_call_method(
4263 "org.freedesktop.systemd1",
4265 "org.freedesktop.DBus.Properties",
4271 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4275 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4277 return bus_log_parse_error(r);
4284 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4285 const char *name, *contents;
4287 r = sd_bus_message_read(reply, "s", &name);
4289 return bus_log_parse_error(r);
4291 r = sd_bus_message_peek_type(reply, NULL, &contents);
4293 return bus_log_parse_error(r);
4295 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4297 return bus_log_parse_error(r);
4299 if (show_properties)
4300 r = print_property(name, reply, contents);
4302 r = status_property(name, reply, &info, contents);
4306 r = sd_bus_message_exit_container(reply);
4308 return bus_log_parse_error(r);
4310 r = sd_bus_message_exit_container(reply);
4312 return bus_log_parse_error(r);
4315 return bus_log_parse_error(r);
4317 r = sd_bus_message_exit_container(reply);
4319 return bus_log_parse_error(r);
4323 if (!show_properties) {
4324 if (streq(verb, "help"))
4325 show_unit_help(&info);
4327 print_status_info(&info, ellipsized);
4330 strv_free(info.documentation);
4331 strv_free(info.dropin_paths);
4332 strv_free(info.listen);
4334 if (!streq_ptr(info.active_state, "active") &&
4335 !streq_ptr(info.active_state, "reloading") &&
4336 streq(verb, "status")) {
4337 /* According to LSB: "program not running" */
4338 /* 0: program is running or service is OK
4339 * 1: program is dead and /run PID file exists
4340 * 2: program is dead and /run/lock lock file exists
4341 * 3: program is not running
4342 * 4: program or service status is unknown
4344 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4350 while ((p = info.exec)) {
4351 LIST_REMOVE(exec, info.exec, p);
4352 exec_status_info_free(p);
4358 static int get_unit_dbus_path_by_pid(
4363 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4364 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4368 r = sd_bus_call_method(
4370 "org.freedesktop.systemd1",
4371 "/org/freedesktop/systemd1",
4372 "org.freedesktop.systemd1.Manager",
4378 log_error("Failed to get unit for PID "PID_FMT": %s", pid, bus_error_message(&error, r));
4382 r = sd_bus_message_read(reply, "o", &u);
4384 return bus_log_parse_error(r);
4394 static int show_all(
4397 bool show_properties,
4401 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4402 _cleanup_free_ UnitInfo *unit_infos = NULL;
4407 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4411 pager_open_if_enabled();
4415 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4417 for (u = unit_infos; u < unit_infos + c; u++) {
4418 _cleanup_free_ char *p = NULL;
4420 p = unit_dbus_path_from_name(u->id);
4424 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4427 else if (r > 0 && ret == 0)
4434 static int show_system_status(sd_bus *bus) {
4435 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4436 _cleanup_free_ char *hn = NULL;
4437 struct machine_info mi = {};
4438 const char *on, *off;
4441 hn = gethostname_malloc();
4445 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4447 return log_error_errno(r, "Failed to read server status: %m");
4449 if (streq_ptr(mi.state, "degraded")) {
4450 on = ansi_highlight_red();
4451 off = ansi_highlight_off();
4452 } else if (!streq_ptr(mi.state, "running")) {
4453 on = ansi_highlight_yellow();
4454 off = ansi_highlight_off();
4458 printf("%s%s%s %s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4460 printf(" State: %s%s%s\n",
4461 on, strna(mi.state), off);
4463 printf(" Jobs: %u queued\n", mi.n_jobs);
4464 printf(" Failed: %u units\n", mi.n_failed_units);
4466 printf(" Since: %s; %s\n",
4467 format_timestamp(since2, sizeof(since2), mi.timestamp),
4468 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4470 printf(" CGroup: %s\n", mi.control_group ?: "/");
4471 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
4473 arg_all * OUTPUT_SHOW_ALL |
4474 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
4475 on_tty() * OUTPUT_COLOR |
4476 !arg_quiet * OUTPUT_WARN_CUTOFF |
4477 arg_full * OUTPUT_FULL_WIDTH;
4479 static const char prefix[] = " ";
4483 if (c > sizeof(prefix) - 1)
4484 c -= sizeof(prefix) - 1;
4488 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
4492 free(mi.control_group);
4497 static int show(sd_bus *bus, char **args) {
4498 bool show_properties, show_status, new_line = false;
4499 bool ellipsized = false;
4505 show_properties = streq(args[0], "show");
4506 show_status = streq(args[0], "status");
4508 if (show_properties)
4509 pager_open_if_enabled();
4511 /* If no argument is specified inspect the manager itself */
4513 if (show_properties && strv_length(args) <= 1)
4514 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4516 if (show_status && strv_length(args) <= 1) {
4518 pager_open_if_enabled();
4519 show_system_status(bus);
4523 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4525 _cleanup_free_ char **patterns = NULL;
4528 STRV_FOREACH(name, args + 1) {
4529 _cleanup_free_ char *unit = NULL;
4532 if (safe_atou32(*name, &id) < 0) {
4533 if (strv_push(&patterns, *name) < 0)
4537 } else if (show_properties) {
4538 /* Interpret as job id */
4539 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4543 /* Interpret as PID */
4544 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4551 r = show_one(args[0], bus, unit, show_properties,
4552 &new_line, &ellipsized);
4555 else if (r > 0 && ret == 0)
4559 if (!strv_isempty(patterns)) {
4560 _cleanup_strv_free_ char **names = NULL;
4562 r = expand_names(bus, patterns, NULL, &names);
4564 log_error_errno(r, "Failed to expand names: %m");
4566 STRV_FOREACH(name, names) {
4567 _cleanup_free_ char *unit;
4569 unit = unit_dbus_path_from_name(*name);
4573 r = show_one(args[0], bus, unit, show_properties,
4574 &new_line, &ellipsized);
4577 else if (r > 0 && ret == 0)
4583 if (ellipsized && !arg_quiet)
4584 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4589 static int cat(sd_bus *bus, char **args) {
4590 _cleanup_strv_free_ char **names = NULL;
4598 r = expand_names(bus, args + 1, NULL, &names);
4600 log_error_errno(r, "Failed to expand names: %m");
4602 pager_open_if_enabled();
4604 STRV_FOREACH(name, names) {
4605 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4606 _cleanup_strv_free_ char **dropin_paths = NULL;
4607 _cleanup_free_ char *fragment_path = NULL, *unit = NULL;
4610 unit = unit_dbus_path_from_name(*name);
4614 if (need_daemon_reload(bus, *name) > 0)
4615 log_warning("Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'.",
4616 *name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
4618 r = sd_bus_get_property_string(
4620 "org.freedesktop.systemd1",
4622 "org.freedesktop.systemd1.Unit",
4627 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
4631 r = sd_bus_get_property_strv(
4633 "org.freedesktop.systemd1",
4635 "org.freedesktop.systemd1.Unit",
4640 log_warning("Failed to get DropInPaths: %s", bus_error_message(&error, r));
4649 if (!isempty(fragment_path)) {
4650 printf("%s# %s%s\n",
4651 ansi_highlight_blue(),
4653 ansi_highlight_off());
4656 r = copy_file_fd(fragment_path, STDOUT_FILENO, false);
4658 log_warning_errno(r, "Failed to cat %s: %m", fragment_path);
4663 STRV_FOREACH(path, dropin_paths) {
4664 printf("%s%s# %s%s\n",
4665 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4666 ansi_highlight_blue(),
4668 ansi_highlight_off());
4671 r = copy_file_fd(*path, STDOUT_FILENO, false);
4673 log_warning_errno(r, "Failed to cat %s: %m", *path);
4679 return r < 0 ? r : 0;
4682 static int set_property(sd_bus *bus, char **args) {
4683 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4684 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4685 _cleanup_free_ char *n = NULL;
4689 r = sd_bus_message_new_method_call(
4692 "org.freedesktop.systemd1",
4693 "/org/freedesktop/systemd1",
4694 "org.freedesktop.systemd1.Manager",
4695 "SetUnitProperties");
4697 return bus_log_create_error(r);
4699 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4701 return bus_log_create_error(r);
4703 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4707 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4709 return bus_log_create_error(r);
4711 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4713 return bus_log_create_error(r);
4715 STRV_FOREACH(i, args + 2) {
4716 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4718 return bus_log_create_error(r);
4720 r = bus_append_unit_property_assignment(m, *i);
4724 r = sd_bus_message_close_container(m);
4726 return bus_log_create_error(r);
4729 r = sd_bus_message_close_container(m);
4731 return bus_log_create_error(r);
4733 r = sd_bus_call(bus, m, 0, &error, NULL);
4735 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4742 static int snapshot(sd_bus *bus, char **args) {
4743 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4744 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
4745 _cleanup_free_ char *n = NULL, *id = NULL;
4749 if (strv_length(args) > 1)
4750 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4756 r = sd_bus_message_new_method_call(
4759 "org.freedesktop.systemd1",
4760 "/org/freedesktop/systemd1",
4761 "org.freedesktop.systemd1.Manager",
4764 return bus_log_create_error(r);
4766 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4768 return bus_log_create_error(r);
4770 r = sd_bus_message_append(m, "sb", n, false);
4772 return bus_log_create_error(r);
4774 r = sd_bus_call(bus, m, 0, &error, &reply);
4776 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4780 r = sd_bus_message_read(reply, "o", &path);
4782 return bus_log_parse_error(r);
4784 r = sd_bus_get_property_string(
4786 "org.freedesktop.systemd1",
4788 "org.freedesktop.systemd1.Unit",
4793 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4803 static int delete_snapshot(sd_bus *bus, char **args) {
4804 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4805 _cleanup_strv_free_ char **names = NULL;
4811 r = expand_names(bus, args + 1, ".snapshot", &names);
4813 log_error_errno(r, "Failed to expand names: %m");
4815 STRV_FOREACH(name, names) {
4816 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4819 q = sd_bus_message_new_method_call(
4822 "org.freedesktop.systemd1",
4823 "/org/freedesktop/systemd1",
4824 "org.freedesktop.systemd1.Manager",
4827 return bus_log_create_error(q);
4829 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4831 return bus_log_create_error(q);
4833 q = sd_bus_message_append(m, "s", *name);
4835 return bus_log_create_error(q);
4837 q = sd_bus_call(bus, m, 0, &error, NULL);
4839 log_error("Failed to remove snapshot %s: %s", *name, bus_error_message(&error, q));
4848 static int daemon_reload(sd_bus *bus, char **args) {
4849 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4850 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4854 if (arg_action == ACTION_RELOAD)
4856 else if (arg_action == ACTION_REEXEC)
4857 method = "Reexecute";
4859 assert(arg_action == ACTION_SYSTEMCTL);
4862 streq(args[0], "clear-jobs") ||
4863 streq(args[0], "cancel") ? "ClearJobs" :
4864 streq(args[0], "daemon-reexec") ? "Reexecute" :
4865 streq(args[0], "reset-failed") ? "ResetFailed" :
4866 streq(args[0], "halt") ? "Halt" :
4867 streq(args[0], "poweroff") ? "PowerOff" :
4868 streq(args[0], "reboot") ? "Reboot" :
4869 streq(args[0], "kexec") ? "KExec" :
4870 streq(args[0], "exit") ? "Exit" :
4871 /* "daemon-reload" */ "Reload";
4874 r = sd_bus_message_new_method_call(
4877 "org.freedesktop.systemd1",
4878 "/org/freedesktop/systemd1",
4879 "org.freedesktop.systemd1.Manager",
4882 return bus_log_create_error(r);
4884 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4886 return bus_log_create_error(r);
4888 r = sd_bus_call(bus, m, 0, &error, NULL);
4889 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4890 /* There's always a fallback possible for
4891 * legacy actions. */
4893 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4894 /* On reexecution, we expect a disconnect, not a
4898 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4900 return r < 0 ? r : 0;
4903 static int reset_failed(sd_bus *bus, char **args) {
4904 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4905 _cleanup_strv_free_ char **names = NULL;
4909 if (strv_length(args) <= 1)
4910 return daemon_reload(bus, args);
4912 r = expand_names(bus, args + 1, NULL, &names);
4914 log_error_errno(r, "Failed to expand names: %m");
4916 STRV_FOREACH(name, names) {
4917 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4919 q = sd_bus_message_new_method_call(
4922 "org.freedesktop.systemd1",
4923 "/org/freedesktop/systemd1",
4924 "org.freedesktop.systemd1.Manager",
4927 return bus_log_create_error(q);
4929 q = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
4931 return bus_log_create_error(q);
4933 q = sd_bus_message_append(m, "s", *name);
4935 return bus_log_create_error(q);
4937 q = sd_bus_call(bus, m, 0, &error, NULL);
4939 log_error("Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q));
4948 static int show_environment(sd_bus *bus, char **args) {
4949 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4950 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4954 pager_open_if_enabled();
4956 r = sd_bus_get_property(
4958 "org.freedesktop.systemd1",
4959 "/org/freedesktop/systemd1",
4960 "org.freedesktop.systemd1.Manager",
4966 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4970 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4972 return bus_log_parse_error(r);
4974 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4977 return bus_log_parse_error(r);
4979 r = sd_bus_message_exit_container(reply);
4981 return bus_log_parse_error(r);
4986 static int switch_root(sd_bus *bus, char **args) {
4987 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4988 _cleanup_free_ char *cmdline_init = NULL;
4989 const char *root, *init;
4993 l = strv_length(args);
4994 if (l < 2 || l > 3) {
4995 log_error("Wrong number of arguments.");
5004 r = parse_env_file("/proc/cmdline", WHITESPACE,
5005 "init", &cmdline_init,
5008 log_debug_errno(r, "Failed to parse /proc/cmdline: %m");
5010 init = cmdline_init;
5017 const char *root_systemd_path = NULL, *root_init_path = NULL;
5019 root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
5020 root_init_path = strappenda(root, "/", init);
5022 /* If the passed init is actually the same as the
5023 * systemd binary, then let's suppress it. */
5024 if (files_same(root_init_path, root_systemd_path) > 0)
5028 log_debug("Switching root - root: %s; init: %s", root, strna(init));
5030 r = sd_bus_call_method(
5032 "org.freedesktop.systemd1",
5033 "/org/freedesktop/systemd1",
5034 "org.freedesktop.systemd1.Manager",
5040 log_error("Failed to switch root: %s", bus_error_message(&error, r));
5047 static int set_environment(sd_bus *bus, char **args) {
5048 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5049 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
5056 method = streq(args[0], "set-environment")
5058 : "UnsetEnvironment";
5060 r = sd_bus_message_new_method_call(
5063 "org.freedesktop.systemd1",
5064 "/org/freedesktop/systemd1",
5065 "org.freedesktop.systemd1.Manager",
5068 return bus_log_create_error(r);
5070 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5072 return bus_log_create_error(r);
5074 r = sd_bus_message_append_strv(m, args + 1);
5076 return bus_log_create_error(r);
5078 r = sd_bus_call(bus, m, 0, &error, NULL);
5080 log_error("Failed to set environment: %s", bus_error_message(&error, r));
5087 static int import_environment(sd_bus *bus, char **args) {
5088 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5089 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
5095 r = sd_bus_message_new_method_call(
5098 "org.freedesktop.systemd1",
5099 "/org/freedesktop/systemd1",
5100 "org.freedesktop.systemd1.Manager",
5103 return bus_log_create_error(r);
5105 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5107 return bus_log_create_error(r);
5109 if (strv_isempty(args + 1))
5110 r = sd_bus_message_append_strv(m, environ);
5114 r = sd_bus_message_open_container(m, 'a', "s");
5116 return bus_log_create_error(r);
5118 STRV_FOREACH(a, args + 1) {
5120 if (!env_name_is_valid(*a)) {
5121 log_error("Not a valid environment variable name: %s", *a);
5125 STRV_FOREACH(b, environ) {
5128 eq = startswith(*b, *a);
5129 if (eq && *eq == '=') {
5131 r = sd_bus_message_append(m, "s", *b);
5133 return bus_log_create_error(r);
5140 r = sd_bus_message_close_container(m);
5143 return bus_log_create_error(r);
5145 r = sd_bus_call(bus, m, 0, &error, NULL);
5147 log_error("Failed to import environment: %s", bus_error_message(&error, r));
5154 static int enable_sysv_units(const char *verb, char **args) {
5157 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
5159 _cleanup_lookup_paths_free_ LookupPaths paths = {};
5161 if (arg_scope != UNIT_FILE_SYSTEM)
5164 if (!streq(verb, "enable") &&
5165 !streq(verb, "disable") &&
5166 !streq(verb, "is-enabled"))
5169 /* Processes all SysV units, and reshuffles the array so that
5170 * afterwards only the native units remain */
5172 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, arg_root, NULL, NULL, NULL);
5179 _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL;
5180 bool found_native = false, found_sysv;
5182 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
5190 if (!endswith(name, ".service"))
5193 if (path_is_absolute(name))
5196 STRV_FOREACH(k, paths.unit_path) {
5197 _cleanup_free_ char *path = NULL;
5199 path = path_join(arg_root, *k, name);
5203 found_native = access(path, F_OK) >= 0;
5211 p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name);
5215 p[strlen(p) - strlen(".service")] = 0;
5216 found_sysv = access(p, F_OK) >= 0;
5220 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
5222 if (!isempty(arg_root))
5223 argv[c++] = q = strappend("--root=", arg_root);
5225 argv[c++] = basename(p);
5227 streq(verb, "enable") ? "on" :
5228 streq(verb, "disable") ? "off" : "--level=5";
5231 l = strv_join((char**)argv, " ");
5235 log_info("Executing %s", l);
5239 return log_error_errno(errno, "Failed to fork: %m");
5240 else if (pid == 0) {
5243 execv(argv[0], (char**) argv);
5244 _exit(EXIT_FAILURE);
5247 j = wait_for_terminate(pid, &status);
5249 log_error_errno(r, "Failed to wait for child: %m");
5253 if (status.si_code == CLD_EXITED) {
5254 if (streq(verb, "is-enabled")) {
5255 if (status.si_status == 0) {
5264 } else if (status.si_status != 0)
5269 /* Remove this entry, so that we don't try enabling it as native unit */
5270 assert(f > 0 && streq(args[f-1], name));
5271 assert_se(strv_remove(args + f - 1, name));
5278 static int mangle_names(char **original_names, char ***mangled_names) {
5279 char **i, **l, **name;
5281 l = new(char*, strv_length(original_names) + 1);
5286 STRV_FOREACH(name, original_names) {
5288 /* When enabling units qualified path names are OK,
5289 * too, hence allow them explicitly. */
5294 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5310 static int enable_unit(sd_bus *bus, char **args) {
5311 _cleanup_strv_free_ char **names = NULL;
5312 const char *verb = args[0];
5313 UnitFileChange *changes = NULL;
5314 unsigned n_changes = 0;
5315 int carries_install_info = -1;
5321 r = mangle_names(args+1, &names);
5325 r = enable_sysv_units(verb, names);
5329 /* If the operation was fully executed by the SysV compat,
5330 * let's finish early */
5331 if (strv_isempty(names))
5334 if (!bus || avoid_bus()) {
5335 if (streq(verb, "enable")) {
5336 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5337 carries_install_info = r;
5338 } else if (streq(verb, "disable"))
5339 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5340 else if (streq(verb, "reenable")) {
5341 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5342 carries_install_info = r;
5343 } else if (streq(verb, "link"))
5344 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5345 else if (streq(verb, "preset")) {
5346 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_preset_mode, arg_force, &changes, &n_changes);
5347 carries_install_info = r;
5348 } else if (streq(verb, "mask"))
5349 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5350 else if (streq(verb, "unmask"))
5351 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5353 assert_not_reached("Unknown verb");
5356 log_error_errno(r, "Operation failed: %m");
5361 dump_unit_file_changes(changes, n_changes);
5365 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5366 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5367 int expect_carries_install_info = false;
5368 bool send_force = true, send_preset_mode = false;
5371 if (streq(verb, "enable")) {
5372 method = "EnableUnitFiles";
5373 expect_carries_install_info = true;
5374 } else if (streq(verb, "disable")) {
5375 method = "DisableUnitFiles";
5377 } else if (streq(verb, "reenable")) {
5378 method = "ReenableUnitFiles";
5379 expect_carries_install_info = true;
5380 } else if (streq(verb, "link"))
5381 method = "LinkUnitFiles";
5382 else if (streq(verb, "preset")) {
5384 if (arg_preset_mode != UNIT_FILE_PRESET_FULL) {
5385 method = "PresetUnitFilesWithMode";
5386 send_preset_mode = true;
5388 method = "PresetUnitFiles";
5390 expect_carries_install_info = true;
5391 } else if (streq(verb, "mask"))
5392 method = "MaskUnitFiles";
5393 else if (streq(verb, "unmask")) {
5394 method = "UnmaskUnitFiles";
5397 assert_not_reached("Unknown verb");
5399 r = sd_bus_message_new_method_call(
5402 "org.freedesktop.systemd1",
5403 "/org/freedesktop/systemd1",
5404 "org.freedesktop.systemd1.Manager",
5407 return bus_log_create_error(r);
5409 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5411 return bus_log_create_error(r);
5413 r = sd_bus_message_append_strv(m, names);
5415 return bus_log_create_error(r);
5417 if (send_preset_mode) {
5418 r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode));
5420 return bus_log_create_error(r);
5423 r = sd_bus_message_append(m, "b", arg_runtime);
5425 return bus_log_create_error(r);
5428 r = sd_bus_message_append(m, "b", arg_force);
5430 return bus_log_create_error(r);
5433 r = sd_bus_call(bus, m, 0, &error, &reply);
5435 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5439 if (expect_carries_install_info) {
5440 r = sd_bus_message_read(reply, "b", &carries_install_info);
5442 return bus_log_parse_error(r);
5445 r = deserialize_and_dump_unit_file_changes(reply);
5449 /* Try to reload if enabled */
5451 r = daemon_reload(bus, args);
5456 if (carries_install_info == 0)
5457 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5458 "using systemctl.\n"
5459 "Possible reasons for having this kind of units are:\n"
5460 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5461 " .wants/ or .requires/ directory.\n"
5462 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5463 " a requirement dependency on it.\n"
5464 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5465 " D-Bus, udev, scripted systemctl call, ...).\n");
5468 unit_file_changes_free(changes, n_changes);
5473 static int add_dependency(sd_bus *bus, char **args) {
5474 _cleanup_strv_free_ char **names = NULL;
5475 _cleanup_free_ char *target = NULL;
5476 const char *verb = args[0];
5483 target = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
5487 r = mangle_names(args+2, &names);
5491 if (streq(verb, "add-wants"))
5493 else if (streq(verb, "add-requires"))
5494 dep = UNIT_REQUIRES;
5496 assert_not_reached("Unknown verb");
5498 if (!bus || avoid_bus()) {
5499 UnitFileChange *changes = NULL;
5500 unsigned n_changes = 0;
5502 r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes);
5505 return log_error_errno(r, "Can't add dependency: %m");
5508 dump_unit_file_changes(changes, n_changes);
5510 unit_file_changes_free(changes, n_changes);
5513 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5514 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5516 r = sd_bus_message_new_method_call(
5519 "org.freedesktop.systemd1",
5520 "/org/freedesktop/systemd1",
5521 "org.freedesktop.systemd1.Manager",
5522 "AddDependencyUnitFiles");
5524 return bus_log_create_error(r);
5526 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5528 return bus_log_create_error(r);
5530 r = sd_bus_message_append_strv(m, names);
5532 return bus_log_create_error(r);
5534 r = sd_bus_message_append(m, "ssbb", target, unit_dependency_to_string(dep), arg_runtime, arg_force);
5536 return bus_log_create_error(r);
5538 r = sd_bus_call(bus, m, 0, &error, &reply);
5540 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5544 r = deserialize_and_dump_unit_file_changes(reply);
5549 r = daemon_reload(bus, args);
5557 static int preset_all(sd_bus *bus, char **args) {
5558 UnitFileChange *changes = NULL;
5559 unsigned n_changes = 0;
5562 if (!bus || avoid_bus()) {
5564 r = unit_file_preset_all(arg_scope, arg_runtime, arg_root, arg_preset_mode, arg_force, &changes, &n_changes);
5566 log_error_errno(r, "Operation failed: %m");
5571 dump_unit_file_changes(changes, n_changes);
5576 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
5577 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5579 r = sd_bus_message_new_method_call(
5582 "org.freedesktop.systemd1",
5583 "/org/freedesktop/systemd1",
5584 "org.freedesktop.systemd1.Manager",
5585 "PresetAllUnitFiles");
5587 return bus_log_create_error(r);
5589 r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
5591 return bus_log_create_error(r);
5593 r = sd_bus_message_append(
5596 unit_file_preset_mode_to_string(arg_preset_mode),
5600 return bus_log_create_error(r);
5602 r = sd_bus_call(bus, m, 0, &error, &reply);
5604 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5608 r = deserialize_and_dump_unit_file_changes(reply);
5613 r = daemon_reload(bus, args);
5619 unit_file_changes_free(changes, n_changes);
5624 static int unit_is_enabled(sd_bus *bus, char **args) {
5626 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5627 _cleanup_strv_free_ char **names = NULL;
5632 r = mangle_names(args+1, &names);
5636 r = enable_sysv_units(args[0], names);
5642 if (!bus || avoid_bus()) {
5644 STRV_FOREACH(name, names) {
5645 UnitFileState state;
5647 state = unit_file_get_state(arg_scope, arg_root, *name);
5649 return log_error_errno(state, "Failed to get unit file state for %s: %m", *name);
5651 if (state == UNIT_FILE_ENABLED ||
5652 state == UNIT_FILE_ENABLED_RUNTIME ||
5653 state == UNIT_FILE_STATIC ||
5654 state == UNIT_FILE_INDIRECT)
5658 puts(unit_file_state_to_string(state));
5662 STRV_FOREACH(name, names) {
5663 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5666 r = sd_bus_call_method(
5668 "org.freedesktop.systemd1",
5669 "/org/freedesktop/systemd1",
5670 "org.freedesktop.systemd1.Manager",
5676 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5680 r = sd_bus_message_read(reply, "s", &s);
5682 return bus_log_parse_error(r);
5684 if (STR_IN_SET(s, "enabled", "enabled-runtime", "static", "indirect"))
5695 static int is_system_running(sd_bus *bus, char **args) {
5696 _cleanup_free_ char *state = NULL;
5699 r = sd_bus_get_property_string(
5701 "org.freedesktop.systemd1",
5702 "/org/freedesktop/systemd1",
5703 "org.freedesktop.systemd1.Manager",
5716 return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE;
5719 static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **unit_path) {
5726 STRV_FOREACH(p, lp->unit_path) {
5729 path = path_join(arg_root, *p, unit_name);
5733 if (access(path, F_OK) == 0) {
5744 static int create_edit_temp_file(const char *new_path, const char *original_path, char **ret_tmp_fn) {
5749 assert(original_path);
5752 r = tempfn_random(new_path, &t);
5754 return log_error_errno(r, "Failed to determine temporary filename for %s: %m", new_path);
5756 r = mkdir_parents(new_path, 0755);
5758 log_error_errno(r, "Failed to create directories for %s: %m", new_path);
5763 r = copy_file(original_path, t, 0, 0644);
5767 log_error_errno(r, "Failed to create temporary file %s: %m", t);
5772 log_error_errno(r, "Failed to copy %s to %s: %m", original_path, t);
5782 static int get_drop_in_to_edit(const char *unit_name, const char *user_home, const char *user_runtime, char **ret_path) {
5789 switch (arg_scope) {
5790 case UNIT_FILE_SYSTEM:
5791 tmp = strappenda(arg_runtime ? "/run/systemd/system/" : SYSTEM_CONFIG_UNIT_PATH "/", unit_name, ".d/override.conf");
5793 case UNIT_FILE_GLOBAL:
5794 tmp = strappenda(arg_runtime ? "/run/systemd/user/" : USER_CONFIG_UNIT_PATH "/", unit_name, ".d/override.conf");
5796 case UNIT_FILE_USER:
5798 assert(user_runtime);
5800 tmp = strappenda(arg_runtime ? user_runtime : user_home, "/", unit_name, ".d/override.conf");
5803 assert_not_reached("Invalid scope");
5806 tmp_new_path = path_join(arg_root, tmp, NULL);
5810 *ret_path = tmp_new_path;
5815 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) {
5821 assert(ret_new_path);
5822 assert(ret_tmp_path);
5824 r = get_drop_in_to_edit(unit_name, user_home, user_runtime, &tmp_new_path);
5828 r = create_edit_temp_file(tmp_new_path, tmp_new_path, &tmp_tmp_path);
5834 *ret_new_path = tmp_new_path;
5835 *ret_tmp_path = tmp_tmp_path;
5840 static bool unit_is_editable(const char *unit_name, const char *fragment_path, const char *user_home) {
5841 bool editable = true;
5842 const char *invalid_path;
5849 switch (arg_scope) {
5850 case UNIT_FILE_SYSTEM:
5851 if (path_startswith(fragment_path, "/etc/systemd/system")) {
5853 invalid_path = "/etc/systemd/system";
5854 } else if (path_startswith(fragment_path, SYSTEM_CONFIG_UNIT_PATH)) {
5856 invalid_path = SYSTEM_CONFIG_UNIT_PATH;
5859 case UNIT_FILE_GLOBAL:
5860 if (path_startswith(fragment_path, "/etc/systemd/user")) {
5862 invalid_path = "/etc/systemd/user";
5863 } else if (path_startswith(fragment_path, USER_CONFIG_UNIT_PATH)) {
5865 invalid_path = USER_CONFIG_UNIT_PATH;
5868 case UNIT_FILE_USER:
5871 if (path_startswith(fragment_path, "/etc/systemd/user")) {
5873 invalid_path = "/etc/systemd/user";
5874 } else if (path_startswith(fragment_path, USER_CONFIG_UNIT_PATH)) {
5876 invalid_path = USER_CONFIG_UNIT_PATH;
5877 } else if (path_startswith(fragment_path, user_home)) {
5879 invalid_path = user_home;
5883 assert_not_reached("Invalid scope");
5887 log_error("%s ignored: cannot temporarily edit units from %s", unit_name, invalid_path);
5892 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) {
5898 if (!unit_is_editable(unit_name, fragment_path, user_home))
5901 switch (arg_scope) {
5902 case UNIT_FILE_SYSTEM:
5903 tmp_new_path = path_join(arg_root, arg_runtime ? "/run/systemd/system/" : SYSTEM_CONFIG_UNIT_PATH, unit_name);
5905 case UNIT_FILE_GLOBAL:
5906 tmp_new_path = path_join(arg_root, arg_runtime ? "/run/systemd/user/" : USER_CONFIG_UNIT_PATH, unit_name);
5908 case UNIT_FILE_USER:
5910 assert(user_runtime);
5912 tmp_new_path = path_join(arg_root, arg_runtime ? user_runtime : user_home, unit_name);
5915 assert_not_reached("Invalid scope");
5920 *ret_path = tmp_new_path;
5925 static int unit_file_create_copy(const char *unit_name,
5926 const char *fragment_path,
5927 const char *user_home,
5928 const char *user_runtime,
5929 char **ret_new_path,
5930 char **ret_tmp_path) {
5935 assert(fragment_path);
5937 assert(ret_new_path);
5938 assert(ret_tmp_path);
5940 r = get_copy_to_edit(unit_name, fragment_path, user_home, user_runtime, &tmp_new_path);
5944 if (!path_equal(fragment_path, tmp_new_path) && access(tmp_new_path, F_OK) == 0) {
5947 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);
5952 if (response != 'y') {
5953 log_warning("%s ignored", unit_name);
5959 r = create_edit_temp_file(tmp_new_path, fragment_path, &tmp_tmp_path);
5961 log_error_errno(r, "Failed to create temporary file for %s: %m", tmp_new_path);
5966 *ret_new_path = tmp_new_path;
5967 *ret_tmp_path = tmp_tmp_path;
5972 static int run_editor(char **paths) {
5980 log_error_errno(errno, "Failed to fork: %m");
5986 char **backup_editors = STRV_MAKE("nano", "vim", "vi");
5988 char **tmp_path, **original_path, **p;
5992 argc = strv_length(paths)/2 + 1;
5993 args = newa(const char*, argc + 1);
5996 STRV_FOREACH_PAIR(original_path, tmp_path, paths) {
5997 args[i] = *tmp_path;
6002 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
6003 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
6004 * we try to execute well known editors
6006 editor = getenv("SYSTEMD_EDITOR");
6008 editor = getenv("EDITOR");
6010 editor = getenv("VISUAL");
6012 if (!isempty(editor)) {
6014 execvp(editor, (char* const*) args);
6017 STRV_FOREACH(p, backup_editors) {
6019 execvp(*p, (char* const*) args);
6020 /* We do not fail if the editor doesn't exist
6021 * because we want to try each one of them before
6024 if (errno != ENOENT) {
6025 log_error("Failed to execute %s: %m", editor);
6026 _exit(EXIT_FAILURE);
6030 log_error("Cannot edit unit(s): No editor available. Please set either SYSTEMD_EDITOR or EDITOR or VISUAL environment variable");
6031 _exit(EXIT_FAILURE);
6034 r = wait_for_terminate_and_warn("editor", pid, true);
6036 return log_error_errno(r, "Failed to wait for child: %m");
6041 static int unit_find_path(sd_bus *bus, const char *unit_name, const char *template, bool avoid_bus_cache, LookupPaths *lp, char **path) {
6048 if (!avoid_bus_cache && !unit_name_is_template(unit_name)) {
6049 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
6050 _cleanup_free_ char *unit = NULL;
6051 _cleanup_free_ char *tmp_path = NULL;
6053 unit = unit_dbus_path_from_name(unit_name);
6057 if (need_daemon_reload(bus, unit_name) > 0) {
6058 log_warning("%s ignored: unit file changed on disk. Run 'systemctl%s daemon-reload'.",
6059 unit_name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
6063 r = sd_bus_get_property_string(
6065 "org.freedesktop.systemd1",
6067 "org.freedesktop.systemd1.Unit",
6072 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
6076 if (isempty(tmp_path)) {
6077 log_warning("%s ignored: not found", template);
6086 r = unit_file_find_path(lp, template, path);
6088 log_warning("%s ignored: not found", template);
6095 static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
6096 _cleanup_free_ char *user_home = NULL;
6097 _cleanup_free_ char *user_runtime = NULL;
6098 _cleanup_lookup_paths_free_ LookupPaths lp = {};
6099 bool avoid_bus_cache;
6106 if (arg_scope == UNIT_FILE_USER) {
6107 r = user_config_home(&user_home);
6109 return log_error_errno(r, "Failed to query XDG_CONFIG_HOME: %m");
6111 return log_error_errno(ENOTDIR, "Cannot edit units: $XDG_CONFIG_HOME and $HOME are not set.");
6113 r = user_runtime_dir(&user_runtime);
6115 return log_error_errno(r, "Failed to query XDG_CONFIG_HOME: %m");
6117 return log_error_errno(ENOTDIR, "Cannot edit units: $XDG_RUNTIME_DIR is not set.");
6120 r = lookup_paths_init(&lp,
6121 arg_scope == UNIT_FILE_SYSTEM ? SYSTEMD_SYSTEM : SYSTEMD_USER,
6122 arg_scope == UNIT_FILE_USER,
6126 return log_error_errno(r, "Failed get lookup paths: %m");
6128 avoid_bus_cache = !bus || avoid_bus();
6130 STRV_FOREACH(name, names) {
6131 _cleanup_free_ char *path = NULL;
6132 _cleanup_free_ char *template = NULL;
6133 char *new_path, *tmp_path;
6135 template = unit_name_template(*name);
6139 r = unit_find_path(bus, *name, template, avoid_bus_cache, &lp, &path);
6147 r = unit_file_create_copy(template, path, user_home, user_runtime, &new_path, &tmp_path);
6149 r = unit_file_create_drop_in(template, user_home, user_runtime, &new_path, &tmp_path);
6154 r = strv_push_pair(paths, new_path, tmp_path);
6162 static int edit(sd_bus *bus, char **args) {
6163 _cleanup_strv_free_ char **names = NULL;
6164 _cleanup_strv_free_ char **paths = NULL;
6165 char **original, **tmp;
6171 log_error("Cannot edit units if we are not on a tty");
6175 if (arg_transport != BUS_TRANSPORT_LOCAL) {
6176 log_error("Cannot remotely edit units");
6180 r = expand_names(bus, args + 1, NULL, &names);
6182 return log_error_errno(r, "Failed to expand names: %m");
6185 log_error("No unit name found by expanding names");
6189 r = find_paths_to_edit(bus, names, &paths);
6193 if (strv_isempty(paths)) {
6194 log_error("Cannot find any units to edit");
6198 r = run_editor(paths);
6202 STRV_FOREACH_PAIR(original, tmp, paths) {
6203 /* If the temporary file is empty we ignore it.
6204 * It's useful if the user wants to cancel its modification
6206 if (null_or_empty_path(*tmp)) {
6207 log_warning("Edition of %s canceled: temporary file empty", *original);
6210 r = rename(*tmp, *original);
6212 r = log_error_errno(errno, "Failed to rename %s to %s: %m", *tmp, *original);
6217 if (!arg_no_reload && bus && !avoid_bus())
6218 r = daemon_reload(bus, args);
6221 STRV_FOREACH_PAIR(original, tmp, paths)
6222 unlink_noerrno(*tmp);
6227 static void systemctl_help(void) {
6229 pager_open_if_enabled();
6231 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
6232 "Query or send control commands to the systemd manager.\n\n"
6233 " -h --help Show this help\n"
6234 " --version Show package version\n"
6235 " --system Connect to system manager\n"
6236 " --user Connect to user service manager\n"
6237 " -H --host=[USER@]HOST\n"
6238 " Operate on remote host\n"
6239 " -M --machine=CONTAINER\n"
6240 " Operate on local container\n"
6241 " -t --type=TYPE List only units of a particular type\n"
6242 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
6243 " -p --property=NAME Show only properties by this name\n"
6244 " -a --all Show all loaded units/properties, including dead/empty\n"
6245 " ones. To list all units installed on the system, use\n"
6246 " the 'list-unit-files' command instead.\n"
6247 " -l --full Don't ellipsize unit names on output\n"
6248 " -r --recursive Show unit list of host and local containers\n"
6249 " --reverse Show reverse dependencies with 'list-dependencies'\n"
6250 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
6251 " queueing a new job\n"
6252 " --show-types When showing sockets, explicitly show their type\n"
6253 " -i --ignore-inhibitors\n"
6254 " When shutting down or sleeping, ignore inhibitors\n"
6255 " --kill-who=WHO Who to send signal to\n"
6256 " -s --signal=SIGNAL Which signal to send\n"
6257 " -q --quiet Suppress output\n"
6258 " --no-block Do not wait until operation finished\n"
6259 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6260 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
6262 " --no-legend Do not print a legend (column headers and hints)\n"
6263 " --no-pager Do not pipe output into a pager\n"
6264 " --no-ask-password\n"
6265 " Do not ask for system passwords\n"
6266 " --global Enable/disable unit files globally\n"
6267 " --runtime Enable unit files only temporarily until next reboot\n"
6268 " -f --force When enabling unit files, override existing symlinks\n"
6269 " When shutting down, execute action immediately\n"
6270 " --preset-mode= Specifies whether fully apply presets, or only enable,\n"
6271 " or only disable\n"
6272 " --root=PATH Enable unit files in the specified root directory\n"
6273 " -n --lines=INTEGER Number of journal entries to show\n"
6274 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
6275 " verbose, export, json, json-pretty, json-sse, cat)\n"
6276 " --plain Print unit dependencies as a list instead of a tree\n\n"
6278 " list-units [PATTERN...] List loaded units\n"
6279 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
6280 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
6281 " start NAME... Start (activate) one or more units\n"
6282 " stop NAME... Stop (deactivate) one or more units\n"
6283 " reload NAME... Reload one or more units\n"
6284 " restart NAME... Start or restart one or more units\n"
6285 " try-restart NAME... Restart one or more units if active\n"
6286 " reload-or-restart NAME... Reload one or more units if possible,\n"
6287 " otherwise start or restart\n"
6288 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
6289 " otherwise restart if active\n"
6290 " isolate NAME Start one unit and stop all others\n"
6291 " kill NAME... Send signal to processes of a unit\n"
6292 " is-active PATTERN... Check whether units are active\n"
6293 " is-failed PATTERN... Check whether units are failed\n"
6294 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
6295 " show [PATTERN...|JOB...] Show properties of one or more\n"
6296 " units/jobs or the manager\n"
6297 " cat PATTERN... Show files and drop-ins of one or more units\n"
6298 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
6299 " help PATTERN...|PID... Show manual for one or more units\n"
6300 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
6302 " list-dependencies [NAME] Recursively show units which are required\n"
6303 " or wanted by this unit or by which this\n"
6304 " unit is required or wanted\n\n"
6305 "Unit File Commands:\n"
6306 " list-unit-files [PATTERN...] List installed unit files\n"
6307 " enable NAME... Enable one or more unit files\n"
6308 " disable NAME... Disable one or more unit files\n"
6309 " reenable NAME... Reenable one or more unit files\n"
6310 " preset NAME... Enable/disable one or more unit files\n"
6311 " based on preset configuration\n"
6312 " preset-all Enable/disable all unit files based on\n"
6313 " preset configuration\n"
6314 " is-enabled NAME... Check whether unit files are enabled\n\n"
6315 " mask NAME... Mask one or more units\n"
6316 " unmask NAME... Unmask one or more units\n"
6317 " link PATH... Link one or more units files into\n"
6318 " the search path\n"
6319 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6320 " on specified one or more units\n"
6321 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6322 " on specified one or more units\n"
6323 " get-default Get the name of the default target\n"
6324 " set-default NAME Set the default target\n"
6325 " edit NAME... Edit one or more unit files\n"
6327 "Machine Commands:\n"
6328 " list-machines [PATTERN...] List local containers and host\n\n"
6330 " list-jobs [PATTERN...] List jobs\n"
6331 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
6332 "Snapshot Commands:\n"
6333 " snapshot [NAME] Create a snapshot\n"
6334 " delete NAME... Remove one or more snapshots\n\n"
6335 "Environment Commands:\n"
6336 " show-environment Dump environment\n"
6337 " set-environment NAME=VALUE... Set one or more environment variables\n"
6338 " unset-environment NAME... Unset one or more environment variables\n"
6339 " import-environment NAME... Import all, one or more environment variables\n\n"
6340 "Manager Lifecycle Commands:\n"
6341 " daemon-reload Reload systemd manager configuration\n"
6342 " daemon-reexec Reexecute systemd manager\n\n"
6343 "System Commands:\n"
6344 " is-system-running Check whether system is fully running\n"
6345 " default Enter system default mode\n"
6346 " rescue Enter system rescue mode\n"
6347 " emergency Enter system emergency mode\n"
6348 " halt Shut down and halt the system\n"
6349 " poweroff Shut down and power-off the system\n"
6350 " reboot [ARG] Shut down and reboot the system\n"
6351 " kexec Shut down and reboot the system with kexec\n"
6352 " exit Request user instance exit\n"
6353 " switch-root ROOT [INIT] Change to a different root file system\n"
6354 " suspend Suspend the system\n"
6355 " hibernate Hibernate the system\n"
6356 " hybrid-sleep Hibernate and suspend the system\n",
6357 program_invocation_short_name);
6360 static void halt_help(void) {
6361 printf("%s [OPTIONS...]%s\n\n"
6362 "%s the system.\n\n"
6363 " --help Show this help\n"
6364 " --halt Halt the machine\n"
6365 " -p --poweroff Switch off the machine\n"
6366 " --reboot Reboot the machine\n"
6367 " -f --force Force immediate halt/power-off/reboot\n"
6368 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
6369 " -d --no-wtmp Don't write wtmp record\n"
6370 " --no-wall Don't send wall message before halt/power-off/reboot\n",
6371 program_invocation_short_name,
6372 arg_action == ACTION_REBOOT ? " [ARG]" : "",
6373 arg_action == ACTION_REBOOT ? "Reboot" :
6374 arg_action == ACTION_POWEROFF ? "Power off" :
6378 static void shutdown_help(void) {
6379 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
6380 "Shut down the system.\n\n"
6381 " --help Show this help\n"
6382 " -H --halt Halt the machine\n"
6383 " -P --poweroff Power-off the machine\n"
6384 " -r --reboot Reboot the machine\n"
6385 " -h Equivalent to --poweroff, overridden by --halt\n"
6386 " -k Don't halt/power-off/reboot, just send warnings\n"
6387 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6388 " -c Cancel a pending shutdown\n",
6389 program_invocation_short_name);
6392 static void telinit_help(void) {
6393 printf("%s [OPTIONS...] {COMMAND}\n\n"
6394 "Send control commands to the init daemon.\n\n"
6395 " --help Show this help\n"
6396 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
6398 " 0 Power-off the machine\n"
6399 " 6 Reboot the machine\n"
6400 " 2, 3, 4, 5 Start runlevelX.target unit\n"
6401 " 1, s, S Enter rescue mode\n"
6402 " q, Q Reload init daemon configuration\n"
6403 " u, U Reexecute init daemon\n",
6404 program_invocation_short_name);
6407 static void runlevel_help(void) {
6408 printf("%s [OPTIONS...]\n\n"
6409 "Prints the previous and current runlevel of the init system.\n\n"
6410 " --help Show this help\n",
6411 program_invocation_short_name);
6414 static void help_types(void) {
6419 puts("Available unit types:");
6420 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
6421 t = unit_type_to_string(i);
6427 static int systemctl_parse_argv(int argc, char *argv[]) {
6436 ARG_IGNORE_DEPENDENCIES,
6448 ARG_NO_ASK_PASSWORD,
6458 static const struct option options[] = {
6459 { "help", no_argument, NULL, 'h' },
6460 { "version", no_argument, NULL, ARG_VERSION },
6461 { "type", required_argument, NULL, 't' },
6462 { "property", required_argument, NULL, 'p' },
6463 { "all", no_argument, NULL, 'a' },
6464 { "reverse", no_argument, NULL, ARG_REVERSE },
6465 { "after", no_argument, NULL, ARG_AFTER },
6466 { "before", no_argument, NULL, ARG_BEFORE },
6467 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
6468 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
6469 { "full", no_argument, NULL, 'l' },
6470 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
6471 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
6472 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
6473 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
6474 { "ignore-inhibitors", no_argument, NULL, 'i' },
6475 { "user", no_argument, NULL, ARG_USER },
6476 { "system", no_argument, NULL, ARG_SYSTEM },
6477 { "global", no_argument, NULL, ARG_GLOBAL },
6478 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
6479 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
6480 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
6481 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6482 { "quiet", no_argument, NULL, 'q' },
6483 { "root", required_argument, NULL, ARG_ROOT },
6484 { "force", no_argument, NULL, ARG_FORCE },
6485 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
6486 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
6487 { "signal", required_argument, NULL, 's' },
6488 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
6489 { "host", required_argument, NULL, 'H' },
6490 { "machine", required_argument, NULL, 'M' },
6491 { "runtime", no_argument, NULL, ARG_RUNTIME },
6492 { "lines", required_argument, NULL, 'n' },
6493 { "output", required_argument, NULL, 'o' },
6494 { "plain", no_argument, NULL, ARG_PLAIN },
6495 { "state", required_argument, NULL, ARG_STATE },
6496 { "recursive", no_argument, NULL, 'r' },
6497 { "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
6506 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
6515 puts(PACKAGE_STRING);
6516 puts(SYSTEMD_FEATURES);
6520 const char *word, *state;
6523 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6524 _cleanup_free_ char *type;
6526 type = strndup(word, size);
6530 if (streq(type, "help")) {
6535 if (unit_type_from_string(type) >= 0) {
6536 if (strv_push(&arg_types, type))
6542 /* It's much nicer to use --state= for
6543 * load states, but let's support this
6544 * in --types= too for compatibility
6545 * with old versions */
6546 if (unit_load_state_from_string(optarg) >= 0) {
6547 if (strv_push(&arg_states, type) < 0)
6553 log_error("Unknown unit type or load state '%s'.", type);
6554 log_info("Use -t help to see a list of allowed values.");
6562 /* Make sure that if the empty property list
6563 was specified, we won't show any properties. */
6564 if (isempty(optarg) && !arg_properties) {
6565 arg_properties = new0(char*, 1);
6566 if (!arg_properties)
6569 const char *word, *state;
6572 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6575 prop = strndup(word, size);
6579 if (strv_consume(&arg_properties, prop) < 0)
6584 /* If the user asked for a particular
6585 * property, show it to him, even if it is
6597 arg_dependency = DEPENDENCY_REVERSE;
6601 arg_dependency = DEPENDENCY_AFTER;
6605 arg_dependency = DEPENDENCY_BEFORE;
6608 case ARG_SHOW_TYPES:
6609 arg_show_types = true;
6613 arg_job_mode = optarg;
6617 arg_job_mode = "fail";
6620 case ARG_IRREVERSIBLE:
6621 arg_job_mode = "replace-irreversibly";
6624 case ARG_IGNORE_DEPENDENCIES:
6625 arg_job_mode = "ignore-dependencies";
6629 arg_scope = UNIT_FILE_USER;
6633 arg_scope = UNIT_FILE_SYSTEM;
6637 arg_scope = UNIT_FILE_GLOBAL;
6641 arg_no_block = true;
6645 arg_no_legend = true;
6649 arg_no_pager = true;
6665 if (strv_extend(&arg_states, "failed") < 0)
6683 arg_no_reload = true;
6687 arg_kill_who = optarg;
6691 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
6692 log_error("Failed to parse signal string %s.", optarg);
6697 case ARG_NO_ASK_PASSWORD:
6698 arg_ask_password = false;
6702 arg_transport = BUS_TRANSPORT_REMOTE;
6707 arg_transport = BUS_TRANSPORT_CONTAINER;
6716 if (safe_atou(optarg, &arg_lines) < 0) {
6717 log_error("Failed to parse lines '%s'", optarg);
6723 arg_output = output_mode_from_string(optarg);
6724 if (arg_output < 0) {
6725 log_error("Unknown output '%s'.", optarg);
6731 arg_ignore_inhibitors = true;
6739 const char *word, *state;
6742 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6745 s = strndup(word, size);
6749 if (strv_consume(&arg_states, s) < 0)
6756 if (geteuid() != 0) {
6757 log_error("--recursive requires root privileges.");
6761 arg_recursive = true;
6764 case ARG_PRESET_MODE:
6766 arg_preset_mode = unit_file_preset_mode_from_string(optarg);
6767 if (arg_preset_mode < 0) {
6768 log_error("Failed to parse preset mode: %s.", optarg);
6778 assert_not_reached("Unhandled option");
6781 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
6782 log_error("Cannot access user instance remotely.");
6789 static int halt_parse_argv(int argc, char *argv[]) {
6798 static const struct option options[] = {
6799 { "help", no_argument, NULL, ARG_HELP },
6800 { "halt", no_argument, NULL, ARG_HALT },
6801 { "poweroff", no_argument, NULL, 'p' },
6802 { "reboot", no_argument, NULL, ARG_REBOOT },
6803 { "force", no_argument, NULL, 'f' },
6804 { "wtmp-only", no_argument, NULL, 'w' },
6805 { "no-wtmp", no_argument, NULL, 'd' },
6806 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6815 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
6816 if (runlevel == '0' || runlevel == '6')
6819 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
6827 arg_action = ACTION_HALT;
6831 if (arg_action != ACTION_REBOOT)
6832 arg_action = ACTION_POWEROFF;
6836 arg_action = ACTION_REBOOT;
6858 /* Compatibility nops */
6865 assert_not_reached("Unhandled option");
6868 if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
6869 r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL);
6872 } else if (optind < argc) {
6873 log_error("Too many arguments.");
6880 static int parse_time_spec(const char *t, usec_t *_u) {
6884 if (streq(t, "now"))
6886 else if (!strchr(t, ':')) {
6889 if (safe_atou64(t, &u) < 0)
6892 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
6901 hour = strtol(t, &e, 10);
6902 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
6905 minute = strtol(e+1, &e, 10);
6906 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
6909 n = now(CLOCK_REALTIME);
6910 s = (time_t) (n / USEC_PER_SEC);
6912 assert_se(localtime_r(&s, &tm));
6914 tm.tm_hour = (int) hour;
6915 tm.tm_min = (int) minute;
6918 assert_se(s = mktime(&tm));
6920 *_u = (usec_t) s * USEC_PER_SEC;
6923 *_u += USEC_PER_DAY;
6929 static int shutdown_parse_argv(int argc, char *argv[]) {
6936 static const struct option options[] = {
6937 { "help", no_argument, NULL, ARG_HELP },
6938 { "halt", no_argument, NULL, 'H' },
6939 { "poweroff", no_argument, NULL, 'P' },
6940 { "reboot", no_argument, NULL, 'r' },
6941 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
6942 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6951 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0)
6959 arg_action = ACTION_HALT;
6963 arg_action = ACTION_POWEROFF;
6968 arg_action = ACTION_KEXEC;
6970 arg_action = ACTION_REBOOT;
6974 arg_action = ACTION_KEXEC;
6978 if (arg_action != ACTION_HALT)
6979 arg_action = ACTION_POWEROFF;
6992 /* Compatibility nops */
6996 arg_action = ACTION_CANCEL_SHUTDOWN;
7003 assert_not_reached("Unhandled option");
7006 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
7007 r = parse_time_spec(argv[optind], &arg_when);
7009 log_error("Failed to parse time specification: %s", argv[optind]);
7013 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
7015 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
7016 /* No time argument for shutdown cancel */
7017 arg_wall = argv + optind;
7018 else if (argc > optind + 1)
7019 /* We skip the time argument */
7020 arg_wall = argv + optind + 1;
7027 static int telinit_parse_argv(int argc, char *argv[]) {
7034 static const struct option options[] = {
7035 { "help", no_argument, NULL, ARG_HELP },
7036 { "no-wall", no_argument, NULL, ARG_NO_WALL },
7040 static const struct {
7044 { '0', ACTION_POWEROFF },
7045 { '6', ACTION_REBOOT },
7046 { '1', ACTION_RESCUE },
7047 { '2', ACTION_RUNLEVEL2 },
7048 { '3', ACTION_RUNLEVEL3 },
7049 { '4', ACTION_RUNLEVEL4 },
7050 { '5', ACTION_RUNLEVEL5 },
7051 { 's', ACTION_RESCUE },
7052 { 'S', ACTION_RESCUE },
7053 { 'q', ACTION_RELOAD },
7054 { 'Q', ACTION_RELOAD },
7055 { 'u', ACTION_REEXEC },
7056 { 'U', ACTION_REEXEC }
7065 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
7080 assert_not_reached("Unhandled option");
7083 if (optind >= argc) {
7084 log_error("%s: required argument missing.",
7085 program_invocation_short_name);
7089 if (optind + 1 < argc) {
7090 log_error("Too many arguments.");
7094 if (strlen(argv[optind]) != 1) {
7095 log_error("Expected single character argument.");
7099 for (i = 0; i < ELEMENTSOF(table); i++)
7100 if (table[i].from == argv[optind][0])
7103 if (i >= ELEMENTSOF(table)) {
7104 log_error("Unknown command '%s'.", argv[optind]);
7108 arg_action = table[i].to;
7115 static int runlevel_parse_argv(int argc, char *argv[]) {
7121 static const struct option options[] = {
7122 { "help", no_argument, NULL, ARG_HELP },
7131 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
7142 assert_not_reached("Unhandled option");
7145 if (optind < argc) {
7146 log_error("Too many arguments.");
7153 static int parse_argv(int argc, char *argv[]) {
7157 if (program_invocation_short_name) {
7159 if (strstr(program_invocation_short_name, "halt")) {
7160 arg_action = ACTION_HALT;
7161 return halt_parse_argv(argc, argv);
7162 } else if (strstr(program_invocation_short_name, "poweroff")) {
7163 arg_action = ACTION_POWEROFF;
7164 return halt_parse_argv(argc, argv);
7165 } else if (strstr(program_invocation_short_name, "reboot")) {
7167 arg_action = ACTION_KEXEC;
7169 arg_action = ACTION_REBOOT;
7170 return halt_parse_argv(argc, argv);
7171 } else if (strstr(program_invocation_short_name, "shutdown")) {
7172 arg_action = ACTION_POWEROFF;
7173 return shutdown_parse_argv(argc, argv);
7174 } else if (strstr(program_invocation_short_name, "init")) {
7176 if (sd_booted() > 0) {
7177 arg_action = _ACTION_INVALID;
7178 return telinit_parse_argv(argc, argv);
7180 /* Hmm, so some other init system is
7181 * running, we need to forward this
7182 * request to it. For now we simply
7183 * guess that it is Upstart. */
7185 execv(TELINIT, argv);
7187 log_error("Couldn't find an alternative telinit implementation to spawn.");
7191 } else if (strstr(program_invocation_short_name, "runlevel")) {
7192 arg_action = ACTION_RUNLEVEL;
7193 return runlevel_parse_argv(argc, argv);
7197 arg_action = ACTION_SYSTEMCTL;
7198 return systemctl_parse_argv(argc, argv);
7201 _pure_ static int action_to_runlevel(void) {
7203 static const char table[_ACTION_MAX] = {
7204 [ACTION_HALT] = '0',
7205 [ACTION_POWEROFF] = '0',
7206 [ACTION_REBOOT] = '6',
7207 [ACTION_RUNLEVEL2] = '2',
7208 [ACTION_RUNLEVEL3] = '3',
7209 [ACTION_RUNLEVEL4] = '4',
7210 [ACTION_RUNLEVEL5] = '5',
7211 [ACTION_RESCUE] = '1'
7214 assert(arg_action < _ACTION_MAX);
7216 return table[arg_action];
7219 static int talk_initctl(void) {
7221 struct init_request request = {
7222 .magic = INIT_MAGIC,
7224 .cmd = INIT_CMD_RUNLVL
7227 _cleanup_close_ int fd = -1;
7231 rl = action_to_runlevel();
7235 request.runlevel = rl;
7237 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
7239 if (errno == ENOENT)
7242 log_error_errno(errno, "Failed to open "INIT_FIFO": %m");
7246 r = loop_write(fd, &request, sizeof(request), false);
7248 return log_error_errno(r, "Failed to write to "INIT_FIFO": %m");
7253 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
7255 static const struct {
7263 int (* const dispatch)(sd_bus *bus, char **args);
7269 { "list-units", MORE, 0, list_units },
7270 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
7271 { "list-sockets", MORE, 1, list_sockets },
7272 { "list-timers", MORE, 1, list_timers },
7273 { "list-jobs", MORE, 1, list_jobs },
7274 { "list-machines", MORE, 1, list_machines },
7275 { "clear-jobs", EQUAL, 1, daemon_reload },
7276 { "cancel", MORE, 2, cancel_job },
7277 { "start", MORE, 2, start_unit },
7278 { "stop", MORE, 2, start_unit },
7279 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
7280 { "reload", MORE, 2, start_unit },
7281 { "restart", MORE, 2, start_unit },
7282 { "try-restart", MORE, 2, start_unit },
7283 { "reload-or-restart", MORE, 2, start_unit },
7284 { "reload-or-try-restart", MORE, 2, start_unit },
7285 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
7286 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
7287 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
7288 { "isolate", EQUAL, 2, start_unit },
7289 { "kill", MORE, 2, kill_unit },
7290 { "is-active", MORE, 2, check_unit_active },
7291 { "check", MORE, 2, check_unit_active },
7292 { "is-failed", MORE, 2, check_unit_failed },
7293 { "show", MORE, 1, show },
7294 { "cat", MORE, 2, cat },
7295 { "status", MORE, 1, show },
7296 { "help", MORE, 2, show },
7297 { "snapshot", LESS, 2, snapshot },
7298 { "delete", MORE, 2, delete_snapshot },
7299 { "daemon-reload", EQUAL, 1, daemon_reload },
7300 { "daemon-reexec", EQUAL, 1, daemon_reload },
7301 { "show-environment", EQUAL, 1, show_environment },
7302 { "set-environment", MORE, 2, set_environment },
7303 { "unset-environment", MORE, 2, set_environment },
7304 { "import-environment", MORE, 1, import_environment},
7305 { "halt", EQUAL, 1, start_special, FORCE },
7306 { "poweroff", EQUAL, 1, start_special, FORCE },
7307 { "reboot", EQUAL, 1, start_special, FORCE },
7308 { "kexec", EQUAL, 1, start_special },
7309 { "suspend", EQUAL, 1, start_special },
7310 { "hibernate", EQUAL, 1, start_special },
7311 { "hybrid-sleep", EQUAL, 1, start_special },
7312 { "default", EQUAL, 1, start_special },
7313 { "rescue", EQUAL, 1, start_special },
7314 { "emergency", EQUAL, 1, start_special },
7315 { "exit", EQUAL, 1, start_special },
7316 { "reset-failed", MORE, 1, reset_failed },
7317 { "enable", MORE, 2, enable_unit, NOBUS },
7318 { "disable", MORE, 2, enable_unit, NOBUS },
7319 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
7320 { "reenable", MORE, 2, enable_unit, NOBUS },
7321 { "preset", MORE, 2, enable_unit, NOBUS },
7322 { "preset-all", EQUAL, 1, preset_all, NOBUS },
7323 { "mask", MORE, 2, enable_unit, NOBUS },
7324 { "unmask", MORE, 2, enable_unit, NOBUS },
7325 { "link", MORE, 2, enable_unit, NOBUS },
7326 { "switch-root", MORE, 2, switch_root },
7327 { "list-dependencies", LESS, 2, list_dependencies },
7328 { "set-default", EQUAL, 2, set_default, NOBUS },
7329 { "get-default", EQUAL, 1, get_default, NOBUS },
7330 { "set-property", MORE, 3, set_property },
7331 { "is-system-running", EQUAL, 1, is_system_running },
7332 { "add-wants", MORE, 3, add_dependency, NOBUS },
7333 { "add-requires", MORE, 3, add_dependency, NOBUS },
7334 { "edit", MORE, 2, edit, NOBUS },
7343 left = argc - optind;
7345 /* Special rule: no arguments (left == 0) means "list-units" */
7347 if (streq(argv[optind], "help") && !argv[optind+1]) {
7348 log_error("This command expects one or more "
7349 "unit names. Did you mean --help?");
7353 for (; verb->verb; verb++)
7354 if (streq(argv[optind], verb->verb))
7357 log_error("Unknown operation '%s'.", argv[optind]);
7362 switch (verb->argc_cmp) {
7365 if (left != verb->argc) {
7366 log_error("Invalid number of arguments.");
7373 if (left < verb->argc) {
7374 log_error("Too few arguments.");
7381 if (left > verb->argc) {
7382 log_error("Too many arguments.");
7389 assert_not_reached("Unknown comparison operator.");
7392 /* Require a bus connection for all operations but
7394 if (verb->bus == NOBUS) {
7395 if (!bus && !avoid_bus()) {
7396 log_error_errno(bus_error, "Failed to get D-Bus connection: %m");
7401 if (running_in_chroot() > 0) {
7402 log_info("Running in chroot, ignoring request.");
7406 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
7407 log_error_errno(bus_error, "Failed to get D-Bus connection: %m");
7412 return verb->dispatch(bus, argv + optind);
7415 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
7417 struct sd_shutdown_command c = {
7424 union sockaddr_union sockaddr = {
7425 .un.sun_family = AF_UNIX,
7426 .un.sun_path = "/run/systemd/shutdownd",
7429 struct iovec iovec[2] = {{
7430 .iov_base = (char*) &c,
7431 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
7434 struct msghdr msghdr = {
7435 .msg_name = &sockaddr,
7436 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
7437 + strlen("/run/systemd/shutdownd"),
7442 _cleanup_close_ int fd;
7444 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
7448 if (!isempty(message)) {
7449 iovec[1].iov_base = (char*) message;
7450 iovec[1].iov_len = strlen(message);
7451 msghdr.msg_iovlen++;
7454 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
7460 static int reload_with_fallback(sd_bus *bus) {
7463 /* First, try systemd via D-Bus. */
7464 if (daemon_reload(bus, NULL) >= 0)
7468 /* Nothing else worked, so let's try signals */
7469 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
7471 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0)
7472 return log_error_errno(errno, "kill() failed: %m");
7477 static int start_with_fallback(sd_bus *bus) {
7480 /* First, try systemd via D-Bus. */
7481 if (start_unit(bus, NULL) >= 0)
7485 /* Nothing else worked, so let's try
7487 if (talk_initctl() > 0)
7490 log_error("Failed to talk to init daemon.");
7494 warn_wall(arg_action);
7498 static int halt_now(enum action a) {
7500 /* The kernel will automaticall flush ATA disks and suchlike
7501 * on reboot(), but the file systems need to be synce'd
7502 * explicitly in advance. */
7505 /* Make sure C-A-D is handled by the kernel from this point
7507 reboot(RB_ENABLE_CAD);
7512 log_info("Halting.");
7513 reboot(RB_HALT_SYSTEM);
7516 case ACTION_POWEROFF:
7517 log_info("Powering off.");
7518 reboot(RB_POWER_OFF);
7521 case ACTION_REBOOT: {
7522 _cleanup_free_ char *param = NULL;
7524 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
7525 log_info("Rebooting with argument '%s'.", param);
7526 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
7527 LINUX_REBOOT_CMD_RESTART2, param);
7530 log_info("Rebooting.");
7531 reboot(RB_AUTOBOOT);
7536 assert_not_reached("Unknown action.");
7540 static int halt_main(sd_bus *bus) {
7543 r = check_inhibitors(bus, arg_action);
7547 if (geteuid() != 0) {
7548 /* Try logind if we are a normal user and no special
7549 * mode applies. Maybe PolicyKit allows us to shutdown
7552 if (arg_when <= 0 &&
7555 (arg_action == ACTION_POWEROFF ||
7556 arg_action == ACTION_REBOOT)) {
7557 r = reboot_with_logind(bus, arg_action);
7562 log_error("Must be root.");
7567 _cleanup_free_ char *m;
7569 m = strv_join(arg_wall, " ");
7573 r = send_shutdownd(arg_when,
7574 arg_action == ACTION_HALT ? 'H' :
7575 arg_action == ACTION_POWEROFF ? 'P' :
7576 arg_action == ACTION_KEXEC ? 'K' :
7583 log_warning_errno(r, "Failed to talk to shutdownd, proceeding with immediate shutdown: %m");
7585 char date[FORMAT_TIMESTAMP_MAX];
7587 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
7588 format_timestamp(date, sizeof(date), arg_when));
7593 if (!arg_dry && !arg_force)
7594 return start_with_fallback(bus);
7597 if (sd_booted() > 0)
7598 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7600 r = utmp_put_shutdown();
7602 log_warning_errno(r, "Failed to write utmp record: %m");
7609 r = halt_now(arg_action);
7610 log_error_errno(r, "Failed to reboot: %m");
7615 static int runlevel_main(void) {
7616 int r, runlevel, previous;
7618 r = utmp_get_runlevel(&runlevel, &previous);
7625 previous <= 0 ? 'N' : previous,
7626 runlevel <= 0 ? 'N' : runlevel);
7631 int main(int argc, char*argv[]) {
7632 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
7635 setlocale(LC_ALL, "");
7636 log_parse_environment();
7639 /* Explicitly not on_tty() to avoid setting cached value.
7640 * This becomes relevant for piping output which might be
7642 original_stdout_is_tty = isatty(STDOUT_FILENO);
7644 r = parse_argv(argc, argv);
7648 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
7649 * let's shortcut this */
7650 if (arg_action == ACTION_RUNLEVEL) {
7651 r = runlevel_main();
7655 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
7656 log_info("Running in chroot, ignoring request.");
7662 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
7664 /* systemctl_main() will print an error message for the bus
7665 * connection, but only if it needs to */
7667 switch (arg_action) {
7669 case ACTION_SYSTEMCTL:
7670 r = systemctl_main(bus, argc, argv, r);
7674 case ACTION_POWEROFF:
7680 case ACTION_RUNLEVEL2:
7681 case ACTION_RUNLEVEL3:
7682 case ACTION_RUNLEVEL4:
7683 case ACTION_RUNLEVEL5:
7685 case ACTION_EMERGENCY:
7686 case ACTION_DEFAULT:
7687 r = start_with_fallback(bus);
7692 r = reload_with_fallback(bus);
7695 case ACTION_CANCEL_SHUTDOWN: {
7696 _cleanup_free_ char *m = NULL;
7699 m = strv_join(arg_wall, " ");
7706 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
7708 log_warning_errno(r, "Failed to talk to shutdownd, shutdown hasn't been cancelled: %m");
7712 case ACTION_RUNLEVEL:
7713 case _ACTION_INVALID:
7715 assert_not_reached("Unknown action");
7720 ask_password_agent_close();
7721 polkit_agent_close();
7723 strv_free(arg_types);
7724 strv_free(arg_states);
7725 strv_free(arg_properties);
7727 return r < 0 ? EXIT_FAILURE : r;