1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Marc-Antoine Perennou
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/reboot.h>
24 #include <linux/reboot.h>
25 #include <sys/syscall.h>
32 #include <sys/ioctl.h>
36 #include <sys/socket.h>
39 #include <sys/prctl.h>
42 #include "sd-daemon.h"
43 #include "sd-shutdown.h"
50 #include "utmp-wtmp.h"
53 #include "path-util.h"
55 #include "cgroup-show.h"
56 #include "cgroup-util.h"
58 #include "path-lookup.h"
59 #include "conf-parser.h"
60 #include "exit-status.h"
62 #include "unit-name.h"
64 #include "spawn-ask-password-agent.h"
65 #include "spawn-polkit-agent.h"
67 #include "logs-show.h"
68 #include "socket-util.h"
72 #include "bus-message.h"
73 #include "bus-error.h"
74 #include "bus-errors.h"
76 static char **arg_types = NULL;
77 static char **arg_states = NULL;
78 static char **arg_properties = NULL;
79 static bool arg_all = false;
80 static enum dependency {
86 } arg_dependency = DEPENDENCY_FORWARD;
87 static const char *arg_job_mode = "replace";
88 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
89 static bool arg_no_block = false;
90 static bool arg_no_legend = false;
91 static bool arg_no_pager = false;
92 static bool arg_no_wtmp = false;
93 static bool arg_no_wall = false;
94 static bool arg_no_reload = false;
95 static bool arg_show_types = false;
96 static bool arg_ignore_inhibitors = false;
97 static bool arg_dry = false;
98 static bool arg_quiet = false;
99 static bool arg_full = false;
100 static bool arg_recursive = false;
101 static int arg_force = 0;
102 static bool arg_ask_password = true;
103 static bool arg_runtime = false;
104 static char **arg_wall = NULL;
105 static const char *arg_kill_who = NULL;
106 static int arg_signal = SIGTERM;
107 static const char *arg_root = NULL;
108 static usec_t arg_when = 0;
130 ACTION_CANCEL_SHUTDOWN,
132 } arg_action = ACTION_SYSTEMCTL;
133 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
134 static char *arg_host = NULL;
135 static unsigned arg_lines = 10;
136 static OutputMode arg_output = OUTPUT_SHORT;
137 static bool arg_plain = false;
139 static const struct {
143 { "start", "StartUnit" },
144 { "stop", "StopUnit" },
145 { "condstop", "StopUnit" },
146 { "reload", "ReloadUnit" },
147 { "restart", "RestartUnit" },
148 { "try-restart", "TryRestartUnit" },
149 { "condrestart", "TryRestartUnit" },
150 { "reload-or-restart", "ReloadOrRestartUnit" },
151 { "reload-or-try-restart", "ReloadOrTryRestartUnit" },
152 { "condreload", "ReloadOrTryRestartUnit" },
153 { "force-reload", "ReloadOrTryRestartUnit" }
156 static bool original_stdout_is_tty;
158 static int daemon_reload(sd_bus *bus, char **args);
159 static int halt_now(enum action a);
160 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet);
162 static char** strv_skip_first(char **strv) {
163 if (strv_length(strv) > 0)
168 static void pager_open_if_enabled(void) {
176 static void ask_password_agent_open_if_enabled(void) {
178 /* Open the password agent as a child process if necessary */
180 if (!arg_ask_password)
183 if (arg_scope != UNIT_FILE_SYSTEM)
186 if (arg_transport != BUS_TRANSPORT_LOCAL)
189 ask_password_agent_open();
193 static void polkit_agent_open_if_enabled(void) {
195 /* Open the polkit agent as a child process if necessary */
197 if (!arg_ask_password)
200 if (arg_scope != UNIT_FILE_SYSTEM)
203 if (arg_transport != BUS_TRANSPORT_LOCAL)
210 static int translate_bus_error_to_exit_status(int r, const sd_bus_error *error) {
213 if (!sd_bus_error_is_set(error))
216 if (sd_bus_error_has_name(error, SD_BUS_ERROR_ACCESS_DENIED) ||
217 sd_bus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
218 sd_bus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
219 sd_bus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
220 return EXIT_NOPERMISSION;
222 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
223 return EXIT_NOTINSTALLED;
225 if (sd_bus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
226 sd_bus_error_has_name(error, SD_BUS_ERROR_NOT_SUPPORTED))
227 return EXIT_NOTIMPLEMENTED;
229 if (sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
230 return EXIT_NOTCONFIGURED;
238 static void warn_wall(enum action a) {
239 static const char *table[_ACTION_MAX] = {
240 [ACTION_HALT] = "The system is going down for system halt NOW!",
241 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
242 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
243 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
244 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
245 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
246 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
253 _cleanup_free_ char *p;
255 p = strv_join(arg_wall, " ");
262 utmp_wall(p, NULL, NULL);
270 utmp_wall(table[a], NULL, NULL);
273 static bool avoid_bus(void) {
275 if (running_in_chroot() > 0)
278 if (sd_booted() <= 0)
281 if (!isempty(arg_root))
284 if (arg_scope == UNIT_FILE_GLOBAL)
290 static int compare_unit_info(const void *a, const void *b) {
291 const UnitInfo *u = a, *v = b;
295 /* First, order by machine */
296 if (!u->machine && v->machine)
298 if (u->machine && !v->machine)
300 if (u->machine && v->machine) {
301 r = strcasecmp(u->machine, v->machine);
306 /* Second, order by unit type */
307 d1 = strrchr(u->id, '.');
308 d2 = strrchr(v->id, '.');
310 r = strcasecmp(d1, d2);
315 /* Third, order by name */
316 return strcasecmp(u->id, v->id);
319 static bool output_show_unit(const UnitInfo *u, char **patterns) {
322 if (!strv_isempty(arg_states))
324 strv_contains(arg_states, u->load_state) ||
325 strv_contains(arg_states, u->sub_state) ||
326 strv_contains(arg_states, u->active_state);
328 if (!strv_isempty(patterns)) {
331 STRV_FOREACH(pattern, patterns)
332 if (fnmatch(*pattern, u->id, FNM_NOESCAPE) == 0)
337 return (!arg_types || ((dot = strrchr(u->id, '.')) &&
338 strv_find(arg_types, dot+1))) &&
339 (arg_all || !(streq(u->active_state, "inactive")
340 || u->following[0]) || u->job_id > 0);
343 static int output_units_list(const UnitInfo *unit_infos, unsigned c) {
344 unsigned id_len, max_id_len, load_len, active_len, sub_len, job_len, desc_len;
346 unsigned n_shown = 0;
349 max_id_len = strlen("UNIT");
350 load_len = strlen("LOAD");
351 active_len = strlen("ACTIVE");
352 sub_len = strlen("SUB");
353 job_len = strlen("JOB");
356 for (u = unit_infos; u < unit_infos + c; u++) {
357 max_id_len = MAX(max_id_len, strlen(u->id) + (u->machine ? strlen(u->machine)+1 : 0));
358 load_len = MAX(load_len, strlen(u->load_state));
359 active_len = MAX(active_len, strlen(u->active_state));
360 sub_len = MAX(sub_len, strlen(u->sub_state));
362 if (u->job_id != 0) {
363 job_len = MAX(job_len, strlen(u->job_type));
368 if (!arg_full && original_stdout_is_tty) {
371 id_len = MIN(max_id_len, 25u);
372 basic_len = 5 + id_len + 5 + active_len + sub_len;
375 basic_len += job_len + 1;
377 if (basic_len < (unsigned) columns()) {
378 unsigned extra_len, incr;
379 extra_len = columns() - basic_len;
381 /* Either UNIT already got 25, or is fully satisfied.
382 * Grant up to 25 to DESC now. */
383 incr = MIN(extra_len, 25u);
387 /* split the remaining space between UNIT and DESC,
388 * but do not give UNIT more than it needs. */
390 incr = MIN(extra_len / 2, max_id_len - id_len);
392 desc_len += extra_len - incr;
398 for (u = unit_infos; u < unit_infos + c; u++) {
399 _cleanup_free_ char *e = NULL, *j = NULL;
400 const char *on_loaded, *off_loaded, *on = "";
401 const char *on_active, *off_active, *off = "";
404 if (!n_shown && !arg_no_legend) {
405 printf("%-*s %-*s %-*s %-*s ",
408 active_len, "ACTIVE",
412 printf("%-*s ", job_len, "JOB");
414 if (!arg_full && arg_no_pager)
415 printf("%.*s\n", desc_len, "DESCRIPTION");
417 printf("%s\n", "DESCRIPTION");
422 if (streq(u->load_state, "error") ||
423 streq(u->load_state, "not-found")) {
424 on_loaded = on = ansi_highlight_red();
425 off_loaded = off = ansi_highlight_off();
427 on_loaded = off_loaded = "";
429 if (streq(u->active_state, "failed")) {
430 on_active = on = ansi_highlight_red();
431 off_active = off = ansi_highlight_off();
433 on_active = off_active = "";
436 j = strjoin(u->machine, ":", u->id, NULL);
445 e = ellipsize(id, id_len, 33);
452 printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s",
454 on_loaded, load_len, u->load_state, off_loaded,
455 on_active, active_len, u->active_state,
456 sub_len, u->sub_state, off_active,
457 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
460 printf("%.*s\n", desc_len, u->description);
462 printf("%s\n", u->description);
465 if (!arg_no_legend) {
466 const char *on, *off;
469 puts("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
470 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
471 "SUB = The low-level unit activation state, values depend on unit type.");
472 puts(job_count ? "JOB = Pending job for the unit.\n" : "");
473 on = ansi_highlight();
474 off = ansi_highlight_off();
476 on = ansi_highlight_red();
477 off = ansi_highlight_off();
481 printf("%s%u loaded units listed.%s\n"
482 "To show all installed unit files use 'systemctl list-unit-files'.\n",
485 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
486 "To show all installed unit files use 'systemctl list-unit-files'.\n",
493 static int get_unit_list(
497 UnitInfo **unit_infos,
499 sd_bus_message **_reply) {
501 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
502 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
511 size = sizeof(UnitInfo) * c;
513 r = sd_bus_call_method(
515 "org.freedesktop.systemd1",
516 "/org/freedesktop/systemd1",
517 "org.freedesktop.systemd1.Manager",
523 log_error("Failed to list units: %s", bus_error_message(&error, r));
527 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
529 return bus_log_parse_error(r);
531 while ((r = bus_parse_unit_info(reply, &u)) > 0) {
534 if (!output_show_unit(&u, patterns))
537 if (!GREEDY_REALLOC(*unit_infos, size, c+1))
540 (*unit_infos)[c++] = u;
543 return bus_log_parse_error(r);
545 r = sd_bus_message_exit_container(reply);
547 return bus_log_parse_error(r);
555 static void message_set_freep(Set **set) {
558 while ((m = set_steal_first(*set)))
559 sd_bus_message_unref(m);
564 static int get_unit_list_recursive(
567 UnitInfo **_unit_infos,
571 _cleanup_free_ UnitInfo *unit_infos = NULL;
572 _cleanup_(message_set_freep) Set *replies;
573 sd_bus_message *reply;
581 replies = set_new(NULL, NULL);
585 c = get_unit_list(bus, NULL, patterns, &unit_infos, 0, &reply);
589 r = set_put(replies, reply);
591 sd_bus_message_unref(reply);
596 _cleanup_strv_free_ char **machines = NULL;
599 r = sd_get_machine_names(&machines);
603 STRV_FOREACH(i, machines) {
604 _cleanup_bus_unref_ sd_bus *container = NULL;
607 r = sd_bus_open_system_container(&container, *i);
609 log_error("Failed to connect to container %s: %s", *i, strerror(-r));
613 k = get_unit_list(container, *i, patterns, &unit_infos, c, &reply);
619 r = set_put(replies, reply);
621 sd_bus_message_unref(reply);
626 *_machines = machines;
631 *_unit_infos = unit_infos;
640 static int list_units(sd_bus *bus, char **args) {
641 _cleanup_free_ UnitInfo *unit_infos = NULL;
642 _cleanup_(message_set_freep) Set *replies = NULL;
643 _cleanup_strv_free_ char **machines = NULL;
646 pager_open_if_enabled();
648 r = get_unit_list_recursive(bus, strv_skip_first(args), &unit_infos, &replies, &machines);
652 qsort_safe(unit_infos, r, sizeof(UnitInfo), compare_unit_info);
653 return output_units_list(unit_infos, r);
656 static int get_triggered_units(
661 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
664 r = sd_bus_get_property_strv(
666 "org.freedesktop.systemd1",
668 "org.freedesktop.systemd1.Unit",
674 log_error("Failed to determine triggers: %s", bus_error_message(&error, r));
679 static int get_listening(
681 const char* unit_path,
684 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
685 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
686 const char *type, *path;
689 r = sd_bus_get_property(
691 "org.freedesktop.systemd1",
693 "org.freedesktop.systemd1.Socket",
699 log_error("Failed to get list of listening sockets: %s", bus_error_message(&error, r));
703 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
705 return bus_log_parse_error(r);
707 while ((r = sd_bus_message_read(reply, "(ss)", &type, &path)) > 0) {
709 r = strv_extend(listening, type);
713 r = strv_extend(listening, path);
720 return bus_log_parse_error(r);
722 r = sd_bus_message_exit_container(reply);
724 return bus_log_parse_error(r);
735 /* Note: triggered is a list here, although it almost certainly
736 * will always be one unit. Nevertheless, dbus API allows for multiple
737 * values, so let's follow that.*/
740 /* The strv above is shared. free is set only in the first one. */
744 static int socket_info_compare(const struct socket_info *a, const struct socket_info *b) {
750 o = strcmp(a->path, b->path);
752 o = strcmp(a->type, b->type);
757 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
758 struct socket_info *s;
759 unsigned pathlen = strlen("LISTEN"),
760 typelen = strlen("TYPE") * arg_show_types,
761 socklen = strlen("UNIT"),
762 servlen = strlen("ACTIVATES");
763 const char *on, *off;
765 for (s = socket_infos; s < socket_infos + cs; s++) {
769 socklen = MAX(socklen, strlen(s->id));
771 typelen = MAX(typelen, strlen(s->type));
772 pathlen = MAX(pathlen, strlen(s->path));
774 STRV_FOREACH(a, s->triggered)
775 tmp += strlen(*a) + 2*(a != s->triggered);
776 servlen = MAX(servlen, tmp);
781 printf("%-*s %-*.*s%-*s %s\n",
783 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
787 for (s = socket_infos; s < socket_infos + cs; s++) {
791 printf("%-*s %-*s %-*s",
792 pathlen, s->path, typelen, s->type, socklen, s->id);
795 pathlen, s->path, socklen, s->id);
796 STRV_FOREACH(a, s->triggered)
798 a == s->triggered ? "" : ",", *a);
802 on = ansi_highlight();
803 off = ansi_highlight_off();
807 on = ansi_highlight_red();
808 off = ansi_highlight_off();
811 if (!arg_no_legend) {
812 printf("%s%u sockets listed.%s\n", on, cs, off);
814 printf("Pass --all to see loaded but inactive sockets, too.\n");
820 static int list_sockets(sd_bus *bus, char **args) {
821 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
822 _cleanup_free_ UnitInfo *unit_infos = NULL;
823 _cleanup_free_ struct socket_info *socket_infos = NULL;
825 struct socket_info *s;
830 pager_open_if_enabled();
832 n = get_unit_list(bus, NULL, strv_skip_first(args), &unit_infos, 0, &reply);
836 for (u = unit_infos; u < unit_infos + n; u++) {
837 _cleanup_strv_free_ char **listening = NULL, **triggered = NULL;
840 if (!endswith(u->id, ".socket"))
843 r = get_triggered_units(bus, u->unit_path, &triggered);
847 c = get_listening(bus, u->unit_path, &listening);
853 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
858 for (i = 0; i < c; i++)
859 socket_infos[cs + i] = (struct socket_info) {
861 .type = listening[i*2],
862 .path = listening[i*2 + 1],
863 .triggered = triggered,
864 .own_triggered = i==0,
867 /* from this point on we will cleanup those socket_infos */
870 listening = triggered = NULL; /* avoid cleanup */
873 qsort_safe(socket_infos, cs, sizeof(struct socket_info),
874 (__compar_fn_t) socket_info_compare);
876 output_sockets_list(socket_infos, cs);
879 assert(cs == 0 || socket_infos);
880 for (s = socket_infos; s < socket_infos + cs; s++) {
883 if (s->own_triggered)
884 strv_free(s->triggered);
890 static int get_next_elapse(
893 dual_timestamp *next) {
895 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
903 r = sd_bus_get_property_trivial(
905 "org.freedesktop.systemd1",
907 "org.freedesktop.systemd1.Timer",
908 "NextElapseUSecMonotonic",
913 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
917 r = sd_bus_get_property_trivial(
919 "org.freedesktop.systemd1",
921 "org.freedesktop.systemd1.Timer",
922 "NextElapseUSecRealtime",
927 log_error("Failed to get next elapsation time: %s", bus_error_message(&error, r));
941 static int timer_info_compare(const struct timer_info *a, const struct timer_info *b) {
945 if (a->next_elapse < b->next_elapse)
947 if (a->next_elapse > b->next_elapse)
950 return strcmp(a->id, b->id);
953 static int output_timers_list(struct timer_info *timer_infos, unsigned n) {
954 struct timer_info *t;
956 nextlen = strlen("NEXT"),
957 leftlen = strlen("LEFT"),
958 unitlen = strlen("UNIT"),
959 activatelen = strlen("ACTIVATES");
961 const char *on, *off;
963 assert(timer_infos || n == 0);
965 for (t = timer_infos; t < timer_infos + n; t++) {
969 if (t->next_elapse > 0) {
970 char tstamp[FORMAT_TIMESTAMP_MAX] = "", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "";
972 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
973 nextlen = MAX(nextlen, strlen(tstamp) + 1);
975 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
976 leftlen = MAX(leftlen, strlen(trel));
979 unitlen = MAX(unitlen, strlen(t->id));
981 STRV_FOREACH(a, t->triggered)
982 ul += strlen(*a) + 2*(a != t->triggered);
983 activatelen = MAX(activatelen, ul);
988 printf("%-*s %-*s %-*s %s\n",
994 for (t = timer_infos; t < timer_infos + n; t++) {
995 char tstamp[FORMAT_TIMESTAMP_MAX] = "n/a", trel[FORMAT_TIMESTAMP_RELATIVE_MAX] = "n/a";
998 format_timestamp(tstamp, sizeof(tstamp), t->next_elapse);
999 format_timestamp_relative(trel, sizeof(trel), t->next_elapse);
1001 printf("%-*s %-*s %-*s",
1002 nextlen, tstamp, leftlen, trel, unitlen, t->id);
1004 STRV_FOREACH(a, t->triggered)
1006 a == t->triggered ? "" : ",", *a);
1010 on = ansi_highlight();
1011 off = ansi_highlight_off();
1015 on = ansi_highlight_red();
1016 off = ansi_highlight_off();
1019 if (!arg_no_legend) {
1020 printf("%s%u timers listed.%s\n", on, n, off);
1022 printf("Pass --all to see loaded but inactive timers, too.\n");
1028 static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) {
1034 if (next->monotonic != (usec_t) -1 && next->monotonic > 0) {
1037 if (next->monotonic > nw->monotonic)
1038 converted = nw->realtime + (next->monotonic - nw->monotonic);
1040 converted = nw->realtime - (nw->monotonic - next->monotonic);
1042 if (next->realtime != (usec_t) -1 && next->realtime > 0)
1043 next_elapse = MIN(converted, next->realtime);
1045 next_elapse = converted;
1048 next_elapse = next->realtime;
1053 static int list_timers(sd_bus *bus, char **args) {
1055 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1056 _cleanup_free_ struct timer_info *timer_infos = NULL;
1057 _cleanup_free_ UnitInfo *unit_infos = NULL;
1058 struct timer_info *t;
1065 pager_open_if_enabled();
1067 n = get_unit_list(bus, NULL, strv_skip_first(args), &unit_infos, 0, &reply);
1071 dual_timestamp_get(&nw);
1073 for (u = unit_infos; u < unit_infos + n; u++) {
1074 _cleanup_strv_free_ char **triggered = NULL;
1075 dual_timestamp next = {};
1078 if (!endswith(u->id, ".timer"))
1081 r = get_triggered_units(bus, u->unit_path, &triggered);
1085 r = get_next_elapse(bus, u->unit_path, &next);
1089 if (!GREEDY_REALLOC(timer_infos, size, c+1)) {
1094 m = calc_next_elapse(&nw, &next);
1096 timer_infos[c++] = (struct timer_info) {
1099 .triggered = triggered,
1102 triggered = NULL; /* avoid cleanup */
1105 qsort_safe(timer_infos, c, sizeof(struct timer_info),
1106 (__compar_fn_t) timer_info_compare);
1108 output_timers_list(timer_infos, c);
1111 for (t = timer_infos; t < timer_infos + c; t++)
1112 strv_free(t->triggered);
1117 static int compare_unit_file_list(const void *a, const void *b) {
1118 const char *d1, *d2;
1119 const UnitFileList *u = a, *v = b;
1121 d1 = strrchr(u->path, '.');
1122 d2 = strrchr(v->path, '.');
1127 r = strcasecmp(d1, d2);
1132 return strcasecmp(basename(u->path), basename(v->path));
1135 static bool output_show_unit_file(const UnitFileList *u, char **patterns) {
1138 if (!strv_isempty(patterns)) {
1141 STRV_FOREACH(pattern, patterns)
1142 if (fnmatch(*pattern, basename(u->path), FNM_NOESCAPE) == 0)
1147 return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
1150 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
1151 unsigned max_id_len, id_cols, state_cols;
1152 const UnitFileList *u;
1154 max_id_len = strlen("UNIT FILE");
1155 state_cols = strlen("STATE");
1157 for (u = units; u < units + c; u++) {
1158 max_id_len = MAX(max_id_len, strlen(basename(u->path)));
1159 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
1163 unsigned basic_cols;
1165 id_cols = MIN(max_id_len, 25u);
1166 basic_cols = 1 + id_cols + state_cols;
1167 if (basic_cols < (unsigned) columns())
1168 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
1170 id_cols = max_id_len;
1173 printf("%-*s %-*s\n",
1174 id_cols, "UNIT FILE",
1175 state_cols, "STATE");
1177 for (u = units; u < units + c; u++) {
1178 _cleanup_free_ char *e = NULL;
1179 const char *on, *off;
1182 if (u->state == UNIT_FILE_MASKED ||
1183 u->state == UNIT_FILE_MASKED_RUNTIME ||
1184 u->state == UNIT_FILE_DISABLED ||
1185 u->state == UNIT_FILE_INVALID) {
1186 on = ansi_highlight_red();
1187 off = ansi_highlight_off();
1188 } else if (u->state == UNIT_FILE_ENABLED) {
1189 on = ansi_highlight_green();
1190 off = ansi_highlight_off();
1194 id = basename(u->path);
1196 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
1198 printf("%-*s %s%-*s%s\n",
1199 id_cols, e ? e : id,
1200 on, state_cols, unit_file_state_to_string(u->state), off);
1204 printf("\n%u unit files listed.\n", c);
1207 static int list_unit_files(sd_bus *bus, char **args) {
1208 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1209 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1210 _cleanup_free_ UnitFileList *units = NULL;
1218 pager_open_if_enabled();
1226 h = hashmap_new(string_hash_func, string_compare_func);
1230 r = unit_file_get_list(arg_scope, arg_root, h);
1232 unit_file_list_free(h);
1233 log_error("Failed to get unit file list: %s", strerror(-r));
1237 n_units = hashmap_size(h);
1238 units = new(UnitFileList, n_units);
1240 unit_file_list_free(h);
1244 HASHMAP_FOREACH(u, h, i) {
1245 if (!output_show_unit_file(u, strv_skip_first(args)))
1252 assert(c <= n_units);
1255 r = sd_bus_call_method(
1257 "org.freedesktop.systemd1",
1258 "/org/freedesktop/systemd1",
1259 "org.freedesktop.systemd1.Manager",
1265 log_error("Failed to list unit files: %s", bus_error_message(&error, r));
1269 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
1271 return bus_log_parse_error(r);
1273 while ((r = sd_bus_message_read(reply, "(ss)", &path, &state)) > 0) {
1275 if (!GREEDY_REALLOC(units, size, c + 1))
1278 units[c] = (struct UnitFileList) {
1280 unit_file_state_from_string(state)
1283 if (output_show_unit_file(&units[c], strv_skip_first(args)))
1288 return bus_log_parse_error(r);
1290 r = sd_bus_message_exit_container(reply);
1292 return bus_log_parse_error(r);
1296 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
1297 output_unit_file_list(units, c);
1301 for (unit = units; unit < units + c; unit++)
1307 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
1308 _cleanup_free_ char *n = NULL;
1309 size_t max_len = MAX(columns(),20u);
1315 for (i = level - 1; i >= 0; i--) {
1317 if (len > max_len - 3 && !arg_full) {
1318 printf("%s...\n",max_len % 2 ? "" : " ");
1321 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
1325 if (len > max_len - 3 && !arg_full) {
1326 printf("%s...\n",max_len % 2 ? "" : " ");
1330 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
1334 printf("%s\n", name);
1338 n = ellipsize(name, max_len-len, 100);
1346 static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) {
1348 static const char *dependencies[_DEPENDENCY_MAX] = {
1349 [DEPENDENCY_FORWARD] = "Requires\0"
1350 "RequiresOverridable\0"
1352 "RequisiteOverridable\0"
1354 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1355 "RequiredByOverridable\0"
1358 [DEPENDENCY_AFTER] = "After\0",
1359 [DEPENDENCY_BEFORE] = "Before\0",
1362 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1363 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1364 _cleanup_strv_free_ char **ret = NULL;
1365 _cleanup_free_ char *path = NULL;
1371 assert_cc(ELEMENTSOF(dependencies) == _DEPENDENCY_MAX);
1373 path = unit_dbus_path_from_name(name);
1377 r = sd_bus_call_method(
1379 "org.freedesktop.systemd1",
1381 "org.freedesktop.DBus.Properties",
1385 "s", "org.freedesktop.systemd1.Unit");
1387 log_error("Failed to get properties of %s: %s", name, bus_error_message(&error, r));
1391 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
1393 return bus_log_parse_error(r);
1395 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1398 r = sd_bus_message_read(reply, "s", &prop);
1400 return bus_log_parse_error(r);
1402 if (!nulstr_contains(dependencies[arg_dependency], prop)) {
1403 r = sd_bus_message_skip(reply, "v");
1405 return bus_log_parse_error(r);
1408 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, "as");
1410 return bus_log_parse_error(r);
1412 r = bus_message_read_strv_extend(reply, &ret);
1414 return bus_log_parse_error(r);
1416 r = sd_bus_message_exit_container(reply);
1418 return bus_log_parse_error(r);
1421 r = sd_bus_message_exit_container(reply);
1423 return bus_log_parse_error(r);
1427 return bus_log_parse_error(r);
1429 r = sd_bus_message_exit_container(reply);
1431 return bus_log_parse_error(r);
1439 static int list_dependencies_compare(const void *_a, const void *_b) {
1440 const char **a = (const char**) _a, **b = (const char**) _b;
1442 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1444 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1447 return strcasecmp(*a, *b);
1450 static int list_dependencies_one(
1455 unsigned int branches) {
1457 _cleanup_strv_free_ char **deps = NULL;
1465 r = strv_extend(units, name);
1469 r = list_dependencies_get_dependencies(bus, name, &deps);
1473 qsort_safe(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1475 STRV_FOREACH(c, deps) {
1478 if (strv_contains(*units, *c)) {
1480 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1487 state = check_one_unit(bus, *c, "activating\0active\0reloading\0", true);
1489 printf("%s%s%s", ansi_highlight_green(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1491 printf("%s%s%s", ansi_highlight_red(), draw_special_char(DRAW_BLACK_CIRCLE), ansi_highlight_off());
1493 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1497 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1498 r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
1505 strv_remove(*units, name);
1510 static int list_dependencies(sd_bus *bus, char **args) {
1511 _cleanup_strv_free_ char **units = NULL;
1512 _cleanup_free_ char *unit = NULL;
1518 unit = unit_name_mangle(args[1], MANGLE_NOGLOB);
1523 u = SPECIAL_DEFAULT_TARGET;
1525 pager_open_if_enabled();
1529 return list_dependencies_one(bus, u, 0, &units, 0);
1532 struct machine_info {
1536 char *control_group;
1537 uint32_t n_failed_units;
1542 static const struct bus_properties_map machine_info_property_map[] = {
1543 { "SystemState", "s", NULL, offsetof(struct machine_info, state) },
1544 { "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
1545 { "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
1546 { "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
1547 { "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
1551 static void free_machines_list(struct machine_info *machine_infos, int n) {
1557 for (i = 0; i < n; i++) {
1558 free(machine_infos[i].name);
1559 free(machine_infos[i].state);
1560 free(machine_infos[i].control_group);
1563 free(machine_infos);
1566 static int compare_machine_info(const void *a, const void *b) {
1567 const struct machine_info *u = a, *v = b;
1569 if (u->is_host != v->is_host)
1570 return u->is_host > v->is_host ? 1 : -1;
1572 return strcasecmp(u->name, v->name);
1575 static int get_machine_properties(sd_bus *bus, struct machine_info *mi) {
1576 _cleanup_bus_unref_ sd_bus *container = NULL;
1582 r = sd_bus_open_system_container(&container, mi->name);
1589 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, mi);
1596 static bool output_show_machine(const char *name, char **patterns) {
1601 if (strv_isempty(patterns))
1604 STRV_FOREACH(i, patterns)
1605 if (fnmatch(*i, name, FNM_NOESCAPE) == 0)
1611 static int get_machine_list(
1613 struct machine_info **_machine_infos,
1616 struct machine_info *machine_infos = NULL;
1617 _cleanup_strv_free_ char **m = NULL;
1618 _cleanup_free_ char *hn = NULL;
1623 hn = gethostname_malloc();
1627 if (output_show_machine(hn, patterns)) {
1628 if (!GREEDY_REALLOC0(machine_infos, sz, c+1))
1631 machine_infos[c].is_host = true;
1632 machine_infos[c].name = hn;
1635 get_machine_properties(bus, &machine_infos[c]);
1639 sd_get_machine_names(&m);
1640 STRV_FOREACH(i, m) {
1641 _cleanup_free_ char *class = NULL;
1643 if (!output_show_machine(*i, patterns))
1646 sd_machine_get_class(*i, &class);
1647 if (!streq_ptr(class, "container"))
1650 if (!GREEDY_REALLOC0(machine_infos, sz, c+1)) {
1651 free_machines_list(machine_infos, c);
1655 machine_infos[c].is_host = false;
1656 machine_infos[c].name = strdup(*i);
1657 if (!machine_infos[c].name) {
1658 free_machines_list(machine_infos, c);
1662 get_machine_properties(NULL, &machine_infos[c]);
1666 *_machine_infos = machine_infos;
1670 static void output_machines_list(struct machine_info *machine_infos, unsigned n) {
1671 struct machine_info *m;
1673 namelen = sizeof("NAME") - 1,
1674 statelen = sizeof("STATE") - 1,
1675 failedlen = sizeof("FAILED") - 1,
1676 jobslen = sizeof("JOBS") - 1;
1678 assert(machine_infos || n == 0);
1680 for (m = machine_infos; m < machine_infos + n; m++) {
1681 namelen = MAX(namelen, strlen(m->name) + (m->is_host ? sizeof(" (host)") - 1 : 0));
1682 statelen = MAX(statelen, m->state ? strlen(m->state) : 0);
1683 failedlen = MAX(failedlen, DECIMAL_STR_WIDTH(m->n_failed_units));
1684 jobslen = MAX(jobslen, DECIMAL_STR_WIDTH(m->n_jobs));
1688 printf("%-*s %-*s %-*s %-*s\n",
1691 failedlen, "FAILED",
1694 for (m = machine_infos; m < machine_infos + n; m++) {
1695 const char *on_state, *off_state, *on_failed, *off_failed;
1697 if (streq_ptr(m->state, "degraded")) {
1698 on_state = ansi_highlight_red();
1699 off_state = ansi_highlight_off();
1700 } else if (!streq_ptr(m->state, "running")) {
1701 on_state = ansi_highlight_yellow();
1702 off_state = ansi_highlight_off();
1704 on_state = off_state = "";
1706 if (m->n_failed_units > 0) {
1707 on_failed = ansi_highlight_red();
1708 off_failed = ansi_highlight_off();
1710 on_failed = off_failed = "";
1713 printf("%-*s (host) %s%-*s%s %s%*u%s %*u\n",
1714 (int) (namelen - (sizeof(" (host)")-1)), strna(m->name),
1715 on_state, statelen, strna(m->state), off_state,
1716 on_failed, failedlen, m->n_failed_units, off_failed,
1717 jobslen, m->n_jobs);
1719 printf("%-*s %s%-*s%s %s%*u%s %*u\n",
1720 namelen, strna(m->name),
1721 on_state, statelen, strna(m->state), off_state,
1722 on_failed, failedlen, m->n_failed_units, off_failed,
1723 jobslen, m->n_jobs);
1727 printf("\n%u machines listed.\n", n);
1730 static int list_machines(sd_bus *bus, char **args) {
1731 struct machine_info *machine_infos = NULL;
1736 if (geteuid() != 0) {
1737 log_error("Must be root.");
1741 pager_open_if_enabled();
1743 r = get_machine_list(bus, &machine_infos, strv_skip_first(args));
1747 qsort_safe(machine_infos, r, sizeof(struct machine_info), compare_machine_info);
1748 output_machines_list(machine_infos, r);
1749 free_machines_list(machine_infos, r);
1754 static int get_default(sd_bus *bus, char **args) {
1755 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1756 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1757 _cleanup_free_ char *_path = NULL;
1761 if (!bus || avoid_bus()) {
1762 r = unit_file_get_default(arg_scope, arg_root, &_path);
1764 log_error("Failed to get default target: %s", strerror(-r));
1770 r = sd_bus_call_method(
1772 "org.freedesktop.systemd1",
1773 "/org/freedesktop/systemd1",
1774 "org.freedesktop.systemd1.Manager",
1780 log_error("Failed to get default target: %s", bus_error_message(&error, -r));
1784 r = sd_bus_message_read(reply, "s", &path);
1786 return bus_log_parse_error(r);
1790 printf("%s\n", path);
1795 static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_changes) {
1798 assert(changes || n_changes == 0);
1800 for (i = 0; i < n_changes; i++) {
1801 if (changes[i].type == UNIT_FILE_SYMLINK)
1802 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
1804 log_info("rm '%s'", changes[i].path);
1808 static int deserialize_and_dump_unit_file_changes(sd_bus_message *m) {
1809 const char *type, *path, *source;
1812 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1814 return bus_log_parse_error(r);
1816 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1818 if (streq(type, "symlink"))
1819 log_info("ln -s '%s' '%s'", source, path);
1821 log_info("rm '%s'", path);
1825 return bus_log_parse_error(r);
1827 r = sd_bus_message_exit_container(m);
1829 return bus_log_parse_error(r);
1834 static int set_default(sd_bus *bus, char **args) {
1835 _cleanup_free_ char *unit = NULL;
1836 UnitFileChange *changes = NULL;
1837 unsigned n_changes = 0;
1840 unit = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".target");
1844 if (!bus || avoid_bus()) {
1845 r = unit_file_set_default(arg_scope, arg_root, unit, arg_force, &changes, &n_changes);
1847 log_error("Failed to set default target: %s", strerror(-r));
1852 dump_unit_file_changes(changes, n_changes);
1856 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1857 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1859 r = sd_bus_call_method(
1861 "org.freedesktop.systemd1",
1862 "/org/freedesktop/systemd1",
1863 "org.freedesktop.systemd1.Manager",
1867 "sb", unit, arg_force);
1869 log_error("Failed to set default target: %s", bus_error_message(&error, -r));
1873 r = deserialize_and_dump_unit_file_changes(reply);
1877 /* Try to reload if enabeld */
1879 r = daemon_reload(bus, args);
1884 unit_file_changes_free(changes, n_changes);
1891 const char *name, *type, *state;
1894 static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
1895 unsigned id_len, unit_len, type_len, state_len;
1896 const struct job_info *j;
1897 const char *on, *off;
1898 bool shorten = false;
1900 assert(n == 0 || jobs);
1903 on = ansi_highlight_green();
1904 off = ansi_highlight_off();
1906 printf("%sNo jobs %s.%s\n", on, skipped ? "listed" : "running", off);
1910 pager_open_if_enabled();
1912 id_len = strlen("JOB");
1913 unit_len = strlen("UNIT");
1914 type_len = strlen("TYPE");
1915 state_len = strlen("STATE");
1917 for (j = jobs; j < jobs + n; j++) {
1918 uint32_t id = j->id;
1919 assert(j->name && j->type && j->state);
1921 id_len = MAX(id_len, DECIMAL_STR_WIDTH(id));
1922 unit_len = MAX(unit_len, strlen(j->name));
1923 type_len = MAX(type_len, strlen(j->type));
1924 state_len = MAX(state_len, strlen(j->state));
1927 if (!arg_full && id_len + 1 + unit_len + type_len + 1 + state_len > columns()) {
1928 unit_len = MAX(33u, columns() - id_len - type_len - state_len - 3);
1933 printf("%*s %-*s %-*s %-*s\n",
1937 state_len, "STATE");
1939 for (j = jobs; j < jobs + n; j++) {
1940 _cleanup_free_ char *e = NULL;
1942 if (streq(j->state, "running")) {
1943 on = ansi_highlight();
1944 off = ansi_highlight_off();
1948 e = shorten ? ellipsize(j->name, unit_len, 33) : NULL;
1949 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
1951 on, unit_len, e ? e : j->name, off,
1953 on, state_len, j->state, off);
1956 if (!arg_no_legend) {
1957 on = ansi_highlight();
1958 off = ansi_highlight_off();
1960 printf("\n%s%u jobs listed%s.\n", on, n, off);
1964 static bool output_show_job(struct job_info *job, char **patterns) {
1969 if (strv_isempty(patterns))
1972 STRV_FOREACH(pattern, patterns)
1973 if (fnmatch(*pattern, job->name, FNM_NOESCAPE) == 0)
1978 static int list_jobs(sd_bus *bus, char **args) {
1979 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1980 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1981 const char *name, *type, *state, *job_path, *unit_path;
1982 _cleanup_free_ struct job_info *jobs = NULL;
1987 bool skipped = false;
1989 r = sd_bus_call_method(
1991 "org.freedesktop.systemd1",
1992 "/org/freedesktop/systemd1",
1993 "org.freedesktop.systemd1.Manager",
1999 log_error("Failed to list jobs: %s", bus_error_message(&error, r));
2003 r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
2005 return bus_log_parse_error(r);
2007 while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) {
2008 struct job_info job = { id, name, type, state };
2010 if (!output_show_job(&job, strv_skip_first(args))) {
2015 if (!GREEDY_REALLOC(jobs, size, c + 1))
2021 return bus_log_parse_error(r);
2023 r = sd_bus_message_exit_container(reply);
2025 return bus_log_parse_error(r);
2027 output_jobs_list(jobs, c, skipped);
2031 static int cancel_job(sd_bus *bus, char **args) {
2032 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2037 if (strv_length(args) <= 1)
2038 return daemon_reload(bus, args);
2040 STRV_FOREACH(name, args+1) {
2044 r = safe_atou32(*name, &id);
2046 log_error("Failed to parse job id \"%s\": %s", *name, strerror(-r));
2050 r = sd_bus_call_method(
2052 "org.freedesktop.systemd1",
2053 "/org/freedesktop/systemd1",
2054 "org.freedesktop.systemd1.Manager",
2060 log_error("Failed to cancel job %u: %s", (unsigned) id, bus_error_message(&error, r));
2068 static int need_daemon_reload(sd_bus *bus, const char *unit) {
2069 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2073 /* We ignore all errors here, since this is used to show a
2076 /* We don't use unit_dbus_path_from_name() directly since we
2077 * don't want to load the unit if it isn't loaded. */
2079 r = sd_bus_call_method(
2081 "org.freedesktop.systemd1",
2082 "/org/freedesktop/systemd1",
2083 "org.freedesktop.systemd1.Manager",
2091 r = sd_bus_message_read(reply, "o", &path);
2095 r = sd_bus_get_property_trivial(
2097 "org.freedesktop.systemd1",
2099 "org.freedesktop.systemd1.Unit",
2109 typedef struct WaitData {
2116 static int wait_filter(sd_bus *bus, sd_bus_message *m, void *data, sd_bus_error *error) {
2123 log_debug("Got D-Bus request: %s.%s() on %s",
2124 sd_bus_message_get_interface(m),
2125 sd_bus_message_get_member(m),
2126 sd_bus_message_get_path(m));
2128 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
2129 log_error("Warning! D-Bus connection terminated.");
2131 } else if (sd_bus_message_is_signal(m, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
2133 const char *path, *result, *unit;
2137 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
2139 ret = set_remove(d->set, (char*) path);
2145 if (!isempty(result))
2146 d->result = strdup(result);
2149 d->name = strdup(unit);
2154 r = sd_bus_message_read(m, "uos", &id, &path, &result);
2156 ret = set_remove(d->set, (char*) path);
2163 d->result = strdup(result);
2169 bus_log_parse_error(r);
2175 static int enable_wait_for_jobs(sd_bus *bus) {
2180 r = sd_bus_add_match(
2183 "sender='org.freedesktop.systemd1',"
2184 "interface='org.freedesktop.systemd1.Manager',"
2185 "member='JobRemoved',"
2186 "path='/org/freedesktop/systemd1'",
2189 log_error("Failed to add match");
2193 /* This is slightly dirty, since we don't undo the match registrations. */
2197 static int bus_process_wait(sd_bus *bus) {
2201 r = sd_bus_process(bus, NULL);
2206 r = sd_bus_wait(bus, (uint64_t) -1);
2212 static int check_wait_response(WaitData *d) {
2218 if (streq(d->result, "timeout"))
2219 log_error("Job for %s timed out.", strna(d->name));
2220 else if (streq(d->result, "canceled"))
2221 log_error("Job for %s canceled.", strna(d->name));
2222 else if (streq(d->result, "dependency"))
2223 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d->name));
2224 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2225 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d->name), strna(d->name));
2228 if (streq(d->result, "timeout"))
2230 else if (streq(d->result, "canceled"))
2232 else if (streq(d->result, "dependency"))
2234 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2240 static int wait_for_jobs(sd_bus *bus, Set *s) {
2241 WaitData d = { .set = s };
2247 q = sd_bus_add_filter(bus, wait_filter, &d);
2251 while (!set_isempty(s)) {
2252 q = bus_process_wait(bus);
2254 log_error("Failed to wait for response: %s", strerror(-r));
2259 q = check_wait_response(&d);
2260 /* Return the first error as it is most likely to be
2262 if (q < 0 && r == 0)
2264 log_debug("Got result %s/%s for job %s",
2265 strna(d.result), strerror(-q), strna(d.name));
2275 q = sd_bus_remove_filter(bus, wait_filter, &d);
2276 if (q < 0 && r == 0)
2282 static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet) {
2283 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2284 _cleanup_free_ char *n = NULL, *state = NULL;
2290 n = unit_name_mangle(name, MANGLE_NOGLOB);
2294 /* We don't use unit_dbus_path_from_name() directly since we
2295 * don't want to load the unit if it isn't loaded. */
2297 r = sd_bus_call_method(
2299 "org.freedesktop.systemd1",
2300 "/org/freedesktop/systemd1",
2301 "org.freedesktop.systemd1.Manager",
2312 r = sd_bus_message_read(reply, "o", &path);
2314 return bus_log_parse_error(r);
2316 r = sd_bus_get_property_string(
2318 "org.freedesktop.systemd1",
2320 "org.freedesktop.systemd1.Unit",
2333 return nulstr_contains(good_states, state);
2336 static int check_triggering_units(
2340 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2341 _cleanup_free_ char *path = NULL, *n = NULL, *state = NULL;
2342 _cleanup_strv_free_ char **triggered_by = NULL;
2343 bool print_warning_label = true;
2347 n = unit_name_mangle(name, MANGLE_NOGLOB);
2351 path = unit_dbus_path_from_name(n);
2355 r = sd_bus_get_property_string(
2357 "org.freedesktop.systemd1",
2359 "org.freedesktop.systemd1.Unit",
2364 log_error("Failed to get load state of %s: %s", n, bus_error_message(&error, r));
2368 if (streq(state, "masked"))
2371 r = sd_bus_get_property_strv(
2373 "org.freedesktop.systemd1",
2375 "org.freedesktop.systemd1.Unit",
2380 log_error("Failed to get triggered by array of %s: %s", n, bus_error_message(&error, r));
2384 STRV_FOREACH(i, triggered_by) {
2385 r = check_one_unit(bus, *i, "active\0reloading\0", true);
2387 log_error("Failed to check unit: %s", strerror(-r));
2394 if (print_warning_label) {
2395 log_warning("Warning: Stopping %s, but it can still be activated by:", n);
2396 print_warning_label = false;
2399 log_warning(" %s", *i);
2405 static const char *verb_to_method(const char *verb) {
2408 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2409 if (streq_ptr(unit_actions[i].verb, verb))
2410 return unit_actions[i].method;
2415 static const char *method_to_verb(const char *method) {
2418 for (i = 0; i < ELEMENTSOF(unit_actions); i++)
2419 if (streq_ptr(unit_actions[i].method, method))
2420 return unit_actions[i].verb;
2425 static int start_unit_one(
2430 sd_bus_error *error,
2433 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2442 log_debug("Calling manager for %s on %s, %s", method, name, mode);
2443 r = sd_bus_call_method(
2445 "org.freedesktop.systemd1",
2446 "/org/freedesktop/systemd1",
2447 "org.freedesktop.systemd1.Manager",
2455 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
2456 /* There's always a fallback possible for
2457 * legacy actions. */
2458 return -EADDRNOTAVAIL;
2460 verb = method_to_verb(method);
2462 log_error("Failed to %s %s: %s", verb, name, bus_error_message(error, r));
2466 r = sd_bus_message_read(reply, "o", &path);
2468 return bus_log_parse_error(r);
2470 if (need_daemon_reload(bus, name) > 0)
2471 log_warning("Warning: Unit file of %s changed on disk, 'systemctl%s daemon-reload' recommended.",
2472 name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
2481 log_debug("Adding %s to the set", p);
2482 r = set_consume(s, p);
2490 static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***ret) {
2492 _cleanup_strv_free_ char **mangled = NULL, **globs = NULL;
2496 STRV_FOREACH(name, names) {
2500 t = unit_name_mangle_with_suffix(*name, MANGLE_GLOB, suffix);
2502 t = unit_name_mangle(*name, MANGLE_GLOB);
2506 if (string_is_glob(t))
2507 r = strv_consume(&globs, t);
2509 r = strv_consume(&mangled, t);
2514 /* Query the manager only if any of the names are a glob, since
2515 * this is fairly expensive */
2516 if (!strv_isempty(globs)) {
2517 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2518 _cleanup_free_ UnitInfo *unit_infos = NULL;
2520 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
2524 for (i = 0; i < r; i++)
2525 if (strv_extend(&mangled, unit_infos[i].id) < 0)
2530 mangled = NULL; /* do not free */
2535 static const struct {
2539 } action_table[_ACTION_MAX] = {
2540 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
2541 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
2542 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
2543 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
2544 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
2545 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
2546 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
2547 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
2548 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
2549 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
2550 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
2551 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
2552 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
2553 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
2554 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
2557 static enum action verb_to_action(const char *verb) {
2560 for (i = _ACTION_INVALID; i < _ACTION_MAX; i++)
2561 if (streq_ptr(action_table[i].verb, verb))
2564 return _ACTION_INVALID;
2567 static int start_unit(sd_bus *bus, char **args) {
2568 _cleanup_set_free_free_ Set *s = NULL;
2569 _cleanup_strv_free_ char **names = NULL;
2570 const char *method, *mode, *one_name;
2576 ask_password_agent_open_if_enabled();
2578 if (arg_action == ACTION_SYSTEMCTL) {
2580 method = verb_to_method(args[0]);
2581 action = verb_to_action(args[0]);
2583 mode = streq(args[0], "isolate") ? "isolate" :
2584 action_table[action].mode ?: arg_job_mode;
2586 one_name = action_table[action].target;
2588 assert(arg_action < ELEMENTSOF(action_table));
2589 assert(action_table[arg_action].target);
2591 method = "StartUnit";
2593 mode = action_table[arg_action].mode;
2594 one_name = action_table[arg_action].target;
2598 names = strv_new(one_name, NULL);
2600 r = expand_names(bus, args + 1, NULL, &names);
2602 log_error("Failed to expand names: %s", strerror(-r));
2605 if (!arg_no_block) {
2606 r = enable_wait_for_jobs(bus);
2608 log_error("Could not watch jobs: %s", strerror(-r));
2612 s = set_new(string_hash_func, string_compare_func);
2617 STRV_FOREACH(name, names) {
2618 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2621 q = start_unit_one(bus, method, *name, mode, &error, s);
2622 if (r >= 0 && q < 0)
2623 r = translate_bus_error_to_exit_status(q, &error);
2626 if (!arg_no_block) {
2629 q = wait_for_jobs(bus, s);
2633 /* When stopping units, warn if they can still be triggered by
2634 * another active unit (socket, path, timer) */
2635 if (!arg_quiet && streq(method, "StopUnit"))
2636 STRV_FOREACH(name, names)
2637 check_triggering_units(bus, *name);
2643 /* Ask systemd-logind, which might grant access to unprivileged users
2644 * through PolicyKit */
2645 static int reboot_with_logind(sd_bus *bus, enum action a) {
2647 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2654 polkit_agent_open_if_enabled();
2662 case ACTION_POWEROFF:
2663 method = "PowerOff";
2666 case ACTION_SUSPEND:
2670 case ACTION_HIBERNATE:
2671 method = "Hibernate";
2674 case ACTION_HYBRID_SLEEP:
2675 method = "HybridSleep";
2682 r = sd_bus_call_method(
2684 "org.freedesktop.login1",
2685 "/org/freedesktop/login1",
2686 "org.freedesktop.login1.Manager",
2692 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
2700 static int check_inhibitors(sd_bus *bus, enum action a) {
2702 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
2703 _cleanup_strv_free_ char **sessions = NULL;
2704 const char *what, *who, *why, *mode;
2713 if (arg_ignore_inhibitors || arg_force > 0)
2725 r = sd_bus_call_method(
2727 "org.freedesktop.login1",
2728 "/org/freedesktop/login1",
2729 "org.freedesktop.login1.Manager",
2735 /* If logind is not around, then there are no inhibitors... */
2738 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssuu)");
2740 return bus_log_parse_error(r);
2742 while ((r = sd_bus_message_read(reply, "(ssssuu)", &what, &who, &why, &mode, &uid, &pid)) > 0) {
2743 _cleanup_free_ char *comm = NULL, *user = NULL;
2744 _cleanup_strv_free_ char **sv = NULL;
2746 if (!streq(mode, "block"))
2749 sv = strv_split(what, ":");
2753 if (!strv_contains(sv,
2755 a == ACTION_POWEROFF ||
2756 a == ACTION_REBOOT ||
2757 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2760 get_process_comm(pid, &comm);
2761 user = uid_to_name(uid);
2763 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2764 who, (unsigned long) pid, strna(comm), strna(user), why);
2769 return bus_log_parse_error(r);
2771 r = sd_bus_message_exit_container(reply);
2773 return bus_log_parse_error(r);
2775 /* Check for current sessions */
2776 sd_get_sessions(&sessions);
2777 STRV_FOREACH(s, sessions) {
2778 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2780 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2783 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2786 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2789 sd_session_get_tty(*s, &tty);
2790 sd_session_get_seat(*s, &seat);
2791 sd_session_get_service(*s, &service);
2792 user = uid_to_name(uid);
2794 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2801 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2802 action_table[a].verb);
2810 static int start_special(sd_bus *bus, char **args) {
2816 a = verb_to_action(args[0]);
2818 r = check_inhibitors(bus, a);
2822 if (arg_force >= 2 && geteuid() != 0) {
2823 log_error("Must be root.");
2827 if (arg_force >= 2 &&
2828 (a == ACTION_HALT ||
2829 a == ACTION_POWEROFF ||
2830 a == ACTION_REBOOT))
2833 if (arg_force >= 1 &&
2834 (a == ACTION_HALT ||
2835 a == ACTION_POWEROFF ||
2836 a == ACTION_REBOOT ||
2837 a == ACTION_KEXEC ||
2839 return daemon_reload(bus, args);
2841 /* first try logind, to allow authentication with polkit */
2842 if (geteuid() != 0 &&
2843 (a == ACTION_POWEROFF ||
2844 a == ACTION_REBOOT ||
2845 a == ACTION_SUSPEND ||
2846 a == ACTION_HIBERNATE ||
2847 a == ACTION_HYBRID_SLEEP)) {
2848 r = reboot_with_logind(bus, a);
2853 r = start_unit(bus, args);
2854 if (r == EXIT_SUCCESS)
2860 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
2861 _cleanup_strv_free_ char **names = NULL;
2868 r = expand_names(bus, args, NULL, &names);
2870 log_error("Failed to expand names: %s", strerror(-r));
2874 STRV_FOREACH(name, names) {
2877 state = check_one_unit(bus, *name, good_states, arg_quiet);
2887 static int check_unit_active(sd_bus *bus, char **args) {
2888 /* According to LSB: 3, "program is not running" */
2889 return check_unit_generic(bus, 3, "active\0reloading\0", args + 1);
2892 static int check_unit_failed(sd_bus *bus, char **args) {
2893 return check_unit_generic(bus, 1, "failed\0", args + 1);
2896 static int kill_unit(sd_bus *bus, char **args) {
2897 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2898 _cleanup_strv_free_ char **names = NULL;
2906 arg_kill_who = "all";
2908 r = expand_names(bus, args + 1, NULL, &names);
2910 log_error("Failed to expand names: %s", strerror(-r));
2912 STRV_FOREACH(name, names) {
2913 q = sd_bus_call_method(
2915 "org.freedesktop.systemd1",
2916 "/org/freedesktop/systemd1",
2917 "org.freedesktop.systemd1.Manager",
2921 "ssi", *names, arg_kill_who, arg_signal);
2923 log_error("Failed to kill unit %s: %s",
2924 *names, bus_error_message(&error, r));
2933 typedef struct ExecStatusInfo {
2941 usec_t start_timestamp;
2942 usec_t exit_timestamp;
2947 LIST_FIELDS(struct ExecStatusInfo, exec);
2950 static void exec_status_info_free(ExecStatusInfo *i) {
2959 static int exec_status_info_deserialize(sd_bus_message *m, ExecStatusInfo *i) {
2960 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2963 int32_t code, status;
2969 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_STRUCT, "sasbttttuii");
2971 return bus_log_parse_error(r);
2975 r = sd_bus_message_read(m, "s", &path);
2977 return bus_log_parse_error(r);
2979 i->path = strdup(path);
2983 r = sd_bus_message_read_strv(m, &i->argv);
2985 return bus_log_parse_error(r);
2987 r = sd_bus_message_read(m,
2990 &start_timestamp, &start_timestamp_monotonic,
2991 &exit_timestamp, &exit_timestamp_monotonic,
2995 return bus_log_parse_error(r);
2998 i->start_timestamp = (usec_t) start_timestamp;
2999 i->exit_timestamp = (usec_t) exit_timestamp;
3000 i->pid = (pid_t) pid;
3004 r = sd_bus_message_exit_container(m);
3006 return bus_log_parse_error(r);
3011 typedef struct UnitStatusInfo {
3013 const char *load_state;
3014 const char *active_state;
3015 const char *sub_state;
3016 const char *unit_file_state;
3018 const char *description;
3019 const char *following;
3021 char **documentation;
3023 const char *fragment_path;
3024 const char *source_path;
3025 const char *control_group;
3027 char **dropin_paths;
3029 const char *load_error;
3032 usec_t inactive_exit_timestamp;
3033 usec_t inactive_exit_timestamp_monotonic;
3034 usec_t active_enter_timestamp;
3035 usec_t active_exit_timestamp;
3036 usec_t inactive_enter_timestamp;
3038 bool need_daemon_reload;
3043 const char *status_text;
3044 const char *pid_file;
3047 usec_t start_timestamp;
3048 usec_t exit_timestamp;
3050 int exit_code, exit_status;
3052 usec_t condition_timestamp;
3053 bool condition_result;
3054 bool failed_condition_trigger;
3055 bool failed_condition_negate;
3056 const char *failed_condition;
3057 const char *failed_condition_param;
3060 unsigned n_accepted;
3061 unsigned n_connections;
3064 /* Pairs of type, path */
3068 const char *sysfs_path;
3070 /* Mount, Automount */
3076 LIST_HEAD(ExecStatusInfo, exec);
3079 static void print_status_info(
3084 const char *active_on, *active_off, *on, *off, *ss;
3086 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
3087 char since2[FORMAT_TIMESTAMP_MAX], *s2;
3090 arg_all * OUTPUT_SHOW_ALL |
3091 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
3092 on_tty() * OUTPUT_COLOR |
3093 !arg_quiet * OUTPUT_WARN_CUTOFF |
3094 arg_full * OUTPUT_FULL_WIDTH;
3099 /* This shows pretty information about a unit. See
3100 * print_property() for a low-level property printer */
3102 if (streq_ptr(i->active_state, "failed")) {
3103 active_on = ansi_highlight_red();
3104 active_off = ansi_highlight_off();
3105 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
3106 active_on = ansi_highlight_green();
3107 active_off = ansi_highlight_off();
3109 active_on = active_off = "";
3111 printf("%s%s%s%s", active_on, draw_special_char(DRAW_BLACK_CIRCLE), active_off, strna(i->id));
3113 if (i->description && !streq_ptr(i->id, i->description))
3114 printf(" - %s", i->description);
3119 printf(" Follow: unit currently follows state of %s\n", i->following);
3121 if (streq_ptr(i->load_state, "error")) {
3122 on = ansi_highlight_red();
3123 off = ansi_highlight_off();
3127 path = i->source_path ? i->source_path : i->fragment_path;
3130 printf(" Loaded: %s%s%s (Reason: %s)\n",
3131 on, strna(i->load_state), off, i->load_error);
3132 else if (path && i->unit_file_state)
3133 printf(" Loaded: %s%s%s (%s; %s)\n",
3134 on, strna(i->load_state), off, path, i->unit_file_state);
3136 printf(" Loaded: %s%s%s (%s)\n",
3137 on, strna(i->load_state), off, path);
3139 printf(" Loaded: %s%s%s\n",
3140 on, strna(i->load_state), off);
3142 if (!strv_isempty(i->dropin_paths)) {
3143 _cleanup_free_ char *dir = NULL;
3147 STRV_FOREACH(dropin, i->dropin_paths) {
3148 if (! dir || last) {
3149 printf(dir ? " " : " Drop-In: ");
3154 if (path_get_parent(*dropin, &dir) < 0) {
3159 printf("%s\n %s", dir,
3160 draw_special_char(DRAW_TREE_RIGHT));
3163 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
3165 printf("%s%s", basename(*dropin), last ? "\n" : ", ");
3169 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
3171 printf(" Active: %s%s (%s)%s",
3172 active_on, strna(i->active_state), ss, active_off);
3174 printf(" Active: %s%s%s",
3175 active_on, strna(i->active_state), active_off);
3177 if (!isempty(i->result) && !streq(i->result, "success"))
3178 printf(" (Result: %s)", i->result);
3180 timestamp = (streq_ptr(i->active_state, "active") ||
3181 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
3182 (streq_ptr(i->active_state, "inactive") ||
3183 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
3184 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
3185 i->active_exit_timestamp;
3187 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
3188 s2 = format_timestamp(since2, sizeof(since2), timestamp);
3191 printf(" since %s; %s\n", s2, s1);
3193 printf(" since %s\n", s2);
3197 if (!i->condition_result && i->condition_timestamp > 0) {
3198 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
3199 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
3201 printf(" start condition failed at %s%s%s\n",
3202 s2, s1 ? "; " : "", s1 ? s1 : "");
3203 if (i->failed_condition_trigger)
3204 printf(" none of the trigger conditions were met\n");
3205 else if (i->failed_condition)
3206 printf(" %s=%s%s was not met\n",
3207 i->failed_condition,
3208 i->failed_condition_negate ? "!" : "",
3209 i->failed_condition_param);
3213 printf(" Device: %s\n", i->sysfs_path);
3215 printf(" Where: %s\n", i->where);
3217 printf(" What: %s\n", i->what);
3219 STRV_FOREACH(t, i->documentation)
3220 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
3222 STRV_FOREACH_PAIR(t, t2, i->listen)
3223 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
3226 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
3228 LIST_FOREACH(exec, p, i->exec) {
3229 _cleanup_free_ char *argv = NULL;
3232 /* Only show exited processes here */
3236 argv = strv_join(p->argv, " ");
3237 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
3239 good = is_clean_exit_lsb(p->code, p->status, NULL);
3241 on = ansi_highlight_red();
3242 off = ansi_highlight_off();
3246 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
3248 if (p->code == CLD_EXITED) {
3251 printf("status=%i", p->status);
3253 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
3258 printf("signal=%s", signal_to_string(p->status));
3260 printf(")%s\n", off);
3262 if (i->main_pid == p->pid &&
3263 i->start_timestamp == p->start_timestamp &&
3264 i->exit_timestamp == p->start_timestamp)
3265 /* Let's not show this twice */
3268 if (p->pid == i->control_pid)
3272 if (i->main_pid > 0 || i->control_pid > 0) {
3273 if (i->main_pid > 0) {
3274 printf(" Main PID: %u", (unsigned) i->main_pid);
3277 _cleanup_free_ char *comm = NULL;
3278 get_process_comm(i->main_pid, &comm);
3280 printf(" (%s)", comm);
3281 } else if (i->exit_code > 0) {
3282 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
3284 if (i->exit_code == CLD_EXITED) {
3287 printf("status=%i", i->exit_status);
3289 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
3294 printf("signal=%s", signal_to_string(i->exit_status));
3298 if (i->control_pid > 0)
3302 if (i->control_pid > 0) {
3303 _cleanup_free_ char *c = NULL;
3305 printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
3307 get_process_comm(i->control_pid, &c);
3316 printf(" Status: \"%s\"\n", i->status_text);
3318 if (i->control_group &&
3319 (i->main_pid > 0 || i->control_pid > 0 ||
3320 ((arg_transport != BUS_TRANSPORT_LOCAL && arg_transport != BUS_TRANSPORT_CONTAINER) || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0))) {
3323 printf(" CGroup: %s\n", i->control_group);
3325 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
3328 static const char prefix[] = " ";
3331 if (c > sizeof(prefix) - 1)
3332 c -= sizeof(prefix) - 1;
3336 if (i->main_pid > 0)
3337 extra[k++] = i->main_pid;
3339 if (i->control_pid > 0)
3340 extra[k++] = i->control_pid;
3342 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix, c, false, extra, k, flags);
3346 if (i->id && arg_transport == BUS_TRANSPORT_LOCAL) {
3347 show_journal_by_unit(stdout,
3351 i->inactive_exit_timestamp_monotonic,
3354 flags | OUTPUT_BEGIN_NEWLINE,
3355 arg_scope == UNIT_FILE_SYSTEM,
3359 if (i->need_daemon_reload)
3360 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
3361 ansi_highlight_red(),
3362 ansi_highlight_off(),
3363 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
3366 static void show_unit_help(UnitStatusInfo *i) {
3371 if (!i->documentation) {
3372 log_info("Documentation for %s not known.", i->id);
3376 STRV_FOREACH(p, i->documentation) {
3378 if (startswith(*p, "man:")) {
3379 const char *args[4] = { "man", NULL, NULL, NULL };
3380 _cleanup_free_ char *page = NULL, *section = NULL;
3387 if ((*p)[k-1] == ')')
3388 e = strrchr(*p, '(');
3391 page = strndup((*p) + 4, e - *p - 4);
3392 section = strndup(e + 1, *p + k - e - 2);
3393 if (!page || !section) {
3405 log_error("Failed to fork: %m");
3411 execvp(args[0], (char**) args);
3412 log_error("Failed to execute man: %m");
3413 _exit(EXIT_FAILURE);
3416 wait_for_terminate(pid, NULL);
3418 log_info("Can't show: %s", *p);
3422 static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *i, const char *contents) {
3429 switch (contents[0]) {
3431 case SD_BUS_TYPE_STRING: {
3434 r = sd_bus_message_read(m, "s", &s);
3436 return bus_log_parse_error(r);
3439 if (streq(name, "Id"))
3441 else if (streq(name, "LoadState"))
3443 else if (streq(name, "ActiveState"))
3444 i->active_state = s;
3445 else if (streq(name, "SubState"))
3447 else if (streq(name, "Description"))
3449 else if (streq(name, "FragmentPath"))
3450 i->fragment_path = s;
3451 else if (streq(name, "SourcePath"))
3454 else if (streq(name, "DefaultControlGroup")) {
3456 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
3458 i->control_group = e;
3461 else if (streq(name, "ControlGroup"))
3462 i->control_group = s;
3463 else if (streq(name, "StatusText"))
3465 else if (streq(name, "PIDFile"))
3467 else if (streq(name, "SysFSPath"))
3469 else if (streq(name, "Where"))
3471 else if (streq(name, "What"))
3473 else if (streq(name, "Following"))
3475 else if (streq(name, "UnitFileState"))
3476 i->unit_file_state = s;
3477 else if (streq(name, "Result"))
3484 case SD_BUS_TYPE_BOOLEAN: {
3487 r = sd_bus_message_read(m, "b", &b);
3489 return bus_log_parse_error(r);
3491 if (streq(name, "Accept"))
3493 else if (streq(name, "NeedDaemonReload"))
3494 i->need_daemon_reload = b;
3495 else if (streq(name, "ConditionResult"))
3496 i->condition_result = b;
3501 case SD_BUS_TYPE_UINT32: {
3504 r = sd_bus_message_read(m, "u", &u);
3506 return bus_log_parse_error(r);
3508 if (streq(name, "MainPID")) {
3510 i->main_pid = (pid_t) u;
3513 } else if (streq(name, "ControlPID"))
3514 i->control_pid = (pid_t) u;
3515 else if (streq(name, "ExecMainPID")) {
3517 i->main_pid = (pid_t) u;
3518 } else if (streq(name, "NAccepted"))
3520 else if (streq(name, "NConnections"))
3521 i->n_connections = u;
3526 case SD_BUS_TYPE_INT32: {
3529 r = sd_bus_message_read(m, "i", &j);
3531 return bus_log_parse_error(r);
3533 if (streq(name, "ExecMainCode"))
3534 i->exit_code = (int) j;
3535 else if (streq(name, "ExecMainStatus"))
3536 i->exit_status = (int) j;
3541 case SD_BUS_TYPE_UINT64: {
3544 r = sd_bus_message_read(m, "t", &u);
3546 return bus_log_parse_error(r);
3548 if (streq(name, "ExecMainStartTimestamp"))
3549 i->start_timestamp = (usec_t) u;
3550 else if (streq(name, "ExecMainExitTimestamp"))
3551 i->exit_timestamp = (usec_t) u;
3552 else if (streq(name, "ActiveEnterTimestamp"))
3553 i->active_enter_timestamp = (usec_t) u;
3554 else if (streq(name, "InactiveEnterTimestamp"))
3555 i->inactive_enter_timestamp = (usec_t) u;
3556 else if (streq(name, "InactiveExitTimestamp"))
3557 i->inactive_exit_timestamp = (usec_t) u;
3558 else if (streq(name, "InactiveExitTimestampMonotonic"))
3559 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3560 else if (streq(name, "ActiveExitTimestamp"))
3561 i->active_exit_timestamp = (usec_t) u;
3562 else if (streq(name, "ConditionTimestamp"))
3563 i->condition_timestamp = (usec_t) u;
3568 case SD_BUS_TYPE_ARRAY:
3570 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3571 _cleanup_free_ ExecStatusInfo *info = NULL;
3573 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3575 return bus_log_parse_error(r);
3577 info = new0(ExecStatusInfo, 1);
3581 while ((r = exec_status_info_deserialize(m, info)) > 0) {
3583 info->name = strdup(name);
3587 LIST_PREPEND(exec, i->exec, info);
3589 info = new0(ExecStatusInfo, 1);
3595 return bus_log_parse_error(r);
3597 r = sd_bus_message_exit_container(m);
3599 return bus_log_parse_error(r);
3603 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3604 const char *type, *path;
3606 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3608 return bus_log_parse_error(r);
3610 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0) {
3612 r = strv_extend(&i->listen, type);
3616 r = strv_extend(&i->listen, path);
3621 return bus_log_parse_error(r);
3623 r = sd_bus_message_exit_container(m);
3625 return bus_log_parse_error(r);
3629 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "DropInPaths")) {
3631 r = sd_bus_message_read_strv(m, &i->dropin_paths);
3633 return bus_log_parse_error(r);
3635 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Documentation")) {
3637 r = sd_bus_message_read_strv(m, &i->documentation);
3639 return bus_log_parse_error(r);
3641 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Conditions")) {
3642 const char *cond, *param;
3643 int trigger, negate;
3646 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sbbsi)");
3648 return bus_log_parse_error(r);
3650 while ((r = sd_bus_message_read(m, "(sbbsi)", &cond, &trigger, &negate, ¶m, &state)) > 0) {
3651 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3652 if (state < 0 && (!trigger || !i->failed_condition)) {
3653 i->failed_condition = cond;
3654 i->failed_condition_trigger = trigger;
3655 i->failed_condition_negate = negate;
3656 i->failed_condition_param = param;
3660 return bus_log_parse_error(r);
3662 r = sd_bus_message_exit_container(m);
3664 return bus_log_parse_error(r);
3671 case SD_BUS_TYPE_STRUCT_BEGIN:
3673 if (streq(name, "LoadError")) {
3674 const char *n, *message;
3676 r = sd_bus_message_read(m, "(ss)", &n, &message);
3678 return bus_log_parse_error(r);
3680 if (!isempty(message))
3681 i->load_error = message;
3694 r = sd_bus_message_skip(m, contents);
3696 return bus_log_parse_error(r);
3701 static int print_property(const char *name, sd_bus_message *m, const char *contents) {
3707 /* This is a low-level property printer, see
3708 * print_status_info() for the nicer output */
3710 if (arg_properties && !strv_find(arg_properties, name)) {
3711 /* skip what we didn't read */
3712 r = sd_bus_message_skip(m, contents);
3716 switch (contents[0]) {
3718 case SD_BUS_TYPE_STRUCT_BEGIN:
3720 if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "Job")) {
3723 r = sd_bus_message_read(m, "(uo)", &u, NULL);
3725 return bus_log_parse_error(r);
3728 printf("%s=%u\n", name, (unsigned) u);
3730 printf("%s=\n", name);
3734 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "Unit")) {
3737 r = sd_bus_message_read(m, "(so)", &s, NULL);
3739 return bus_log_parse_error(r);
3741 if (arg_all || !isempty(s))
3742 printf("%s=%s\n", name, s);
3746 } else if (contents[1] == SD_BUS_TYPE_STRING && streq(name, "LoadError")) {
3747 const char *a = NULL, *b = NULL;
3749 r = sd_bus_message_read(m, "(ss)", &a, &b);
3751 return bus_log_parse_error(r);
3753 if (arg_all || !isempty(a) || !isempty(b))
3754 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3757 } else if (streq_ptr(name, "SystemCallFilter")) {
3758 _cleanup_strv_free_ char **l = NULL;
3761 r = sd_bus_message_enter_container(m, 'r', "bas");
3763 return bus_log_parse_error(r);
3765 r = sd_bus_message_read(m, "b", &whitelist);
3767 return bus_log_parse_error(r);
3769 r = sd_bus_message_read_strv(m, &l);
3771 return bus_log_parse_error(r);
3773 r = sd_bus_message_exit_container(m);
3775 return bus_log_parse_error(r);
3777 if (arg_all || whitelist || !strv_isempty(l)) {
3781 fputs(name, stdout);
3787 STRV_FOREACH(i, l) {
3795 fputc('\n', stdout);
3803 case SD_BUS_TYPE_ARRAY:
3805 if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "EnvironmentFiles")) {
3809 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sb)");
3811 return bus_log_parse_error(r);
3813 while ((r = sd_bus_message_read(m, "(sb)", &path, &ignore)) > 0)
3814 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3817 return bus_log_parse_error(r);
3819 r = sd_bus_message_exit_container(m);
3821 return bus_log_parse_error(r);
3825 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Paths")) {
3826 const char *type, *path;
3828 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3830 return bus_log_parse_error(r);
3832 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3833 printf("%s=%s\n", type, path);
3835 return bus_log_parse_error(r);
3837 r = sd_bus_message_exit_container(m);
3839 return bus_log_parse_error(r);
3843 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Listen")) {
3844 const char *type, *path;
3846 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3848 return bus_log_parse_error(r);
3850 while ((r = sd_bus_message_read(m, "(ss)", &type, &path)) > 0)
3851 printf("Listen%s=%s\n", type, path);
3853 return bus_log_parse_error(r);
3855 r = sd_bus_message_exit_container(m);
3857 return bus_log_parse_error(r);
3861 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Timers")) {
3863 uint64_t value, next_elapse;
3865 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(stt)");
3867 return bus_log_parse_error(r);
3869 while ((r = sd_bus_message_read(m, "(stt)", &base, &value, &next_elapse)) > 0) {
3870 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3872 printf("%s={ value=%s ; next_elapse=%s }\n",
3874 format_timespan(timespan1, sizeof(timespan1), value, 0),
3875 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3878 return bus_log_parse_error(r);
3880 r = sd_bus_message_exit_container(m);
3882 return bus_log_parse_error(r);
3886 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && startswith(name, "Exec")) {
3887 ExecStatusInfo info = {};
3889 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sasbttttuii)");
3891 return bus_log_parse_error(r);
3893 while ((r = exec_status_info_deserialize(m, &info)) > 0) {
3894 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3895 _cleanup_free_ char *tt;
3897 tt = strv_join(info.argv, " ");
3899 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3903 yes_no(info.ignore),
3904 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3905 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3906 (unsigned) info. pid,
3907 sigchld_code_to_string(info.code),
3909 info.code == CLD_EXITED ? "" : "/",
3910 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3913 strv_free(info.argv);
3917 r = sd_bus_message_exit_container(m);
3919 return bus_log_parse_error(r);
3923 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "DeviceAllow")) {
3924 const char *path, *rwm;
3926 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)");
3928 return bus_log_parse_error(r);
3930 while ((r = sd_bus_message_read(m, "(ss)", &path, &rwm)) > 0)
3931 printf("%s=%s %s\n", name, strna(path), strna(rwm));
3933 return bus_log_parse_error(r);
3935 r = sd_bus_message_exit_container(m);
3937 return bus_log_parse_error(r);
3941 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
3945 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
3947 return bus_log_parse_error(r);
3949 while ((r = sd_bus_message_read(m, "(st)", &path, &weight)) > 0)
3950 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
3952 return bus_log_parse_error(r);
3954 r = sd_bus_message_exit_container(m);
3956 return bus_log_parse_error(r);
3960 } else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
3964 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(st)");
3966 return bus_log_parse_error(r);
3968 while ((r = sd_bus_message_read(m, "(st)", &path, &bandwidth)) > 0)
3969 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
3971 return bus_log_parse_error(r);
3973 r = sd_bus_message_exit_container(m);
3975 return bus_log_parse_error(r);
3983 r = bus_print_property(name, m, arg_all);
3985 return bus_log_parse_error(r);
3988 r = sd_bus_message_skip(m, contents);
3990 return bus_log_parse_error(r);
3993 printf("%s=[unprintable]\n", name);
3999 static int show_one(
4003 bool show_properties,
4007 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4008 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4009 UnitStatusInfo info = {};
4016 log_debug("Showing one %s", path);
4018 r = sd_bus_call_method(
4020 "org.freedesktop.systemd1",
4022 "org.freedesktop.DBus.Properties",
4028 log_error("Failed to get properties: %s", bus_error_message(&error, r));
4032 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
4034 return bus_log_parse_error(r);
4041 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
4042 const char *name, *contents;
4044 r = sd_bus_message_read(reply, "s", &name);
4046 return bus_log_parse_error(r);
4048 r = sd_bus_message_peek_type(reply, NULL, &contents);
4050 return bus_log_parse_error(r);
4052 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
4054 return bus_log_parse_error(r);
4056 if (show_properties)
4057 r = print_property(name, reply, contents);
4059 r = status_property(name, reply, &info, contents);
4063 r = sd_bus_message_exit_container(reply);
4065 return bus_log_parse_error(r);
4067 r = sd_bus_message_exit_container(reply);
4069 return bus_log_parse_error(r);
4072 return bus_log_parse_error(r);
4074 r = sd_bus_message_exit_container(reply);
4076 return bus_log_parse_error(r);
4080 if (!show_properties) {
4081 if (streq(verb, "help"))
4082 show_unit_help(&info);
4084 print_status_info(&info, ellipsized);
4087 strv_free(info.documentation);
4088 strv_free(info.dropin_paths);
4089 strv_free(info.listen);
4091 if (!streq_ptr(info.active_state, "active") &&
4092 !streq_ptr(info.active_state, "reloading") &&
4093 streq(verb, "status")) {
4094 /* According to LSB: "program not running" */
4095 /* 0: program is running or service is OK
4096 * 1: program is dead and /run PID file exists
4097 * 2: program is dead and /run/lock lock file exists
4098 * 3: program is not running
4099 * 4: program or service status is unknown
4101 if (info.pid_file && access(info.pid_file, F_OK) == 0)
4107 while ((p = info.exec)) {
4108 LIST_REMOVE(exec, info.exec, p);
4109 exec_status_info_free(p);
4115 static int get_unit_dbus_path_by_pid(
4120 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4121 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4125 r = sd_bus_call_method(
4127 "org.freedesktop.systemd1",
4128 "/org/freedesktop/systemd1",
4129 "org.freedesktop.systemd1.Manager",
4135 log_error("Failed to get unit for PID %lu: %s", (unsigned long) pid, bus_error_message(&error, r));
4139 r = sd_bus_message_read(reply, "o", &u);
4141 return bus_log_parse_error(r);
4151 static int show_all(
4154 bool show_properties,
4158 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4159 _cleanup_free_ UnitInfo *unit_infos = NULL;
4164 r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply);
4168 pager_open_if_enabled();
4172 qsort_safe(unit_infos, c, sizeof(UnitInfo), compare_unit_info);
4174 for (u = unit_infos; u < unit_infos + c; u++) {
4175 _cleanup_free_ char *p = NULL;
4177 p = unit_dbus_path_from_name(u->id);
4181 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
4189 static int show_system_status(sd_bus *bus) {
4190 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], since2[FORMAT_TIMESTAMP_MAX];
4191 _cleanup_free_ char *hn = NULL;
4192 struct machine_info mi = {};
4193 const char *on, *off;
4196 hn = gethostname_malloc();
4200 r = bus_map_all_properties(bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", machine_info_property_map, &mi);
4202 log_error("Failed to read server status: %s", strerror(-r));
4206 if (streq_ptr(mi.state, "degraded")) {
4207 on = ansi_highlight_red();
4208 off = ansi_highlight_off();
4209 } else if (!streq_ptr(mi.state, "running")) {
4210 on = ansi_highlight_yellow();
4211 off = ansi_highlight_off();
4215 printf("%s%s%s%s\n", on, draw_special_char(DRAW_BLACK_CIRCLE), off, arg_host ? arg_host : hn);
4217 printf(" State: %s%s%s\n",
4218 on, strna(mi.state), off);
4220 printf(" Jobs: %u queued\n", mi.n_jobs);
4221 printf(" Failed: %u units\n", mi.n_failed_units);
4223 printf(" Since: %s; %s\n",
4224 format_timestamp(since2, sizeof(since2), mi.timestamp),
4225 format_timestamp_relative(since1, sizeof(since1), mi.timestamp));
4227 printf(" CGroup: %s\n", mi.control_group ?: "/");
4228 if (arg_transport == BUS_TRANSPORT_LOCAL || arg_transport == BUS_TRANSPORT_CONTAINER) {
4230 arg_all * OUTPUT_SHOW_ALL |
4231 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
4232 on_tty() * OUTPUT_COLOR |
4233 !arg_quiet * OUTPUT_WARN_CUTOFF |
4234 arg_full * OUTPUT_FULL_WIDTH;
4236 static const char prefix[] = " ";
4240 if (c > sizeof(prefix) - 1)
4241 c -= sizeof(prefix) - 1;
4245 show_cgroup(SYSTEMD_CGROUP_CONTROLLER, strempty(mi.control_group), prefix, c, false, flags);
4249 free(mi.control_group);
4254 static int show(sd_bus *bus, char **args) {
4255 bool show_properties, show_status, new_line = false;
4256 bool ellipsized = false;
4262 show_properties = streq(args[0], "show");
4263 show_status = streq(args[0], "status");
4265 if (show_properties)
4266 pager_open_if_enabled();
4268 /* If no argument is specified inspect the manager itself */
4270 if (show_properties && strv_length(args) <= 1)
4271 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
4273 if (show_status && strv_length(args) <= 1) {
4275 pager_open_if_enabled();
4276 show_system_status(bus);
4280 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
4282 _cleanup_free_ char **patterns = NULL;
4285 STRV_FOREACH(name, args + 1) {
4286 _cleanup_free_ char *unit = NULL;
4289 if (safe_atou32(*name, &id) < 0) {
4290 if (strv_push(&patterns, *name) < 0)
4294 } else if (show_properties) {
4295 /* Interpret as job id */
4296 if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
4300 /* Interpret as PID */
4301 r = get_unit_dbus_path_by_pid(bus, id, &unit);
4308 show_one(args[0], bus, unit, show_properties, &new_line, &ellipsized);
4311 if (!strv_isempty(patterns)) {
4312 _cleanup_strv_free_ char **names = NULL;
4314 r = expand_names(bus, patterns, NULL, &names);
4316 log_error("Failed to expand names: %s", strerror(-r));
4318 STRV_FOREACH(name, names) {
4319 _cleanup_free_ char *unit;
4321 unit = unit_dbus_path_from_name(*name);
4325 show_one(args[0], bus, unit, show_properties, &new_line, &ellipsized);
4330 if (ellipsized && !arg_quiet)
4331 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
4336 static int cat(sd_bus *bus, char **args) {
4337 _cleanup_free_ char *unit = NULL;
4338 _cleanup_strv_free_ char **names = NULL;
4346 r = expand_names(bus, args + 1, NULL, &names);
4348 log_error("Failed to expand names: %s", strerror(-r));
4350 pager_open_if_enabled();
4352 STRV_FOREACH(name, names) {
4353 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4354 _cleanup_strv_free_ char **dropin_paths = NULL;
4355 _cleanup_free_ char *fragment_path = NULL;
4358 unit = unit_dbus_path_from_name(*name);
4362 if (need_daemon_reload(bus, *name) > 0)
4363 log_warning("Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'.",
4364 *name, arg_scope == UNIT_FILE_SYSTEM ? "" : " --user");
4366 r = sd_bus_get_property_string(
4368 "org.freedesktop.systemd1",
4370 "org.freedesktop.systemd1.Unit",
4375 log_warning("Failed to get FragmentPath: %s", bus_error_message(&error, r));
4379 r = sd_bus_get_property_strv(
4381 "org.freedesktop.systemd1",
4383 "org.freedesktop.systemd1.Unit",
4388 log_warning("Failed to get DropInPaths: %s", bus_error_message(&error, r));
4397 if (!isempty(fragment_path)) {
4398 printf("%s# %s%s\n",
4399 ansi_highlight_blue(),
4401 ansi_highlight_off());
4404 r = sendfile_full(STDOUT_FILENO, fragment_path);
4406 log_warning("Failed to cat %s: %s", fragment_path, strerror(-r));
4411 STRV_FOREACH(path, dropin_paths) {
4412 printf("%s%s# %s%s\n",
4413 isempty(fragment_path) && path == dropin_paths ? "" : "\n",
4414 ansi_highlight_blue(),
4416 ansi_highlight_off());
4419 r = sendfile_full(STDOUT_FILENO, *path);
4421 log_warning("Failed to cat %s: %s", *path, strerror(-r));
4427 return r < 0 ? r : 0;
4430 static int set_property(sd_bus *bus, char **args) {
4431 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4432 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4433 _cleanup_free_ char *n = NULL;
4437 r = sd_bus_message_new_method_call(
4440 "org.freedesktop.systemd1",
4441 "/org/freedesktop/systemd1",
4442 "org.freedesktop.systemd1.Manager",
4443 "SetUnitProperties");
4445 return bus_log_create_error(r);
4447 n = unit_name_mangle(args[1], MANGLE_NOGLOB);
4451 r = sd_bus_message_append(m, "sb", n, arg_runtime);
4453 return bus_log_create_error(r);
4455 r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, "(sv)");
4457 return bus_log_create_error(r);
4459 STRV_FOREACH(i, args + 2) {
4460 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
4462 return bus_log_create_error(r);
4464 r = bus_append_unit_property_assignment(m, *i);
4468 r = sd_bus_message_close_container(m);
4470 return bus_log_create_error(r);
4473 r = sd_bus_message_close_container(m);
4475 return bus_log_create_error(r);
4477 r = sd_bus_call(bus, m, 0, &error, NULL);
4479 log_error("Failed to set unit properties on %s: %s", n, bus_error_message(&error, r));
4486 static int snapshot(sd_bus *bus, char **args) {
4487 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4488 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4489 _cleanup_free_ char *n = NULL, *id = NULL;
4493 if (strv_length(args) > 1)
4494 n = unit_name_mangle_with_suffix(args[1], MANGLE_NOGLOB, ".snapshot");
4500 r = sd_bus_call_method(
4502 "org.freedesktop.systemd1",
4503 "/org/freedesktop/systemd1",
4504 "org.freedesktop.systemd1.Manager",
4510 log_error("Failed to create snapshot: %s", bus_error_message(&error, r));
4514 r = sd_bus_message_read(reply, "o", &path);
4516 return bus_log_parse_error(r);
4518 r = sd_bus_get_property_string(
4520 "org.freedesktop.systemd1",
4522 "org.freedesktop.systemd1.Unit",
4527 log_error("Failed to get ID of snapshot: %s", bus_error_message(&error, r));
4537 static int delete_snapshot(sd_bus *bus, char **args) {
4538 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4539 _cleanup_strv_free_ char **names = NULL;
4545 r = expand_names(bus, args + 1, ".snapshot", &names);
4547 log_error("Failed to expand names: %s", strerror(-r));
4549 STRV_FOREACH(name, names) {
4550 q = sd_bus_call_method(
4552 "org.freedesktop.systemd1",
4553 "/org/freedesktop/systemd1",
4554 "org.freedesktop.systemd1.Manager",
4560 log_error("Failed to remove snapshot %s: %s",
4561 *name, bus_error_message(&error, r));
4570 static int daemon_reload(sd_bus *bus, char **args) {
4571 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4575 if (arg_action == ACTION_RELOAD)
4577 else if (arg_action == ACTION_REEXEC)
4578 method = "Reexecute";
4580 assert(arg_action == ACTION_SYSTEMCTL);
4583 streq(args[0], "clear-jobs") ||
4584 streq(args[0], "cancel") ? "ClearJobs" :
4585 streq(args[0], "daemon-reexec") ? "Reexecute" :
4586 streq(args[0], "reset-failed") ? "ResetFailed" :
4587 streq(args[0], "halt") ? "Halt" :
4588 streq(args[0], "poweroff") ? "PowerOff" :
4589 streq(args[0], "reboot") ? "Reboot" :
4590 streq(args[0], "kexec") ? "KExec" :
4591 streq(args[0], "exit") ? "Exit" :
4592 /* "daemon-reload" */ "Reload";
4595 r = sd_bus_call_method(
4597 "org.freedesktop.systemd1",
4598 "/org/freedesktop/systemd1",
4599 "org.freedesktop.systemd1.Manager",
4605 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4606 /* There's always a fallback possible for
4607 * legacy actions. */
4609 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4610 /* On reexecution, we expect a disconnect, not a
4614 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
4616 return r < 0 ? r : 0;
4619 static int reset_failed(sd_bus *bus, char **args) {
4620 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4621 _cleanup_strv_free_ char **names = NULL;
4625 if (strv_length(args) <= 1)
4626 return daemon_reload(bus, args);
4628 r = expand_names(bus, args + 1, NULL, &names);
4630 log_error("Failed to expand names: %s", strerror(-r));
4632 STRV_FOREACH(name, names) {
4633 q = sd_bus_call_method(
4635 "org.freedesktop.systemd1",
4636 "/org/freedesktop/systemd1",
4637 "org.freedesktop.systemd1.Manager",
4643 log_error("Failed to reset failed state of unit %s: %s",
4644 *name, bus_error_message(&error, r));
4653 static int show_environment(sd_bus *bus, char **args) {
4654 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4655 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4659 pager_open_if_enabled();
4661 r = sd_bus_get_property(
4663 "org.freedesktop.systemd1",
4664 "/org/freedesktop/systemd1",
4665 "org.freedesktop.systemd1.Manager",
4671 log_error("Failed to get environment: %s", bus_error_message(&error, r));
4675 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "s");
4677 return bus_log_parse_error(r);
4679 while ((r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &text)) > 0)
4682 return bus_log_parse_error(r);
4684 r = sd_bus_message_exit_container(reply);
4686 return bus_log_parse_error(r);
4691 static int switch_root(sd_bus *bus, char **args) {
4692 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4693 _cleanup_free_ char *cmdline_init = NULL;
4694 const char *root, *init;
4698 l = strv_length(args);
4699 if (l < 2 || l > 3) {
4700 log_error("Wrong number of arguments.");
4709 r = parse_env_file("/proc/cmdline", WHITESPACE,
4710 "init", &cmdline_init,
4713 log_debug("Failed to parse /proc/cmdline: %s", strerror(-r));
4715 init = cmdline_init;
4722 const char *root_systemd_path = NULL, *root_init_path = NULL;
4724 root_systemd_path = strappenda(root, "/" SYSTEMD_BINARY_PATH);
4725 root_init_path = strappenda3(root, "/", init);
4727 /* If the passed init is actually the same as the
4728 * systemd binary, then let's suppress it. */
4729 if (files_same(root_init_path, root_systemd_path) > 0)
4733 log_debug("Switching root - root: %s; init: %s", root, strna(init));
4735 r = sd_bus_call_method(
4737 "org.freedesktop.systemd1",
4738 "/org/freedesktop/systemd1",
4739 "org.freedesktop.systemd1.Manager",
4745 log_error("Failed to switch root: %s", bus_error_message(&error, r));
4752 static int set_environment(sd_bus *bus, char **args) {
4753 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4754 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4761 method = streq(args[0], "set-environment")
4763 : "UnsetEnvironment";
4765 r = sd_bus_message_new_method_call(
4768 "org.freedesktop.systemd1",
4769 "/org/freedesktop/systemd1",
4770 "org.freedesktop.systemd1.Manager",
4773 return bus_log_create_error(r);
4775 r = sd_bus_message_append_strv(m, args + 1);
4777 return bus_log_create_error(r);
4779 r = sd_bus_call(bus, m, 0, &error, NULL);
4781 log_error("Failed to set environment: %s", bus_error_message(&error, r));
4788 static int import_environment(sd_bus *bus, char **args) {
4789 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4790 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
4796 r = sd_bus_message_new_method_call(
4799 "org.freedesktop.systemd1",
4800 "/org/freedesktop/systemd1",
4801 "org.freedesktop.systemd1.Manager",
4804 return bus_log_create_error(r);
4806 if (strv_isempty(args + 1))
4807 r = sd_bus_message_append_strv(m, environ);
4811 r = sd_bus_message_open_container(m, 'a', "s");
4813 return bus_log_create_error(r);
4815 STRV_FOREACH(a, args + 1) {
4817 if (!env_name_is_valid(*a)) {
4818 log_error("Not a valid environment variable name: %s", *a);
4822 STRV_FOREACH(b, environ) {
4825 eq = startswith(*b, *a);
4826 if (eq && *eq == '=') {
4828 r = sd_bus_message_append(m, "s", *b);
4830 return bus_log_create_error(r);
4837 r = sd_bus_message_close_container(m);
4840 return bus_log_create_error(r);
4842 r = sd_bus_call(bus, m, 0, &error, NULL);
4844 log_error("Failed to import environment: %s", bus_error_message(&error, r));
4851 static int enable_sysv_units(const char *verb, char **args) {
4854 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4855 unsigned f = 1, t = 1;
4856 _cleanup_lookup_paths_free_ LookupPaths paths = {};
4858 if (arg_scope != UNIT_FILE_SYSTEM)
4861 if (!streq(verb, "enable") &&
4862 !streq(verb, "disable") &&
4863 !streq(verb, "is-enabled"))
4866 /* Processes all SysV units, and reshuffles the array so that
4867 * afterwards only the native units remain */
4869 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4874 for (f = 0; args[f]; f++) {
4876 _cleanup_free_ char *p = NULL, *q = NULL;
4877 bool found_native = false, found_sysv;
4879 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4887 if (!endswith(name, ".service"))
4890 if (path_is_absolute(name))
4893 STRV_FOREACH(k, paths.unit_path) {
4894 if (!isempty(arg_root))
4895 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4897 asprintf(&p, "%s/%s", *k, name);
4904 found_native = access(p, F_OK) >= 0;
4915 if (!isempty(arg_root))
4916 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4918 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4924 p[strlen(p) - sizeof(".service") + 1] = 0;
4925 found_sysv = access(p, F_OK) >= 0;
4930 /* Mark this entry, so that we don't try enabling it as native unit */
4931 args[f] = (char*) "";
4933 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4935 if (!isempty(arg_root))
4936 argv[c++] = q = strappend("--root=", arg_root);
4938 argv[c++] = basename(p);
4940 streq(verb, "enable") ? "on" :
4941 streq(verb, "disable") ? "off" : "--level=5";
4944 l = strv_join((char**)argv, " ");
4950 log_info("Executing %s", l);
4955 log_error("Failed to fork: %m");
4958 } else if (pid == 0) {
4961 execv(argv[0], (char**) argv);
4962 _exit(EXIT_FAILURE);
4965 j = wait_for_terminate(pid, &status);
4967 log_error("Failed to wait for child: %s", strerror(-r));
4972 if (status.si_code == CLD_EXITED) {
4973 if (streq(verb, "is-enabled")) {
4974 if (status.si_status == 0) {
4983 } else if (status.si_status != 0) {
4994 /* Drop all SysV units */
4995 for (f = 0, t = 0; args[f]; f++) {
4997 if (isempty(args[f]))
5000 args[t++] = args[f];
5009 static int mangle_names(char **original_names, char ***mangled_names) {
5010 char **i, **l, **name;
5012 l = new(char*, strv_length(original_names) + 1);
5017 STRV_FOREACH(name, original_names) {
5019 /* When enabling units qualified path names are OK,
5020 * too, hence allow them explicitly. */
5025 *i = unit_name_mangle(*name, MANGLE_NOGLOB);
5041 static int enable_unit(sd_bus *bus, char **args) {
5042 _cleanup_strv_free_ char **names = NULL;
5043 const char *verb = args[0];
5044 UnitFileChange *changes = NULL;
5045 unsigned n_changes = 0;
5046 int carries_install_info = -1;
5052 r = mangle_names(args+1, &names);
5056 r = enable_sysv_units(verb, names);
5060 /* If the operation was fully executed by the SysV compat,
5061 * let's finish early */
5062 if (strv_isempty(names))
5065 if (!bus || avoid_bus()) {
5066 if (streq(verb, "enable")) {
5067 r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5068 carries_install_info = r;
5069 } else if (streq(verb, "disable"))
5070 r = unit_file_disable(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5071 else if (streq(verb, "reenable")) {
5072 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5073 carries_install_info = r;
5074 } else if (streq(verb, "link"))
5075 r = unit_file_link(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5076 else if (streq(verb, "preset")) {
5077 r = unit_file_preset(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5078 carries_install_info = r;
5079 } else if (streq(verb, "mask"))
5080 r = unit_file_mask(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
5081 else if (streq(verb, "unmask"))
5082 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, names, &changes, &n_changes);
5084 assert_not_reached("Unknown verb");
5087 log_error("Operation failed: %s", strerror(-r));
5092 dump_unit_file_changes(changes, n_changes);
5096 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
5097 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5098 int expect_carries_install_info = false;
5099 bool send_force = true;
5102 if (streq(verb, "enable")) {
5103 method = "EnableUnitFiles";
5104 expect_carries_install_info = true;
5105 } else if (streq(verb, "disable")) {
5106 method = "DisableUnitFiles";
5108 } else if (streq(verb, "reenable")) {
5109 method = "ReenableUnitFiles";
5110 expect_carries_install_info = true;
5111 } else if (streq(verb, "link"))
5112 method = "LinkUnitFiles";
5113 else if (streq(verb, "preset")) {
5114 method = "PresetUnitFiles";
5115 expect_carries_install_info = true;
5116 } else if (streq(verb, "mask"))
5117 method = "MaskUnitFiles";
5118 else if (streq(verb, "unmask")) {
5119 method = "UnmaskUnitFiles";
5122 assert_not_reached("Unknown verb");
5124 r = sd_bus_message_new_method_call(
5127 "org.freedesktop.systemd1",
5128 "/org/freedesktop/systemd1",
5129 "org.freedesktop.systemd1.Manager",
5132 return bus_log_create_error(r);
5134 r = sd_bus_message_append_strv(m, names);
5136 return bus_log_create_error(r);
5138 r = sd_bus_message_append(m, "b", arg_runtime);
5140 return bus_log_create_error(r);
5143 r = sd_bus_message_append(m, "b", arg_force);
5145 return bus_log_create_error(r);
5148 r = sd_bus_call(bus, m, 0, &error, &reply);
5150 log_error("Failed to execute operation: %s", bus_error_message(&error, r));
5154 if (expect_carries_install_info) {
5155 r = sd_bus_message_read(reply, "b", &carries_install_info);
5157 return bus_log_parse_error(r);
5160 r = deserialize_and_dump_unit_file_changes(reply);
5164 /* Try to reload if enabeld */
5166 r = daemon_reload(bus, args);
5171 if (carries_install_info == 0)
5172 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
5173 "using systemctl.\n"
5174 "Possible reasons for having this kind of units are:\n"
5175 "1) A unit may be statically enabled by being symlinked from another unit's\n"
5176 " .wants/ or .requires/ directory.\n"
5177 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
5178 " a requirement dependency on it.\n"
5179 "3) A unit may be started when needed via activation (socket, path, timer,\n"
5180 " D-Bus, udev, scripted systemctl call, ...).\n");
5183 unit_file_changes_free(changes, n_changes);
5188 static int unit_is_enabled(sd_bus *bus, char **args) {
5190 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
5191 _cleanup_strv_free_ char **names = NULL;
5196 r = mangle_names(args+1, &names);
5200 r = enable_sysv_units(args[0], names);
5206 if (!bus || avoid_bus()) {
5208 STRV_FOREACH(name, names) {
5209 UnitFileState state;
5211 state = unit_file_get_state(arg_scope, arg_root, *name);
5213 log_error("Failed to get unit file state for %s: %s", *name, strerror(-state));
5217 if (state == UNIT_FILE_ENABLED ||
5218 state == UNIT_FILE_ENABLED_RUNTIME ||
5219 state == UNIT_FILE_STATIC)
5223 puts(unit_file_state_to_string(state));
5227 STRV_FOREACH(name, names) {
5228 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
5231 r = sd_bus_call_method(
5233 "org.freedesktop.systemd1",
5234 "/org/freedesktop/systemd1",
5235 "org.freedesktop.systemd1.Manager",
5241 log_error("Failed to get unit file state for %s: %s", *name, bus_error_message(&error, r));
5245 r = sd_bus_message_read(reply, "s", &s);
5247 return bus_log_parse_error(r);
5249 if (streq(s, "enabled") ||
5250 streq(s, "enabled-runtime") ||
5262 static int systemctl_help(void) {
5264 pager_open_if_enabled();
5266 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
5267 "Query or send control commands to the systemd manager.\n\n"
5268 " -h --help Show this help\n"
5269 " --version Show package version\n"
5270 " --system Connect to system manager\n"
5271 " --user Connect to user service manager\n"
5272 " -H --host=[USER@]HOST\n"
5273 " Operate on remote host\n"
5274 " -M --machine=CONTAINER\n"
5275 " Operate on local container\n"
5276 " -t --type=TYPE List only units of a particular type\n"
5277 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
5278 " -p --property=NAME Show only properties by this name\n"
5279 " -a --all Show all loaded units/properties, including dead/empty\n"
5280 " ones. To list all units installed on the system, use\n"
5281 " the 'list-unit-files' command instead.\n"
5282 " -l --full Don't ellipsize unit names on output\n"
5283 " -r --recursive Show unit list of host and local containers\n"
5284 " --reverse Show reverse dependencies with 'list-dependencies'\n"
5285 " --job-mode=MODE Specify how to deal with already queued jobs, when\n"
5286 " queueing a new job\n"
5287 " --show-types When showing sockets, explicitly show their type\n"
5288 " -i --ignore-inhibitors\n"
5289 " When shutting down or sleeping, ignore inhibitors\n"
5290 " --kill-who=WHO Who to send signal to\n"
5291 " -s --signal=SIGNAL Which signal to send\n"
5292 " -q --quiet Suppress output\n"
5293 " --no-block Do not wait until operation finished\n"
5294 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5295 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
5297 " --no-legend Do not print a legend (column headers and hints)\n"
5298 " --no-pager Do not pipe output into a pager\n"
5299 " --no-ask-password\n"
5300 " Do not ask for system passwords\n"
5301 " --global Enable/disable unit files globally\n"
5302 " --runtime Enable unit files only temporarily until next reboot\n"
5303 " -f --force When enabling unit files, override existing symlinks\n"
5304 " When shutting down, execute action immediately\n"
5305 " --root=PATH Enable unit files in the specified root directory\n"
5306 " -n --lines=INTEGER Number of journal entries to show\n"
5307 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
5308 " verbose, export, json, json-pretty, json-sse, cat)\n"
5309 " --plain Print unit dependencies as a list instead of a tree\n\n"
5311 " list-units [PATTERN...] List loaded units\n"
5312 " list-sockets [PATTERN...] List loaded sockets ordered by address\n"
5313 " list-timers [PATTERN...] List loaded timers ordered by next elapse\n"
5314 " start NAME... Start (activate) one or more units\n"
5315 " stop NAME... Stop (deactivate) one or more units\n"
5316 " reload NAME... Reload one or more units\n"
5317 " restart NAME... Start or restart one or more units\n"
5318 " try-restart NAME... Restart one or more units if active\n"
5319 " reload-or-restart NAME... Reload one or more units if possible,\n"
5320 " otherwise start or restart\n"
5321 " reload-or-try-restart NAME... Reload one or more units if possible,\n"
5322 " otherwise restart if active\n"
5323 " isolate NAME Start one unit and stop all others\n"
5324 " kill NAME... Send signal to processes of a unit\n"
5325 " is-active NAME... Check whether units are active\n"
5326 " is-failed NAME... Check whether units are failed\n"
5327 " status [NAME...|PID...] Show runtime status of one or more units\n"
5328 " show [NAME...|JOB...] Show properties of one or more\n"
5329 " units/jobs or the manager\n"
5330 " cat NAME... Show files and drop-ins of one or more units\n"
5331 " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n"
5332 " help NAME...|PID... Show manual for one or more units\n"
5333 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
5335 " list-dependencies [NAME] Recursively show units which are required\n"
5336 " or wanted by this unit or by which this\n"
5337 " unit is required or wanted\n\n"
5338 "Unit File Commands:\n"
5339 " list-unit-files [PATTERN...] List installed unit files\n"
5340 " enable NAME... Enable one or more unit files\n"
5341 " disable NAME... Disable one or more unit files\n"
5342 " reenable NAME... Reenable one or more unit files\n"
5343 " preset NAME... Enable/disable one or more unit files\n"
5344 " based on preset configuration\n"
5345 " is-enabled NAME... Check whether unit files are enabled\n\n"
5346 " mask NAME... Mask one or more units\n"
5347 " unmask NAME... Unmask one or more units\n"
5348 " link PATH... Link one or more units files into\n"
5349 " the search path\n"
5350 " get-default Get the name of the default target\n"
5351 " set-default NAME Set the default target\n\n"
5352 "Machine Commands:\n"
5353 " list-machines [PATTERN...] List local containers and host\n\n"
5355 " list-jobs [PATTERN...] List jobs\n"
5356 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
5357 "Snapshot Commands:\n"
5358 " snapshot [NAME] Create a snapshot\n"
5359 " delete NAME... Remove one or more snapshots\n\n"
5360 "Environment Commands:\n"
5361 " show-environment Dump environment\n"
5362 " set-environment NAME=VALUE... Set one or more environment variables\n"
5363 " unset-environment NAME... Unset one or more environment variables\n"
5364 " import-environment NAME... Import all, one or more environment variables\n\n"
5365 "Manager Lifecycle Commands:\n"
5366 " daemon-reload Reload systemd manager configuration\n"
5367 " daemon-reexec Reexecute systemd manager\n\n"
5368 "System Commands:\n"
5369 " default Enter system default mode\n"
5370 " rescue Enter system rescue mode\n"
5371 " emergency Enter system emergency mode\n"
5372 " halt Shut down and halt the system\n"
5373 " poweroff Shut down and power-off the system\n"
5374 " reboot [ARG] Shut down and reboot the system\n"
5375 " kexec Shut down and reboot the system with kexec\n"
5376 " exit Request user instance exit\n"
5377 " switch-root ROOT [INIT] Change to a different root file system\n"
5378 " suspend Suspend the system\n"
5379 " hibernate Hibernate the system\n"
5380 " hybrid-sleep Hibernate and suspend the system\n",
5381 program_invocation_short_name);
5386 static int halt_help(void) {
5388 printf("%s [OPTIONS...]%s\n\n"
5389 "%s the system.\n\n"
5390 " --help Show this help\n"
5391 " --halt Halt the machine\n"
5392 " -p --poweroff Switch off the machine\n"
5393 " --reboot Reboot the machine\n"
5394 " -f --force Force immediate halt/power-off/reboot\n"
5395 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
5396 " -d --no-wtmp Don't write wtmp record\n"
5397 " --no-wall Don't send wall message before halt/power-off/reboot\n",
5398 program_invocation_short_name,
5399 arg_action == ACTION_REBOOT ? " [ARG]" : "",
5400 arg_action == ACTION_REBOOT ? "Reboot" :
5401 arg_action == ACTION_POWEROFF ? "Power off" :
5407 static int shutdown_help(void) {
5409 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
5410 "Shut down the system.\n\n"
5411 " --help Show this help\n"
5412 " -H --halt Halt the machine\n"
5413 " -P --poweroff Power-off the machine\n"
5414 " -r --reboot Reboot the machine\n"
5415 " -h Equivalent to --poweroff, overridden by --halt\n"
5416 " -k Don't halt/power-off/reboot, just send warnings\n"
5417 " --no-wall Don't send wall message before halt/power-off/reboot\n"
5418 " -c Cancel a pending shutdown\n",
5419 program_invocation_short_name);
5424 static int telinit_help(void) {
5426 printf("%s [OPTIONS...] {COMMAND}\n\n"
5427 "Send control commands to the init daemon.\n\n"
5428 " --help Show this help\n"
5429 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
5431 " 0 Power-off the machine\n"
5432 " 6 Reboot the machine\n"
5433 " 2, 3, 4, 5 Start runlevelX.target unit\n"
5434 " 1, s, S Enter rescue mode\n"
5435 " q, Q Reload init daemon configuration\n"
5436 " u, U Reexecute init daemon\n",
5437 program_invocation_short_name);
5442 static int runlevel_help(void) {
5444 printf("%s [OPTIONS...]\n\n"
5445 "Prints the previous and current runlevel of the init system.\n\n"
5446 " --help Show this help\n",
5447 program_invocation_short_name);
5452 static int help_types(void) {
5456 puts("Available unit types:");
5457 for (i = 0; i < _UNIT_TYPE_MAX; i++) {
5458 t = unit_type_to_string(i);
5466 static int systemctl_parse_argv(int argc, char *argv[]) {
5475 ARG_IGNORE_DEPENDENCIES,
5487 ARG_NO_ASK_PASSWORD,
5496 static const struct option options[] = {
5497 { "help", no_argument, NULL, 'h' },
5498 { "version", no_argument, NULL, ARG_VERSION },
5499 { "type", required_argument, NULL, 't' },
5500 { "property", required_argument, NULL, 'p' },
5501 { "all", no_argument, NULL, 'a' },
5502 { "reverse", no_argument, NULL, ARG_REVERSE },
5503 { "after", no_argument, NULL, ARG_AFTER },
5504 { "before", no_argument, NULL, ARG_BEFORE },
5505 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
5506 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
5507 { "full", no_argument, NULL, 'l' },
5508 { "job-mode", required_argument, NULL, ARG_JOB_MODE },
5509 { "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
5510 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
5511 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
5512 { "ignore-inhibitors", no_argument, NULL, 'i' },
5513 { "user", no_argument, NULL, ARG_USER },
5514 { "system", no_argument, NULL, ARG_SYSTEM },
5515 { "global", no_argument, NULL, ARG_GLOBAL },
5516 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
5517 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
5518 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
5519 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5520 { "quiet", no_argument, NULL, 'q' },
5521 { "root", required_argument, NULL, ARG_ROOT },
5522 { "force", no_argument, NULL, ARG_FORCE },
5523 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
5524 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
5525 { "signal", required_argument, NULL, 's' },
5526 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
5527 { "host", required_argument, NULL, 'H' },
5528 { "machine", required_argument, NULL, 'M' },
5529 { "runtime", no_argument, NULL, ARG_RUNTIME },
5530 { "lines", required_argument, NULL, 'n' },
5531 { "output", required_argument, NULL, 'o' },
5532 { "plain", no_argument, NULL, ARG_PLAIN },
5533 { "state", required_argument, NULL, ARG_STATE },
5534 { "recursive", no_argument, NULL, 'r' },
5543 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:M:n:o:ir", options, NULL)) >= 0) {
5548 return systemctl_help();
5551 puts(PACKAGE_STRING);
5552 puts(SYSTEMD_FEATURES);
5559 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5560 _cleanup_free_ char *type;
5562 type = strndup(word, size);
5566 if (streq(type, "help")) {
5571 if (unit_type_from_string(type) >= 0) {
5572 if (strv_push(&arg_types, type))
5578 /* It's much nicer to use --state= for
5579 * load states, but let's support this
5580 * in --types= too for compatibility
5581 * with old versions */
5582 if (unit_load_state_from_string(optarg) >= 0) {
5583 if (strv_push(&arg_states, type) < 0)
5589 log_error("Unknown unit type or load state '%s'.", type);
5590 log_info("Use -t help to see a list of allowed values.");
5598 /* Make sure that if the empty property list
5599 was specified, we won't show any properties. */
5600 if (isempty(optarg) && !arg_properties) {
5601 arg_properties = new0(char*, 1);
5602 if (!arg_properties)
5608 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5611 prop = strndup(word, size);
5615 if (strv_consume(&arg_properties, prop) < 0)
5620 /* If the user asked for a particular
5621 * property, show it to him, even if it is
5633 arg_dependency = DEPENDENCY_REVERSE;
5637 arg_dependency = DEPENDENCY_AFTER;
5641 arg_dependency = DEPENDENCY_BEFORE;
5644 case ARG_SHOW_TYPES:
5645 arg_show_types = true;
5649 arg_job_mode = optarg;
5653 arg_job_mode = "fail";
5656 case ARG_IRREVERSIBLE:
5657 arg_job_mode = "replace-irreversibly";
5660 case ARG_IGNORE_DEPENDENCIES:
5661 arg_job_mode = "ignore-dependencies";
5665 arg_scope = UNIT_FILE_USER;
5669 arg_scope = UNIT_FILE_SYSTEM;
5673 arg_scope = UNIT_FILE_GLOBAL;
5677 arg_no_block = true;
5681 arg_no_legend = true;
5685 arg_no_pager = true;
5701 if (strv_extend(&arg_states, "failed") < 0)
5719 arg_no_reload = true;
5723 arg_kill_who = optarg;
5727 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5728 log_error("Failed to parse signal string %s.", optarg);
5733 case ARG_NO_ASK_PASSWORD:
5734 arg_ask_password = false;
5738 arg_transport = BUS_TRANSPORT_REMOTE;
5743 arg_transport = BUS_TRANSPORT_CONTAINER;
5752 if (safe_atou(optarg, &arg_lines) < 0) {
5753 log_error("Failed to parse lines '%s'", optarg);
5759 arg_output = output_mode_from_string(optarg);
5760 if (arg_output < 0) {
5761 log_error("Unknown output '%s'.", optarg);
5767 arg_ignore_inhibitors = true;
5778 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5781 s = strndup(word, size);
5785 if (strv_consume(&arg_states, s) < 0)
5792 if (geteuid() != 0) {
5793 log_error("--recursive requires root priviliges.");
5797 arg_recursive = true;
5804 assert_not_reached("Unhandled option");
5808 if (arg_transport != BUS_TRANSPORT_LOCAL && arg_scope != UNIT_FILE_SYSTEM) {
5809 log_error("Cannot access user instance remotely.");
5816 static int halt_parse_argv(int argc, char *argv[]) {
5825 static const struct option options[] = {
5826 { "help", no_argument, NULL, ARG_HELP },
5827 { "halt", no_argument, NULL, ARG_HALT },
5828 { "poweroff", no_argument, NULL, 'p' },
5829 { "reboot", no_argument, NULL, ARG_REBOOT },
5830 { "force", no_argument, NULL, 'f' },
5831 { "wtmp-only", no_argument, NULL, 'w' },
5832 { "no-wtmp", no_argument, NULL, 'd' },
5833 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5842 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5843 if (runlevel == '0' || runlevel == '6')
5846 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5853 arg_action = ACTION_HALT;
5857 if (arg_action != ACTION_REBOOT)
5858 arg_action = ACTION_POWEROFF;
5862 arg_action = ACTION_REBOOT;
5884 /* Compatibility nops */
5891 assert_not_reached("Unhandled option");
5895 if (arg_action == ACTION_REBOOT && argc == optind + 1) {
5896 r = write_string_file(REBOOT_PARAM_FILE, argv[optind]);
5898 log_error("Failed to write reboot param to "
5899 REBOOT_PARAM_FILE": %s", strerror(-r));
5902 } else if (optind < argc) {
5903 log_error("Too many arguments.");
5910 static int parse_time_spec(const char *t, usec_t *_u) {
5914 if (streq(t, "now"))
5916 else if (!strchr(t, ':')) {
5919 if (safe_atou64(t, &u) < 0)
5922 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5931 hour = strtol(t, &e, 10);
5932 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5935 minute = strtol(e+1, &e, 10);
5936 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5939 n = now(CLOCK_REALTIME);
5940 s = (time_t) (n / USEC_PER_SEC);
5942 assert_se(localtime_r(&s, &tm));
5944 tm.tm_hour = (int) hour;
5945 tm.tm_min = (int) minute;
5948 assert_se(s = mktime(&tm));
5950 *_u = (usec_t) s * USEC_PER_SEC;
5953 *_u += USEC_PER_DAY;
5959 static int shutdown_parse_argv(int argc, char *argv[]) {
5966 static const struct option options[] = {
5967 { "help", no_argument, NULL, ARG_HELP },
5968 { "halt", no_argument, NULL, 'H' },
5969 { "poweroff", no_argument, NULL, 'P' },
5970 { "reboot", no_argument, NULL, 'r' },
5971 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5972 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5981 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5985 return shutdown_help();
5988 arg_action = ACTION_HALT;
5992 arg_action = ACTION_POWEROFF;
5997 arg_action = ACTION_KEXEC;
5999 arg_action = ACTION_REBOOT;
6003 arg_action = ACTION_KEXEC;
6007 if (arg_action != ACTION_HALT)
6008 arg_action = ACTION_POWEROFF;
6021 /* Compatibility nops */
6025 arg_action = ACTION_CANCEL_SHUTDOWN;
6032 assert_not_reached("Unhandled option");
6036 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
6037 r = parse_time_spec(argv[optind], &arg_when);
6039 log_error("Failed to parse time specification: %s", argv[optind]);
6043 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
6045 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
6046 /* No time argument for shutdown cancel */
6047 arg_wall = argv + optind;
6048 else if (argc > optind + 1)
6049 /* We skip the time argument */
6050 arg_wall = argv + optind + 1;
6057 static int telinit_parse_argv(int argc, char *argv[]) {
6064 static const struct option options[] = {
6065 { "help", no_argument, NULL, ARG_HELP },
6066 { "no-wall", no_argument, NULL, ARG_NO_WALL },
6070 static const struct {
6074 { '0', ACTION_POWEROFF },
6075 { '6', ACTION_REBOOT },
6076 { '1', ACTION_RESCUE },
6077 { '2', ACTION_RUNLEVEL2 },
6078 { '3', ACTION_RUNLEVEL3 },
6079 { '4', ACTION_RUNLEVEL4 },
6080 { '5', ACTION_RUNLEVEL5 },
6081 { 's', ACTION_RESCUE },
6082 { 'S', ACTION_RESCUE },
6083 { 'q', ACTION_RELOAD },
6084 { 'Q', ACTION_RELOAD },
6085 { 'u', ACTION_REEXEC },
6086 { 'U', ACTION_REEXEC }
6095 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
6099 return telinit_help();
6109 assert_not_reached("Unhandled option");
6113 if (optind >= argc) {
6118 if (optind + 1 < argc) {
6119 log_error("Too many arguments.");
6123 if (strlen(argv[optind]) != 1) {
6124 log_error("Expected single character argument.");
6128 for (i = 0; i < ELEMENTSOF(table); i++)
6129 if (table[i].from == argv[optind][0])
6132 if (i >= ELEMENTSOF(table)) {
6133 log_error("Unknown command '%s'.", argv[optind]);
6137 arg_action = table[i].to;
6144 static int runlevel_parse_argv(int argc, char *argv[]) {
6150 static const struct option options[] = {
6151 { "help", no_argument, NULL, ARG_HELP },
6160 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
6164 return runlevel_help();
6170 assert_not_reached("Unhandled option");
6174 if (optind < argc) {
6175 log_error("Too many arguments.");
6182 static int parse_argv(int argc, char *argv[]) {
6186 if (program_invocation_short_name) {
6188 if (strstr(program_invocation_short_name, "halt")) {
6189 arg_action = ACTION_HALT;
6190 return halt_parse_argv(argc, argv);
6191 } else if (strstr(program_invocation_short_name, "poweroff")) {
6192 arg_action = ACTION_POWEROFF;
6193 return halt_parse_argv(argc, argv);
6194 } else if (strstr(program_invocation_short_name, "reboot")) {
6196 arg_action = ACTION_KEXEC;
6198 arg_action = ACTION_REBOOT;
6199 return halt_parse_argv(argc, argv);
6200 } else if (strstr(program_invocation_short_name, "shutdown")) {
6201 arg_action = ACTION_POWEROFF;
6202 return shutdown_parse_argv(argc, argv);
6203 } else if (strstr(program_invocation_short_name, "init")) {
6205 if (sd_booted() > 0) {
6206 arg_action = _ACTION_INVALID;
6207 return telinit_parse_argv(argc, argv);
6209 /* Hmm, so some other init system is
6210 * running, we need to forward this
6211 * request to it. For now we simply
6212 * guess that it is Upstart. */
6214 execv(TELINIT, argv);
6216 log_error("Couldn't find an alternative telinit implementation to spawn.");
6220 } else if (strstr(program_invocation_short_name, "runlevel")) {
6221 arg_action = ACTION_RUNLEVEL;
6222 return runlevel_parse_argv(argc, argv);
6226 arg_action = ACTION_SYSTEMCTL;
6227 return systemctl_parse_argv(argc, argv);
6230 _pure_ static int action_to_runlevel(void) {
6232 static const char table[_ACTION_MAX] = {
6233 [ACTION_HALT] = '0',
6234 [ACTION_POWEROFF] = '0',
6235 [ACTION_REBOOT] = '6',
6236 [ACTION_RUNLEVEL2] = '2',
6237 [ACTION_RUNLEVEL3] = '3',
6238 [ACTION_RUNLEVEL4] = '4',
6239 [ACTION_RUNLEVEL5] = '5',
6240 [ACTION_RESCUE] = '1'
6243 assert(arg_action < _ACTION_MAX);
6245 return table[arg_action];
6248 static int talk_initctl(void) {
6250 struct init_request request = {
6251 .magic = INIT_MAGIC,
6253 .cmd = INIT_CMD_RUNLVL
6256 _cleanup_close_ int fd = -1;
6260 rl = action_to_runlevel();
6264 request.runlevel = rl;
6266 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
6268 if (errno == ENOENT)
6271 log_error("Failed to open "INIT_FIFO": %m");
6276 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
6278 log_error("Failed to write to "INIT_FIFO": %m");
6279 return errno > 0 ? -errno : -EIO;
6285 static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
6287 static const struct {
6295 int (* const dispatch)(sd_bus *bus, char **args);
6301 { "list-units", MORE, 0, list_units },
6302 { "list-unit-files", MORE, 1, list_unit_files, NOBUS },
6303 { "list-sockets", MORE, 1, list_sockets },
6304 { "list-timers", MORE, 1, list_timers },
6305 { "list-jobs", MORE, 1, list_jobs },
6306 { "list-machines", MORE, 1, list_machines },
6307 { "clear-jobs", EQUAL, 1, daemon_reload },
6308 { "cancel", MORE, 2, cancel_job },
6309 { "start", MORE, 2, start_unit },
6310 { "stop", MORE, 2, start_unit },
6311 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6312 { "reload", MORE, 2, start_unit },
6313 { "restart", MORE, 2, start_unit },
6314 { "try-restart", MORE, 2, start_unit },
6315 { "reload-or-restart", MORE, 2, start_unit },
6316 { "reload-or-try-restart", MORE, 2, start_unit },
6317 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
6318 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
6319 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
6320 { "isolate", EQUAL, 2, start_unit },
6321 { "kill", MORE, 2, kill_unit },
6322 { "is-active", MORE, 2, check_unit_active },
6323 { "check", MORE, 2, check_unit_active },
6324 { "is-failed", MORE, 2, check_unit_failed },
6325 { "show", MORE, 1, show },
6326 { "cat", MORE, 2, cat },
6327 { "status", MORE, 1, show },
6328 { "help", MORE, 2, show },
6329 { "snapshot", LESS, 2, snapshot },
6330 { "delete", MORE, 2, delete_snapshot },
6331 { "daemon-reload", EQUAL, 1, daemon_reload },
6332 { "daemon-reexec", EQUAL, 1, daemon_reload },
6333 { "show-environment", EQUAL, 1, show_environment },
6334 { "set-environment", MORE, 2, set_environment },
6335 { "unset-environment", MORE, 2, set_environment },
6336 { "import-environment", MORE, 1, import_environment},
6337 { "halt", EQUAL, 1, start_special, FORCE },
6338 { "poweroff", EQUAL, 1, start_special, FORCE },
6339 { "reboot", EQUAL, 1, start_special, FORCE },
6340 { "kexec", EQUAL, 1, start_special },
6341 { "suspend", EQUAL, 1, start_special },
6342 { "hibernate", EQUAL, 1, start_special },
6343 { "hybrid-sleep", EQUAL, 1, start_special },
6344 { "default", EQUAL, 1, start_special },
6345 { "rescue", EQUAL, 1, start_special },
6346 { "emergency", EQUAL, 1, start_special },
6347 { "exit", EQUAL, 1, start_special },
6348 { "reset-failed", MORE, 1, reset_failed },
6349 { "enable", MORE, 2, enable_unit, NOBUS },
6350 { "disable", MORE, 2, enable_unit, NOBUS },
6351 { "is-enabled", MORE, 2, unit_is_enabled, NOBUS },
6352 { "reenable", MORE, 2, enable_unit, NOBUS },
6353 { "preset", MORE, 2, enable_unit, NOBUS },
6354 { "mask", MORE, 2, enable_unit, NOBUS },
6355 { "unmask", MORE, 2, enable_unit, NOBUS },
6356 { "link", MORE, 2, enable_unit, NOBUS },
6357 { "switch-root", MORE, 2, switch_root },
6358 { "list-dependencies", LESS, 2, list_dependencies },
6359 { "set-default", EQUAL, 2, set_default, NOBUS },
6360 { "get-default", EQUAL, 1, get_default, NOBUS },
6361 { "set-property", MORE, 3, set_property },
6370 left = argc - optind;
6372 /* Special rule: no arguments (left == 0) means "list-units" */
6374 if (streq(argv[optind], "help") && !argv[optind+1]) {
6375 log_error("This command expects one or more "
6376 "unit names. Did you mean --help?");
6380 for (; verb->verb; verb++)
6381 if (streq(argv[optind], verb->verb))
6384 log_error("Unknown operation '%s'.", argv[optind]);
6389 switch (verb->argc_cmp) {
6392 if (left != verb->argc) {
6393 log_error("Invalid number of arguments.");
6400 if (left < verb->argc) {
6401 log_error("Too few arguments.");
6408 if (left > verb->argc) {
6409 log_error("Too many arguments.");
6416 assert_not_reached("Unknown comparison operator.");
6419 /* Require a bus connection for all operations but
6421 if (verb->bus == NOBUS) {
6422 if (!bus && !avoid_bus()) {
6423 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6428 if (running_in_chroot() > 0) {
6429 log_info("Running in chroot, ignoring request.");
6433 if ((verb->bus != FORCE || arg_force <= 0) && !bus) {
6434 log_error("Failed to get D-Bus connection: %s", strerror(-bus_error));
6439 return verb->dispatch(bus, argv + optind);
6442 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
6444 struct sd_shutdown_command c = {
6451 union sockaddr_union sockaddr = {
6452 .un.sun_family = AF_UNIX,
6453 .un.sun_path = "/run/systemd/shutdownd",
6456 struct iovec iovec[2] = {{
6457 .iov_base = (char*) &c,
6458 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
6461 struct msghdr msghdr = {
6462 .msg_name = &sockaddr,
6463 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
6464 + strlen("/run/systemd/shutdownd"),
6469 _cleanup_close_ int fd;
6471 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
6475 if (!isempty(message)) {
6476 iovec[1].iov_base = (char*) message;
6477 iovec[1].iov_len = strlen(message);
6478 msghdr.msg_iovlen++;
6481 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
6487 static int reload_with_fallback(sd_bus *bus) {
6490 /* First, try systemd via D-Bus. */
6491 if (daemon_reload(bus, NULL) >= 0)
6495 /* Nothing else worked, so let's try signals */
6496 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
6498 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
6499 log_error("kill() failed: %m");
6506 static int start_with_fallback(sd_bus *bus) {
6509 /* First, try systemd via D-Bus. */
6510 if (start_unit(bus, NULL) >= 0)
6514 /* Nothing else worked, so let's try
6516 if (talk_initctl() > 0)
6519 log_error("Failed to talk to init daemon.");
6523 warn_wall(arg_action);
6527 static int halt_now(enum action a) {
6529 /* Make sure C-A-D is handled by the kernel from this
6531 reboot(RB_ENABLE_CAD);
6536 log_info("Halting.");
6537 reboot(RB_HALT_SYSTEM);
6540 case ACTION_POWEROFF:
6541 log_info("Powering off.");
6542 reboot(RB_POWER_OFF);
6545 case ACTION_REBOOT: {
6546 _cleanup_free_ char *param = NULL;
6548 if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) {
6549 log_info("Rebooting with argument '%s'.", param);
6550 syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
6551 LINUX_REBOOT_CMD_RESTART2, param);
6554 log_info("Rebooting.");
6555 reboot(RB_AUTOBOOT);
6560 assert_not_reached("Unknown action.");
6564 static int halt_main(sd_bus *bus) {
6567 r = check_inhibitors(bus, arg_action);
6571 if (geteuid() != 0) {
6572 /* Try logind if we are a normal user and no special
6573 * mode applies. Maybe PolicyKit allows us to shutdown
6576 if (arg_when <= 0 &&
6579 (arg_action == ACTION_POWEROFF ||
6580 arg_action == ACTION_REBOOT)) {
6581 r = reboot_with_logind(bus, arg_action);
6586 log_error("Must be root.");
6591 _cleanup_free_ char *m;
6593 m = strv_join(arg_wall, " ");
6597 r = send_shutdownd(arg_when,
6598 arg_action == ACTION_HALT ? 'H' :
6599 arg_action == ACTION_POWEROFF ? 'P' :
6600 arg_action == ACTION_KEXEC ? 'K' :
6607 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6609 char date[FORMAT_TIMESTAMP_MAX];
6611 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6612 format_timestamp(date, sizeof(date), arg_when));
6617 if (!arg_dry && !arg_force)
6618 return start_with_fallback(bus);
6621 if (sd_booted() > 0)
6622 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6624 r = utmp_put_shutdown();
6626 log_warning("Failed to write utmp record: %s", strerror(-r));
6633 r = halt_now(arg_action);
6634 log_error("Failed to reboot: %s", strerror(-r));
6639 static int runlevel_main(void) {
6640 int r, runlevel, previous;
6642 r = utmp_get_runlevel(&runlevel, &previous);
6649 previous <= 0 ? 'N' : previous,
6650 runlevel <= 0 ? 'N' : runlevel);
6655 int main(int argc, char*argv[]) {
6656 _cleanup_bus_unref_ sd_bus *bus = NULL;
6659 setlocale(LC_ALL, "");
6660 log_parse_environment();
6663 /* Explicitly not on_tty() to avoid setting cached value.
6664 * This becomes relevant for piping output which might be
6666 original_stdout_is_tty = isatty(STDOUT_FILENO);
6668 r = parse_argv(argc, argv);
6672 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6673 * let's shortcut this */
6674 if (arg_action == ACTION_RUNLEVEL) {
6675 r = runlevel_main();
6679 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6680 log_info("Running in chroot, ignoring request.");
6686 r = bus_open_transport_systemd(arg_transport, arg_host, arg_scope != UNIT_FILE_SYSTEM, &bus);
6688 /* systemctl_main() will print an error message for the bus
6689 * connection, but only if it needs to */
6691 switch (arg_action) {
6693 case ACTION_SYSTEMCTL:
6694 r = systemctl_main(bus, argc, argv, r);
6698 case ACTION_POWEROFF:
6704 case ACTION_RUNLEVEL2:
6705 case ACTION_RUNLEVEL3:
6706 case ACTION_RUNLEVEL4:
6707 case ACTION_RUNLEVEL5:
6709 case ACTION_EMERGENCY:
6710 case ACTION_DEFAULT:
6711 r = start_with_fallback(bus);
6716 r = reload_with_fallback(bus);
6719 case ACTION_CANCEL_SHUTDOWN: {
6720 _cleanup_free_ char *m = NULL;
6723 m = strv_join(arg_wall, " ");
6730 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6732 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6736 case ACTION_RUNLEVEL:
6737 case _ACTION_INVALID:
6739 assert_not_reached("Unknown action");
6744 ask_password_agent_close();
6745 polkit_agent_close();
6747 strv_free(arg_types);
6748 strv_free(arg_states);
6749 strv_free(arg_properties);
6751 return r < 0 ? EXIT_FAILURE : r;