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>
41 #include "sd-daemon.h"
42 #include "sd-shutdown.h"
49 #include "utmp-wtmp.h"
52 #include "path-util.h"
54 #include "cgroup-show.h"
55 #include "cgroup-util.h"
57 #include "path-lookup.h"
58 #include "conf-parser.h"
59 #include "exit-status.h"
61 #include "unit-name.h"
63 #include "spawn-ask-password-agent.h"
64 #include "spawn-polkit-agent.h"
66 #include "logs-show.h"
67 #include "socket-util.h"
72 #include "bus-message.h"
73 #include "bus-error.h"
74 #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();
178 static void polkit_agent_open_if_enabled(void) {
180 /* Open the polkit agent as a child process if necessary */
182 if (!arg_ask_password)
185 if (arg_scope != UNIT_FILE_SYSTEM)
188 if (arg_transport != BUS_TRANSPORT_LOCAL)
194 static OutputFlags get_output_flags(void) {
196 arg_all * OUTPUT_SHOW_ALL |
197 arg_full * OUTPUT_FULL_WIDTH |
198 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
199 on_tty() * OUTPUT_COLOR |
200 !arg_quiet * OUTPUT_WARN_CUTOFF;
203 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
206 if (!sd_bus_error_is_set(error))
209 if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) ||
210 sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
211 sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
212 sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
213 return EXIT_NOPERMISSION;
215 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
216 return EXIT_NOTINSTALLED;
218 if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
219 sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED))
220 return EXIT_NOTIMPLEMENTED;
222 if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
223 return EXIT_NOTCONFIGURED;
231 static void warn_wall(enum action a) {
232 static const char *table[_ACTION_MAX] = {
233 [ACTION_HALT] = "The system is going down for system halt NOW!",
234 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
235 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
236 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
237 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
238 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
239 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
246 _cleanup_free_ char *p;
248 p = strv_join(arg_wall, " ");
255 utmp_wall(p, NULL, NULL);
263 utmp_wall(table[a], NULL, NULL);
266 static bool avoid_bus(void) {
268 if (running_in_chroot() > 0)
271 if (sd_booted() <= 0)
274 if (!isempty(arg_root))
277 if (arg_scope == UNIT_FILE_GLOBAL)
283 static int compare_unit_info(const void *a, const void *b) {
284 const UnitInfo *u = a, *v = b;
288 /* First, order by machine */
289 if (!u->machine && v->machine)
291 if (u->machine && !v->machine)
293 if (u->machine && v->machine) {
294 r = strcasecmp(u->machine, v->machine);
299 /* Second, order by unit type */
300 d1 = strrchr(u->id, '.');
301 d2 = strrchr(v->id, '.');
303 r = strcasecmp(d1, d2);
308 /* Third, order by name */
309 return strcasecmp(u->id, v->id);
312 static bool output_show_unit(const UnitInfo *u, char **patterns) {
313 if (!strv_fnmatch_or_empty(patterns, u->id, FNM_NOESCAPE))
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") && !arg_plain) {
430 on_loaded = ansi_highlight_red();
431 on_circle = ansi_highlight_yellow();
432 off_loaded = off_circle = ansi_highlight_off();
434 } else if (streq(u->active_state, "failed") && !arg_plain) {
435 on_circle = on_active = ansi_highlight_red();
436 off_circle = off_active = ansi_highlight_off();
441 j = strjoin(u->machine, ":", u->id, NULL);
450 e = ellipsize(id, id_len, 33);
458 printf("%s%s%s ", on_circle, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_circle);
460 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
461 on_active, id_len, id, off_active,
462 on_loaded, load_len, u->load_state, off_loaded,
463 on_active, active_len, u->active_state,
464 sub_len, u->sub_state, off_active,
465 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
468 printf("%.*s\n", desc_len, u->description);
470 printf("%s\n", u->description);
473 if (!arg_no_legend) {
474 const char *on, *off;
478 "LOAD = Reflects whether the unit definition was properly loaded.\n"
479 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
480 "SUB = The low-level unit activation state, values depend on unit type.");
481 puts(job_count ? "JOB = Pending job for the unit.\n" : "");
482 on = ansi_highlight();
483 off = ansi_highlight_off();
485 on = ansi_highlight_red();
486 off = ansi_highlight_off();
490 printf("%s%u loaded units listed.%s\n"
491 "To show all installed unit files use 'systemctl list-unit-files'.\n",
494 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
495 "To show all installed unit files use 'systemctl list-unit-files'.\n",
502 static int get_unit_list(
506 UnitInfo **unit_infos,
508 sd_bus_message **_reply) {
510 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
511 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
512 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
521 r = sd_bus_message_new_method_call(
524 "org.freedesktop.systemd1",
525 "/org/freedesktop/systemd1",
526 "org.freedesktop.systemd1.Manager",
527 "ListUnitsFiltered");
530 return bus_log_create_error(r);
532 r = sd_bus_message_append_strv(m, arg_states);
534 return bus_log_create_error(r);
536 r = sd_bus_call(bus, m, 0, &error, &reply);
538 log_error("Failed to list units: %s", bus_error_message(&error, r));
542 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
544 return bus_log_parse_error(r);
546 while ((r = bus_parse_unit_info(reply, &u)) > 0) {
549 if (!output_show_unit(&u, patterns))
552 if (!GREEDY_REALLOC(*unit_infos, size, c+1))
555 (*unit_infos)[c++] = u;
558 return bus_log_parse_error(r);
560 r = sd_bus_message_exit_container(reply);
562 return bus_log_parse_error(r);
570 static void message_set_freep(Set **set) {
573 while ((m = set_steal_first(*set)))
574 sd_bus_message_unref(m);
579 static int get_unit_list_recursive(
582 UnitInfo **_unit_infos,
586 _cleanup_free_ UnitInfo *unit_infos = NULL;
587 _cleanup_(message_set_freep) Set *replies;
588 sd_bus_message *reply;
596 replies = set_new(NULL);
600 c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
604 r = set_put(replies, reply);
606 sd_bus_message_unref(reply);
611 _cleanup_strv_free_ char **machines = NULL;
614 r = sd_get_machine_names(&machines);
618 STRV_FOREACH(i, machines) {
619 _cleanup_bus_close_unref_ sd_bus *container = NULL;
622 r = sd_bus_open_system_machine(&container, *i);
624 log_error_errno(r, "Failed to connect to container %s: %m", *i);
628 k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
634 r = set_put(replies, reply);
636 sd_bus_message_unref(reply);
641 *_machines = machines;
646 *_unit_infos = unit_infos;
655 static int list_units(sd_bus *bus, char **args) {
656 _cleanup_free_ UnitInfo *unit_infos = NULL;
657 _cleanup_(message_set_freep) Set *replies = NULL;
658 _cleanup_strv_free_ char **machines = NULL;
661 pager_open_if_enabled();
663 r = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
667 qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
668 return output_units_list(unit_infos, r);
671 static int get_triggered_units(
676 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
679 r = sd_bus_get_property_strv(
681 "org.freedesktop.systemd1",
683 "org.freedesktop.systemd1.Unit",
689 log_error("Failed to determine triggers: %s", bus_error_message(&error, r));
694 static int get_listening(
696 const char* unit_path,
699 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
700 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
701 const char *type, *path;
704 r = sd_bus_get_property(
706 "org.freedesktop.systemd1",
708 "org.freedesktop.systemd1.Socket",
714 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r));
718 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
720 return bus_log_parse_error(r);
722 while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
724 r = strv_extend(listening, type);
728 r = strv_extend(listening, path);
735 return bus_log_parse_error(r);
737 r = sd_bus_message_exit_container(reply);
739 return bus_log_parse_error(r);
751 /* Note: triggered is a list here, although it almost certainly
752 * will always be one unit. Nevertheless, dbus API allows for multiple
753 * values, so let's follow that. */
756 /* The strv above is shared. free is set only in the first one. */
760 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
766 if (!a->machine && b->machine)
768 if (a->machine && !b->machine)
770 if (a->machine && b->machine) {
771 o = strcasecmp(a->machine, b->machine);
776 o = strcmp(a->path, b->path);
778 o = strcmp(a->type, b->type);
783 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
784 struct socket_info *s;
785 unsigned pathlen = strlen("LISTEN"),
786 typelen = strlen("TYPE") * arg_show_types,
787 socklen = strlen("UNIT"),
788 servlen = strlen("ACTIVATES");
789 const char *on, *off;
791 for (s = socket_infos; s < socket_infos + cs; s++) {
795 socklen = MAX(socklen, strlen(s->id));
797 typelen = MAX(typelen, strlen(s->type));
798 pathlen = MAX(pathlen, strlen(s->path) + (s->machine ? strlen(s->machine)+1 : 0));
800 STRV_FOREACH(a, s->triggered)
801 tmp += strlen(*a) + 2*(a != s->triggered);
802 servlen = MAX(servlen, tmp);
807 printf("%-*s %-*.*s%-*s %s\n",
809 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
813 for (s = socket_infos; s < socket_infos + cs; s++) {
814 _cleanup_free_ char *j = NULL;
819 j = strjoin(s->machine, ":", s->path, NULL);
827 printf("%-*s %-*s %-*s",
828 pathlen, path, typelen, s->type, socklen, s->id);
831 pathlen, path, socklen, s->id);
832 STRV_FOREACH(a, s->triggered)
834 a == s->triggered ? "" : ",", *a);
838 on = ansi_highlight();
839 off = ansi_highlight_off();
843 on = ansi_highlight_red();
844 off = ansi_highlight_off();
847 if (!arg_no_legend) {
848 printf("%s%u sockets listed.%s\n", on, cs, off);
850 printf("Pass --all to see loaded but inactive sockets, too.\n");
856 static int list_sockets(sd_bus *bus, char **args) {
857 _cleanup_(message_set_freep) Set *replies = NULL;
858 _cleanup_strv_free_ char **machines = NULL;
859 _cleanup_free_ UnitInfo *unit_infos = NULL;
860 _cleanup_free_ struct socket_info *socket_infos = NULL;
862 struct socket_info *s;
867 pager_open_if_enabled();
869 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
873 for (u = unit_infos; u < unit_infos + n; u++) {
874 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
877 if (!endswith(u->id, ".socket"))
880 r = get_triggered_units(bus, u->unit_path, &triggered);
884 c = get_listening(bus, u->unit_path, &listening);
890 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
895 for (i = 0; i < c; i++)
896 socket_infos[cs + i] = (struct socket_info) {
897 .machine = u->machine,
899 .type = listening[i*2],
900 .path = listening[i*2 + 1],
901 .triggered = triggered,
902 .own_triggered = i==0,
905 /* from this point on we will cleanup those socket_infos */
908 listening = triggered = NULL; /* avoid cleanup */
911 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
912 (__compar_fn_t) socket_info_compare);
914 output_sockets_list(socket_infos, cs);
917 assert(cs == 0 || socket_infos);
918 for (s = socket_infos; s < socket_infos + cs; s++) {
921 if (s->own_triggered)
922 strv_free(s->triggered);
928 static int get_next_elapse(
931 dual_timestamp *next) {
933 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
941 r = sd_bus_get_property_trivial(
943 "org.freedesktop.systemd1",
945 "org.freedesktop.systemd1.Timer",
946 "NextElapseUSecMonotonic",
951 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
955 r = sd_bus_get_property_trivial(
957 "org.freedesktop.systemd1",
959 "org.freedesktop.systemd1.Timer",
960 "NextElapseUSecRealtime",
965 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
973 static int get_last_trigger(
978 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
985 r = sd_bus_get_property_trivial(
987 "org.freedesktop.systemd1",
989 "org.freedesktop.systemd1.Timer",
995 log_error("Failed to get last trigger time: %s", bus_error_message(&error, r));
1003 const char* machine;
1006 usec_t last_trigger;
1010 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
1016 if (!a->machine && b->machine)
1018 if (a->machine && !b->machine)
1020 if (a->machine && b->machine) {
1021 o = strcasecmp(a->machine, b->machine);
1026 if (a->next_elapse < b->next_elapse)
1028 if (a->next_elapse > b->next_elapse)
1031 return strcmp(a->id, b->id);
1034 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
1035 struct timer_info *t;
1037 nextlen = strlen("NEXT"),
1038 leftlen = strlen("LEFT"),
1039 lastlen = strlen("LAST"),
1040 passedlen = strlen("PASSED"),
1041 unitlen = strlen("UNIT"),
1042 activatelen = strlen("ACTIVATES");
1044 const char *on, *off;
1046 assert(timer_infos || n == 0);
1048 for (t = timer_infos; t < timer_infos + n; t++) {
1052 if (t->next_elapse > 0) {
1053 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1055 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
1056 nextlen = MAX(nextlen, strlen(tstamp) + 1);
1058 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
1059 leftlen = MAX(leftlen, strlen(trel));
1062 if (t->last_trigger > 0) {
1063 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
1065 format_timestamp(tstamp, sizeof(tstamp), t->last_trigger);
1066 lastlen = MAX(lastlen, strlen(tstamp) + 1);
1068 format_timestamp_relative(trel, sizeof(trel), t->last_trigger);
1069 passedlen = MAX(passedlen, strlen(trel));
1072 unitlen = MAX(unitlen, strlen(t->id) + (t->machine ? strlen(t->machine)+1 : 0));
1074 STRV_FOREACH(a, t->triggered)
1075 ul += strlen(*a) + 2*(a != t->triggered);
1077 activatelen = MAX(activatelen, ul);
1082 printf("%-*s %-*s %-*s %-*s %-*s %s\n",
1086 passedlen, "PASSED",
1090 for (t = timer_infos; t < timer_infos + n; t++) {
1091 _cleanup_free_ char *j = NULL;
1093 char tstamp1[FORMAT_TIMESTAMP_MAX] = "n/a", trel1[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1094 char tstamp2[FORMAT_TIMESTAMP_MAX] = "n/a", trel2[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
1097 format_timestamp(tstamp1, sizeof(tstamp1), t->next_elapse);
1098 format_timestamp_relative(trel1, sizeof(trel1), t->next_elapse);
1100 format_timestamp(tstamp2, sizeof(tstamp2), t->last_trigger);
1101 format_timestamp_relative(trel2, sizeof(trel2), t->last_trigger);
1104 j = strjoin(t->machine, ":", t->id, NULL);
1111 printf("%-*s %-*s %-*s %-*s %-*s",
1112 nextlen, tstamp1, leftlen, trel1, lastlen, tstamp2, passedlen, trel2, unitlen, unit);
1114 STRV_FOREACH(a, t->triggered)
1116 a == t->triggered ? "" : ",", *a);
1120 on = ansi_highlight();
1121 off = ansi_highlight_off();
1125 on = ansi_highlight_red();
1126 off = ansi_highlight_off();
1129 if (!arg_no_legend) {
1130 printf("%s%u timers listed.%s\n", on, n, off);
1132 printf("Pass --all to see loaded but inactive timers, too.\n");
1138 static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
1144 if (next->monotonic != USEC_INFINITY && next->monotonic > 0) {
1147 if (next->monotonic > nw->monotonic)
1148 converted = nw->realtime + (next->monotonic - nw->monotonic);
1150 converted = nw->realtime - (nw->monotonic - next->monotonic);
1152 if (next->realtime != USEC_INFINITY && next->realtime > 0)
1153 next_elapse = MIN(converted, next->realtime);
1155 next_elapse = converted;
1158 next_elapse = next->realtime;
1163 static int list_timers(sd_bus *bus, char **args) {
1164 _cleanup_(message_set_freep) Set *replies = NULL;
1165 _cleanup_strv_free_ char **machines = NULL;
1166 _cleanup_free_ struct timer_info *timer_infos = NULL;
1167 _cleanup_free_ UnitInfo *unit_infos = NULL;
1168 struct timer_info *t;
1175 pager_open_if_enabled();
1177 n = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
1181 dual_timestamp_get(&nw);
1183 for (u = unit_infos; u < unit_infos + n; u++) {
1184 _cleanup_strv_free_ char **triggered = NULL;
1185 dual_timestamp next = {};
1188 if (!endswith(u->id, ".timer"))
1191 r = get_triggered_units(bus, u->unit_path, &triggered);
1195 r = get_next_elapse(bus, u->unit_path, &next);
1199 get_last_trigger(bus, u->unit_path, &last);
1201 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
1206 m = calc_next_elapse(&nw, &next);
1208 timer_infos[c++] = (struct timer_info) {
1209 .machine = u->machine,
1212 .last_trigger = last,
1213 .triggered = triggered,
1216 triggered = NULL; /* avoid cleanup */
1219 qsort_safe(timer_infos, c, sizeof(struct timer_info),
1220 (__compar_fn_t) timer_info_compare);
1222 output_timers_list(timer_infos, c);
1225 for (t = timer_infos; t < timer_infos + c; t++)
1226 strv_free(t->triggered);
1231 static int compare_unit_file_list(const void *a, const void *b) {
1232 const char *d1, *d2;
1233 const UnitFileList *u = a, *v = b;
1235 d1 = strrchr(u->path, '.');
1236 d2 = strrchr(v->path, '.');
1241 r = strcasecmp(d1, d2);
1246 return strcasecmp(basename(u->path), basename(v->path));
1249 static bool output_show_unit_file(const UnitFileList *u, char **patterns) {
1250 if (!strv_fnmatch_or_empty(patterns, basename(u->path), FNM_NOESCAPE))
1253 if (!strv_isempty(arg_types)) {
1256 dot = strrchr(u->path, '.');
1260 if (!strv_find(arg_types, dot+1))
1264 if (!strv_isempty(arg_states) &&
1265 !strv_find(arg_states, unit_file_state_to_string(u->state)))
1271 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
1272 unsigned max_id_len, id_cols, state_cols;
1273 const UnitFileList *u;
1275 max_id_len = strlen("UNIT FILE");
1276 state_cols = strlen("STATE");
1278 for (u = units; u < units + c; u++) {
1279 max_id_len = MAX(max_id_len, strlen(basename(u->path)));
1280 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1284 unsigned basic_cols;
1286 id_cols = MIN(max_id_len, 25u);
1287 basic_cols = 1 + id_cols + state_cols;
1288 if (basic_cols < (unsigned) columns())
1289 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1291 id_cols = max_id_len;
1294 printf("%-*s %-*s\n",
1295 id_cols, "UNIT FILE",
1296 state_cols, "STATE");
1298 for (u = units; u < units + c; u++) {
1299 _cleanup_free_ char *e = NULL;
1300 const char *on, *off;
1303 if (u->state == UNIT_FILE_MASKED ||
1304 u->state == UNIT_FILE_MASKED_RUNTIME ||
1305 u->state == UNIT_FILE_DISABLED ||
1306 u->state == UNIT_FILE_INVALID) {
1307 on = ansi_highlight_red();
1308 off = ansi_highlight_off();
1309 } else if (u->state == UNIT_FILE_ENABLED) {
1310 on = ansi_highlight_green();
1311 off = ansi_highlight_off();
1315 id = basename(u->path);
1317 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1319 printf("%-*s %s%-*s%s\n",
1320 id_cols, e ? e : id,
1321 on, state_cols, unit_file_state_to_string(u->state), off);
1325 printf("\n%u unit files listed.\n", c);
1328 static int list_unit_files(sd_bus *bus, char **args) {
1329 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1330 _cleanup_free_ UnitFileList *units = NULL;
1338 pager_open_if_enabled();
1346 h = hashmap_new(&string_hash_ops);
1350 r = unit_file_get_list(arg_scope, arg_root, h);
1352 unit_file_list_free(h);
1353 log_error_errno(r, "Failed to get unit file list: %m");
1357 n_units = hashmap_size(h);
1359 units = new(UnitFileList, n_units);
1360 if (!units && n_units > 0) {
1361 unit_file_list_free(h);
1365 HASHMAP_FOREACH(u, h, i) {
1366 if (!output_show_unit_file(u, strv_skip_first(args)))
1373 assert(c <= n_units);
1376 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1378 r = sd_bus_call_method(
1380 "org.freedesktop.systemd1",
1381 "/org/freedesktop/systemd1",
1382 "org.freedesktop.systemd1.Manager",
1388 log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1392 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1394 return bus_log_parse_error(r);
1396 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1398 if (!GREEDY_REALLOC(units, size, c + 1))
1401 units[c] = (struct UnitFileList) {
1403 unit_file_state_from_string(state)
1406 if (output_show_unit_file(&units[c], strv_skip_first(args)))
1411 return bus_log_parse_error(r);
1413 r = sd_bus_message_exit_container(reply);
1415 return bus_log_parse_error(r);
1418 qsort_safe(units, c, sizeof(UnitFileList), compare_unit_file_list);
1419 output_unit_file_list(units, c);
1422 for (unit = units; unit < units + c; unit++)
1429 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1430 _cleanup_free_ char *n = NULL;
1431 size_t max_len = MAX(columns(),20u);
1437 for (i = level - 1; i >= 0; i--) {
1439 if (len > max_len - 3 && !arg_full) {
1440 printf("%s...\n",max_len % 2 ? "" : " ");
1443 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERTICAL : DRAW_TREE_SPACE));
1447 if (len > max_len - 3 && !arg_full) {
1448 printf("%s...\n",max_len % 2 ? "" : " ");
1452 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
1456 printf("%s\n", name);
1460 n = ellipsize(name, max_len-len, 100);
1468 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1470 static const char *dependencies[_DEPENDENCY_MAX] = {
1471 [DEPENDENCY_FORWARD] = "Requires\0"
1472 "RequiresOverridable\0"
1474 "RequisiteOverridable\0"
1477 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1478 "RequiredByOverridable\0"
1482 [DEPENDENCY_AFTER] = "After\0",
1483 [DEPENDENCY_BEFORE] = "Before\0",
1486 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1487 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1488 _cleanup_strv_free_ char **ret = NULL;
1489 _cleanup_free_ char *path = NULL;
1495 assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
1497 path = unit_dbus_path_from_name(name);
1501 r = sd_bus_call_method(
1503 "org.freedesktop.systemd1",
1505 "org.freedesktop.DBus.Properties",
1509 "s", "org.freedesktop.systemd1.Unit");
1511 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1515 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1517 return bus_log_parse_error(r);
1519 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1522 r = sd_bus_message_read(reply, "s", &prop);
1524 return bus_log_parse_error(r);
1526 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1527 r = sd_bus_message_skip(reply, "v");
1529 return bus_log_parse_error(r);
1532 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1534 return bus_log_parse_error(r);
1536 r = bus_message_read_strv_extend(reply, &ret);
1538 return bus_log_parse_error(r);
1540 r = sd_bus_message_exit_container(reply);
1542 return bus_log_parse_error(r);
1545 r = sd_bus_message_exit_container(reply);
1547 return bus_log_parse_error(r);
1551 return bus_log_parse_error(r);
1553 r = sd_bus_message_exit_container(reply);
1555 return bus_log_parse_error(r);
1563 static int list_dependencies_compare(const void *_a, const void *_b) {
1564 const char **a = (const char**) _a, **b = (const char**) _b;
1566 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1568 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1571 return strcasecmp(*a, *b);
1574 static int list_dependencies_one(
1579 unsigned int branches) {
1581 _cleanup_strv_free_ char **deps = NULL;
1589 r = strv_extend(units, name);
1593 r = list_dependencies_get_dependencies(bus, name, &deps);
1597 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1599 STRV_FOREACH(c, deps) {
1600 if (strv_contains(*units, *c)) {
1602 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1615 state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true);
1616 on = state > 0 ? ansi_highlight_green() : ansi_highlight_red();
1617 printf("%s%s%s ", on, draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1620 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1624 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1625 r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1632 strv_remove(*units, name);
1637 static int list_dependencies(sd_bus *bus, char **args) {
1638 _cleanup_strv_free_ char **units = NULL;
1639 _cleanup_free_ char *unit = NULL;
1645 unit = unit_name_mangle(args[1], MANGLE_NOGLOB);
1650 u = SPECIAL_DEFAULT_TARGET;
1652 pager_open_if_enabled();
1656 return list_dependencies_one(bus, u, 0, &units, 0);
1659 struct machine_info {
1663 char *control_group;
1664 uint32_t n_failed_units;
1669 static const struct bus_properties_map machine_info_property_map[] = {
1670 { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
1671 { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
1672 { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
1673 { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
1674 { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
1678 static void free_machines_list(struct machine_info *machine_infos, int n) {
1684 for (i = 0; i < n; i++) {
1685 free(machine_infos[i].name);
1686 free(machine_infos[i].state);
1687 free(machine_infos[i].control_group);
1690 free(machine_infos);
1693 static int compare_machine_info(const void *a, const void *b) {
1694 const struct machine_info *u = a, *v = b;
1696 if (u->is_host != v->is_host)
1697 return u->is_host > v->is_host ? -1 : 1;
1699 return strcasecmp(u->name, v->name);
1702 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1703 _cleanup_bus_close_unref_ sd_bus *container = NULL;
1709 r = sd_bus_open_system_machine(&container, mi->name);
1716 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi);
1723 static bool output_show_machine(const char *name, char **patterns) {
1724 return strv_fnmatch_or_empty(patterns, name, FNM_NOESCAPE);
1727 static int get_machine_list(
1729 struct machine_info **_machine_infos,
1732 struct machine_info *machine_infos = NULL;
1733 _cleanup_strv_free_ char **m = NULL;
1734 _cleanup_free_ char *hn = NULL;
1739 hn = gethostname_malloc();
1743 if (output_show_machine(hn, patterns)) {
1744 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1747 machine_infos[c].is_host = true;
1748 machine_infos[c].name = hn;
1751 get_machine_properties(bus, &machine_infos[c]);
1755 sd_get_machine_names(&m);
1756 STRV_FOREACH(i, m) {
1757 _cleanup_free_ char *class = NULL;
1759 if (!output_show_machine(*i, patterns))
1762 sd_machine_get_class(*i, &class);
1763 if (!streq_ptr(class, "container"))
1766 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1767 free_machines_list(machine_infos, c);
1771 machine_infos[c].is_host = false;
1772 machine_infos[c].name = strdup(*i);
1773 if (!machine_infos[c].name) {
1774 free_machines_list(machine_infos, c);
1778 get_machine_properties(NULL, &machine_infos[c]);
1782 *_machine_infos = machine_infos;
1786 static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1787 struct machine_info *m;
1790 namelen = sizeof("NAME") - 1,
1791 statelen = sizeof("STATE") - 1,
1792 failedlen = sizeof("FAILED") - 1,
1793 jobslen = sizeof("JOBS") - 1;
1795 assert(machine_infos || n == 0);
1797 for (m = machine_infos; m < machine_infos + n; m++) {
1798 namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
1799 statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
1800 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
1801 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
1803 if (!arg_plain && !streq_ptr(m->state, "running"))
1807 if (!arg_no_legend) {
1811 printf("%-*s %-*s %-*s %-*s\n",
1814 failedlen, "FAILED",
1818 for (m = machine_infos; m < machine_infos + n; m++) {
1819 const char *on_state = "", *off_state = "";
1820 const char *on_failed = "", *off_failed = "";
1821 bool circle = false;
1823 if (streq_ptr(m->state, "degraded")) {
1824 on_state = ansi_highlight_red();
1825 off_state = ansi_highlight_off();
1827 } else if (!streq_ptr(m->state, "running")) {
1828 on_state = ansi_highlight_yellow();
1829 off_state = ansi_highlight_off();
1833 if (m->n_failed_units > 0) {
1834 on_failed = ansi_highlight_red();
1835 off_failed = ansi_highlight_off();
1837 on_failed = off_failed = "";
1840 printf("%s%s%s ", on_state, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_state);
1843 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1844 (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
1845 on_state, statelen, strna(m->state), off_state,
1846 on_failed, failedlen, m->n_failed_units, off_failed,
1847 jobslen, m->n_jobs);
1849 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1850 namelen, strna(m->name),
1851 on_state, statelen, strna(m->state), off_state,
1852 on_failed, failedlen, m->n_failed_units, off_failed,
1853 jobslen, m->n_jobs);
1857 printf("\n%u machines listed.\n", n);
1860 static int list_machines(sd_bus *bus, char **args) {
1861 struct machine_info *machine_infos = NULL;
1866 if (geteuid() != 0) {
1867 log_error("Must be root.");
1871 pager_open_if_enabled();
1873 r = get_machine_list(bus, &machine_infos, strv_skip_first(args));
1877 qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
1878 output_machines_list(machine_infos, r);
1879 free_machines_list(machine_infos, r);
1884 static int get_default(sd_bus *bus, char **args) {
1885 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1886 _cleanup_free_ char *_path = NULL;
1890 if (!bus || avoid_bus()) {
1891 r = unit_file_get_default(arg_scope, arg_root, &_path);
1893 return log_error_errno(r, "Failed to get default target: %m");
1897 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1899 r = sd_bus_call_method(
1901 "org.freedesktop.systemd1",
1902 "/org/freedesktop/systemd1",
1903 "org.freedesktop.systemd1.Manager",
1909 log_error("Failed to get default target: %s", bus_error_message(&error, -r));
1913 r = sd_bus_message_read(reply, "s", &path);
1915 return bus_log_parse_error(r);
1919 printf("%s\n", path);
1924 static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) {
1927 assert(changes || n_changes == 0);
1929 for (i = 0; i < n_changes; i++) {
1930 if (changes[i].type == UNIT_FILE_SYMLINK)
1931 log_info("Created symlink from %s to %s.", changes[i].path, changes[i].source);
1933 log_info("Removed symlink %s.", changes[i].path);
1937 static int set_default(sd_bus *bus, char **args) {
1938 _cleanup_free_ char *unit = NULL;
1939 UnitFileChange *changes = NULL;
1940 unsigned n_changes = 0;
1943 unit = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
1947 if (!bus || avoid_bus()) {
1948 r = unit_file_set_default(arg_scope, arg_root, unit, true, &changes, &n_changes);
1950 return log_error_errno(r, "Failed to set default target: %m");
1953 dump_unit_file_changes(changes, n_changes);
1957 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1958 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1960 polkit_agent_open_if_enabled();
1962 r = sd_bus_call_method(
1964 "org.freedesktop.systemd1",
1965 "/org/freedesktop/systemd1",
1966 "org.freedesktop.systemd1.Manager",
1972 log_error("Failed to set default target: %s", bus_error_message(&error, -r));
1976 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
1980 /* Try to reload if enabled */
1982 r = daemon_reload(bus, args);
1987 unit_file_changes_free(changes, n_changes);
1994 const char *name, *type, *state;
1997 static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
1998 unsigned id_len, unit_len, type_len, state_len;
1999 const struct job_info *j;
2000 const char *on, *off;
2001 bool shorten = false;
2003 assert(n == 0 || jobs);
2006 if (!arg_no_legend) {
2007 on = ansi_highlight_green();
2008 off = ansi_highlight_off();
2010 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
2015 pager_open_if_enabled();
2017 id_len = strlen("JOB");
2018 unit_len = strlen("UNIT");
2019 type_len = strlen("TYPE");
2020 state_len = strlen("STATE");
2022 for (j = jobs; j < jobs + n; j++) {
2023 uint32_t id = j->id;
2024 assert(j->name && j->type && j->state);
2026 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
2027 unit_len = MAX(unit_len, strlen(j->name));
2028 type_len = MAX(type_len, strlen(j->type));
2029 state_len = MAX(state_len, strlen(j->state));
2032 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
2033 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
2038 printf("%*s %-*s %-*s %-*s\n",
2042 state_len, "STATE");
2044 for (j = jobs; j < jobs + n; j++) {
2045 _cleanup_free_ char *e = NULL;
2047 if (streq(j->state, "running")) {
2048 on = ansi_highlight();
2049 off = ansi_highlight_off();
2053 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
2054 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
2056 on, unit_len, e ? e : j->name, off,
2058 on, state_len, j->state, off);
2061 if (!arg_no_legend) {
2062 on = ansi_highlight();
2063 off = ansi_highlight_off();
2065 printf("\n%s%u jobs listed%s.\n", on, n, off);
2069 static bool output_show_job(struct job_info *job, char **patterns) {
2070 return strv_fnmatch_or_empty(patterns, job->name, FNM_NOESCAPE);
2073 static int list_jobs(sd_bus *bus, char **args) {
2074 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2075 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2076 const char *name, *type, *state, *job_path, *unit_path;
2077 _cleanup_free_ struct job_info *jobs = NULL;
2082 bool skipped = false;
2084 r = sd_bus_call_method(
2086 "org.freedesktop.systemd1",
2087 "/org/freedesktop/systemd1",
2088 "org.freedesktop.systemd1.Manager",
2094 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
2098 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2100 return bus_log_parse_error(r);
2102 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
2103 struct job_info job = { id, name, type, state };
2105 if (!output_show_job(&job, strv_skip_first(args))) {
2110 if (!GREEDY_REALLOC(jobs, size, c + 1))
2116 return bus_log_parse_error(r);
2118 r = sd_bus_message_exit_container(reply);
2120 return bus_log_parse_error(r);
2122 output_jobs_list(jobs, c, skipped);
2126 static int cancel_job(sd_bus *bus, char **args) {
2132 if (strv_length(args) <= 1)
2133 return daemon_reload(bus, args);
2135 polkit_agent_open_if_enabled();
2137 STRV_FOREACH(name, args+1) {
2138 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2142 q = safe_atou32(*name, &id);
2144 return log_error_errno(q, "Failed to parse job id \"%s\": %m", *name);
2146 q = sd_bus_call_method(
2148 "org.freedesktop.systemd1",
2149 "/org/freedesktop/systemd1",
2150 "org.freedesktop.systemd1.Manager",
2156 log_error("Failed to cancel job %"PRIu32": %s", id, bus_error_message(&error, q));
2165 static int need_daemon_reload(sd_bus *bus, const char *unit) {
2166 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2170 /* We ignore all errors here, since this is used to show a
2173 /* We don't use unit_dbus_path_from_name() directly since we
2174 * don't want to load the unit if it isn't loaded. */
2176 r = sd_bus_call_method(
2178 "org.freedesktop.systemd1",
2179 "/org/freedesktop/systemd1",
2180 "org.freedesktop.systemd1.Manager",
2188 r = sd_bus_message_read(reply, "o", &path);
2192 r = sd_bus_get_property_trivial(
2194 "org.freedesktop.systemd1",
2196 "org.freedesktop.systemd1.Unit",
2206 static void warn_unit_file_changed(const char *name) {
2207 log_warning("%sWarning:%s %s changed on disk. Run 'systemctl%s daemon-reload' to reload units.",
2208 ansi_highlight_red(),
2209 ansi_highlight_off(),
2211 arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2214 static int unit_file_find_path(LookupPaths *lp, const char *unit_name, char **unit_path) {
2221 STRV_FOREACH(p, lp->unit_path) {
2222 _cleanup_free_ char *path;
2224 path = path_join(arg_root, *p, unit_name);
2228 if (access(path, F_OK) == 0) {
2238 static int unit_find_paths(
2240 const char *unit_name,
2241 bool avoid_bus_cache,
2243 char **fragment_path,
2244 char ***dropin_paths) {
2246 _cleanup_free_ char *path = NULL;
2247 _cleanup_strv_free_ char **dropins = NULL;
2251 * Finds where the unit is defined on disk. Returns 0 if the unit
2252 * is not found. Returns 1 if it is found, and sets
2253 * - the path to the unit in *path, if it exists on disk,
2254 * - and a strv of existing drop-ins in *dropins,
2255 * if the arg is not NULL and any dropins were found.
2259 assert(fragment_path);
2262 if (!avoid_bus_cache && !unit_name_is_template(unit_name)) {
2263 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2264 _cleanup_bus_message_unref_ sd_bus_message *unit_load_error = NULL;
2265 _cleanup_free_ char *unit = NULL;
2266 char *unit_load_error_name, *unit_load_error_message;
2268 unit = unit_dbus_path_from_name(unit_name);
2272 if (need_daemon_reload(bus, unit_name) > 0)
2273 warn_unit_file_changed(unit_name);
2275 r = sd_bus_get_property(
2277 "org.freedesktop.systemd1",
2279 "org.freedesktop.systemd1.Unit",
2285 return log_error_errno(r, "Failed to get LoadError: %s", bus_error_message(&error, r));
2287 r = sd_bus_message_read(
2290 &unit_load_error_name,
2291 &unit_load_error_message);
2293 return bus_log_parse_error(r);
2295 if (!isempty(unit_load_error_name)) {
2296 log_error("Unit %s is not loaded: %s", unit_name, unit_load_error_message);
2300 r = sd_bus_get_property_string(
2302 "org.freedesktop.systemd1",
2304 "org.freedesktop.systemd1.Unit",
2309 return log_error_errno(r, "Failed to get FragmentPath: %s", bus_error_message(&error, r));
2312 r = sd_bus_get_property_strv(
2314 "org.freedesktop.systemd1",
2316 "org.freedesktop.systemd1.Unit",
2321 return log_error_errno(r, "Failed to get DropInPaths: %s", bus_error_message(&error, r));
2324 _cleanup_set_free_ Set *names;
2326 names = set_new(NULL);
2330 r = set_put(names, unit_name);
2334 r = unit_file_find_path(lp, unit_name, &path);
2339 _cleanup_free_ char *template;
2341 template = unit_name_template(unit_name);
2345 if (!streq(template, unit_name)) {
2346 r = unit_file_find_path(lp, template, &path);
2353 r = unit_file_find_dropin_paths(lp->unit_path, NULL, names, &dropins);
2361 if (!isempty(path)) {
2362 *fragment_path = path;
2367 if (dropin_paths && !strv_isempty(dropins)) {
2368 *dropin_paths = dropins;
2374 log_error("No files found for %s.", unit_name);
2379 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2380 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2381 _cleanup_free_ char *n = NULL, *state = NULL;
2387 n = unit_name_mangle(name, MANGLE_NOGLOB);
2391 /* We don't use unit_dbus_path_from_name() directly since we
2392 * don't want to load the unit if it isn't loaded. */
2394 r = sd_bus_call_method(
2396 "org.freedesktop.systemd1",
2397 "/org/freedesktop/systemd1",
2398 "org.freedesktop.systemd1.Manager",
2409 r = sd_bus_message_read(reply, "o", &path);
2411 return bus_log_parse_error(r);
2413 r = sd_bus_get_property_string(
2415 "org.freedesktop.systemd1",
2417 "org.freedesktop.systemd1.Unit",
2430 return nulstr_contains(good_states, state);
2433 static int check_triggering_units(
2437 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2438 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2439 _cleanup_strv_free_ char **triggered_by = NULL;
2440 bool print_warning_label = true;
2444 n = unit_name_mangle(name, MANGLE_NOGLOB);
2448 path = unit_dbus_path_from_name(n);
2452 r = sd_bus_get_property_string(
2454 "org.freedesktop.systemd1",
2456 "org.freedesktop.systemd1.Unit",
2461 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2465 if (streq(state, "masked"))
2468 r = sd_bus_get_property_strv(
2470 "org.freedesktop.systemd1",
2472 "org.freedesktop.systemd1.Unit",
2477 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2481 STRV_FOREACH(i, triggered_by) {
2482 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2484 return log_error_errno(r, "Failed to check unit: %m");
2489 if (print_warning_label) {
2490 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2491 print_warning_label = false;
2494 log_warning(" %s", *i);
2500 static const struct {
2503 } unit_actions[] = {
2504 { "start", "StartUnit" },
2505 { "stop", "StopUnit" },
2506 { "condstop", "StopUnit" },
2507 { "reload", "ReloadUnit" },
2508 { "restart", "RestartUnit" },
2509 { "try-restart", "TryRestartUnit" },
2510 { "condrestart", "TryRestartUnit" },
2511 { "reload-or-restart", "ReloadOrRestartUnit" },
2512 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
2513 { "condreload", "ReloadOrTryRestartUnit" },
2514 { "force-reload", "ReloadOrTryRestartUnit" }
2517 static const char *verb_to_method(const char *verb) {
2520 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2521 if (streq_ptr(unit_actions[i].verb, verb))
2522 return unit_actions[i].method;
2527 static const char *method_to_verb(const char *method) {
2530 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2531 if (streq_ptr(unit_actions[i].method, method))
2532 return unit_actions[i].verb;
2537 static int start_unit_one(
2542 sd_bus_error *error,
2543 BusWaitForJobs *w) {
2545 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2554 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2556 r = sd_bus_call_method(
2558 "org.freedesktop.systemd1",
2559 "/org/freedesktop/systemd1",
2560 "org.freedesktop.systemd1.Manager",
2568 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2569 /* There's always a fallback possible for
2570 * legacy actions. */
2571 return -EADDRNOTAVAIL;
2573 verb = method_to_verb(method);
2575 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2579 r = sd_bus_message_read(reply, "o", &path);
2581 return bus_log_parse_error(r);
2583 if (need_daemon_reload(bus, name) > 0)
2584 warn_unit_file_changed(name);
2587 log_debug("Adding %s to the set", path);
2588 r = bus_wait_for_jobs_add(w, path);
2596 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2598 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2602 STRV_FOREACH(name, names) {
2606 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2608 t = unit_name_mangle(*name, MANGLE_GLOB);
2612 if (string_is_glob(t))
2613 r = strv_consume(&globs, t);
2615 r = strv_consume(&mangled, t);
2620 /* Query the manager only if any of the names are a glob, since
2621 * this is fairly expensive */
2622 if (!strv_isempty(globs)) {
2623 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2624 _cleanup_free_ UnitInfo *unit_infos = NULL;
2627 return log_error_errno(ENOTSUP, "Unit name globbing without bus is not implemented.");
2629 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2633 for (i = 0; i < r; i++)
2634 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2639 mangled = NULL; /* do not free */
2644 static const struct {
2648 } action_table[_ACTION_MAX] = {
2649 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2650 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2651 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2652 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2653 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
2654 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
2655 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
2656 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
2657 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2658 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2659 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2660 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2661 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2662 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2663 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2666 static enum action verb_to_action(const char *verb) {
2669 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2670 if (streq_ptr(action_table[i].verb, verb))
2673 return _ACTION_INVALID;
2676 static int start_unit(sd_bus *bus, char **args) {
2677 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
2678 const char *method, *mode, *one_name, *suffix = NULL;
2679 _cleanup_strv_free_ char **names = NULL;
2685 ask_password_agent_open_if_enabled();
2686 polkit_agent_open_if_enabled();
2688 if (arg_action == ACTION_SYSTEMCTL) {
2690 method = verb_to_method(args[0]);
2691 action = verb_to_action(args[0]);
2693 if (streq(args[0], "isolate")) {
2697 mode = action_table[action].mode ?: arg_job_mode;
2699 one_name = action_table[action].target;
2701 assert(arg_action < ELEMENTSOF(action_table));
2702 assert(action_table[arg_action].target);
2704 method = "StartUnit";
2706 mode = action_table[arg_action].mode;
2707 one_name = action_table[arg_action].target;
2711 names = strv_new(one_name, NULL);
2713 r = expand_names(bus, args + 1, suffix, &names);
2715 log_error_errno(r, "Failed to expand names: %m");
2718 if (!arg_no_block) {
2719 r = bus_wait_for_jobs_new(bus, &w);
2721 return log_error_errno(r, "Could not watch jobs: %m");
2724 STRV_FOREACH(name, names) {
2725 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2728 q = start_unit_one(bus, method, *name, mode, &error, w);
2729 if (r >= 0 && q < 0)
2730 r = translate_bus_error_to_exit_status(q, &error);
2733 if (!arg_no_block) {
2736 q = bus_wait_for_jobs(w, arg_quiet);
2740 /* When stopping units, warn if they can still be triggered by
2741 * another active unit (socket, path, timer) */
2742 if (!arg_quiet && streq(method, "StopUnit"))
2743 STRV_FOREACH(name, names)
2744 check_triggering_units(bus, *name);
2750 /* Ask systemd-logind, which might grant access to unprivileged users
2751 * through PolicyKit */
2752 static int reboot_with_logind(sd_bus *bus, enum action a) {
2754 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2761 polkit_agent_open_if_enabled();
2769 case ACTION_POWEROFF:
2770 method = "PowerOff";
2773 case ACTION_SUSPEND:
2777 case ACTION_HIBERNATE:
2778 method = "Hibernate";
2781 case ACTION_HYBRID_SLEEP:
2782 method = "HybridSleep";
2789 r = sd_bus_call_method(
2791 "org.freedesktop.login1",
2792 "/org/freedesktop/login1",
2793 "org.freedesktop.login1.Manager",
2797 "b", arg_ask_password);
2799 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2807 static int check_inhibitors(sd_bus *bus, enum action a) {
2809 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2810 _cleanup_strv_free_ char **sessions = NULL;
2811 const char *what, *who, *why, *mode;
2820 if (arg_ignore_inhibitors || arg_force > 0)
2832 r = sd_bus_call_method(
2834 "org.freedesktop.login1",
2835 "/org/freedesktop/login1",
2836 "org.freedesktop.login1.Manager",
2842 /* If logind is not around, then there are no inhibitors... */
2845 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2847 return bus_log_parse_error(r);
2849 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2850 _cleanup_free_ char *comm = NULL, *user = NULL;
2851 _cleanup_strv_free_ char **sv = NULL;
2853 if (!streq(mode, "block"))
2856 sv = strv_split(what, ":");
2860 if (!strv_contains(sv,
2862 a == ACTION_POWEROFF ||
2863 a == ACTION_REBOOT ||
2864 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2867 get_process_comm(pid, &comm);
2868 user = uid_to_name(uid);
2870 log_warning("Operation inhibited by \"%s\" (PID "PID_FMT" \"%s\", user %s), reason is \"%s\".",
2871 who, pid, strna(comm), strna(user), why);
2876 return bus_log_parse_error(r);
2878 r = sd_bus_message_exit_container(reply);
2880 return bus_log_parse_error(r);
2882 /* Check for current sessions */
2883 sd_get_sessions(&sessions);
2884 STRV_FOREACH(s, sessions) {
2885 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2887 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2890 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2893 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2896 sd_session_get_tty(*s, &tty);
2897 sd_session_get_seat(*s, &seat);
2898 sd_session_get_service(*s, &service);
2899 user = uid_to_name(uid);
2901 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2908 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2909 action_table[a].verb);
2917 static int start_special(sd_bus *bus, char **args) {
2923 a = verb_to_action(args[0]);
2925 r = check_inhibitors(bus, a);
2929 if (arg_force >= 2 && geteuid() != 0) {
2930 log_error("Must be root.");
2934 if (a == ACTION_REBOOT && args[1]) {
2935 r = update_reboot_param_file(args[1]);
2940 if (arg_force >= 2 &&
2941 (a == ACTION_HALT ||
2942 a == ACTION_POWEROFF ||
2943 a == ACTION_REBOOT))
2946 if (arg_force >= 1 &&
2947 (a == ACTION_HALT ||
2948 a == ACTION_POWEROFF ||
2949 a == ACTION_REBOOT ||
2950 a == ACTION_KEXEC ||
2952 return daemon_reload(bus, args);
2954 /* first try logind, to allow authentication with polkit */
2955 if (geteuid() != 0 &&
2956 (a == ACTION_POWEROFF ||
2957 a == ACTION_REBOOT ||
2958 a == ACTION_SUSPEND ||
2959 a == ACTION_HIBERNATE ||
2960 a == ACTION_HYBRID_SLEEP)) {
2961 r = reboot_with_logind(bus, a);
2962 if (r >= 0 || IN_SET(r, -ENOTSUP, -EINPROGRESS))
2966 r = start_unit(bus, args);
2967 if (r == EXIT_SUCCESS)
2973 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
2974 _cleanup_strv_free_ char **names = NULL;
2981 r = expand_names(bus, args, NULL, &names);
2983 return log_error_errno(r, "Failed to expand names: %m");
2985 STRV_FOREACH(name, names) {
2988 state = check_one_unit(bus, *name, good_states, arg_quiet);
2998 static int check_unit_active(sd_bus *bus, char **args) {
2999 /* According to LSB: 3, "program is not running" */
3000 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
3003 static int check_unit_failed(sd_bus *bus, char **args) {
3004 return check_unit_generic(bus, 1, "failed\0", args + 1);
3007 static int kill_unit(sd_bus *bus, char **args) {
3008 _cleanup_strv_free_ char **names = NULL;
3015 polkit_agent_open_if_enabled();
3018 arg_kill_who = "all";
3020 r = expand_names(bus, args + 1, NULL, &names);
3022 log_error_errno(r, "Failed to expand names: %m");
3024 STRV_FOREACH(name, names) {
3025 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
3027 q = sd_bus_call_method(
3029 "org.freedesktop.systemd1",
3030 "/org/freedesktop/systemd1",
3031 "org.freedesktop.systemd1.Manager",
3035 "ssi", *names, arg_kill_who, arg_signal);
3037 log_error("Failed to kill unit %s: %s", *names, bus_error_message(&error, q));
3046 typedef struct ExecStatusInfo {
3054 usec_t start_timestamp;
3055 usec_t exit_timestamp;
3060 LIST_FIELDS(struct ExecStatusInfo, exec);
3063 static void exec_status_info_free(ExecStatusInfo *i) {
3072 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
3073 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
3076 int32_t code, status;
3082 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
3084 return bus_log_parse_error(r);
3088 r = sd_bus_message_read(m, "s", &path);
3090 return bus_log_parse_error(r);
3092 i->path = strdup(path);
3096 r = sd_bus_message_read_strv(m, &i->argv);
3098 return bus_log_parse_error(r);
3100 r = sd_bus_message_read(m,
3103 &start_timestamp, &start_timestamp_monotonic,
3104 &exit_timestamp, &exit_timestamp_monotonic,
3108 return bus_log_parse_error(r);
3111 i->start_timestamp = (usec_t) start_timestamp;
3112 i->exit_timestamp = (usec_t) exit_timestamp;
3113 i->pid = (pid_t) pid;
3117 r = sd_bus_message_exit_container(m);
3119 return bus_log_parse_error(r);
3124 typedef struct UnitStatusInfo {
3126 const char *load_state;
3127 const char *active_state;
3128 const char *sub_state;
3129 const char *unit_file_state;
3130 const char *unit_file_preset;
3132 const char *description;
3133 const char *following;
3135 char **documentation;
3137 const char *fragment_path;
3138 const char *source_path;
3139 const char *control_group;
3141 char **dropin_paths;
3143 const char *load_error;
3146 usec_t inactive_exit_timestamp;
3147 usec_t inactive_exit_timestamp_monotonic;
3148 usec_t active_enter_timestamp;
3149 usec_t active_exit_timestamp;
3150 usec_t inactive_enter_timestamp;
3152 bool need_daemon_reload;
3157 const char *status_text;
3158 const char *pid_file;
3162 usec_t start_timestamp;
3163 usec_t exit_timestamp;
3165 int exit_code, exit_status;
3167 usec_t condition_timestamp;
3168 bool condition_result;
3169 bool failed_condition_trigger;
3170 bool failed_condition_negate;
3171 const char *failed_condition;
3172 const char *failed_condition_parameter;
3174 usec_t assert_timestamp;
3176 bool failed_assert_trigger;
3177 bool failed_assert_negate;
3178 const char *failed_assert;
3179 const char *failed_assert_parameter;
3182 unsigned n_accepted;
3183 unsigned n_connections;
3186 /* Pairs of type, path */
3190 const char *sysfs_path;
3192 /* Mount, Automount */
3199 uint64_t memory_current;
3200 uint64_t memory_limit;
3202 LIST_HEAD(ExecStatusInfo, exec);
3205 static void print_status_info(
3210 const char *active_on, *active_off, *on, *off, *ss;
3212 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3213 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3219 /* This shows pretty information about a unit. See
3220 * print_property() for a low-level property printer */
3222 if (streq_ptr(i->active_state, "failed")) {
3223 active_on = ansi_highlight_red();
3224 active_off = ansi_highlight_off();
3225 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3226 active_on = ansi_highlight_green();
3227 active_off = ansi_highlight_off();
3229 active_on = active_off = "";
3231 printf("%s%s%s %s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3233 if (i->description && !streq_ptr(i->id, i->description))
3234 printf(" - %s", i->description);
3239 printf(" Follow: unit currently follows state of %s\n", i->following);
3241 if (streq_ptr(i->load_state, "error")) {
3242 on = ansi_highlight_red();
3243 off = ansi_highlight_off();
3247 path = i->source_path ? i->source_path : i->fragment_path;
3250 printf(" Loaded: %s%s%s (Reason: %s)\n",
3251 on, strna(i->load_state), off, i->load_error);
3252 else if (path && !isempty(i->unit_file_state) && !isempty(i->unit_file_preset))
3253 printf(" Loaded: %s%s%s (%s; %s; vendor preset: %s)\n",
3254 on, strna(i->load_state), off, path, i->unit_file_state, i->unit_file_preset);
3255 else if (path && !isempty(i->unit_file_state))
3256 printf(" Loaded: %s%s%s (%s; %s)\n",
3257 on, strna(i->load_state), off, path, i->unit_file_state);
3259 printf(" Loaded: %s%s%s (%s)\n",
3260 on, strna(i->load_state), off, path);
3262 printf(" Loaded: %s%s%s\n",
3263 on, strna(i->load_state), off);
3265 if (!strv_isempty(i->dropin_paths)) {
3266 _cleanup_free_ char *dir = NULL;
3270 STRV_FOREACH(dropin, i->dropin_paths) {
3271 if (! dir || last) {
3272 printf(dir ? " " : " Drop-In: ");
3277 if (path_get_parent(*dropin, &dir) < 0) {
3282 printf("%s\n %s", dir,
3283 draw_special_char(DRAW_TREE_RIGHT));
3286 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3288 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3292 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3294 printf(" Active: %s%s (%s)%s",
3295 active_on, strna(i->active_state), ss, active_off);
3297 printf(" Active: %s%s%s",
3298 active_on, strna(i->active_state), active_off);
3300 if (!isempty(i->result) && !streq(i->result, "success"))
3301 printf(" (Result: %s)", i->result);
3303 timestamp = (streq_ptr(i->active_state, "active") ||
3304 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
3305 (streq_ptr(i->active_state, "inactive") ||
3306 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
3307 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
3308 i->active_exit_timestamp;
3310 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3311 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3314 printf(" since %s; %s\n", s2, s1);
3316 printf(" since %s\n", s2);
3320 if (!i->condition_result && i->condition_timestamp > 0) {
3321 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3322 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3324 printf("Condition: start %scondition failed%s at %s%s%s\n",
3325 ansi_highlight_yellow(), ansi_highlight_off(),
3326 s2, s1 ? "; " : "", s1 ? s1 : "");
3327 if (i->failed_condition_trigger)
3328 printf(" none of the trigger conditions were met\n");
3329 else if (i->failed_condition)
3330 printf(" %s=%s%s was not met\n",
3331 i->failed_condition,
3332 i->failed_condition_negate ? "!" : "",
3333 i->failed_condition_parameter);
3336 if (!i->assert_result && i->assert_timestamp > 0) {
3337 s1 = format_timestamp_relative(since1, sizeof(since1), i->assert_timestamp);
3338 s2 = format_timestamp(since2, sizeof(since2), i->assert_timestamp);
3340 printf(" Assert: start %sassertion failed%s at %s%s%s\n",
3341 ansi_highlight_red(), ansi_highlight_off(),
3342 s2, s1 ? "; " : "", s1 ? s1 : "");
3343 if (i->failed_assert_trigger)
3344 printf(" none of the trigger assertions were met\n");
3345 else if (i->failed_assert)
3346 printf(" %s=%s%s was not met\n",
3348 i->failed_assert_negate ? "!" : "",
3349 i->failed_assert_parameter);
3353 printf(" Device: %s\n", i->sysfs_path);
3355 printf(" Where: %s\n", i->where);
3357 printf(" What: %s\n", i->what);
3359 STRV_FOREACH(t, i->documentation)
3360 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3362 STRV_FOREACH_PAIR(t, t2, i->listen)
3363 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3366 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3368 LIST_FOREACH(exec, p, i->exec) {
3369 _cleanup_free_ char *argv = NULL;
3372 /* Only show exited processes here */
3376 argv = strv_join(p->argv, " ");
3377 printf(" Process: "PID_FMT" %s=%s ", p->pid, p->name, strna(argv));
3379 good = is_clean_exit_lsb(p->code, p->status, NULL);
3381 on = ansi_highlight_red();
3382 off = ansi_highlight_off();
3386 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3388 if (p->code == CLD_EXITED) {
3391 printf("status=%i", p->status);
3393 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3398 printf("signal=%s", signal_to_string(p->status));
3400 printf(")%s\n", off);
3402 if (i->main_pid == p->pid &&
3403 i->start_timestamp == p->start_timestamp &&
3404 i->exit_timestamp == p->start_timestamp)
3405 /* Let's not show this twice */
3408 if (p->pid == i->control_pid)
3412 if (i->main_pid > 0 || i->control_pid > 0) {
3413 if (i->main_pid > 0) {
3414 printf(" Main PID: "PID_FMT, i->main_pid);
3417 _cleanup_free_ char *comm = NULL;
3418 get_process_comm(i->main_pid, &comm);
3420 printf(" (%s)", comm);
3421 } else if (i->exit_code > 0) {
3422 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3424 if (i->exit_code == CLD_EXITED) {
3427 printf("status=%i", i->exit_status);
3429 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3434 printf("signal=%s", signal_to_string(i->exit_status));
3438 if (i->control_pid > 0)
3442 if (i->control_pid > 0) {
3443 _cleanup_free_ char *c = NULL;
3445 printf(" %8s: "PID_FMT, i->main_pid ? "" : " Control", i->control_pid);
3447 get_process_comm(i->control_pid, &c);
3456 printf(" Status: \"%s\"\n", i->status_text);
3457 if (i->status_errno > 0)
3458 printf(" Error: %i (%s)\n", i->status_errno, strerror(i->status_errno));
3460 if (i->memory_current != (uint64_t) -1) {
3461 char buf[FORMAT_BYTES_MAX];
3463 printf(" Memory: %s", format_bytes(buf, sizeof(buf), i->memory_current));
3465 if (i->memory_limit != (uint64_t) -1)
3466 printf(" (limit: %s)\n", format_bytes(buf, sizeof(buf), i->memory_limit));
3471 if (i->control_group &&
3472 (i->main_pid > 0 || i->control_pid > 0 ||
3473 ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_MACHINE) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3476 printf(" CGroup: %s\n", i->control_group);
3478 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_MACHINE) {
3481 static const char prefix[] = " ";
3484 if (c > sizeof(prefix) - 1)
3485 c -= sizeof(prefix) - 1;
3489 if (i->main_pid > 0)
3490 extra[k++] = i->main_pid;
3492 if (i->control_pid > 0)
3493 extra[k++] = i->control_pid;
3495 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, get_output_flags());
3499 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3500 show_journal_by_unit(
3505 i->inactive_exit_timestamp_monotonic,
3508 get_output_flags() | OUTPUT_BEGIN_NEWLINE,
3509 SD_JOURNAL_LOCAL_ONLY,
3510 arg_scope == UNIT_FILE_SYSTEM,
3514 if (i->need_daemon_reload)
3515 warn_unit_file_changed(i->id);
3518 static void show_unit_help(UnitStatusInfo *i) {
3523 if (!i->documentation) {
3524 log_info("Documentation for %s not known.", i->id);
3528 STRV_FOREACH(p, i->documentation)
3529 if (startswith(*p, "man:"))
3530 show_man_page(*p + 4, false);
3532 log_info("Can't show: %s", *p);
3535 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3542 switch (contents[0]) {
3544 case SD_BUS_TYPE_STRING: {
3547 r = sd_bus_message_read(m, "s", &s);
3549 return bus_log_parse_error(r);
3552 if (streq(name, "Id"))
3554 else if (streq(name, "LoadState"))
3556 else if (streq(name, "ActiveState"))
3557 i->active_state = s;
3558 else if (streq(name, "SubState"))
3560 else if (streq(name, "Description"))
3562 else if (streq(name, "FragmentPath"))
3563 i->fragment_path = s;
3564 else if (streq(name, "SourcePath"))
3567 else if (streq(name, "DefaultControlGroup")) {
3569 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3571 i->control_group = e;
3574 else if (streq(name, "ControlGroup"))
3575 i->control_group = s;
3576 else if (streq(name, "StatusText"))
3578 else if (streq(name, "PIDFile"))
3580 else if (streq(name, "SysFSPath"))
3582 else if (streq(name, "Where"))
3584 else if (streq(name, "What"))
3586 else if (streq(name, "Following"))
3588 else if (streq(name, "UnitFileState"))
3589 i->unit_file_state = s;
3590 else if (streq(name, "UnitFilePreset"))
3591 i->unit_file_preset = s;
3592 else if (streq(name, "Result"))
3599 case SD_BUS_TYPE_BOOLEAN: {
3602 r = sd_bus_message_read(m, "b", &b);
3604 return bus_log_parse_error(r);
3606 if (streq(name, "Accept"))
3608 else if (streq(name, "NeedDaemonReload"))
3609 i->need_daemon_reload = b;
3610 else if (streq(name, "ConditionResult"))
3611 i->condition_result = b;
3612 else if (streq(name, "AssertResult"))
3613 i->assert_result = b;
3618 case SD_BUS_TYPE_UINT32: {
3621 r = sd_bus_message_read(m, "u", &u);
3623 return bus_log_parse_error(r);
3625 if (streq(name, "MainPID")) {
3627 i->main_pid = (pid_t) u;
3630 } else if (streq(name, "ControlPID"))
3631 i->control_pid = (pid_t) u;
3632 else if (streq(name, "ExecMainPID")) {
3634 i->main_pid = (pid_t) u;
3635 } else if (streq(name, "NAccepted"))
3637 else if (streq(name, "NConnections"))
3638 i->n_connections = u;
3643 case SD_BUS_TYPE_INT32: {
3646 r = sd_bus_message_read(m, "i", &j);
3648 return bus_log_parse_error(r);
3650 if (streq(name, "ExecMainCode"))
3651 i->exit_code = (int) j;
3652 else if (streq(name, "ExecMainStatus"))
3653 i->exit_status = (int) j;
3654 else if (streq(name, "StatusErrno"))
3655 i->status_errno = (int) j;
3660 case SD_BUS_TYPE_UINT64: {
3663 r = sd_bus_message_read(m, "t", &u);
3665 return bus_log_parse_error(r);
3667 if (streq(name, "ExecMainStartTimestamp"))
3668 i->start_timestamp = (usec_t) u;
3669 else if (streq(name, "ExecMainExitTimestamp"))
3670 i->exit_timestamp = (usec_t) u;
3671 else if (streq(name, "ActiveEnterTimestamp"))
3672 i->active_enter_timestamp = (usec_t) u;
3673 else if (streq(name, "InactiveEnterTimestamp"))
3674 i->inactive_enter_timestamp = (usec_t) u;
3675 else if (streq(name, "InactiveExitTimestamp"))
3676 i->inactive_exit_timestamp = (usec_t) u;
3677 else if (streq(name, "InactiveExitTimestampMonotonic"))
3678 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3679 else if (streq(name, "ActiveExitTimestamp"))
3680 i->active_exit_timestamp = (usec_t) u;
3681 else if (streq(name, "ConditionTimestamp"))
3682 i->condition_timestamp = (usec_t) u;
3683 else if (streq(name, "AssertTimestamp"))
3684 i->assert_timestamp = (usec_t) u;
3685 else if (streq(name, "MemoryCurrent"))
3686 i->memory_current = u;
3687 else if (streq(name, "MemoryLimit"))
3688 i->memory_limit = u;
3693 case SD_BUS_TYPE_ARRAY:
3695 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3696 _cleanup_free_ ExecStatusInfo *info = NULL;
3698 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3700 return bus_log_parse_error(r);
3702 info = new0(ExecStatusInfo, 1);
3706 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3708 info->name = strdup(name);
3712 LIST_PREPEND(exec, i->exec, info);
3714 info = new0(ExecStatusInfo, 1);
3720 return bus_log_parse_error(r);
3722 r = sd_bus_message_exit_container(m);
3724 return bus_log_parse_error(r);
3728 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3729 const char *type, *path;
3731 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3733 return bus_log_parse_error(r);
3735 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3737 r = strv_extend(&i->listen, type);
3741 r = strv_extend(&i->listen, path);
3746 return bus_log_parse_error(r);
3748 r = sd_bus_message_exit_container(m);
3750 return bus_log_parse_error(r);
3754 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3756 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3758 return bus_log_parse_error(r);
3760 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3762 r = sd_bus_message_read_strv(m, &i->documentation);
3764 return bus_log_parse_error(r);
3766 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3767 const char *cond, *param;
3768 int trigger, negate;
3771 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3773 return bus_log_parse_error(r);
3775 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3776 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3777 if (state < 0 && (!trigger || !i->failed_condition)) {
3778 i->failed_condition = cond;
3779 i->failed_condition_trigger = trigger;
3780 i->failed_condition_negate = negate;
3781 i->failed_condition_parameter = param;
3785 return bus_log_parse_error(r);
3787 r = sd_bus_message_exit_container(m);
3789 return bus_log_parse_error(r);
3791 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Asserts")) {
3792 const char *cond, *param;
3793 int trigger, negate;
3796 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3798 return bus_log_parse_error(r);
3800 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3801 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3802 if (state < 0 && (!trigger || !i->failed_assert)) {
3803 i->failed_assert = cond;
3804 i->failed_assert_trigger = trigger;
3805 i->failed_assert_negate = negate;
3806 i->failed_assert_parameter = param;
3810 return bus_log_parse_error(r);
3812 r = sd_bus_message_exit_container(m);
3814 return bus_log_parse_error(r);
3821 case SD_BUS_TYPE_STRUCT_BEGIN:
3823 if (streq(name, "LoadError")) {
3824 const char *n, *message;
3826 r = sd_bus_message_read(m, "(ss)", &n, &message);
3828 return bus_log_parse_error(r);
3830 if (!isempty(message))
3831 i->load_error = message;
3844 r = sd_bus_message_skip(m, contents);
3846 return bus_log_parse_error(r);
3851 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3857 /* This is a low-level property printer, see
3858 * print_status_info() for the nicer output */
3860 if (arg_properties && !strv_find(arg_properties, name)) {
3861 /* skip what we didn't read */
3862 r = sd_bus_message_skip(m, contents);
3866 switch (contents[0]) {
3868 case SD_BUS_TYPE_STRUCT_BEGIN:
3870 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3873 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3875 return bus_log_parse_error(r);
3878 printf("%s=%"PRIu32"\n", name, u);
3880 printf("%s=\n", name);
3884 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3887 r = sd_bus_message_read(m, "(so)", &s, NULL);
3889 return bus_log_parse_error(r);
3891 if (arg_all || !isempty(s))
3892 printf("%s=%s\n", name, s);
3896 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3897 const char *a = NULL, *b = NULL;
3899 r = sd_bus_message_read(m, "(ss)", &a, &b);
3901 return bus_log_parse_error(r);
3903 if (arg_all || !isempty(a) || !isempty(b))
3904 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3907 } else if (streq_ptr(name, "SystemCallFilter")) {
3908 _cleanup_strv_free_ char **l = NULL;
3911 r = sd_bus_message_enter_container(m, 'r', "bas");
3913 return bus_log_parse_error(r);
3915 r = sd_bus_message_read(m, "b", &whitelist);
3917 return bus_log_parse_error(r);
3919 r = sd_bus_message_read_strv(m, &l);
3921 return bus_log_parse_error(r);
3923 r = sd_bus_message_exit_container(m);
3925 return bus_log_parse_error(r);
3927 if (arg_all || whitelist || !strv_isempty(l)) {
3931 fputs(name, stdout);
3937 STRV_FOREACH(i, l) {
3945 fputc('\n', stdout);
3953 case SD_BUS_TYPE_ARRAY:
3955 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
3959 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
3961 return bus_log_parse_error(r);
3963 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
3964 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3967 return bus_log_parse_error(r);
3969 r = sd_bus_message_exit_container(m);
3971 return bus_log_parse_error(r);
3975 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
3976 const char *type, *path;
3978 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3980 return bus_log_parse_error(r);
3982 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3983 printf("%s=%s\n", type, path);
3985 return bus_log_parse_error(r);
3987 r = sd_bus_message_exit_container(m);
3989 return bus_log_parse_error(r);
3993 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3994 const char *type, *path;
3996 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3998 return bus_log_parse_error(r);
4000 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
4001 printf("Listen%s=%s\n", type, path);
4003 return bus_log_parse_error(r);
4005 r = sd_bus_message_exit_container(m);
4007 return bus_log_parse_error(r);
4011 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
4013 uint64_t value, next_elapse;
4015 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
4017 return bus_log_parse_error(r);
4019 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
4020 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
4022 printf("%s={ value=%s ; next_elapse=%s }\n",
4024 format_timespan(timespan1, sizeof(timespan1), value, 0),
4025 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
4028 return bus_log_parse_error(r);
4030 r = sd_bus_message_exit_container(m);
4032 return bus_log_parse_error(r);
4036 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
4037 ExecStatusInfo info = {};
4039 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
4041 return bus_log_parse_error(r);
4043 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
4044 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
4045 _cleanup_free_ char *tt;
4047 tt = strv_join(info.argv, " ");
4049 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",
4053 yes_no(info.ignore),
4054 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
4055 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
4057 sigchld_code_to_string(info.code),
4059 info.code == CLD_EXITED ? "" : "/",
4060 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
4063 strv_free(info.argv);
4067 r = sd_bus_message_exit_container(m);
4069 return bus_log_parse_error(r);
4073 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
4074 const char *path, *rwm;
4076 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
4078 return bus_log_parse_error(r);
4080 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
4081 printf("%s=%s %s\n", name, strna(path), strna(rwm));
4083 return bus_log_parse_error(r);
4085 r = sd_bus_message_exit_container(m);
4087 return bus_log_parse_error(r);
4091 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
4095 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4097 return bus_log_parse_error(r);
4099 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
4100 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
4102 return bus_log_parse_error(r);
4104 r = sd_bus_message_exit_container(m);
4106 return bus_log_parse_error(r);
4110 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
4114 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
4116 return bus_log_parse_error(r);
4118 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
4119 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
4121 return bus_log_parse_error(r);
4123 r = sd_bus_message_exit_container(m);
4125 return bus_log_parse_error(r);
4133 r = bus_print_property(name, m, arg_all);
4135 return bus_log_parse_error(r);
4138 r = sd_bus_message_skip(m, contents);
4140 return bus_log_parse_error(r);
4143 printf("%s=[unprintable]\n", name);
4149 static int show_one(
4153 bool show_properties,
4157 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4158 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4159 UnitStatusInfo info = {
4160 .memory_current = (uint64_t) -1,
4161 .memory_limit = (uint64_t) -1,
4169 log_debug("Showing one %s", path);
4171 r = sd_bus_call_method(
4173 "org.freedesktop.systemd1",
4175 "org.freedesktop.DBus.Properties",
4181 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4185 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4187 return bus_log_parse_error(r);
4194 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4195 const char *name, *contents;
4197 r = sd_bus_message_read(reply, "s", &name);
4199 return bus_log_parse_error(r);
4201 r = sd_bus_message_peek_type(reply, NULL, &contents);
4203 return bus_log_parse_error(r);
4205 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4207 return bus_log_parse_error(r);
4209 if (show_properties)
4210 r = print_property(name, reply, contents);
4212 r = status_property(name, reply, &info, contents);
4216 r = sd_bus_message_exit_container(reply);
4218 return bus_log_parse_error(r);
4220 r = sd_bus_message_exit_container(reply);
4222 return bus_log_parse_error(r);
4225 return bus_log_parse_error(r);
4227 r = sd_bus_message_exit_container(reply);
4229 return bus_log_parse_error(r);
4233 if (!show_properties) {
4234 if (streq(verb, "help"))
4235 show_unit_help(&info);
4237 print_status_info(&info, ellipsized);
4240 strv_free(info.documentation);
4241 strv_free(info.dropin_paths);
4242 strv_free(info.listen);
4244 if (!streq_ptr(info.active_state, "active") &&
4245 !streq_ptr(info.active_state, "reloading") &&
4246 streq(verb, "status")) {
4247 /* According to LSB: "program not running" */
4248 /* 0: program is running or service is OK
4249 * 1: program is dead and /run PID file exists
4250 * 2: program is dead and /run/lock lock file exists
4251 * 3: program is not running
4252 * 4: program or service status is unknown
4254 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4260 while ((p = info.exec)) {
4261 LIST_REMOVE(exec, info.exec, p);
4262 exec_status_info_free(p);
4268 static int get_unit_dbus_path_by_pid(
4273 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4274 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4278 r = sd_bus_call_method(
4280 "org.freedesktop.systemd1",
4281 "/org/freedesktop/systemd1",
4282 "org.freedesktop.systemd1.Manager",
4288 log_error("Failed to get unit for PID %"PRIu32": %s", pid, bus_error_message(&error, r));
4292 r = sd_bus_message_read(reply, "o", &u);
4294 return bus_log_parse_error(r);
4304 static int show_all(
4307 bool show_properties,
4311 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4312 _cleanup_free_ UnitInfo *unit_infos = NULL;
4317 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4321 pager_open_if_enabled();
4325 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4327 for (u = unit_infos; u < unit_infos + c; u++) {
4328 _cleanup_free_ char *p = NULL;
4330 p = unit_dbus_path_from_name(u->id);
4334 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4337 else if (r > 0 && ret == 0)
4344 static int show_system_status(sd_bus *bus) {
4345 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4346 _cleanup_free_ char *hn = NULL;
4347 struct machine_info mi = {};
4348 const char *on, *off;
4351 hn = gethostname_malloc();
4355 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4357 return log_error_errno(r, "Failed to read server status: %m");
4359 if (streq_ptr(mi.state, "degraded")) {
4360 on = ansi_highlight_red();
4361 off = ansi_highlight_off();
4362 } else if (!streq_ptr(mi.state, "running")) {
4363 on = ansi_highlight_yellow();
4364 off = ansi_highlight_off();
4368 printf("%s%s%s %s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4370 printf(" State: %s%s%s\n",
4371 on, strna(mi.state), off);
4373 printf(" Jobs: %u queued\n", mi.n_jobs);
4374 printf(" Failed: %u units\n", mi.n_failed_units);
4376 printf(" Since: %s; %s\n",
4377 format_timestamp(since2, sizeof(since2), mi.timestamp),
4378 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4380 printf(" CGroup: %s\n", mi.control_group ?: "/");
4381 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_MACHINE) {
4382 static const char prefix[] = " ";
4386 if (c > sizeof(prefix) - 1)
4387 c -= sizeof(prefix) - 1;
4391 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, get_output_flags());
4395 free(mi.control_group);
4400 static int show(sd_bus *bus, char **args) {
4401 bool show_properties, show_status, new_line = false;
4402 bool ellipsized = false;
4408 show_properties = streq(args[0], "show");
4409 show_status = streq(args[0], "status");
4411 if (show_properties)
4412 pager_open_if_enabled();
4414 /* If no argument is specified inspect the manager itself */
4416 if (show_properties && strv_length(args) <= 1)
4417 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4419 if (show_status && strv_length(args) <= 1) {
4421 pager_open_if_enabled();
4422 show_system_status(bus);
4426 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4428 _cleanup_free_ char **patterns = NULL;
4431 STRV_FOREACH(name, args + 1) {
4432 _cleanup_free_ char *unit = NULL;
4435 if (safe_atou32(*name, &id) < 0) {
4436 if (strv_push(&patterns, *name) < 0)
4440 } else if (show_properties) {
4441 /* Interpret as job id */
4442 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4446 /* Interpret as PID */
4447 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4454 r = show_one(args[0], bus, unit, show_properties,
4455 &new_line, &ellipsized);
4458 else if (r > 0 && ret == 0)
4462 if (!strv_isempty(patterns)) {
4463 _cleanup_strv_free_ char **names = NULL;
4465 r = expand_names(bus, patterns, NULL, &names);
4467 log_error_errno(r, "Failed to expand names: %m");
4469 STRV_FOREACH(name, names) {
4470 _cleanup_free_ char *unit;
4472 unit = unit_dbus_path_from_name(*name);
4476 r = show_one(args[0], bus, unit, show_properties,
4477 &new_line, &ellipsized);
4480 else if (r > 0 && ret == 0)
4486 if (ellipsized && !arg_quiet)
4487 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4492 static int init_home_and_lookup_paths(char **user_home, char **user_runtime, LookupPaths *lp) {
4496 assert(user_runtime);
4499 if (arg_scope == UNIT_FILE_USER) {
4500 r = user_config_home(user_home);
4502 return log_error_errno(r, "Failed to query XDG_CONFIG_HOME: %m");
4504 return log_error_errno(ENOTDIR, "Cannot find units: $XDG_CONFIG_HOME and $HOME are not set.");
4506 r = user_runtime_dir(user_runtime);
4508 return log_error_errno(r, "Failed to query XDG_CONFIG_HOME: %m");
4510 return log_error_errno(ENOTDIR, "Cannot find units: $XDG_RUNTIME_DIR is not set.");
4513 r = lookup_paths_init_from_scope(lp, arg_scope, arg_root);
4515 return log_error_errno(r, "Failed to query unit lookup paths: %m");
4520 static int cat(sd_bus *bus, char **args) {
4521 _cleanup_free_ char *user_home = NULL;
4522 _cleanup_free_ char *user_runtime = NULL;
4523 _cleanup_lookup_paths_free_ LookupPaths lp = {};
4524 _cleanup_strv_free_ char **names = NULL;
4526 bool first = true, avoid_bus_cache;
4531 if (arg_transport != BUS_TRANSPORT_LOCAL) {
4532 log_error("Cannot remotely cat units");
4536 r = init_home_and_lookup_paths(&user_home, &user_runtime, &lp);
4540 r = expand_names(bus, args + 1, NULL, &names);
4542 return log_error_errno(r, "Failed to expand names: %m");
4544 avoid_bus_cache = !bus || avoid_bus();
4546 pager_open_if_enabled();
4548 STRV_FOREACH(name, names) {
4549 _cleanup_free_ char *fragment_path = NULL;
4550 _cleanup_strv_free_ char **dropin_paths = NULL;
4553 r = unit_find_paths(bus, *name, avoid_bus_cache, &lp, &fragment_path, &dropin_paths);
4564 if (fragment_path) {
4565 printf("%s# %s%s\n",
4566 ansi_highlight_blue(),
4568 ansi_highlight_off());
4571 r = copy_file_fd(fragment_path, STDOUT_FILENO, false);
4573 log_warning_errno(r, "Failed to cat %s: %m", fragment_path);
4578 STRV_FOREACH(path, dropin_paths) {
4579 printf("%s%s# %s%s\n",
4580 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4581 ansi_highlight_blue(),
4583 ansi_highlight_off());
4586 r = copy_file_fd(*path, STDOUT_FILENO, false);
4588 log_warning_errno(r, "Failed to cat %s: %m", *path);
4594 return r < 0 ? r : 0;
4597 static int set_property(sd_bus *bus, char **args) {
4598 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4599 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4600 _cleanup_free_ char *n = NULL;
4604 polkit_agent_open_if_enabled();
4606 r = sd_bus_message_new_method_call(
4609 "org.freedesktop.systemd1",
4610 "/org/freedesktop/systemd1",
4611 "org.freedesktop.systemd1.Manager",
4612 "SetUnitProperties");
4614 return bus_log_create_error(r);
4616 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4620 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4622 return bus_log_create_error(r);
4624 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4626 return bus_log_create_error(r);
4628 STRV_FOREACH(i, args + 2) {
4629 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4631 return bus_log_create_error(r);
4633 r = bus_append_unit_property_assignment(m, *i);
4637 r = sd_bus_message_close_container(m);
4639 return bus_log_create_error(r);
4642 r = sd_bus_message_close_container(m);
4644 return bus_log_create_error(r);
4646 r = sd_bus_call(bus, m, 0, &error, NULL);
4648 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4655 static int snapshot(sd_bus *bus, char **args) {
4656 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4657 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4658 _cleanup_free_ char *n = NULL, *id = NULL;
4662 polkit_agent_open_if_enabled();
4664 if (strv_length(args) > 1)
4665 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4671 r = sd_bus_call_method(
4673 "org.freedesktop.systemd1",
4674 "/org/freedesktop/systemd1",
4675 "org.freedesktop.systemd1.Manager",
4681 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4685 r = sd_bus_message_read(reply, "o", &path);
4687 return bus_log_parse_error(r);
4689 r = sd_bus_get_property_string(
4691 "org.freedesktop.systemd1",
4693 "org.freedesktop.systemd1.Unit",
4698 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4708 static int delete_snapshot(sd_bus *bus, char **args) {
4709 _cleanup_strv_free_ char **names = NULL;
4715 polkit_agent_open_if_enabled();
4717 r = expand_names(bus, args + 1, ".snapshot", &names);
4719 log_error_errno(r, "Failed to expand names: %m");
4721 STRV_FOREACH(name, names) {
4722 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4725 q = sd_bus_call_method(
4727 "org.freedesktop.systemd1",
4728 "/org/freedesktop/systemd1",
4729 "org.freedesktop.systemd1.Manager",
4735 log_error("Failed to remove snapshot %s: %s", *name, bus_error_message(&error, q));
4744 static int daemon_reload(sd_bus *bus, char **args) {
4745 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4749 polkit_agent_open_if_enabled();
4751 if (arg_action == ACTION_RELOAD)
4753 else if (arg_action == ACTION_REEXEC)
4754 method = "Reexecute";
4756 assert(arg_action == ACTION_SYSTEMCTL);
4759 streq(args[0], "clear-jobs") ||
4760 streq(args[0], "cancel") ? "ClearJobs" :
4761 streq(args[0], "daemon-reexec") ? "Reexecute" :
4762 streq(args[0], "reset-failed") ? "ResetFailed" :
4763 streq(args[0], "halt") ? "Halt" :
4764 streq(args[0], "poweroff") ? "PowerOff" :
4765 streq(args[0], "reboot") ? "Reboot" :
4766 streq(args[0], "kexec") ? "KExec" :
4767 streq(args[0], "exit") ? "Exit" :
4768 /* "daemon-reload" */ "Reload";
4771 r = sd_bus_call_method(
4773 "org.freedesktop.systemd1",
4774 "/org/freedesktop/systemd1",
4775 "org.freedesktop.systemd1.Manager",
4780 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4781 /* There's always a fallback possible for
4782 * legacy actions. */
4784 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4785 /* On reexecution, we expect a disconnect, not a
4789 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4791 return r < 0 ? r : 0;
4794 static int reset_failed(sd_bus *bus, char **args) {
4795 _cleanup_strv_free_ char **names = NULL;
4799 if (strv_length(args) <= 1)
4800 return daemon_reload(bus, args);
4802 polkit_agent_open_if_enabled();
4804 r = expand_names(bus, args + 1, NULL, &names);
4806 log_error_errno(r, "Failed to expand names: %m");
4808 STRV_FOREACH(name, names) {
4809 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4811 q = sd_bus_call_method(
4813 "org.freedesktop.systemd1",
4814 "/org/freedesktop/systemd1",
4815 "org.freedesktop.systemd1.Manager",
4821 log_error("Failed to reset failed state of unit %s: %s", *name, bus_error_message(&error, q));
4830 static int show_environment(sd_bus *bus, char **args) {
4831 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4832 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4836 pager_open_if_enabled();
4838 r = sd_bus_get_property(
4840 "org.freedesktop.systemd1",
4841 "/org/freedesktop/systemd1",
4842 "org.freedesktop.systemd1.Manager",
4848 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4852 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4854 return bus_log_parse_error(r);
4856 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4859 return bus_log_parse_error(r);
4861 r = sd_bus_message_exit_container(reply);
4863 return bus_log_parse_error(r);
4868 static int switch_root(sd_bus *bus, char **args) {
4869 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4870 _cleanup_free_ char *cmdline_init = NULL;
4871 const char *root, *init;
4875 l = strv_length(args);
4876 if (l < 2 || l > 3) {
4877 log_error("Wrong number of arguments.");
4886 r = parse_env_file("/proc/cmdline", WHITESPACE,
4887 "init", &cmdline_init,
4890 log_debug_errno(r, "Failed to parse /proc/cmdline: %m");
4892 init = cmdline_init;
4899 const char *root_systemd_path = NULL, *root_init_path = NULL;
4901 root_systemd_path = strjoina(root, "/" SYSTEMD_BINARY_PATH);
4902 root_init_path = strjoina(root, "/", init);
4904 /* If the passed init is actually the same as the
4905 * systemd binary, then let's suppress it. */
4906 if (files_same(root_init_path, root_systemd_path) > 0)
4910 log_debug("Switching root - root: %s; init: %s", root, strna(init));
4912 r = sd_bus_call_method(
4914 "org.freedesktop.systemd1",
4915 "/org/freedesktop/systemd1",
4916 "org.freedesktop.systemd1.Manager",
4922 log_error("Failed to switch root: %s", bus_error_message(&error, r));
4929 static int set_environment(sd_bus *bus, char **args) {
4930 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4931 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4938 polkit_agent_open_if_enabled();
4940 method = streq(args[0], "set-environment")
4942 : "UnsetEnvironment";
4944 r = sd_bus_message_new_method_call(
4947 "org.freedesktop.systemd1",
4948 "/org/freedesktop/systemd1",
4949 "org.freedesktop.systemd1.Manager",
4952 return bus_log_create_error(r);
4954 r = sd_bus_message_append_strv(m, args + 1);
4956 return bus_log_create_error(r);
4958 r = sd_bus_call(bus, m, 0, &error, NULL);
4960 log_error("Failed to set environment: %s", bus_error_message(&error, r));
4967 static int import_environment(sd_bus *bus, char **args) {
4968 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4969 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4975 polkit_agent_open_if_enabled();
4977 r = sd_bus_message_new_method_call(
4980 "org.freedesktop.systemd1",
4981 "/org/freedesktop/systemd1",
4982 "org.freedesktop.systemd1.Manager",
4985 return bus_log_create_error(r);
4987 if (strv_isempty(args + 1))
4988 r = sd_bus_message_append_strv(m, environ);
4992 r = sd_bus_message_open_container(m, 'a', "s");
4994 return bus_log_create_error(r);
4996 STRV_FOREACH(a, args + 1) {
4998 if (!env_name_is_valid(*a)) {
4999 log_error("Not a valid environment variable name: %s", *a);
5003 STRV_FOREACH(b, environ) {
5006 eq = startswith(*b, *a);
5007 if (eq && *eq == '=') {
5009 r = sd_bus_message_append(m, "s", *b);
5011 return bus_log_create_error(r);
5018 r = sd_bus_message_close_container(m);
5021 return bus_log_create_error(r);
5023 r = sd_bus_call(bus, m, 0, &error, NULL);
5025 log_error("Failed to import environment: %s", bus_error_message(&error, r));
5032 static int enable_sysv_units(const char *verb, char **args) {
5035 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
5037 _cleanup_lookup_paths_free_ LookupPaths paths = {};
5039 if (arg_scope != UNIT_FILE_SYSTEM)
5042 if (!streq(verb, "enable") &&
5043 !streq(verb, "disable") &&
5044 !streq(verb, "is-enabled"))
5047 /* Processes all SysV units, and reshuffles the array so that
5048 * afterwards only the native units remain */
5050 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, arg_root, NULL, NULL, NULL);
5057 _cleanup_free_ char *p = NULL, *q = NULL, *l = NULL;
5058 bool found_native = false, found_sysv;
5060 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
5068 if (!endswith(name, ".service"))
5071 if (path_is_absolute(name))
5074 STRV_FOREACH(k, paths.unit_path) {
5075 _cleanup_free_ char *path = NULL;
5077 path = path_join(arg_root, *k, name);
5081 found_native = access(path, F_OK) >= 0;
5089 p = path_join(arg_root, SYSTEM_SYSVINIT_PATH, name);
5093 p[strlen(p) - strlen(".service")] = 0;
5094 found_sysv = access(p, F_OK) >= 0;
5098 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
5100 if (!isempty(arg_root))
5101 argv[c++] = q = strappend("--root=", arg_root);
5103 argv[c++] = basename(p);
5105 streq(verb, "enable") ? "on" :
5106 streq(verb, "disable") ? "off" : "--level=5";
5109 l = strv_join((char**)argv, " ");
5113 log_info("Executing %s", l);
5117 return log_error_errno(errno, "Failed to fork: %m");
5118 else if (pid == 0) {
5121 execv(argv[0], (char**) argv);
5122 _exit(EXIT_FAILURE);
5125 j = wait_for_terminate(pid, &status);
5127 log_error_errno(r, "Failed to wait for child: %m");
5131 if (status.si_code == CLD_EXITED) {
5132 if (streq(verb, "is-enabled")) {
5133 if (status.si_status == 0) {
5142 } else if (status.si_status != 0)
5147 /* Remove this entry, so that we don't try enabling it as native unit */
5150 assert(args[f] == name);
5151 strv_remove(args, name);
5158 static int mangle_names(char **original_names, char ***mangled_names) {
5159 char **i, **l, **name;
5161 l = new(char*, strv_length(original_names) + 1);
5166 STRV_FOREACH(name, original_names) {
5168 /* When enabling units qualified path names are OK,
5169 * too, hence allow them explicitly. */
5174 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5190 static int enable_unit(sd_bus *bus, char **args) {
5191 _cleanup_strv_free_ char **names = NULL;
5192 const char *verb = args[0];
5193 UnitFileChange *changes = NULL;
5194 unsigned n_changes = 0;
5195 int carries_install_info = -1;
5201 r = mangle_names(args+1, &names);
5205 r = enable_sysv_units(verb, names);
5209 /* If the operation was fully executed by the SysV compat,
5210 * let's finish early */
5211 if (strv_isempty(names))
5214 if (!bus || avoid_bus()) {
5215 if (streq(verb, "enable")) {
5216 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5217 carries_install_info = r;
5218 } else if (streq(verb, "disable"))
5219 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5220 else if (streq(verb, "reenable")) {
5221 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5222 carries_install_info = r;
5223 } else if (streq(verb, "link"))
5224 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5225 else if (streq(verb, "preset")) {
5226 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_preset_mode, arg_force, &changes, &n_changes);
5227 carries_install_info = r;
5228 } else if (streq(verb, "mask"))
5229 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5230 else if (streq(verb, "unmask"))
5231 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5233 assert_not_reached("Unknown verb");
5236 log_error_errno(r, "Operation failed: %m");
5241 dump_unit_file_changes(changes, n_changes);
5245 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5246 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5247 int expect_carries_install_info = false;
5248 bool send_force = true, send_preset_mode = false;
5251 polkit_agent_open_if_enabled();
5253 if (streq(verb, "enable")) {
5254 method = "EnableUnitFiles";
5255 expect_carries_install_info = true;
5256 } else if (streq(verb, "disable")) {
5257 method = "DisableUnitFiles";
5259 } else if (streq(verb, "reenable")) {
5260 method = "ReenableUnitFiles";
5261 expect_carries_install_info = true;
5262 } else if (streq(verb, "link"))
5263 method = "LinkUnitFiles";
5264 else if (streq(verb, "preset")) {
5266 if (arg_preset_mode != UNIT_FILE_PRESET_FULL) {
5267 method = "PresetUnitFilesWithMode";
5268 send_preset_mode = true;
5270 method = "PresetUnitFiles";
5272 expect_carries_install_info = true;
5273 } else if (streq(verb, "mask"))
5274 method = "MaskUnitFiles";
5275 else if (streq(verb, "unmask")) {
5276 method = "UnmaskUnitFiles";
5279 assert_not_reached("Unknown verb");
5281 r = sd_bus_message_new_method_call(
5284 "org.freedesktop.systemd1",
5285 "/org/freedesktop/systemd1",
5286 "org.freedesktop.systemd1.Manager",
5289 return bus_log_create_error(r);
5291 r = sd_bus_message_append_strv(m, names);
5293 return bus_log_create_error(r);
5295 if (send_preset_mode) {
5296 r = sd_bus_message_append(m, "s", unit_file_preset_mode_to_string(arg_preset_mode));
5298 return bus_log_create_error(r);
5301 r = sd_bus_message_append(m, "b", arg_runtime);
5303 return bus_log_create_error(r);
5306 r = sd_bus_message_append(m, "b", arg_force);
5308 return bus_log_create_error(r);
5311 r = sd_bus_call(bus, m, 0, &error, &reply);
5313 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5317 if (expect_carries_install_info) {
5318 r = sd_bus_message_read(reply, "b", &carries_install_info);
5320 return bus_log_parse_error(r);
5323 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
5327 /* Try to reload if enabled */
5329 r = daemon_reload(bus, args);
5334 if (carries_install_info == 0)
5335 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5336 "using systemctl.\n"
5337 "Possible reasons for having this kind of units are:\n"
5338 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5339 " .wants/ or .requires/ directory.\n"
5340 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5341 " a requirement dependency on it.\n"
5342 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5343 " D-Bus, udev, scripted systemctl call, ...).\n");
5346 unit_file_changes_free(changes, n_changes);
5351 static int add_dependency(sd_bus *bus, char **args) {
5352 _cleanup_strv_free_ char **names = NULL;
5353 _cleanup_free_ char *target = NULL;
5354 const char *verb = args[0];
5361 target = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
5365 r = mangle_names(args+2, &names);
5369 if (streq(verb, "add-wants"))
5371 else if (streq(verb, "add-requires"))
5372 dep = UNIT_REQUIRES;
5374 assert_not_reached("Unknown verb");
5376 if (!bus || avoid_bus()) {
5377 UnitFileChange *changes = NULL;
5378 unsigned n_changes = 0;
5380 r = unit_file_add_dependency(arg_scope, arg_runtime, arg_root, names, target, dep, arg_force, &changes, &n_changes);
5383 return log_error_errno(r, "Can't add dependency: %m");
5386 dump_unit_file_changes(changes, n_changes);
5388 unit_file_changes_free(changes, n_changes);
5391 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5392 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5394 polkit_agent_open_if_enabled();
5396 r = sd_bus_message_new_method_call(
5399 "org.freedesktop.systemd1",
5400 "/org/freedesktop/systemd1",
5401 "org.freedesktop.systemd1.Manager",
5402 "AddDependencyUnitFiles");
5404 return bus_log_create_error(r);
5406 r = sd_bus_message_append_strv(m, names);
5408 return bus_log_create_error(r);
5410 r = sd_bus_message_append(m, "ssbb", target, unit_dependency_to_string(dep), arg_runtime, arg_force);
5412 return bus_log_create_error(r);
5414 r = sd_bus_call(bus, m, 0, &error, &reply);
5416 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5420 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
5425 r = daemon_reload(bus, args);
5433 static int preset_all(sd_bus *bus, char **args) {
5434 UnitFileChange *changes = NULL;
5435 unsigned n_changes = 0;
5438 if (!bus || avoid_bus()) {
5440 r = unit_file_preset_all(arg_scope, arg_runtime, arg_root, arg_preset_mode, arg_force, &changes, &n_changes);
5442 log_error_errno(r, "Operation failed: %m");
5447 dump_unit_file_changes(changes, n_changes);
5452 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5453 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5455 polkit_agent_open_if_enabled();
5457 r = sd_bus_call_method(
5459 "org.freedesktop.systemd1",
5460 "/org/freedesktop/systemd1",
5461 "org.freedesktop.systemd1.Manager",
5462 "PresetAllUnitFiles",
5466 unit_file_preset_mode_to_string(arg_preset_mode),
5470 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5474 r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet);
5479 r = daemon_reload(bus, args);
5485 unit_file_changes_free(changes, n_changes);
5490 static int unit_is_enabled(sd_bus *bus, char **args) {
5492 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5493 _cleanup_strv_free_ char **names = NULL;
5498 r = mangle_names(args+1, &names);
5502 r = enable_sysv_units(args[0], names);
5508 if (!bus || avoid_bus()) {
5510 STRV_FOREACH(name, names) {
5511 UnitFileState state;
5513 state = unit_file_get_state(arg_scope, arg_root, *name);
5515 return log_error_errno(state, "Failed to get unit file state for %s: %m", *name);
5517 if (state == UNIT_FILE_ENABLED ||
5518 state == UNIT_FILE_ENABLED_RUNTIME ||
5519 state == UNIT_FILE_STATIC ||
5520 state == UNIT_FILE_INDIRECT)
5524 puts(unit_file_state_to_string(state));
5528 STRV_FOREACH(name, names) {
5529 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5532 r = sd_bus_call_method(
5534 "org.freedesktop.systemd1",
5535 "/org/freedesktop/systemd1",
5536 "org.freedesktop.systemd1.Manager",
5542 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5546 r = sd_bus_message_read(reply, "s", &s);
5548 return bus_log_parse_error(r);
5550 if (STR_IN_SET(s, "enabled", "enabled-runtime", "static", "indirect"))
5561 static int is_system_running(sd_bus *bus, char **args) {
5562 _cleanup_free_ char *state = NULL;
5565 r = sd_bus_get_property_string(
5567 "org.freedesktop.systemd1",
5568 "/org/freedesktop/systemd1",
5569 "org.freedesktop.systemd1.Manager",
5582 return streq(state, "running") ? EXIT_SUCCESS : EXIT_FAILURE;
5585 static int create_edit_temp_file(const char *new_path, const char *original_path, char **ret_tmp_fn) {
5590 assert(original_path);
5593 r = tempfn_random(new_path, &t);
5595 return log_error_errno(r, "Failed to determine temporary filename for \"%s\": %m", new_path);
5597 r = mkdir_parents(new_path, 0755);
5599 log_error_errno(r, "Failed to create directories for \"%s\": %m", new_path);
5604 r = copy_file(original_path, t, 0, 0644, 0);
5608 log_error_errno(r, "Failed to create temporary file \"%s\": %m", t);
5613 log_error_errno(r, "Failed to copy \"%s\" to \"%s\": %m", original_path, t);
5623 static int get_file_to_edit(const char *name, const char *user_home, const char *user_runtime, char **ret_path) {
5624 _cleanup_free_ char *path = NULL, *path2 = NULL, *run = NULL;
5626 switch (arg_scope) {
5627 case UNIT_FILE_SYSTEM:
5628 path = path_join(arg_root, SYSTEM_CONFIG_UNIT_PATH, name);
5630 run = path_join(arg_root, "/run/systemd/system/", name);
5632 case UNIT_FILE_GLOBAL:
5633 path = path_join(arg_root, USER_CONFIG_UNIT_PATH, name);
5635 run = path_join(arg_root, "/run/systemd/user/", name);
5637 case UNIT_FILE_USER:
5639 assert(user_runtime);
5641 path = path_join(arg_root, user_home, name);
5643 path2 = path_join(arg_root, USER_CONFIG_UNIT_PATH, name);
5646 run = path_join(arg_root, user_runtime, name);
5650 assert_not_reached("Invalid scope");
5652 if (!path || (arg_runtime && !run))
5656 if (access(path, F_OK) >= 0)
5657 return log_error_errno(EEXIST, "Refusing to create \"%s\" because it would be overriden by \"%s\" anyway.",
5659 if (path2 && access(path2, F_OK) >= 0)
5660 return log_error_errno(EEXIST, "Refusing to create \"%s\" because it would be overriden by \"%s\" anyway.",
5672 static int unit_file_create_dropin(const char *unit_name, const char *user_home, const char *user_runtime, char **ret_new_path, char **ret_tmp_path) {
5673 char *tmp_new_path, *ending;
5678 assert(ret_new_path);
5679 assert(ret_tmp_path);
5681 ending = strjoina(unit_name, ".d/override.conf");
5682 r = get_file_to_edit(ending, user_home, user_runtime, &tmp_new_path);
5686 r = create_edit_temp_file(tmp_new_path, tmp_new_path, &tmp_tmp_path);
5692 *ret_new_path = tmp_new_path;
5693 *ret_tmp_path = tmp_tmp_path;
5698 static int unit_file_create_copy(
5699 const char *unit_name,
5700 const char *fragment_path,
5701 const char *user_home,
5702 const char *user_runtime,
5703 char **ret_new_path,
5704 char **ret_tmp_path) {
5710 assert(fragment_path);
5712 assert(ret_new_path);
5713 assert(ret_tmp_path);
5715 r = get_file_to_edit(unit_name, user_home, user_runtime, &tmp_new_path);
5719 if (!path_equal(fragment_path, tmp_new_path) && access(tmp_new_path, F_OK) == 0) {
5722 r = ask_char(&response, "yn", "\"%s\" already exists. Overwrite with \"%s\"? [(y)es, (n)o] ", tmp_new_path, fragment_path);
5727 if (response != 'y') {
5728 log_warning("%s ignored", unit_name);
5734 r = create_edit_temp_file(tmp_new_path, fragment_path, &tmp_tmp_path);
5736 log_error_errno(r, "Failed to create temporary file for \"%s\": %m", tmp_new_path);
5741 *ret_new_path = tmp_new_path;
5742 *ret_tmp_path = tmp_tmp_path;
5747 static int run_editor(char **paths) {
5755 log_error_errno(errno, "Failed to fork: %m");
5762 char **tmp_path, **original_path, *p;
5766 argc = strv_length(paths)/2 + 1;
5767 args = newa(const char*, argc + 1);
5770 STRV_FOREACH_PAIR(original_path, tmp_path, paths) {
5771 args[i] = *tmp_path;
5776 /* SYSTEMD_EDITOR takes precedence over EDITOR which takes precedence over VISUAL
5777 * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present,
5778 * we try to execute well known editors
5780 editor = getenv("SYSTEMD_EDITOR");
5782 editor = getenv("EDITOR");
5784 editor = getenv("VISUAL");
5786 if (!isempty(editor)) {
5788 execvp(editor, (char* const*) args);
5791 FOREACH_STRING(p, "nano", "vim", "vi") {
5793 execvp(p, (char* const*) args);
5794 /* We do not fail if the editor doesn't exist
5795 * because we want to try each one of them before
5798 if (errno != ENOENT) {
5799 log_error("Failed to execute %s: %m", editor);
5800 _exit(EXIT_FAILURE);
5804 log_error("Cannot edit unit(s), no editor available. Please set either $SYSTEMD_EDITOR, $EDITOR or $VISUAL.");
5805 _exit(EXIT_FAILURE);
5808 r = wait_for_terminate_and_warn("editor", pid, true);
5810 return log_error_errno(r, "Failed to wait for child: %m");
5815 static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
5816 _cleanup_free_ char *user_home = NULL;
5817 _cleanup_free_ char *user_runtime = NULL;
5818 _cleanup_lookup_paths_free_ LookupPaths lp = {};
5819 bool avoid_bus_cache;
5826 r = init_home_and_lookup_paths(&user_home, &user_runtime, &lp);
5830 avoid_bus_cache = !bus || avoid_bus();
5832 STRV_FOREACH(name, names) {
5833 _cleanup_free_ char *path = NULL;
5834 char *new_path, *tmp_path;
5836 r = unit_find_paths(bus, *name, avoid_bus_cache, &lp, &path, NULL);
5842 // FIXME: support units with path==NULL (no FragmentPath)
5843 log_error("No fragment exists for %s.", *name);
5848 r = unit_file_create_copy(*name, path, user_home, user_runtime, &new_path, &tmp_path);
5850 r = unit_file_create_dropin(*name, user_home, user_runtime, &new_path, &tmp_path);
5854 r = strv_push_pair(paths, new_path, tmp_path);
5862 static int edit(sd_bus *bus, char **args) {
5863 _cleanup_strv_free_ char **names = NULL;
5864 _cleanup_strv_free_ char **paths = NULL;
5865 char **original, **tmp;
5871 log_error("Cannot edit units if not on a tty");
5875 if (arg_transport != BUS_TRANSPORT_LOCAL) {
5876 log_error("Cannot remotely edit units");
5880 r = expand_names(bus, args + 1, NULL, &names);
5882 return log_error_errno(r, "Failed to expand names: %m");
5884 r = find_paths_to_edit(bus, names, &paths);
5888 if (strv_isempty(paths))
5891 r = run_editor(paths);
5895 STRV_FOREACH_PAIR(original, tmp, paths) {
5896 /* If the temporary file is empty we ignore it.
5897 * It's useful if the user wants to cancel its modification
5899 if (null_or_empty_path(*tmp)) {
5900 log_warning("Editing \"%s\" canceled: temporary file is empty", *original);
5903 r = rename(*tmp, *original);
5905 r = log_error_errno(errno, "Failed to rename \"%s\" to \"%s\": %m", *tmp, *original);
5910 if (!arg_no_reload && bus && !avoid_bus())
5911 r = daemon_reload(bus, args);
5914 STRV_FOREACH_PAIR(original, tmp, paths)
5915 unlink_noerrno(*tmp);
5920 static void systemctl_help(void) {
5922 pager_open_if_enabled();
5924 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
5925 "Query or send control commands to the systemd manager.\n\n"
5926 " -h --help Show this help\n"
5927 " --version Show package version\n"
5928 " --system Connect to system manager\n"
5929 " --user Connect to user service manager\n"
5930 " -H --host=[USER@]HOST\n"
5931 " Operate on remote host\n"
5932 " -M --machine=CONTAINER\n"
5933 " Operate on local container\n"
5934 " -t --type=TYPE List units of a particular type\n"
5935 " --state=STATE List units with particular LOAD or SUB or ACTIVE state\n"
5936 " -p --property=NAME Show only properties by this name\n"
5937 " -a --all Show all loaded units/properties, including dead/empty\n"
5938 " ones. To list all units installed on the system, use\n"
5939 " the 'list-unit-files' command instead.\n"
5940 " -l --full Don't ellipsize unit names on output\n"
5941 " -r --recursive Show unit list of host and local containers\n"
5942 " --reverse Show reverse dependencies with 'list-dependencies'\n"
5943 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
5944 " queueing a new job\n"
5945 " --show-types When showing sockets, explicitly show their type\n"
5946 " -i --ignore-inhibitors\n"
5947 " When shutting down or sleeping, ignore inhibitors\n"
5948 " --kill-who=WHO Who to send signal to\n"
5949 " -s --signal=SIGNAL Which signal to send\n"
5950 " -q --quiet Suppress output\n"
5951 " --no-block Do not wait until operation finished\n"
5952 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5953 " --no-reload Don't reload daemon after en-/dis-abling unit files\n"
5954 " --no-legend Do not print a legend (column headers and hints)\n"
5955 " --no-pager Do not pipe output into a pager\n"
5956 " --no-ask-password\n"
5957 " Do not ask for system passwords\n"
5958 " --global Enable/disable unit files globally\n"
5959 " --runtime Enable unit files only temporarily until next reboot\n"
5960 " -f --force When enabling unit files, override existing symlinks\n"
5961 " When shutting down, execute action immediately\n"
5962 " --preset-mode= Apply only enable, only disable, or all presets\n"
5963 " --root=PATH Enable unit files in the specified root directory\n"
5964 " -n --lines=INTEGER Number of journal entries to show\n"
5965 " -o --output=STRING Change journal output mode (short, short-iso,\n"
5966 " short-precise, short-monotonic, verbose,\n"
5967 " export, json, json-pretty, json-sse, cat)\n"
5968 " --plain Print unit dependencies as a list instead of a tree\n\n"
5970 " list-units [PATTERN...] List loaded units\n"
5971 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
5972 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
5973 " start NAME... Start (activate) one or more units\n"
5974 " stop NAME... Stop (deactivate) one or more units\n"
5975 " reload NAME... Reload one or more units\n"
5976 " restart NAME... Start or restart one or more units\n"
5977 " try-restart NAME... Restart one or more units if active\n"
5978 " reload-or-restart NAME... Reload one or more units if possible,\n"
5979 " otherwise start or restart\n"
5980 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
5981 " otherwise restart if active\n"
5982 " isolate NAME Start one unit and stop all others\n"
5983 " kill NAME... Send signal to processes of a unit\n"
5984 " is-active PATTERN... Check whether units are active\n"
5985 " is-failed PATTERN... Check whether units are failed\n"
5986 " status [PATTERN...|PID...] Show runtime status of one or more units\n"
5987 " show [PATTERN...|JOB...] Show properties of one or more\n"
5988 " units/jobs or the manager\n"
5989 " cat PATTERN... Show files and drop-ins of one or more units\n"
5990 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
5991 " help PATTERN...|PID... Show manual for one or more units\n"
5992 " reset-failed [PATTERN...] Reset failed state for all, one, or more\n"
5994 " list-dependencies [NAME] Recursively show units which are required\n"
5995 " or wanted by this unit or by which this\n"
5996 " unit is required or wanted\n\n"
5997 "Unit File Commands:\n"
5998 " list-unit-files [PATTERN...] List installed unit files\n"
5999 " enable NAME... Enable one or more unit files\n"
6000 " disable NAME... Disable one or more unit files\n"
6001 " reenable NAME... Reenable one or more unit files\n"
6002 " preset NAME... Enable/disable one or more unit files\n"
6003 " based on preset configuration\n"
6004 " preset-all Enable/disable all unit files based on\n"
6005 " preset configuration\n"
6006 " is-enabled NAME... Check whether unit files are enabled\n"
6007 " mask NAME... Mask one or more units\n"
6008 " unmask NAME... Unmask one or more units\n"
6009 " link PATH... Link one or more units files into\n"
6010 " the search path\n"
6011 " add-wants TARGET NAME... Add 'Wants' dependency for the target\n"
6012 " on specified one or more units\n"
6013 " add-requires TARGET NAME... Add 'Requires' dependency for the target\n"
6014 " on specified one or more units\n"
6015 " edit NAME... Edit one or more unit files\n"
6016 " get-default Get the name of the default target\n"
6017 " set-default NAME Set the default target\n\n"
6018 "Machine Commands:\n"
6019 " list-machines [PATTERN...] List local containers and host\n\n"
6021 " list-jobs [PATTERN...] List jobs\n"
6022 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
6023 "Snapshot Commands:\n"
6024 " snapshot [NAME] Create a snapshot\n"
6025 " delete NAME... Remove one or more snapshots\n\n"
6026 "Environment Commands:\n"
6027 " show-environment Dump environment\n"
6028 " set-environment NAME=VALUE... Set one or more environment variables\n"
6029 " unset-environment NAME... Unset one or more environment variables\n"
6030 " import-environment [NAME...] Import all or some environment variables\n\n"
6031 "Manager Lifecycle Commands:\n"
6032 " daemon-reload Reload systemd manager configuration\n"
6033 " daemon-reexec Reexecute systemd manager\n\n"
6034 "System Commands:\n"
6035 " is-system-running Check whether system is fully running\n"
6036 " default Enter system default mode\n"
6037 " rescue Enter system rescue mode\n"
6038 " emergency Enter system emergency mode\n"
6039 " halt Shut down and halt the system\n"
6040 " poweroff Shut down and power-off the system\n"
6041 " reboot [ARG] Shut down and reboot the system\n"
6042 " kexec Shut down and reboot the system with kexec\n"
6043 " exit Request user instance exit\n"
6044 " switch-root ROOT [INIT] Change to a different root file system\n"
6045 " suspend Suspend the system\n"
6046 " hibernate Hibernate the system\n"
6047 " hybrid-sleep Hibernate and suspend the system\n",
6048 program_invocation_short_name);
6051 static void halt_help(void) {
6052 printf("%s [OPTIONS...]%s\n\n"
6053 "%s the system.\n\n"
6054 " --help Show this help\n"
6055 " --halt Halt the machine\n"
6056 " -p --poweroff Switch off the machine\n"
6057 " --reboot Reboot the machine\n"
6058 " -f --force Force immediate halt/power-off/reboot\n"
6059 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
6060 " -d --no-wtmp Don't write wtmp record\n"
6061 " --no-wall Don't send wall message before halt/power-off/reboot\n",
6062 program_invocation_short_name,
6063 arg_action == ACTION_REBOOT ? " [ARG]" : "",
6064 arg_action == ACTION_REBOOT ? "Reboot" :
6065 arg_action == ACTION_POWEROFF ? "Power off" :
6069 static void shutdown_help(void) {
6070 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
6071 "Shut down the system.\n\n"
6072 " --help Show this help\n"
6073 " -H --halt Halt the machine\n"
6074 " -P --poweroff Power-off the machine\n"
6075 " -r --reboot Reboot the machine\n"
6076 " -h Equivalent to --poweroff, overridden by --halt\n"
6077 " -k Don't halt/power-off/reboot, just send warnings\n"
6078 " --no-wall Don't send wall message before halt/power-off/reboot\n"
6079 " -c Cancel a pending shutdown\n",
6080 program_invocation_short_name);
6083 static void telinit_help(void) {
6084 printf("%s [OPTIONS...] {COMMAND}\n\n"
6085 "Send control commands to the init daemon.\n\n"
6086 " --help Show this help\n"
6087 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
6089 " 0 Power-off the machine\n"
6090 " 6 Reboot the machine\n"
6091 " 2, 3, 4, 5 Start runlevelX.target unit\n"
6092 " 1, s, S Enter rescue mode\n"
6093 " q, Q Reload init daemon configuration\n"
6094 " u, U Reexecute init daemon\n",
6095 program_invocation_short_name);
6098 static void runlevel_help(void) {
6099 printf("%s [OPTIONS...]\n\n"
6100 "Prints the previous and current runlevel of the init system.\n\n"
6101 " --help Show this help\n",
6102 program_invocation_short_name);
6105 static void help_types(void) {
6110 puts("Available unit types:");
6111 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
6112 t = unit_type_to_string(i);
6118 static int systemctl_parse_argv(int argc, char *argv[]) {
6127 ARG_IGNORE_DEPENDENCIES,
6139 ARG_NO_ASK_PASSWORD,
6149 static const struct option options[] = {
6150 { "help", no_argument, NULL, 'h' },
6151 { "version", no_argument, NULL, ARG_VERSION },
6152 { "type", required_argument, NULL, 't' },
6153 { "property", required_argument, NULL, 'p' },
6154 { "all", no_argument, NULL, 'a' },
6155 { "reverse", no_argument, NULL, ARG_REVERSE },
6156 { "after", no_argument, NULL, ARG_AFTER },
6157 { "before", no_argument, NULL, ARG_BEFORE },
6158 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
6159 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
6160 { "full", no_argument, NULL, 'l' },
6161 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
6162 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
6163 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
6164 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
6165 { "ignore-inhibitors", no_argument, NULL, 'i' },
6166 { "user", no_argument, NULL, ARG_USER },
6167 { "system", no_argument, NULL, ARG_SYSTEM },
6168 { "global", no_argument, NULL, ARG_GLOBAL },
6169 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
6170 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
6171 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
6172 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6173 { "quiet", no_argument, NULL, 'q' },
6174 { "root", required_argument, NULL, ARG_ROOT },
6175 { "force", no_argument, NULL, ARG_FORCE },
6176 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
6177 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
6178 { "signal", required_argument, NULL, 's' },
6179 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
6180 { "host", required_argument, NULL, 'H' },
6181 { "machine", required_argument, NULL, 'M' },
6182 { "runtime", no_argument, NULL, ARG_RUNTIME },
6183 { "lines", required_argument, NULL, 'n' },
6184 { "output", required_argument, NULL, 'o' },
6185 { "plain", no_argument, NULL, ARG_PLAIN },
6186 { "state", required_argument, NULL, ARG_STATE },
6187 { "recursive", no_argument, NULL, 'r' },
6188 { "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
6197 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0)
6206 puts(PACKAGE_STRING);
6207 puts(SYSTEMD_FEATURES);
6211 const char *word, *state;
6214 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6215 _cleanup_free_ char *type;
6217 type = strndup(word, size);
6221 if (streq(type, "help")) {
6226 if (unit_type_from_string(type) >= 0) {
6227 if (strv_push(&arg_types, type))
6233 /* It's much nicer to use --state= for
6234 * load states, but let's support this
6235 * in --types= too for compatibility
6236 * with old versions */
6237 if (unit_load_state_from_string(optarg) >= 0) {
6238 if (strv_push(&arg_states, type) < 0)
6244 log_error("Unknown unit type or load state '%s'.", type);
6245 log_info("Use -t help to see a list of allowed values.");
6253 /* Make sure that if the empty property list
6254 was specified, we won't show any properties. */
6255 if (isempty(optarg) && !arg_properties) {
6256 arg_properties = new0(char*, 1);
6257 if (!arg_properties)
6260 const char *word, *state;
6263 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6266 prop = strndup(word, size);
6270 if (strv_consume(&arg_properties, prop) < 0)
6275 /* If the user asked for a particular
6276 * property, show it to him, even if it is
6288 arg_dependency = DEPENDENCY_REVERSE;
6292 arg_dependency = DEPENDENCY_AFTER;
6296 arg_dependency = DEPENDENCY_BEFORE;
6299 case ARG_SHOW_TYPES:
6300 arg_show_types = true;
6304 arg_job_mode = optarg;
6308 arg_job_mode = "fail";
6311 case ARG_IRREVERSIBLE:
6312 arg_job_mode = "replace-irreversibly";
6315 case ARG_IGNORE_DEPENDENCIES:
6316 arg_job_mode = "ignore-dependencies";
6320 arg_scope = UNIT_FILE_USER;
6324 arg_scope = UNIT_FILE_SYSTEM;
6328 arg_scope = UNIT_FILE_GLOBAL;
6332 arg_no_block = true;
6336 arg_no_legend = true;
6340 arg_no_pager = true;
6356 if (strv_extend(&arg_states, "failed") < 0)
6374 arg_no_reload = true;
6378 arg_kill_who = optarg;
6382 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
6383 log_error("Failed to parse signal string %s.", optarg);
6388 case ARG_NO_ASK_PASSWORD:
6389 arg_ask_password = false;
6393 arg_transport = BUS_TRANSPORT_REMOTE;
6398 arg_transport = BUS_TRANSPORT_MACHINE;
6407 if (safe_atou(optarg, &arg_lines) < 0) {
6408 log_error("Failed to parse lines '%s'", optarg);
6414 arg_output = output_mode_from_string(optarg);
6415 if (arg_output < 0) {
6416 log_error("Unknown output '%s'.", optarg);
6422 arg_ignore_inhibitors = true;
6430 const char *word, *state;
6433 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
6436 s = strndup(word, size);
6440 if (strv_consume(&arg_states, s) < 0)
6447 if (geteuid() != 0) {
6448 log_error("--recursive requires root privileges.");
6452 arg_recursive = true;
6455 case ARG_PRESET_MODE:
6457 arg_preset_mode = unit_file_preset_mode_from_string(optarg);
6458 if (arg_preset_mode < 0) {
6459 log_error("Failed to parse preset mode: %s.", optarg);
6469 assert_not_reached("Unhandled option");
6472 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
6473 log_error("Cannot access user instance remotely.");
6480 static int halt_parse_argv(int argc, char *argv[]) {
6489 static const struct option options[] = {
6490 { "help", no_argument, NULL, ARG_HELP },
6491 { "halt", no_argument, NULL, ARG_HALT },
6492 { "poweroff", no_argument, NULL, 'p' },
6493 { "reboot", no_argument, NULL, ARG_REBOOT },
6494 { "force", no_argument, NULL, 'f' },
6495 { "wtmp-only", no_argument, NULL, 'w' },
6496 { "no-wtmp", no_argument, NULL, 'd' },
6497 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6506 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
6507 if (runlevel == '0' || runlevel == '6')
6510 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0)
6518 arg_action = ACTION_HALT;
6522 if (arg_action != ACTION_REBOOT)
6523 arg_action = ACTION_POWEROFF;
6527 arg_action = ACTION_REBOOT;
6549 /* Compatibility nops */
6556 assert_not_reached("Unhandled option");
6559 if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) {
6560 r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL);
6563 } else if (optind < argc) {
6564 log_error("Too many arguments.");
6571 static int parse_time_spec(const char *t, usec_t *_u) {
6575 if (streq(t, "now"))
6577 else if (!strchr(t, ':')) {
6580 if (safe_atou64(t, &u) < 0)
6583 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
6592 hour = strtol(t, &e, 10);
6593 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
6596 minute = strtol(e+1, &e, 10);
6597 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
6600 n = now(CLOCK_REALTIME);
6601 s = (time_t) (n / USEC_PER_SEC);
6603 assert_se(localtime_r(&s, &tm));
6605 tm.tm_hour = (int) hour;
6606 tm.tm_min = (int) minute;
6609 assert_se(s = mktime(&tm));
6611 *_u = (usec_t) s * USEC_PER_SEC;
6614 *_u += USEC_PER_DAY;
6620 static int shutdown_parse_argv(int argc, char *argv[]) {
6627 static const struct option options[] = {
6628 { "help", no_argument, NULL, ARG_HELP },
6629 { "halt", no_argument, NULL, 'H' },
6630 { "poweroff", no_argument, NULL, 'P' },
6631 { "reboot", no_argument, NULL, 'r' },
6632 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
6633 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6642 while ((c = getopt_long(argc, argv, "HPrhkKt:afFc", options, NULL)) >= 0)
6650 arg_action = ACTION_HALT;
6654 arg_action = ACTION_POWEROFF;
6659 arg_action = ACTION_KEXEC;
6661 arg_action = ACTION_REBOOT;
6665 arg_action = ACTION_KEXEC;
6669 if (arg_action != ACTION_HALT)
6670 arg_action = ACTION_POWEROFF;
6685 /* Compatibility nops */
6689 arg_action = ACTION_CANCEL_SHUTDOWN;
6696 assert_not_reached("Unhandled option");
6699 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
6700 r = parse_time_spec(argv[optind], &arg_when);
6702 log_error("Failed to parse time specification: %s", argv[optind]);
6706 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
6708 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
6709 /* No time argument for shutdown cancel */
6710 arg_wall = argv + optind;
6711 else if (argc > optind + 1)
6712 /* We skip the time argument */
6713 arg_wall = argv + optind + 1;
6720 static int telinit_parse_argv(int argc, char *argv[]) {
6727 static const struct option options[] = {
6728 { "help", no_argument, NULL, ARG_HELP },
6729 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6733 static const struct {
6737 { '0', ACTION_POWEROFF },
6738 { '6', ACTION_REBOOT },
6739 { '1', ACTION_RESCUE },
6740 { '2', ACTION_RUNLEVEL2 },
6741 { '3', ACTION_RUNLEVEL3 },
6742 { '4', ACTION_RUNLEVEL4 },
6743 { '5', ACTION_RUNLEVEL5 },
6744 { 's', ACTION_RESCUE },
6745 { 'S', ACTION_RESCUE },
6746 { 'q', ACTION_RELOAD },
6747 { 'Q', ACTION_RELOAD },
6748 { 'u', ACTION_REEXEC },
6749 { 'U', ACTION_REEXEC }
6758 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6773 assert_not_reached("Unhandled option");
6776 if (optind >= argc) {
6777 log_error("%s: required argument missing.",
6778 program_invocation_short_name);
6782 if (optind + 1 < argc) {
6783 log_error("Too many arguments.");
6787 if (strlen(argv[optind]) != 1) {
6788 log_error("Expected single character argument.");
6792 for (i = 0; i < ELEMENTSOF(table); i++)
6793 if (table[i].from == argv[optind][0])
6796 if (i >= ELEMENTSOF(table)) {
6797 log_error("Unknown command '%s'.", argv[optind]);
6801 arg_action = table[i].to;
6808 static int runlevel_parse_argv(int argc, char *argv[]) {
6814 static const struct option options[] = {
6815 { "help", no_argument, NULL, ARG_HELP },
6824 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
6835 assert_not_reached("Unhandled option");
6838 if (optind < argc) {
6839 log_error("Too many arguments.");
6846 static int parse_argv(int argc, char *argv[]) {
6850 if (program_invocation_short_name) {
6852 if (strstr(program_invocation_short_name, "halt")) {
6853 arg_action = ACTION_HALT;
6854 return halt_parse_argv(argc, argv);
6855 } else if (strstr(program_invocation_short_name, "poweroff")) {
6856 arg_action = ACTION_POWEROFF;
6857 return halt_parse_argv(argc, argv);
6858 } else if (strstr(program_invocation_short_name, "reboot")) {
6860 arg_action = ACTION_KEXEC;
6862 arg_action = ACTION_REBOOT;
6863 return halt_parse_argv(argc, argv);
6864 } else if (strstr(program_invocation_short_name, "shutdown")) {
6865 arg_action = ACTION_POWEROFF;
6866 return shutdown_parse_argv(argc, argv);
6867 } else if (strstr(program_invocation_short_name, "init")) {
6869 if (sd_booted() > 0) {
6870 arg_action = _ACTION_INVALID;
6871 return telinit_parse_argv(argc, argv);
6873 /* Hmm, so some other init system is
6874 * running, we need to forward this
6875 * request to it. For now we simply
6876 * guess that it is Upstart. */
6878 execv(TELINIT, argv);
6880 log_error("Couldn't find an alternative telinit implementation to spawn.");
6884 } else if (strstr(program_invocation_short_name, "runlevel")) {
6885 arg_action = ACTION_RUNLEVEL;
6886 return runlevel_parse_argv(argc, argv);
6890 arg_action = ACTION_SYSTEMCTL;
6891 return systemctl_parse_argv(argc, argv);
6894 _pure_ static int action_to_runlevel(void) {
6896 static const char table[_ACTION_MAX] = {
6897 [ACTION_HALT] = '0',
6898 [ACTION_POWEROFF] = '0',
6899 [ACTION_REBOOT] = '6',
6900 [ACTION_RUNLEVEL2] = '2',
6901 [ACTION_RUNLEVEL3] = '3',
6902 [ACTION_RUNLEVEL4] = '4',
6903 [ACTION_RUNLEVEL5] = '5',
6904 [ACTION_RESCUE] = '1'
6907 assert(arg_action < _ACTION_MAX);
6909 return table[arg_action];
6912 static int talk_initctl(void) {
6914 struct init_request request = {
6915 .magic = INIT_MAGIC,
6917 .cmd = INIT_CMD_RUNLVL
6920 _cleanup_close_ int fd = -1;
6924 rl = action_to_runlevel();
6928 request.runlevel = rl;
6930 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
6932 if (errno == ENOENT)
6935 log_error_errno(errno, "Failed to open "INIT_FIFO": %m");
6939 r = loop_write(fd, &request, sizeof(request), false);
6941 return log_error_errno(r, "Failed to write to "INIT_FIFO": %m");
6946 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
6948 static const struct {
6956 int (* const dispatch)(sd_bus *bus, char **args);
6962 { "list-units", MORE, 0, list_units },
6963 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
6964 { "list-sockets", MORE, 1, list_sockets },
6965 { "list-timers", MORE, 1, list_timers },
6966 { "list-jobs", MORE, 1, list_jobs },
6967 { "list-machines", MORE, 1, list_machines },
6968 { "clear-jobs", EQUAL, 1, daemon_reload },
6969 { "cancel", MORE, 2, cancel_job },
6970 { "start", MORE, 2, start_unit },
6971 { "stop", MORE, 2, start_unit },
6972 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6973 { "reload", MORE, 2, start_unit },
6974 { "restart", MORE, 2, start_unit },
6975 { "try-restart", MORE, 2, start_unit },
6976 { "reload-or-restart", MORE, 2, start_unit },
6977 { "reload-or-try-restart", MORE, 2, start_unit },
6978 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
6979 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6980 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
6981 { "isolate", EQUAL, 2, start_unit },
6982 { "kill", MORE, 2, kill_unit },
6983 { "is-active", MORE, 2, check_unit_active },
6984 { "check", MORE, 2, check_unit_active },
6985 { "is-failed", MORE, 2, check_unit_failed },
6986 { "show", MORE, 1, show },
6987 { "cat", MORE, 2, cat, NOBUS },
6988 { "status", MORE, 1, show },
6989 { "help", MORE, 2, show },
6990 { "snapshot", LESS, 2, snapshot },
6991 { "delete", MORE, 2, delete_snapshot },
6992 { "daemon-reload", EQUAL, 1, daemon_reload },
6993 { "daemon-reexec", EQUAL, 1, daemon_reload },
6994 { "show-environment", EQUAL, 1, show_environment },
6995 { "set-environment", MORE, 2, set_environment },
6996 { "unset-environment", MORE, 2, set_environment },
6997 { "import-environment", MORE, 1, import_environment},
6998 { "halt", EQUAL, 1, start_special, FORCE },
6999 { "poweroff", EQUAL, 1, start_special, FORCE },
7000 { "reboot", MORE, 1, start_special, FORCE },
7001 { "kexec", EQUAL, 1, start_special },
7002 { "suspend", EQUAL, 1, start_special },
7003 { "hibernate", EQUAL, 1, start_special },
7004 { "hybrid-sleep", EQUAL, 1, start_special },
7005 { "default", EQUAL, 1, start_special },
7006 { "rescue", EQUAL, 1, start_special },
7007 { "emergency", EQUAL, 1, start_special },
7008 { "exit", EQUAL, 1, start_special },
7009 { "reset-failed", MORE, 1, reset_failed },
7010 { "enable", MORE, 2, enable_unit, NOBUS },
7011 { "disable", MORE, 2, enable_unit, NOBUS },
7012 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
7013 { "reenable", MORE, 2, enable_unit, NOBUS },
7014 { "preset", MORE, 2, enable_unit, NOBUS },
7015 { "preset-all", EQUAL, 1, preset_all, NOBUS },
7016 { "mask", MORE, 2, enable_unit, NOBUS },
7017 { "unmask", MORE, 2, enable_unit, NOBUS },
7018 { "link", MORE, 2, enable_unit, NOBUS },
7019 { "switch-root", MORE, 2, switch_root },
7020 { "list-dependencies", LESS, 2, list_dependencies },
7021 { "set-default", EQUAL, 2, set_default, NOBUS },
7022 { "get-default", EQUAL, 1, get_default, NOBUS },
7023 { "set-property", MORE, 3, set_property },
7024 { "is-system-running", EQUAL, 1, is_system_running },
7025 { "add-wants", MORE, 3, add_dependency, NOBUS },
7026 { "add-requires", MORE, 3, add_dependency, NOBUS },
7027 { "edit", MORE, 2, edit, NOBUS },
7036 left = argc - optind;
7038 /* Special rule: no arguments (left == 0) means "list-units" */
7040 if (streq(argv[optind], "help") && !argv[optind+1]) {
7041 log_error("This command expects one or more "
7042 "unit names. Did you mean --help?");
7046 for (; verb->verb; verb++)
7047 if (streq(argv[optind], verb->verb))
7050 log_error("Unknown operation '%s'.", argv[optind]);
7055 switch (verb->argc_cmp) {
7058 if (left != verb->argc) {
7059 log_error("Invalid number of arguments.");
7066 if (left < verb->argc) {
7067 log_error("Too few arguments.");
7074 if (left > verb->argc) {
7075 log_error("Too many arguments.");
7082 assert_not_reached("Unknown comparison operator.");
7085 /* Require a bus connection for all operations but
7087 if (verb->bus == NOBUS) {
7088 if (!bus && !avoid_bus()) {
7089 log_error_errno(bus_error, "Failed to get D-Bus connection: %m");
7094 if (running_in_chroot() > 0) {
7095 log_info("Running in chroot, ignoring request.");
7099 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
7100 log_error_errno(bus_error, "Failed to get D-Bus connection: %m");
7105 return verb->dispatch(bus, argv + optind);
7108 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
7110 struct sd_shutdown_command c = {
7117 union sockaddr_union sockaddr = {
7118 .un.sun_family = AF_UNIX,
7119 .un.sun_path = "/run/systemd/shutdownd",
7122 struct iovec iovec[2] = {{
7123 .iov_base = (char*) &c,
7124 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
7127 struct msghdr msghdr = {
7128 .msg_name = &sockaddr,
7129 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
7130 + strlen("/run/systemd/shutdownd"),
7135 _cleanup_close_ int fd;
7137 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
7141 if (!isempty(message)) {
7142 iovec[1].iov_base = (char*) message;
7143 iovec[1].iov_len = strlen(message);
7144 msghdr.msg_iovlen++;
7147 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
7153 static int reload_with_fallback(sd_bus *bus) {
7156 /* First, try systemd via D-Bus. */
7157 if (daemon_reload(bus, NULL) >= 0)
7161 /* Nothing else worked, so let's try signals */
7162 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
7164 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0)
7165 return log_error_errno(errno, "kill() failed: %m");
7170 static int start_with_fallback(sd_bus *bus) {
7173 /* First, try systemd via D-Bus. */
7174 if (start_unit(bus, NULL) >= 0)
7178 /* Nothing else worked, so let's try
7180 if (talk_initctl() > 0)
7183 log_error("Failed to talk to init daemon.");
7187 warn_wall(arg_action);
7191 static int halt_now(enum action a) {
7193 /* The kernel will automaticall flush ATA disks and suchlike
7194 * on reboot(), but the file systems need to be synce'd
7195 * explicitly in advance. */
7198 /* Make sure C-A-D is handled by the kernel from this point
7200 reboot(RB_ENABLE_CAD);
7205 log_info("Halting.");
7206 reboot(RB_HALT_SYSTEM);
7209 case ACTION_POWEROFF:
7210 log_info("Powering off.");
7211 reboot(RB_POWER_OFF);
7214 case ACTION_REBOOT: {
7215 _cleanup_free_ char *param = NULL;
7217 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
7218 log_info("Rebooting with argument '%s'.", param);
7219 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
7220 LINUX_REBOOT_CMD_RESTART2, param);
7223 log_info("Rebooting.");
7224 reboot(RB_AUTOBOOT);
7229 assert_not_reached("Unknown action.");
7233 static int halt_main(sd_bus *bus) {
7236 r = check_inhibitors(bus, arg_action);
7240 if (geteuid() != 0) {
7241 /* Try logind if we are a normal user and no special
7242 * mode applies. Maybe PolicyKit allows us to shutdown
7245 if (arg_when <= 0 &&
7248 (arg_action == ACTION_POWEROFF ||
7249 arg_action == ACTION_REBOOT)) {
7250 r = reboot_with_logind(bus, arg_action);
7255 log_error("Must be root.");
7260 _cleanup_free_ char *m;
7262 m = strv_join(arg_wall, " ");
7266 r = send_shutdownd(arg_when,
7267 arg_action == ACTION_HALT ? 'H' :
7268 arg_action == ACTION_POWEROFF ? 'P' :
7269 arg_action == ACTION_KEXEC ? 'K' :
7276 log_warning_errno(r, "Failed to talk to shutdownd, proceeding with immediate shutdown: %m");
7278 char date[FORMAT_TIMESTAMP_MAX];
7280 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
7281 format_timestamp(date, sizeof(date), arg_when));
7286 if (!arg_dry && !arg_force)
7287 return start_with_fallback(bus);
7290 if (sd_booted() > 0)
7291 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
7293 r = utmp_put_shutdown();
7295 log_warning_errno(r, "Failed to write utmp record: %m");
7302 r = halt_now(arg_action);
7303 log_error_errno(r, "Failed to reboot: %m");
7308 static int runlevel_main(void) {
7309 int r, runlevel, previous;
7311 r = utmp_get_runlevel(&runlevel, &previous);
7318 previous <= 0 ? 'N' : previous,
7319 runlevel <= 0 ? 'N' : runlevel);
7324 int main(int argc, char*argv[]) {
7325 _cleanup_bus_close_unref_ sd_bus *bus = NULL;
7328 setlocale(LC_ALL, "");
7329 log_parse_environment();
7332 /* Explicitly not on_tty() to avoid setting cached value.
7333 * This becomes relevant for piping output which might be
7335 original_stdout_is_tty = isatty(STDOUT_FILENO);
7337 r = parse_argv(argc, argv);
7341 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
7342 * let's shortcut this */
7343 if (arg_action == ACTION_RUNLEVEL) {
7344 r = runlevel_main();
7348 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
7349 log_info("Running in chroot, ignoring request.");
7354 /* Increase max number of open files to 16K if we can, we
7355 * might needs this when browsing journal files, which might
7356 * be split up into many files. */
7357 setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(16384));
7360 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
7363 sd_bus_set_allow_interactive_authorization(bus, arg_ask_password);
7365 /* systemctl_main() will print an error message for the bus
7366 * connection, but only if it needs to */
7368 switch (arg_action) {
7370 case ACTION_SYSTEMCTL:
7371 r = systemctl_main(bus, argc, argv, r);
7375 case ACTION_POWEROFF:
7381 case ACTION_RUNLEVEL2:
7382 case ACTION_RUNLEVEL3:
7383 case ACTION_RUNLEVEL4:
7384 case ACTION_RUNLEVEL5:
7386 case ACTION_EMERGENCY:
7387 case ACTION_DEFAULT:
7388 r = start_with_fallback(bus);
7393 r = reload_with_fallback(bus);
7396 case ACTION_CANCEL_SHUTDOWN: {
7397 _cleanup_free_ char *m = NULL;
7400 m = strv_join(arg_wall, " ");
7407 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
7409 log_warning_errno(r, "Failed to talk to shutdownd, shutdown hasn't been cancelled: %m");
7413 case ACTION_RUNLEVEL:
7414 case _ACTION_INVALID:
7416 assert_not_reached("Unknown action");
7421 ask_password_agent_close();
7422 polkit_agent_close();
7424 strv_free(arg_types);
7425 strv_free(arg_states);
7426 strv_free(arg_properties);
7428 return r < 0 ? EXIT_FAILURE : r;