1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/reboot.h>
29 #include <sys/ioctl.h>
33 #include <sys/socket.h>
36 #include <sys/prctl.h>
37 #include <dbus/dbus.h>
39 #include <systemd/sd-daemon.h>
40 #include <systemd/sd-shutdown.h>
41 #include <systemd/sd-login.h>
47 #include "utmp-wtmp.h"
50 #include "path-util.h"
52 #include "dbus-common.h"
53 #include "cgroup-show.h"
54 #include "cgroup-util.h"
56 #include "path-lookup.h"
57 #include "conf-parser.h"
58 #include "exit-status.h"
59 #include "bus-errors.h"
61 #include "unit-name.h"
63 #include "spawn-ask-password-agent.h"
64 #include "spawn-polkit-agent.h"
66 #include "logs-show.h"
67 #include "path-util.h"
68 #include "socket-util.h"
71 static char **arg_types = NULL;
72 static char **arg_states = NULL;
73 static char **arg_properties = NULL;
74 static bool arg_all = false;
75 static bool original_stdout_is_tty;
76 static enum dependency {
81 } arg_dependency = DEPENDENCY_FORWARD;
82 static const char *arg_job_mode = "replace";
83 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
84 static bool arg_no_block = false;
85 static bool arg_no_legend = false;
86 static bool arg_no_pager = false;
87 static bool arg_no_wtmp = false;
88 static bool arg_no_wall = false;
89 static bool arg_no_reload = false;
90 static bool arg_show_types = false;
91 static bool arg_ignore_inhibitors = false;
92 static bool arg_dry = false;
93 static bool arg_quiet = false;
94 static bool arg_full = false;
95 static int arg_force = 0;
96 static bool arg_ask_password = true;
97 static bool arg_runtime = false;
98 static char **arg_wall = NULL;
99 static const char *arg_kill_who = NULL;
100 static int arg_signal = SIGTERM;
101 static const char *arg_root = NULL;
102 static usec_t arg_when = 0;
124 ACTION_CANCEL_SHUTDOWN,
126 } arg_action = ACTION_SYSTEMCTL;
127 static enum transport {
131 } arg_transport = TRANSPORT_NORMAL;
132 static char *arg_host = NULL;
133 static char *arg_user = NULL;
134 static unsigned arg_lines = 10;
135 static OutputMode arg_output = OUTPUT_SHORT;
136 static bool arg_plain = false;
138 static bool private_bus = false;
140 static int daemon_reload(DBusConnection *bus, char **args);
141 static void halt_now(enum action a);
143 static void pager_open_if_enabled(void) {
151 static void ask_password_agent_open_if_enabled(void) {
153 /* Open the password agent as a child process if necessary */
155 if (!arg_ask_password)
158 if (arg_scope != UNIT_FILE_SYSTEM)
161 ask_password_agent_open();
165 static void polkit_agent_open_if_enabled(void) {
167 /* Open the polkit agent as a child process if necessary */
169 if (!arg_ask_password)
172 if (arg_scope != UNIT_FILE_SYSTEM)
179 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
182 if (!dbus_error_is_set(error))
185 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
186 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
187 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
188 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
189 return EXIT_NOPERMISSION;
191 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
192 return EXIT_NOTINSTALLED;
194 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
195 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
196 return EXIT_NOTIMPLEMENTED;
198 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
199 return EXIT_NOTCONFIGURED;
207 static void warn_wall(enum action a) {
208 static const char *table[_ACTION_MAX] = {
209 [ACTION_HALT] = "The system is going down for system halt NOW!",
210 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
211 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
212 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
213 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
214 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
215 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
222 _cleanup_free_ char *p;
224 p = strv_join(arg_wall, " ");
239 utmp_wall(table[a], NULL);
242 static bool avoid_bus(void) {
244 if (running_in_chroot() > 0)
247 if (sd_booted() <= 0)
250 if (!isempty(arg_root))
253 if (arg_scope == UNIT_FILE_GLOBAL)
259 static int compare_unit_info(const void *a, const void *b) {
261 const struct unit_info *u = a, *v = b;
263 d1 = strrchr(u->id, '.');
264 d2 = strrchr(v->id, '.');
269 r = strcasecmp(d1, d2);
274 return strcasecmp(u->id, v->id);
277 static bool output_show_unit(const struct unit_info *u) {
280 if (!strv_isempty(arg_states))
281 return strv_contains(arg_states, u->load_state) || strv_contains(arg_states, u->sub_state) || strv_contains(arg_states, u->active_state);
283 return (!arg_types || ((dot = strrchr(u->id, '.')) &&
284 strv_find(arg_types, dot+1))) &&
285 (arg_all || !(streq(u->active_state, "inactive")
286 || u->following[0]) || u->job_id > 0);
289 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
290 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
291 const struct unit_info *u;
294 max_id_len = sizeof("UNIT")-1;
295 active_len = sizeof("ACTIVE")-1;
296 sub_len = sizeof("SUB")-1;
297 job_len = sizeof("JOB")-1;
300 for (u = unit_infos; u < unit_infos + c; u++) {
301 if (!output_show_unit(u))
304 max_id_len = MAX(max_id_len, strlen(u->id));
305 active_len = MAX(active_len, strlen(u->active_state));
306 sub_len = MAX(sub_len, strlen(u->sub_state));
307 if (u->job_id != 0) {
308 job_len = MAX(job_len, strlen(u->job_type));
313 if (!arg_full && original_stdout_is_tty) {
315 id_len = MIN(max_id_len, 25u);
316 basic_len = 5 + id_len + 5 + active_len + sub_len;
318 basic_len += job_len + 1;
319 if (basic_len < (unsigned) columns()) {
320 unsigned extra_len, incr;
321 extra_len = columns() - basic_len;
322 /* Either UNIT already got 25, or is fully satisfied.
323 * Grant up to 25 to DESC now. */
324 incr = MIN(extra_len, 25u);
327 /* split the remaining space between UNIT and DESC,
328 * but do not give UNIT more than it needs. */
330 incr = MIN(extra_len / 2, max_id_len - id_len);
332 desc_len += extra_len - incr;
338 for (u = unit_infos; u < unit_infos + c; u++) {
339 _cleanup_free_ char *e = NULL;
340 const char *on_loaded, *off_loaded, *on = "";
341 const char *on_active, *off_active, *off = "";
343 if (!output_show_unit(u))
346 if (!n_shown && !arg_no_legend) {
347 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
348 active_len, "ACTIVE", sub_len, "SUB");
350 printf("%-*s ", job_len, "JOB");
351 if (!arg_full && arg_no_pager)
352 printf("%.*s\n", desc_len, "DESCRIPTION");
354 printf("%s\n", "DESCRIPTION");
359 if (streq(u->load_state, "error") ||
360 streq(u->load_state, "not-found")) {
361 on_loaded = on = ansi_highlight_red();
362 off_loaded = off = ansi_highlight_off();
364 on_loaded = off_loaded = "";
366 if (streq(u->active_state, "failed")) {
367 on_active = on = ansi_highlight_red();
368 off_active = off = ansi_highlight_off();
370 on_active = off_active = "";
372 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
374 printf("%s%-*s%s %s%-6s%s %s%-*s %-*s%s %-*s",
375 on, id_len, e ? e : u->id, off,
376 on_loaded, u->load_state, off_loaded,
377 on_active, active_len, u->active_state,
378 sub_len, u->sub_state, off_active,
379 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
381 printf("%.*s\n", desc_len, u->description);
383 printf("%s\n", u->description);
386 if (!arg_no_legend) {
387 const char *on, *off;
390 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
391 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
392 "SUB = The low-level unit activation state, values depend on unit type.\n");
394 printf("JOB = Pending job for the unit.\n");
396 on = ansi_highlight();
397 off = ansi_highlight_off();
399 on = ansi_highlight_red();
400 off = ansi_highlight_off();
404 printf("%s%u loaded units listed.%s\n"
405 "To show all installed unit files use 'systemctl list-unit-files'.\n",
408 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
409 "To show all installed unit files use 'systemctl list-unit-files'.\n",
414 static int get_unit_list(
417 struct unit_info **unit_infos,
420 DBusMessageIter iter, sub;
428 r = bus_method_call_with_reply(
430 "org.freedesktop.systemd1",
431 "/org/freedesktop/systemd1",
432 "org.freedesktop.systemd1.Manager",
440 if (!dbus_message_iter_init(*reply, &iter) ||
441 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
442 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
443 log_error("Failed to parse reply.");
447 dbus_message_iter_recurse(&iter, &sub);
449 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
450 if (!GREEDY_REALLOC(*unit_infos, size, *c + 1))
453 bus_parse_unit_info(&sub, *unit_infos + *c);
456 dbus_message_iter_next(&sub);
462 static int list_units(DBusConnection *bus, char **args) {
463 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
464 _cleanup_free_ struct unit_info *unit_infos = NULL;
468 pager_open_if_enabled();
470 r = get_unit_list(bus, &reply, &unit_infos, &c);
474 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
476 output_units_list(unit_infos, c);
481 static int get_triggered_units(
483 const char* unit_path,
486 const char *interface = "org.freedesktop.systemd1.Unit",
487 *triggers_property = "Triggers";
488 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
489 DBusMessageIter iter, sub;
492 r = bus_method_call_with_reply(bus,
493 "org.freedesktop.systemd1",
495 "org.freedesktop.DBus.Properties",
499 DBUS_TYPE_STRING, &interface,
500 DBUS_TYPE_STRING, &triggers_property,
505 if (!dbus_message_iter_init(reply, &iter) ||
506 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
507 log_error("Failed to parse reply.");
511 dbus_message_iter_recurse(&iter, &sub);
512 dbus_message_iter_recurse(&sub, &iter);
515 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
518 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
519 log_error("Failed to parse reply.");
523 dbus_message_iter_get_basic(&sub, &unit);
524 r = strv_extend(triggered, unit);
528 dbus_message_iter_next(&sub);
534 static int get_listening(DBusConnection *bus, const char* unit_path,
535 char*** listen, unsigned *c)
537 const char *interface = "org.freedesktop.systemd1.Socket",
538 *listen_property = "Listen";
539 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
540 DBusMessageIter iter, sub;
543 r = bus_method_call_with_reply(bus,
544 "org.freedesktop.systemd1",
546 "org.freedesktop.DBus.Properties",
550 DBUS_TYPE_STRING, &interface,
551 DBUS_TYPE_STRING, &listen_property,
556 if (!dbus_message_iter_init(reply, &iter) ||
557 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
558 log_error("Failed to parse reply.");
562 dbus_message_iter_recurse(&iter, &sub);
563 dbus_message_iter_recurse(&sub, &iter);
566 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
567 DBusMessageIter sub2;
568 const char *type, *path;
570 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
571 log_error("Failed to parse reply.");
575 dbus_message_iter_recurse(&sub, &sub2);
577 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
578 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
579 r = strv_extend(listen, type);
583 r = strv_extend(listen, path);
590 dbus_message_iter_next(&sub);
602 /* Note: triggered is a list here, although it almost certainly
603 * will always be one unit. Nevertheless, dbus API allows for multiple
604 * values, so let's follow that.*/
607 /* The strv above is shared. free is set only in the first one. */
611 static int socket_info_compare(struct socket_info *a, struct socket_info *b) {
612 int o = strcmp(a->path, b->path);
614 o = strcmp(a->type, b->type);
618 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
619 struct socket_info *s;
620 unsigned pathlen = sizeof("LISTEN") - 1,
621 typelen = (sizeof("TYPE") - 1) * arg_show_types,
622 socklen = sizeof("UNIT") - 1,
623 servlen = sizeof("ACTIVATES") - 1;
624 const char *on, *off;
626 for (s = socket_infos; s < socket_infos + cs; s++) {
630 socklen = MAX(socklen, strlen(s->id));
632 typelen = MAX(typelen, strlen(s->type));
633 pathlen = MAX(pathlen, strlen(s->path));
635 STRV_FOREACH(a, s->triggered)
636 tmp += strlen(*a) + 2*(a != s->triggered);
637 servlen = MAX(servlen, tmp);
642 printf("%-*s %-*.*s%-*s %s\n",
644 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
648 for (s = socket_infos; s < socket_infos + cs; s++) {
652 printf("%-*s %-*s %-*s",
653 pathlen, s->path, typelen, s->type, socklen, s->id);
656 pathlen, s->path, socklen, s->id);
657 STRV_FOREACH(a, s->triggered)
659 a == s->triggered ? "" : ",", *a);
663 on = ansi_highlight();
664 off = ansi_highlight_off();
668 on = ansi_highlight_red();
669 off = ansi_highlight_off();
672 if (!arg_no_legend) {
673 printf("%s%u sockets listed.%s\n", on, cs, off);
675 printf("Pass --all to see loaded but inactive sockets, too.\n");
681 static int list_sockets(DBusConnection *bus, char **args) {
682 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
683 _cleanup_free_ struct unit_info *unit_infos = NULL;
684 struct socket_info *socket_infos = NULL;
685 const struct unit_info *u;
686 struct socket_info *s;
687 unsigned cu = 0, cs = 0;
691 pager_open_if_enabled();
693 r = get_unit_list(bus, &reply, &unit_infos, &cu);
697 for (u = unit_infos; u < unit_infos + cu; u++) {
699 _cleanup_strv_free_ char **listen = NULL, **triggered = NULL;
702 if (!output_show_unit(u))
705 if ((dot = strrchr(u->id, '.')) && !streq(dot+1, "socket"))
708 r = get_triggered_units(bus, u->unit_path, &triggered);
712 r = get_listening(bus, u->unit_path, &listen, &c);
716 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
721 for (i = 0; i < c; i++)
722 socket_infos[cs + i] = (struct socket_info) {
725 .path = listen[i*2 + 1],
726 .triggered = triggered,
727 .own_triggered = i==0,
730 /* from this point on we will cleanup those socket_infos */
733 listen = triggered = NULL; /* avoid cleanup */
736 qsort(socket_infos, cs, sizeof(struct socket_info),
737 (__compar_fn_t) socket_info_compare);
739 output_sockets_list(socket_infos, cs);
742 assert(cs == 0 || socket_infos);
743 for (s = socket_infos; s < socket_infos + cs; s++) {
746 if (s->own_triggered)
747 strv_free(s->triggered);
754 static int compare_unit_file_list(const void *a, const void *b) {
756 const UnitFileList *u = a, *v = b;
758 d1 = strrchr(u->path, '.');
759 d2 = strrchr(v->path, '.');
764 r = strcasecmp(d1, d2);
769 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
772 static bool output_show_unit_file(const UnitFileList *u) {
775 return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
778 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
779 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
780 const UnitFileList *u;
782 max_id_len = sizeof("UNIT FILE")-1;
783 state_cols = sizeof("STATE")-1;
784 for (u = units; u < units + c; u++) {
785 if (!output_show_unit_file(u))
788 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
789 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
794 id_cols = MIN(max_id_len, 25u);
795 basic_cols = 1 + id_cols + state_cols;
796 if (basic_cols < (unsigned) columns())
797 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
799 id_cols = max_id_len;
802 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
804 for (u = units; u < units + c; u++) {
805 _cleanup_free_ char *e = NULL;
806 const char *on, *off;
809 if (!output_show_unit_file(u))
814 if (u->state == UNIT_FILE_MASKED ||
815 u->state == UNIT_FILE_MASKED_RUNTIME ||
816 u->state == UNIT_FILE_DISABLED ||
817 u->state == UNIT_FILE_INVALID) {
818 on = ansi_highlight_red();
819 off = ansi_highlight_off();
820 } else if (u->state == UNIT_FILE_ENABLED) {
821 on = ansi_highlight_green();
822 off = ansi_highlight_off();
826 id = path_get_file_name(u->path);
828 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
830 printf("%-*s %s%-*s%s\n",
832 on, state_cols, unit_file_state_to_string(u->state), off);
836 printf("\n%u unit files listed.\n", n_shown);
839 static int list_unit_files(DBusConnection *bus, char **args) {
840 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
841 _cleanup_free_ UnitFileList *units = NULL;
842 DBusMessageIter iter, sub, sub2;
843 unsigned c = 0, n_units = 0;
846 pager_open_if_enabled();
853 h = hashmap_new(string_hash_func, string_compare_func);
857 r = unit_file_get_list(arg_scope, arg_root, h);
859 unit_file_list_free(h);
860 log_error("Failed to get unit file list: %s", strerror(-r));
864 n_units = hashmap_size(h);
865 units = new(UnitFileList, n_units);
867 unit_file_list_free(h);
871 HASHMAP_FOREACH(u, h, i) {
872 memcpy(units + c++, u, sizeof(UnitFileList));
878 r = bus_method_call_with_reply(
880 "org.freedesktop.systemd1",
881 "/org/freedesktop/systemd1",
882 "org.freedesktop.systemd1.Manager",
890 if (!dbus_message_iter_init(reply, &iter) ||
891 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
892 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
893 log_error("Failed to parse reply.");
897 dbus_message_iter_recurse(&iter, &sub);
899 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
903 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
908 n_units = MAX(2*c, 16u);
909 w = realloc(units, sizeof(struct UnitFileList) * n_units);
918 dbus_message_iter_recurse(&sub, &sub2);
920 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
921 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
922 log_error("Failed to parse reply.");
926 u->state = unit_file_state_from_string(state);
928 dbus_message_iter_next(&sub);
934 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
935 output_unit_file_list(units, c);
941 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
943 _cleanup_free_ char *n = NULL;
945 size_t max_len = MAX(columns(),20u);
948 for (i = level - 1; i >= 0; i--) {
950 if(len > max_len - 3 && !arg_full) {
951 printf("%s...\n",max_len % 2 ? "" : " ");
954 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
957 if(len > max_len - 3 && !arg_full) {
958 printf("%s...\n",max_len % 2 ? "" : " ");
961 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
965 printf("%s\n", name);
969 n = ellipsize(name, max_len-len, 100);
977 static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
978 static const char *dependencies[] = {
979 [DEPENDENCY_FORWARD] = "Requires\0"
980 "RequiresOverridable\0"
982 "RequisiteOverridable\0"
984 [DEPENDENCY_REVERSE] = "RequiredBy\0"
985 "RequiredByOverridable\0"
988 [DEPENDENCY_AFTER] = "After\0",
989 [DEPENDENCY_BEFORE] = "Before\0",
992 _cleanup_free_ char *path;
993 const char *interface = "org.freedesktop.systemd1.Unit";
995 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
996 DBusMessageIter iter, sub, sub2, sub3;
1005 path = unit_dbus_path_from_name(name);
1011 r = bus_method_call_with_reply(
1013 "org.freedesktop.systemd1",
1015 "org.freedesktop.DBus.Properties",
1019 DBUS_TYPE_STRING, &interface,
1024 if (!dbus_message_iter_init(reply, &iter) ||
1025 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1026 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
1027 log_error("Failed to parse reply.");
1032 dbus_message_iter_recurse(&iter, &sub);
1034 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1037 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
1038 dbus_message_iter_recurse(&sub, &sub2);
1040 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
1041 log_error("Failed to parse reply.");
1046 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
1047 log_error("Failed to parse reply.");
1052 dbus_message_iter_recurse(&sub2, &sub3);
1053 dbus_message_iter_next(&sub);
1055 assert(arg_dependency < ELEMENTSOF(dependencies));
1056 if (!nulstr_contains(dependencies[arg_dependency], prop))
1059 if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
1060 if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
1061 DBusMessageIter sub4;
1062 dbus_message_iter_recurse(&sub3, &sub4);
1064 while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
1067 assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
1068 dbus_message_iter_get_basic(&sub4, &s);
1070 r = strv_extend(&ret, s);
1076 dbus_message_iter_next(&sub4);
1089 static int list_dependencies_compare(const void *_a, const void *_b) {
1090 const char **a = (const char**) _a, **b = (const char**) _b;
1091 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1093 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1095 return strcasecmp(*a, *b);
1098 static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char ***units, unsigned int branches) {
1099 _cleanup_strv_free_ char **deps = NULL, **u;
1103 u = strv_append(*units, name);
1107 r = list_dependencies_get_dependencies(bus, name, &deps);
1111 qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1113 STRV_FOREACH(c, deps) {
1114 if (strv_contains(u, *c)) {
1116 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1123 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1127 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1128 r = list_dependencies_one(bus, *c, level + 1, &u, (branches << 1) | (c[1] == NULL ? 0 : 1));
1141 static int list_dependencies(DBusConnection *bus, char **args) {
1142 _cleanup_free_ char *unit = NULL;
1143 _cleanup_strv_free_ char **units = NULL;
1149 unit = unit_name_mangle(args[1]);
1154 u = SPECIAL_DEFAULT_TARGET;
1156 pager_open_if_enabled();
1160 return list_dependencies_one(bus, u, 0, &units, 0);
1163 static int get_default(DBusConnection *bus, char **args) {
1165 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1167 _cleanup_dbus_error_free_ DBusError error;
1169 dbus_error_init(&error);
1171 if (!bus || avoid_bus()) {
1172 r = unit_file_get_default(arg_scope, arg_root, &path);
1175 log_error("Operation failed: %s", strerror(-r));
1181 r = bus_method_call_with_reply(
1183 "org.freedesktop.systemd1",
1184 "/org/freedesktop/systemd1",
1185 "org.freedesktop.systemd1.Manager",
1192 log_error("Operation failed: %s", strerror(-r));
1196 if (!dbus_message_get_args(reply, &error,
1197 DBUS_TYPE_STRING, &path,
1198 DBUS_TYPE_INVALID)) {
1199 log_error("Failed to parse reply: %s", bus_error_message(&error));
1200 dbus_error_free(&error);
1206 printf("%s\n", path);
1209 if ((!bus || avoid_bus()) && path)
1218 char *name, *type, *state;
1221 static void list_jobs_print(struct job_info* jobs, size_t n) {
1224 const char *on, *off;
1225 bool shorten = false;
1227 assert(n == 0 || jobs);
1230 on = ansi_highlight_green();
1231 off = ansi_highlight_off();
1233 printf("%sNo jobs running.%s\n", on, off);
1237 pager_open_if_enabled();
1240 /* JOB UNIT TYPE STATE */
1241 unsigned l0 = 3, l1 = 4, l2 = 4, l3 = 5;
1243 for (i = 0, j = jobs; i < n; i++, j++) {
1244 assert(j->name && j->type && j->state);
1245 l0 = MAX(l0, DECIMAL_STR_WIDTH(j->id));
1246 l1 = MAX(l1, strlen(j->name));
1247 l2 = MAX(l2, strlen(j->type));
1248 l3 = MAX(l3, strlen(j->state));
1251 if (!arg_full && l0 + 1 + l1 + l2 + 1 + l3 > columns()) {
1252 l1 = MAX(33u, columns() - l0 - l2 - l3 - 3);
1257 printf("%*s %-*s %-*s %-*s\n",
1263 for (i = 0, j = jobs; i < n; i++, j++) {
1264 _cleanup_free_ char *e = NULL;
1266 if (streq(j->state, "running")) {
1267 on = ansi_highlight();
1268 off = ansi_highlight_off();
1272 e = shorten ? ellipsize(j->name, l1, 33) : NULL;
1273 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
1275 on, l1, e ? e : j->name, off,
1277 on, l3, j->state, off);
1281 on = ansi_highlight();
1282 off = ansi_highlight_off();
1285 printf("\n%s%zu jobs listed%s.\n", on, n, off);
1288 static int list_jobs(DBusConnection *bus, char **args) {
1289 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1290 DBusMessageIter iter, sub, sub2;
1292 struct job_info *jobs = NULL;
1293 size_t size = 0, used = 0;
1295 r = bus_method_call_with_reply(
1297 "org.freedesktop.systemd1",
1298 "/org/freedesktop/systemd1",
1299 "org.freedesktop.systemd1.Manager",
1307 if (!dbus_message_iter_init(reply, &iter) ||
1308 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1309 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1310 log_error("Failed to parse reply.");
1314 dbus_message_iter_recurse(&iter, &sub);
1316 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1317 const char *name, *type, *state, *job_path, *unit_path;
1320 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1321 log_error("Failed to parse reply.");
1325 dbus_message_iter_recurse(&sub, &sub2);
1327 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1328 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1329 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1330 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1331 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1332 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1333 log_error("Failed to parse reply.");
1338 if (!GREEDY_REALLOC(jobs, size, used + 1)) {
1343 jobs[used++] = (struct job_info) { id,
1347 if (!jobs[used-1].name || !jobs[used-1].type || !jobs[used-1].state) {
1352 dbus_message_iter_next(&sub);
1355 list_jobs_print(jobs, used);
1359 free(jobs[used].name);
1360 free(jobs[used].type);
1361 free(jobs[used].state);
1368 static int cancel_job(DBusConnection *bus, char **args) {
1373 if (strv_length(args) <= 1)
1374 return daemon_reload(bus, args);
1376 STRV_FOREACH(name, args+1) {
1380 r = safe_atou32(*name, &id);
1382 log_error("Failed to parse job id: %s", strerror(-r));
1386 r = bus_method_call_with_reply(
1388 "org.freedesktop.systemd1",
1389 "/org/freedesktop/systemd1",
1390 "org.freedesktop.systemd1.Manager",
1394 DBUS_TYPE_UINT32, &id,
1403 static int need_daemon_reload(DBusConnection *bus, const char *unit) {
1404 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1405 _cleanup_dbus_error_free_ DBusError error;
1406 dbus_bool_t b = FALSE;
1407 DBusMessageIter iter, sub;
1409 *interface = "org.freedesktop.systemd1.Unit",
1410 *property = "NeedDaemonReload",
1412 _cleanup_free_ char *n = NULL;
1415 dbus_error_init(&error);
1417 /* We ignore all errors here, since this is used to show a warning only */
1419 n = unit_name_mangle(unit);
1423 r = bus_method_call_with_reply(
1425 "org.freedesktop.systemd1",
1426 "/org/freedesktop/systemd1",
1427 "org.freedesktop.systemd1.Manager",
1431 DBUS_TYPE_STRING, &n,
1436 if (!dbus_message_get_args(reply, NULL,
1437 DBUS_TYPE_OBJECT_PATH, &path,
1441 dbus_message_unref(reply);
1444 r = bus_method_call_with_reply(
1446 "org.freedesktop.systemd1",
1448 "org.freedesktop.DBus.Properties",
1452 DBUS_TYPE_STRING, &interface,
1453 DBUS_TYPE_STRING, &property,
1458 if (!dbus_message_iter_init(reply, &iter) ||
1459 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1462 dbus_message_iter_recurse(&iter, &sub);
1463 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1466 dbus_message_iter_get_basic(&sub, &b);
1470 typedef struct WaitData {
1477 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1478 _cleanup_dbus_error_free_ DBusError error;
1481 dbus_error_init(&error);
1487 log_debug("Got D-Bus request: %s.%s() on %s",
1488 dbus_message_get_interface(message),
1489 dbus_message_get_member(message),
1490 dbus_message_get_path(message));
1492 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1493 log_error("Warning! D-Bus connection terminated.");
1494 dbus_connection_close(connection);
1496 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1498 const char *path, *result, *unit;
1501 if (dbus_message_get_args(message, &error,
1502 DBUS_TYPE_UINT32, &id,
1503 DBUS_TYPE_OBJECT_PATH, &path,
1504 DBUS_TYPE_STRING, &unit,
1505 DBUS_TYPE_STRING, &result,
1506 DBUS_TYPE_INVALID)) {
1508 r = set_remove(d->set, (char*) path);
1510 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1514 if (!isempty(result))
1515 d->result = strdup(result);
1518 d->name = strdup(unit);
1520 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1523 dbus_error_free(&error);
1524 if (dbus_message_get_args(message, &error,
1525 DBUS_TYPE_UINT32, &id,
1526 DBUS_TYPE_OBJECT_PATH, &path,
1527 DBUS_TYPE_STRING, &result,
1528 DBUS_TYPE_INVALID)) {
1529 /* Compatibility with older systemd versions <
1530 * 183 during upgrades. This should be dropped
1532 r = set_remove(d->set, (char*) path);
1534 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1539 d->result = strdup(result);
1541 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1545 log_error("Failed to parse message: %s", bus_error_message(&error));
1548 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1551 static int enable_wait_for_jobs(DBusConnection *bus) {
1559 dbus_error_init(&error);
1560 dbus_bus_add_match(bus,
1562 "sender='org.freedesktop.systemd1',"
1563 "interface='org.freedesktop.systemd1.Manager',"
1564 "member='JobRemoved',"
1565 "path='/org/freedesktop/systemd1'",
1568 if (dbus_error_is_set(&error)) {
1569 log_error("Failed to add match: %s", bus_error_message(&error));
1570 dbus_error_free(&error);
1574 /* This is slightly dirty, since we don't undo the match registrations. */
1578 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1580 WaitData d = { .set = s };
1585 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1588 while (!set_isempty(s)) {
1590 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1591 log_error("Disconnected from bus.");
1592 return -ECONNREFUSED;
1599 if (streq(d.result, "timeout"))
1600 log_error("Job for %s timed out.", strna(d.name));
1601 else if (streq(d.result, "canceled"))
1602 log_error("Job for %s canceled.", strna(d.name));
1603 else if (streq(d.result, "dependency"))
1604 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1605 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1606 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1609 if (streq_ptr(d.result, "timeout"))
1611 else if (streq_ptr(d.result, "canceled"))
1613 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1624 dbus_connection_remove_filter(bus, wait_filter, &d);
1628 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1629 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1630 _cleanup_free_ char *n = NULL;
1631 DBusMessageIter iter, sub;
1633 *interface = "org.freedesktop.systemd1.Unit",
1634 *property = "ActiveState";
1635 const char *state, *path;
1641 dbus_error_init(&error);
1643 n = unit_name_mangle(name);
1647 r = bus_method_call_with_reply (
1649 "org.freedesktop.systemd1",
1650 "/org/freedesktop/systemd1",
1651 "org.freedesktop.systemd1.Manager",
1655 DBUS_TYPE_STRING, &n,
1658 dbus_error_free(&error);
1665 if (!dbus_message_get_args(reply, NULL,
1666 DBUS_TYPE_OBJECT_PATH, &path,
1667 DBUS_TYPE_INVALID)) {
1668 log_error("Failed to parse reply.");
1672 dbus_message_unref(reply);
1675 r = bus_method_call_with_reply(
1677 "org.freedesktop.systemd1",
1679 "org.freedesktop.DBus.Properties",
1683 DBUS_TYPE_STRING, &interface,
1684 DBUS_TYPE_STRING, &property,
1692 if (!dbus_message_iter_init(reply, &iter) ||
1693 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1694 log_error("Failed to parse reply.");
1698 dbus_message_iter_recurse(&iter, &sub);
1700 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1701 log_error("Failed to parse reply.");
1705 dbus_message_iter_get_basic(&sub, &state);
1710 return strv_find(check_states, state) ? 1 : 0;
1713 static void check_triggering_units(
1714 DBusConnection *bus,
1715 const char *unit_name) {
1717 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1718 DBusMessageIter iter, sub;
1719 const char *interface = "org.freedesktop.systemd1.Unit",
1720 *load_state_property = "LoadState",
1721 *triggered_by_property = "TriggeredBy",
1723 _cleanup_free_ char *unit_path = NULL, *n = NULL;
1724 bool print_warning_label = true;
1727 n = unit_name_mangle(unit_name);
1733 unit_path = unit_dbus_path_from_name(n);
1739 r = bus_method_call_with_reply(
1741 "org.freedesktop.systemd1",
1743 "org.freedesktop.DBus.Properties",
1747 DBUS_TYPE_STRING, &interface,
1748 DBUS_TYPE_STRING, &load_state_property,
1753 if (!dbus_message_iter_init(reply, &iter) ||
1754 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1755 log_error("Failed to parse reply.");
1759 dbus_message_iter_recurse(&iter, &sub);
1761 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1762 log_error("Failed to parse reply.");
1766 dbus_message_iter_get_basic(&sub, &state);
1768 if (streq(state, "masked"))
1771 dbus_message_unref(reply);
1774 r = bus_method_call_with_reply(
1776 "org.freedesktop.systemd1",
1778 "org.freedesktop.DBus.Properties",
1782 DBUS_TYPE_STRING, &interface,
1783 DBUS_TYPE_STRING, &triggered_by_property,
1788 if (!dbus_message_iter_init(reply, &iter) ||
1789 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1790 log_error("Failed to parse reply.");
1794 dbus_message_iter_recurse(&iter, &sub);
1795 dbus_message_iter_recurse(&sub, &iter);
1798 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1799 const char * const check_states[] = {
1804 const char *service_trigger;
1806 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1807 log_error("Failed to parse reply.");
1811 dbus_message_iter_get_basic(&sub, &service_trigger);
1813 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1817 if (print_warning_label) {
1818 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1819 print_warning_label = false;
1822 log_warning(" %s", service_trigger);
1825 dbus_message_iter_next(&sub);
1829 static int start_unit_one(
1830 DBusConnection *bus,
1837 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1838 _cleanup_free_ char *n;
1847 n = unit_name_mangle(name);
1851 r = bus_method_call_with_reply(
1853 "org.freedesktop.systemd1",
1854 "/org/freedesktop/systemd1",
1855 "org.freedesktop.systemd1.Manager",
1859 DBUS_TYPE_STRING, &n,
1860 DBUS_TYPE_STRING, &mode,
1863 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1864 /* There's always a fallback possible for
1865 * legacy actions. */
1868 log_error("Failed to issue method call: %s", bus_error_message(error));
1873 if (!dbus_message_get_args(reply, error,
1874 DBUS_TYPE_OBJECT_PATH, &path,
1875 DBUS_TYPE_INVALID)) {
1876 log_error("Failed to parse reply: %s", bus_error_message(error));
1880 if (need_daemon_reload(bus, n) > 0)
1881 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %sdaemon-reload' recommended.",
1882 n, arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
1891 r = set_consume(s, p);
1893 log_error("Failed to add path to set.");
1901 static const struct {
1905 } action_table[_ACTION_MAX] = {
1906 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
1907 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
1908 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
1909 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
1910 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
1911 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
1912 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
1913 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
1914 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
1915 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
1916 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
1917 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
1918 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
1919 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
1920 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1923 static enum action verb_to_action(const char *verb) {
1926 for (i = ACTION_INVALID; i < _ACTION_MAX; i++)
1927 if (action_table[i].verb && streq(verb, action_table[i].verb))
1929 return ACTION_INVALID;
1932 static int start_unit(DBusConnection *bus, char **args) {
1935 const char *method, *mode, *one_name;
1936 _cleanup_set_free_free_ Set *s = NULL;
1937 _cleanup_dbus_error_free_ DBusError error;
1940 dbus_error_init(&error);
1944 ask_password_agent_open_if_enabled();
1946 if (arg_action == ACTION_SYSTEMCTL) {
1949 streq(args[0], "stop") ||
1950 streq(args[0], "condstop") ? "StopUnit" :
1951 streq(args[0], "reload") ? "ReloadUnit" :
1952 streq(args[0], "restart") ? "RestartUnit" :
1954 streq(args[0], "try-restart") ||
1955 streq(args[0], "condrestart") ? "TryRestartUnit" :
1957 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1959 streq(args[0], "reload-or-try-restart") ||
1960 streq(args[0], "condreload") ||
1962 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1964 action = verb_to_action(args[0]);
1966 mode = streq(args[0], "isolate") ? "isolate" :
1967 action_table[action].mode ?: arg_job_mode;
1969 one_name = action_table[action].target;
1972 assert(arg_action < ELEMENTSOF(action_table));
1973 assert(action_table[arg_action].target);
1975 method = "StartUnit";
1977 mode = action_table[arg_action].mode;
1978 one_name = action_table[arg_action].target;
1981 if (!arg_no_block) {
1982 ret = enable_wait_for_jobs(bus);
1984 log_error("Could not watch jobs: %s", strerror(-ret));
1988 s = set_new(string_hash_func, string_compare_func);
1994 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1996 ret = translate_bus_error_to_exit_status(ret, &error);
1998 STRV_FOREACH(name, args+1) {
1999 r = start_unit_one(bus, method, *name, mode, &error, s);
2001 ret = translate_bus_error_to_exit_status(r, &error);
2002 dbus_error_free(&error);
2007 if (!arg_no_block) {
2008 r = wait_for_jobs(bus, s);
2012 /* When stopping units, warn if they can still be triggered by
2013 * another active unit (socket, path, timer) */
2014 if (!arg_quiet && streq(method, "StopUnit")) {
2016 check_triggering_units(bus, one_name);
2018 STRV_FOREACH(name, args+1)
2019 check_triggering_units(bus, *name);
2026 /* Ask systemd-logind, which might grant access to unprivileged users
2027 * through PolicyKit */
2028 static int reboot_with_logind(DBusConnection *bus, enum action a) {
2031 dbus_bool_t interactive = true;
2036 polkit_agent_open_if_enabled();
2044 case ACTION_POWEROFF:
2045 method = "PowerOff";
2048 case ACTION_SUSPEND:
2052 case ACTION_HIBERNATE:
2053 method = "Hibernate";
2056 case ACTION_HYBRID_SLEEP:
2057 method = "HybridSleep";
2064 return bus_method_call_with_reply(
2066 "org.freedesktop.login1",
2067 "/org/freedesktop/login1",
2068 "org.freedesktop.login1.Manager",
2072 DBUS_TYPE_BOOLEAN, &interactive,
2079 static int check_inhibitors(DBusConnection *bus, enum action a) {
2081 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2082 DBusMessageIter iter, sub, sub2;
2085 _cleanup_strv_free_ char **sessions = NULL;
2091 if (arg_ignore_inhibitors || arg_force > 0)
2103 r = bus_method_call_with_reply(
2105 "org.freedesktop.login1",
2106 "/org/freedesktop/login1",
2107 "org.freedesktop.login1.Manager",
2113 /* If logind is not around, then there are no inhibitors... */
2116 if (!dbus_message_iter_init(reply, &iter) ||
2117 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2118 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
2119 log_error("Failed to parse reply.");
2123 dbus_message_iter_recurse(&iter, &sub);
2124 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2125 const char *what, *who, *why, *mode;
2127 _cleanup_strv_free_ char **sv = NULL;
2128 _cleanup_free_ char *comm = NULL, *user = NULL;
2130 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
2131 log_error("Failed to parse reply.");
2135 dbus_message_iter_recurse(&sub, &sub2);
2137 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
2138 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
2139 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
2140 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
2141 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
2142 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
2143 log_error("Failed to parse reply.");
2147 if (!streq(mode, "block"))
2150 sv = strv_split(what, ":");
2154 if (!strv_contains(sv,
2156 a == ACTION_POWEROFF ||
2157 a == ACTION_REBOOT ||
2158 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2161 get_process_comm(pid, &comm);
2162 user = uid_to_name(uid);
2163 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2164 who, (unsigned long) pid, strna(comm), strna(user), why);
2168 dbus_message_iter_next(&sub);
2171 dbus_message_iter_recurse(&iter, &sub);
2173 /* Check for current sessions */
2174 sd_get_sessions(&sessions);
2175 STRV_FOREACH(s, sessions) {
2177 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2179 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2182 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2185 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2188 sd_session_get_tty(*s, &tty);
2189 sd_session_get_seat(*s, &seat);
2190 sd_session_get_service(*s, &service);
2191 user = uid_to_name(uid);
2193 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2200 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2201 action_table[a].verb);
2209 static int start_special(DBusConnection *bus, char **args) {
2215 a = verb_to_action(args[0]);
2217 r = check_inhibitors(bus, a);
2221 if (arg_force >= 2 && geteuid() != 0) {
2222 log_error("Must be root.");
2226 if (arg_force >= 2 &&
2227 (a == ACTION_HALT ||
2228 a == ACTION_POWEROFF ||
2229 a == ACTION_REBOOT))
2232 if (arg_force >= 1 &&
2233 (a == ACTION_HALT ||
2234 a == ACTION_POWEROFF ||
2235 a == ACTION_REBOOT ||
2236 a == ACTION_KEXEC ||
2238 return daemon_reload(bus, args);
2240 /* first try logind, to allow authentication with polkit */
2241 if (geteuid() != 0 &&
2242 (a == ACTION_POWEROFF ||
2243 a == ACTION_REBOOT ||
2244 a == ACTION_SUSPEND ||
2245 a == ACTION_HIBERNATE ||
2246 a == ACTION_HYBRID_SLEEP)) {
2247 r = reboot_with_logind(bus, a);
2252 r = start_unit(bus, args);
2253 if (r == EXIT_SUCCESS)
2259 static int check_unit_active(DBusConnection *bus, char **args) {
2260 const char * const check_states[] = {
2267 int r = 3; /* According to LSB: "program is not running" */
2272 STRV_FOREACH(name, args+1) {
2275 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2285 static int check_unit_failed(DBusConnection *bus, char **args) {
2286 const char * const check_states[] = {
2297 STRV_FOREACH(name, args+1) {
2300 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2310 static int kill_unit(DBusConnection *bus, char **args) {
2318 arg_kill_who = "all";
2320 STRV_FOREACH(name, args+1) {
2321 _cleanup_free_ char *n = NULL;
2323 n = unit_name_mangle(*name);
2327 r = bus_method_call_with_reply(
2329 "org.freedesktop.systemd1",
2330 "/org/freedesktop/systemd1",
2331 "org.freedesktop.systemd1.Manager",
2335 DBUS_TYPE_STRING, &n,
2336 DBUS_TYPE_STRING, &arg_kill_who,
2337 DBUS_TYPE_INT32, &arg_signal,
2345 typedef struct ExecStatusInfo {
2353 usec_t start_timestamp;
2354 usec_t exit_timestamp;
2359 LIST_FIELDS(struct ExecStatusInfo, exec);
2362 static void exec_status_info_free(ExecStatusInfo *i) {
2371 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2372 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2373 DBusMessageIter sub2, sub3;
2377 int32_t code, status;
2383 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2386 dbus_message_iter_recurse(sub, &sub2);
2388 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2391 i->path = strdup(path);
2395 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2396 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2400 dbus_message_iter_recurse(&sub2, &sub3);
2401 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2402 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2403 dbus_message_iter_next(&sub3);
2407 i->argv = new0(char*, n+1);
2412 dbus_message_iter_recurse(&sub2, &sub3);
2413 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2416 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2417 dbus_message_iter_get_basic(&sub3, &s);
2418 dbus_message_iter_next(&sub3);
2420 i->argv[n] = strdup(s);
2427 if (!dbus_message_iter_next(&sub2) ||
2428 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2429 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2430 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2431 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2432 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2433 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2434 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2435 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2439 i->start_timestamp = (usec_t) start_timestamp;
2440 i->exit_timestamp = (usec_t) exit_timestamp;
2441 i->pid = (pid_t) pid;
2448 typedef struct UnitStatusInfo {
2450 const char *load_state;
2451 const char *active_state;
2452 const char *sub_state;
2453 const char *unit_file_state;
2455 const char *description;
2456 const char *following;
2458 char **documentation;
2460 const char *fragment_path;
2461 const char *source_path;
2462 const char *control_group;
2464 char **dropin_paths;
2466 const char *load_error;
2469 usec_t inactive_exit_timestamp;
2470 usec_t inactive_exit_timestamp_monotonic;
2471 usec_t active_enter_timestamp;
2472 usec_t active_exit_timestamp;
2473 usec_t inactive_enter_timestamp;
2475 bool need_daemon_reload;
2480 const char *status_text;
2481 const char *pid_file;
2484 usec_t start_timestamp;
2485 usec_t exit_timestamp;
2487 int exit_code, exit_status;
2489 usec_t condition_timestamp;
2490 bool condition_result;
2491 bool failed_condition_trigger;
2492 bool failed_condition_negate;
2493 const char *failed_condition;
2494 const char *failed_condition_param;
2497 unsigned n_accepted;
2498 unsigned n_connections;
2501 /* Pairs of type, path */
2505 const char *sysfs_path;
2507 /* Mount, Automount */
2513 LIST_HEAD(ExecStatusInfo, exec);
2516 static void print_status_info(UnitStatusInfo *i,
2519 const char *on, *off, *ss;
2521 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2522 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2525 arg_all * OUTPUT_SHOW_ALL |
2526 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2527 on_tty() * OUTPUT_COLOR |
2528 !arg_quiet * OUTPUT_WARN_CUTOFF |
2529 arg_full * OUTPUT_FULL_WIDTH;
2534 /* This shows pretty information about a unit. See
2535 * print_property() for a low-level property printer */
2537 printf("%s", strna(i->id));
2539 if (i->description && !streq_ptr(i->id, i->description))
2540 printf(" - %s", i->description);
2545 printf(" Follow: unit currently follows state of %s\n", i->following);
2547 if (streq_ptr(i->load_state, "error")) {
2548 on = ansi_highlight_red();
2549 off = ansi_highlight_off();
2553 path = i->source_path ? i->source_path : i->fragment_path;
2556 printf(" Loaded: %s%s%s (Reason: %s)\n",
2557 on, strna(i->load_state), off, i->load_error);
2558 else if (path && i->unit_file_state)
2559 printf(" Loaded: %s%s%s (%s; %s)\n",
2560 on, strna(i->load_state), off, path, i->unit_file_state);
2562 printf(" Loaded: %s%s%s (%s)\n",
2563 on, strna(i->load_state), off, path);
2565 printf(" Loaded: %s%s%s\n",
2566 on, strna(i->load_state), off);
2568 if (!strv_isempty(i->dropin_paths)) {
2573 STRV_FOREACH(dropin, i->dropin_paths) {
2574 if (! dir || last) {
2575 printf(dir ? " " : " Drop-In: ");
2579 if (path_get_parent(*dropin, &dir) < 0) {
2584 printf("%s\n %s", dir,
2585 draw_special_char(DRAW_TREE_RIGHT));
2588 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
2590 printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", ");
2596 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2598 if (streq_ptr(i->active_state, "failed")) {
2599 on = ansi_highlight_red();
2600 off = ansi_highlight_off();
2601 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2602 on = ansi_highlight_green();
2603 off = ansi_highlight_off();
2608 printf(" Active: %s%s (%s)%s",
2609 on, strna(i->active_state), ss, off);
2611 printf(" Active: %s%s%s",
2612 on, strna(i->active_state), off);
2614 if (!isempty(i->result) && !streq(i->result, "success"))
2615 printf(" (Result: %s)", i->result);
2617 timestamp = (streq_ptr(i->active_state, "active") ||
2618 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2619 (streq_ptr(i->active_state, "inactive") ||
2620 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2621 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2622 i->active_exit_timestamp;
2624 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2625 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2628 printf(" since %s; %s\n", s2, s1);
2630 printf(" since %s\n", s2);
2634 if (!i->condition_result && i->condition_timestamp > 0) {
2635 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2636 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2638 printf(" start condition failed at %s%s%s\n",
2639 s2, s1 ? "; " : "", s1 ? s1 : "");
2640 if (i->failed_condition_trigger)
2641 printf(" none of the trigger conditions were met\n");
2642 else if (i->failed_condition)
2643 printf(" %s=%s%s was not met\n",
2644 i->failed_condition,
2645 i->failed_condition_negate ? "!" : "",
2646 i->failed_condition_param);
2650 printf(" Device: %s\n", i->sysfs_path);
2652 printf(" Where: %s\n", i->where);
2654 printf(" What: %s\n", i->what);
2656 STRV_FOREACH(t, i->documentation)
2657 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
2659 STRV_FOREACH_PAIR(t, t2, i->listen)
2660 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
2663 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2665 LIST_FOREACH(exec, p, i->exec) {
2666 _cleanup_free_ char *argv = NULL;
2669 /* Only show exited processes here */
2673 argv = strv_join(p->argv, " ");
2674 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
2676 good = is_clean_exit_lsb(p->code, p->status, NULL);
2678 on = ansi_highlight_red();
2679 off = ansi_highlight_off();
2683 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2685 if (p->code == CLD_EXITED) {
2688 printf("status=%i", p->status);
2690 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2695 printf("signal=%s", signal_to_string(p->status));
2697 printf(")%s\n", off);
2699 if (i->main_pid == p->pid &&
2700 i->start_timestamp == p->start_timestamp &&
2701 i->exit_timestamp == p->start_timestamp)
2702 /* Let's not show this twice */
2705 if (p->pid == i->control_pid)
2709 if (i->main_pid > 0 || i->control_pid > 0) {
2710 if (i->main_pid > 0) {
2711 printf(" Main PID: %u", (unsigned) i->main_pid);
2714 _cleanup_free_ char *comm = NULL;
2715 get_process_comm(i->main_pid, &comm);
2717 printf(" (%s)", comm);
2718 } else if (i->exit_code > 0) {
2719 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2721 if (i->exit_code == CLD_EXITED) {
2724 printf("status=%i", i->exit_status);
2726 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2731 printf("signal=%s", signal_to_string(i->exit_status));
2735 if (i->control_pid > 0)
2739 if (i->control_pid > 0) {
2740 _cleanup_free_ char *c = NULL;
2742 printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
2744 get_process_comm(i->control_pid, &c);
2753 printf(" Status: \"%s\"\n", i->status_text);
2755 if (i->control_group &&
2756 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0)) {
2759 printf(" CGroup: %s\n", i->control_group);
2761 if (arg_transport != TRANSPORT_SSH) {
2764 char prefix[] = " ";
2767 if (c > sizeof(prefix) - 1)
2768 c -= sizeof(prefix) - 1;
2772 if (i->main_pid > 0)
2773 extra[k++] = i->main_pid;
2775 if (i->control_pid > 0)
2776 extra[k++] = i->control_pid;
2778 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix,
2779 c, false, extra, k, flags);
2783 if (i->id && arg_transport != TRANSPORT_SSH) {
2785 show_journal_by_unit(stdout,
2789 i->inactive_exit_timestamp_monotonic,
2793 arg_scope == UNIT_FILE_SYSTEM,
2797 if (i->need_daemon_reload)
2798 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
2799 ansi_highlight_red(),
2800 ansi_highlight_off(),
2801 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
2804 static void show_unit_help(UnitStatusInfo *i) {
2809 if (!i->documentation) {
2810 log_info("Documentation for %s not known.", i->id);
2814 STRV_FOREACH(p, i->documentation) {
2816 if (startswith(*p, "man:")) {
2819 _cleanup_free_ char *page = NULL, *section = NULL;
2820 const char *args[4] = { "man", NULL, NULL, NULL };
2825 if ((*p)[k-1] == ')')
2826 e = strrchr(*p, '(');
2829 page = strndup((*p) + 4, e - *p - 4);
2830 section = strndup(e + 1, *p + k - e - 2);
2831 if (!page || !section) {
2843 log_error("Failed to fork: %m");
2849 execvp(args[0], (char**) args);
2850 log_error("Failed to execute man: %m");
2851 _exit(EXIT_FAILURE);
2854 wait_for_terminate(pid, NULL);
2856 log_info("Can't show: %s", *p);
2860 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2866 switch (dbus_message_iter_get_arg_type(iter)) {
2868 case DBUS_TYPE_STRING: {
2871 dbus_message_iter_get_basic(iter, &s);
2874 if (streq(name, "Id"))
2876 else if (streq(name, "LoadState"))
2878 else if (streq(name, "ActiveState"))
2879 i->active_state = s;
2880 else if (streq(name, "SubState"))
2882 else if (streq(name, "Description"))
2884 else if (streq(name, "FragmentPath"))
2885 i->fragment_path = s;
2886 else if (streq(name, "SourcePath"))
2889 else if (streq(name, "DefaultControlGroup")) {
2891 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
2893 i->control_group = e;
2896 else if (streq(name, "ControlGroup"))
2897 i->control_group = s;
2898 else if (streq(name, "StatusText"))
2900 else if (streq(name, "PIDFile"))
2902 else if (streq(name, "SysFSPath"))
2904 else if (streq(name, "Where"))
2906 else if (streq(name, "What"))
2908 else if (streq(name, "Following"))
2910 else if (streq(name, "UnitFileState"))
2911 i->unit_file_state = s;
2912 else if (streq(name, "Result"))
2919 case DBUS_TYPE_BOOLEAN: {
2922 dbus_message_iter_get_basic(iter, &b);
2924 if (streq(name, "Accept"))
2926 else if (streq(name, "NeedDaemonReload"))
2927 i->need_daemon_reload = b;
2928 else if (streq(name, "ConditionResult"))
2929 i->condition_result = b;
2934 case DBUS_TYPE_UINT32: {
2937 dbus_message_iter_get_basic(iter, &u);
2939 if (streq(name, "MainPID")) {
2941 i->main_pid = (pid_t) u;
2944 } else if (streq(name, "ControlPID"))
2945 i->control_pid = (pid_t) u;
2946 else if (streq(name, "ExecMainPID")) {
2948 i->main_pid = (pid_t) u;
2949 } else if (streq(name, "NAccepted"))
2951 else if (streq(name, "NConnections"))
2952 i->n_connections = u;
2957 case DBUS_TYPE_INT32: {
2960 dbus_message_iter_get_basic(iter, &j);
2962 if (streq(name, "ExecMainCode"))
2963 i->exit_code = (int) j;
2964 else if (streq(name, "ExecMainStatus"))
2965 i->exit_status = (int) j;
2970 case DBUS_TYPE_UINT64: {
2973 dbus_message_iter_get_basic(iter, &u);
2975 if (streq(name, "ExecMainStartTimestamp"))
2976 i->start_timestamp = (usec_t) u;
2977 else if (streq(name, "ExecMainExitTimestamp"))
2978 i->exit_timestamp = (usec_t) u;
2979 else if (streq(name, "ActiveEnterTimestamp"))
2980 i->active_enter_timestamp = (usec_t) u;
2981 else if (streq(name, "InactiveEnterTimestamp"))
2982 i->inactive_enter_timestamp = (usec_t) u;
2983 else if (streq(name, "InactiveExitTimestamp"))
2984 i->inactive_exit_timestamp = (usec_t) u;
2985 else if (streq(name, "InactiveExitTimestampMonotonic"))
2986 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2987 else if (streq(name, "ActiveExitTimestamp"))
2988 i->active_exit_timestamp = (usec_t) u;
2989 else if (streq(name, "ConditionTimestamp"))
2990 i->condition_timestamp = (usec_t) u;
2995 case DBUS_TYPE_ARRAY: {
2997 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2998 startswith(name, "Exec")) {
2999 DBusMessageIter sub;
3001 dbus_message_iter_recurse(iter, &sub);
3002 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3003 ExecStatusInfo *info;
3006 info = new0(ExecStatusInfo, 1);
3010 info->name = strdup(name);
3016 r = exec_status_info_deserialize(&sub, info);
3022 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
3024 dbus_message_iter_next(&sub);
3027 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3028 streq(name, "Listen")) {
3029 DBusMessageIter sub, sub2;
3031 dbus_message_iter_recurse(iter, &sub);
3032 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3033 const char *type, *path;
3035 dbus_message_iter_recurse(&sub, &sub2);
3037 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3038 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
3041 r = strv_extend(&i->listen, type);
3044 r = strv_extend(&i->listen, path);
3049 dbus_message_iter_next(&sub);
3054 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3055 streq(name, "DropInPaths")) {
3056 int r = bus_parse_strv_iter(iter, &i->dropin_paths);
3060 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3061 streq(name, "Documentation")) {
3063 DBusMessageIter sub;
3065 dbus_message_iter_recurse(iter, &sub);
3066 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
3070 dbus_message_iter_get_basic(&sub, &s);
3072 r = strv_extend(&i->documentation, s);
3076 dbus_message_iter_next(&sub);
3079 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3080 streq(name, "Conditions")) {
3081 DBusMessageIter sub, sub2;
3083 dbus_message_iter_recurse(iter, &sub);
3084 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3085 const char *cond, *param;
3086 dbus_bool_t trigger, negate;
3089 dbus_message_iter_recurse(&sub, &sub2);
3092 if(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &cond, true) >= 0 &&
3093 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &trigger, true) >= 0 &&
3094 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &negate, true) >= 0 &&
3095 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, ¶m, true) >= 0 &&
3096 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &state, false) >= 0) {
3097 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3098 if (state < 0 && (!trigger || !i->failed_condition)) {
3099 i->failed_condition = cond;
3100 i->failed_condition_trigger = trigger;
3101 i->failed_condition_negate = negate;
3102 i->failed_condition_param = param;
3106 dbus_message_iter_next(&sub);
3113 case DBUS_TYPE_STRUCT: {
3115 if (streq(name, "LoadError")) {
3116 DBusMessageIter sub;
3117 const char *n, *message;
3120 dbus_message_iter_recurse(iter, &sub);
3122 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
3126 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
3130 if (!isempty(message))
3131 i->load_error = message;
3141 static int print_property(const char *name, DBusMessageIter *iter) {
3145 /* This is a low-level property printer, see
3146 * print_status_info() for the nicer output */
3148 if (arg_properties && !strv_find(arg_properties, name))
3151 switch (dbus_message_iter_get_arg_type(iter)) {
3153 case DBUS_TYPE_STRUCT: {
3154 DBusMessageIter sub;
3155 dbus_message_iter_recurse(iter, &sub);
3157 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
3160 dbus_message_iter_get_basic(&sub, &u);
3163 printf("%s=%u\n", name, (unsigned) u);
3165 printf("%s=\n", name);
3168 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
3171 dbus_message_iter_get_basic(&sub, &s);
3173 if (arg_all || s[0])
3174 printf("%s=%s\n", name, s);
3177 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
3178 const char *a = NULL, *b = NULL;
3180 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
3181 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
3183 if (arg_all || !isempty(a) || !isempty(b))
3184 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3192 case DBUS_TYPE_ARRAY:
3194 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
3195 DBusMessageIter sub, sub2;
3197 dbus_message_iter_recurse(iter, &sub);
3198 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3202 dbus_message_iter_recurse(&sub, &sub2);
3204 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3205 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3206 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3208 dbus_message_iter_next(&sub);
3213 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3214 DBusMessageIter sub, sub2;
3216 dbus_message_iter_recurse(iter, &sub);
3218 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3219 const char *type, *path;
3221 dbus_message_iter_recurse(&sub, &sub2);
3223 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3224 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3225 printf("%s=%s\n", type, path);
3227 dbus_message_iter_next(&sub);
3232 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3233 DBusMessageIter sub, sub2;
3235 dbus_message_iter_recurse(iter, &sub);
3236 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3237 const char *type, *path;
3239 dbus_message_iter_recurse(&sub, &sub2);
3241 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3242 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3243 printf("Listen%s=%s\n", type, path);
3245 dbus_message_iter_next(&sub);
3250 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3251 DBusMessageIter sub, sub2;
3253 dbus_message_iter_recurse(iter, &sub);
3254 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3256 uint64_t value, next_elapse;
3258 dbus_message_iter_recurse(&sub, &sub2);
3260 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3261 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3262 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3263 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3265 printf("%s={ value=%s ; next_elapse=%s }\n",
3267 format_timespan(timespan1, sizeof(timespan1), value, 0),
3268 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3271 dbus_message_iter_next(&sub);
3276 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3277 DBusMessageIter sub;
3279 dbus_message_iter_recurse(iter, &sub);
3280 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3281 ExecStatusInfo info = {};
3283 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3284 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3285 _cleanup_free_ char *t;
3287 t = strv_join(info.argv, " ");
3289 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3293 yes_no(info.ignore),
3294 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3295 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3296 (unsigned) info. pid,
3297 sigchld_code_to_string(info.code),
3299 info.code == CLD_EXITED ? "" : "/",
3300 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3304 strv_free(info.argv);
3306 dbus_message_iter_next(&sub);
3311 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "DeviceAllow")) {
3312 DBusMessageIter sub, sub2;
3314 dbus_message_iter_recurse(iter, &sub);
3315 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3316 const char *path, *rwm;
3318 dbus_message_iter_recurse(&sub, &sub2);
3320 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3321 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &rwm, false) >= 0)
3322 printf("%s=%s %s\n", name, strna(path), strna(rwm));
3324 dbus_message_iter_next(&sub);
3328 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "BlockIODeviceWeight")) {
3329 DBusMessageIter sub, sub2;
3331 dbus_message_iter_recurse(iter, &sub);
3332 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3336 dbus_message_iter_recurse(&sub, &sub2);
3338 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3339 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &weight, false) >= 0)
3340 printf("%s=%s %" PRIu64 "\n", name, strna(path), weight);
3342 dbus_message_iter_next(&sub);
3346 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
3347 DBusMessageIter sub, sub2;
3349 dbus_message_iter_recurse(iter, &sub);
3350 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3354 dbus_message_iter_recurse(&sub, &sub2);
3356 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3357 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &bandwidth, false) >= 0)
3358 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
3360 dbus_message_iter_next(&sub);
3369 if (generic_print_property(name, iter, arg_all) > 0)
3373 printf("%s=[unprintable]\n", name);
3378 static int show_one(const char *verb,
3379 DBusConnection *bus,
3381 bool show_properties,
3384 _cleanup_free_ DBusMessage *reply = NULL;
3385 const char *interface = "";
3387 DBusMessageIter iter, sub, sub2, sub3;
3388 UnitStatusInfo info = {};
3394 r = bus_method_call_with_reply(
3396 "org.freedesktop.systemd1",
3398 "org.freedesktop.DBus.Properties",
3402 DBUS_TYPE_STRING, &interface,
3407 if (!dbus_message_iter_init(reply, &iter) ||
3408 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3409 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3410 log_error("Failed to parse reply.");
3414 dbus_message_iter_recurse(&iter, &sub);
3421 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3424 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3425 dbus_message_iter_recurse(&sub, &sub2);
3427 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3428 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3429 log_error("Failed to parse reply.");
3433 dbus_message_iter_recurse(&sub2, &sub3);
3435 if (show_properties)
3436 r = print_property(name, &sub3);
3438 r = status_property(name, &sub3, &info);
3440 log_error("Failed to parse reply.");
3444 dbus_message_iter_next(&sub);
3449 if (!show_properties) {
3450 if (streq(verb, "help"))
3451 show_unit_help(&info);
3453 print_status_info(&info, ellipsized);
3456 strv_free(info.documentation);
3457 strv_free(info.dropin_paths);
3458 strv_free(info.listen);
3460 if (!streq_ptr(info.active_state, "active") &&
3461 !streq_ptr(info.active_state, "reloading") &&
3462 streq(verb, "status")) {
3463 /* According to LSB: "program not running" */
3464 /* 0: program is running or service is OK
3465 * 1: program is dead and /var/run pid file exists
3466 * 2: program is dead and /var/lock lock file exists
3467 * 3: program is not running
3468 * 4: program or service status is unknown
3470 if (info.pid_file && access(info.pid_file, F_OK) == 0)
3476 while ((p = info.exec)) {
3477 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3478 exec_status_info_free(p);
3484 static int show_one_by_pid(const char *verb,
3485 DBusConnection *bus,
3489 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3490 const char *path = NULL;
3491 _cleanup_dbus_error_free_ DBusError error;
3494 dbus_error_init(&error);
3496 r = bus_method_call_with_reply(
3498 "org.freedesktop.systemd1",
3499 "/org/freedesktop/systemd1",
3500 "org.freedesktop.systemd1.Manager",
3504 DBUS_TYPE_UINT32, &pid,
3509 if (!dbus_message_get_args(reply, &error,
3510 DBUS_TYPE_OBJECT_PATH, &path,
3511 DBUS_TYPE_INVALID)) {
3512 log_error("Failed to parse reply: %s", bus_error_message(&error));
3516 r = show_one(verb, bus, path, false, new_line, ellipsized);
3520 static int show_all(const char* verb,
3521 DBusConnection *bus,
3522 bool show_properties,
3525 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3526 _cleanup_free_ struct unit_info *unit_infos = NULL;
3528 const struct unit_info *u;
3531 r = get_unit_list(bus, &reply, &unit_infos, &c);
3535 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
3537 for (u = unit_infos; u < unit_infos + c; u++) {
3538 _cleanup_free_ char *p = NULL;
3540 if (!output_show_unit(u))
3543 p = unit_dbus_path_from_name(u->id);
3547 printf("%s -> '%s'\n", u->id, p);
3549 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
3557 static int show(DBusConnection *bus, char **args) {
3559 bool show_properties, show_status, new_line = false;
3561 bool ellipsized = false;
3566 show_properties = streq(args[0], "show");
3567 show_status = streq(args[0], "status");
3569 if (show_properties)
3570 pager_open_if_enabled();
3572 /* If no argument is specified inspect the manager itself */
3574 if (show_properties && strv_length(args) <= 1)
3575 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
3577 if (show_status && strv_length(args) <= 1)
3578 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
3580 STRV_FOREACH(name, args+1) {
3583 if (safe_atou32(*name, &id) < 0) {
3584 _cleanup_free_ char *p = NULL, *n = NULL;
3585 /* Interpret as unit name */
3587 n = unit_name_mangle(*name);
3591 p = unit_dbus_path_from_name(n);
3595 r = show_one(args[0], bus, p, show_properties, &new_line, &ellipsized);
3599 } else if (show_properties) {
3600 _cleanup_free_ char *p = NULL;
3602 /* Interpret as job id */
3603 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3606 r = show_one(args[0], bus, p, show_properties, &new_line, &ellipsized);
3611 /* Interpret as PID */
3612 r = show_one_by_pid(args[0], bus, id, &new_line, &ellipsized);
3618 if (ellipsized && !arg_quiet)
3619 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
3624 static int append_assignment(DBusMessageIter *iter, const char *assignment) {
3627 DBusMessageIter sub;
3633 eq = strchr(assignment, '=');
3635 log_error("Not an assignment: %s", assignment);
3639 field = strndupa(assignment, eq - assignment);
3642 if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &field))
3645 if (streq(field, "CPUAccounting") ||
3646 streq(field, "MemoryAccounting") ||
3647 streq(field, "BlockIOAccounting")) {
3650 r = parse_boolean(eq);
3652 log_error("Failed to parse boolean assignment %s.", assignment);
3657 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "b", &sub) ||
3658 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &b))
3661 } else if (streq(field, "MemoryLimit")) {
3665 r = parse_bytes(eq, &bytes);
3667 log_error("Failed to parse bytes specification %s", assignment);
3672 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
3673 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
3676 } else if (streq(field, "CPUShares") || streq(field, "BlockIOWeight")) {
3679 r = safe_atou64(eq, &u);
3681 log_error("Failed to parse %s value %s.", field, eq);
3685 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
3686 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
3689 } else if (streq(field, "DevicePolicy")) {
3691 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "s", &sub) ||
3692 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &eq))
3695 } else if (streq(field, "DeviceAllow")) {
3696 DBusMessageIter sub2;
3698 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(ss)", &sub) ||
3699 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(ss)", &sub2))
3703 const char *path, *rwm;
3704 DBusMessageIter sub3;
3707 e = strchr(eq, ' ');
3709 path = strndupa(eq, e - eq);
3716 if (!path_startswith(path, "/dev")) {
3717 log_error("%s is not a device file in /dev.", path);
3721 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3722 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3723 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &rwm) ||
3724 !dbus_message_iter_close_container(&sub2, &sub3))
3728 if (!dbus_message_iter_close_container(&sub, &sub2))
3731 } else if (streq(field, "BlockIOReadBandwidth") || streq(field, "BlockIOWriteBandwidth")) {
3732 DBusMessageIter sub2;
3734 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(st)", &sub) ||
3735 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(st)", &sub2))
3739 const char *path, *bandwidth;
3740 DBusMessageIter sub3;
3745 e = strchr(eq, ' ');
3747 path = strndupa(eq, e - eq);
3750 log_error("Failed to parse %s value %s.", field, eq);
3754 if (!path_startswith(path, "/dev")) {
3755 log_error("%s is not a device file in /dev.", path);
3759 r = parse_bytes(bandwidth, &bytes);
3761 log_error("Failed to parse byte value %s.", bandwidth);
3765 u = (uint64_t) bytes;
3767 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3768 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3769 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_UINT64, &u) ||
3770 !dbus_message_iter_close_container(&sub2, &sub3))
3774 if (!dbus_message_iter_close_container(&sub, &sub2))
3777 } else if (streq(field, "BlockIODeviceWeight")) {
3778 DBusMessageIter sub2;
3780 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(st)", &sub) ||
3781 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(st)", &sub2))
3785 const char *path, *weight;
3786 DBusMessageIter sub3;
3790 e = strchr(eq, ' ');
3792 path = strndupa(eq, e - eq);
3795 log_error("Failed to parse %s value %s.", field, eq);
3799 if (!path_startswith(path, "/dev")) {
3800 log_error("%s is not a device file in /dev.", path);
3804 r = safe_atou64(weight, &u);
3806 log_error("Failed to parse %s value %s.", field, weight);
3809 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3810 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3811 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_UINT64, &u) ||
3812 !dbus_message_iter_close_container(&sub2, &sub3))
3816 if (!dbus_message_iter_close_container(&sub, &sub2))
3820 log_error("Unknown assignment %s.", assignment);
3824 if (!dbus_message_iter_close_container(iter, &sub))
3830 static int set_property(DBusConnection *bus, char **args) {
3832 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3833 _cleanup_free_ char *n = NULL;
3834 DBusMessageIter iter, sub;
3835 dbus_bool_t runtime;
3840 dbus_error_init(&error);
3842 m = dbus_message_new_method_call(
3843 "org.freedesktop.systemd1",
3844 "/org/freedesktop/systemd1",
3845 "org.freedesktop.systemd1.Manager",
3846 "SetUnitProperties");
3850 dbus_message_iter_init_append(m, &iter);
3852 runtime = arg_runtime;
3854 n = unit_name_mangle(args[1]);
3858 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
3859 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &runtime) ||
3860 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sv)", &sub))
3863 STRV_FOREACH(i, args + 2) {
3864 DBusMessageIter sub2;
3866 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
3869 r = append_assignment(&sub2, *i);
3873 if (!dbus_message_iter_close_container(&sub, &sub2))
3878 if (!dbus_message_iter_close_container(&iter, &sub))
3881 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3883 log_error("Failed to issue method call: %s", bus_error_message(&error));
3884 dbus_error_free(&error);
3891 static int snapshot(DBusConnection *bus, char **args) {
3892 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3895 dbus_bool_t cleanup = FALSE;
3896 DBusMessageIter iter, sub;
3899 *interface = "org.freedesktop.systemd1.Unit",
3901 _cleanup_free_ char *n = NULL;
3903 dbus_error_init(&error);
3905 if (strv_length(args) > 1)
3906 n = unit_name_mangle_with_suffix(args[1], ".snapshot");
3912 r = bus_method_call_with_reply(
3914 "org.freedesktop.systemd1",
3915 "/org/freedesktop/systemd1",
3916 "org.freedesktop.systemd1.Manager",
3920 DBUS_TYPE_STRING, &n,
3921 DBUS_TYPE_BOOLEAN, &cleanup,
3926 if (!dbus_message_get_args(reply, &error,
3927 DBUS_TYPE_OBJECT_PATH, &path,
3928 DBUS_TYPE_INVALID)) {
3929 log_error("Failed to parse reply: %s", bus_error_message(&error));
3930 dbus_error_free(&error);
3934 dbus_message_unref(reply);
3937 r = bus_method_call_with_reply (
3939 "org.freedesktop.systemd1",
3941 "org.freedesktop.DBus.Properties",
3945 DBUS_TYPE_STRING, &interface,
3946 DBUS_TYPE_STRING, &property,
3951 if (!dbus_message_iter_init(reply, &iter) ||
3952 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3953 log_error("Failed to parse reply.");
3957 dbus_message_iter_recurse(&iter, &sub);
3959 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3960 log_error("Failed to parse reply.");
3964 dbus_message_iter_get_basic(&sub, &id);
3972 static int delete_snapshot(DBusConnection *bus, char **args) {
3977 STRV_FOREACH(name, args+1) {
3978 _cleanup_free_ char *n = NULL;
3981 n = unit_name_mangle_with_suffix(*name, ".snapshot");
3985 r = bus_method_call_with_reply(
3987 "org.freedesktop.systemd1",
3988 "/org/freedesktop/systemd1",
3989 "org.freedesktop.systemd1.Manager",
3993 DBUS_TYPE_STRING, &n,
4002 static int daemon_reload(DBusConnection *bus, char **args) {
4007 if (arg_action == ACTION_RELOAD)
4009 else if (arg_action == ACTION_REEXEC)
4010 method = "Reexecute";
4012 assert(arg_action == ACTION_SYSTEMCTL);
4015 streq(args[0], "clear-jobs") ||
4016 streq(args[0], "cancel") ? "ClearJobs" :
4017 streq(args[0], "daemon-reexec") ? "Reexecute" :
4018 streq(args[0], "reset-failed") ? "ResetFailed" :
4019 streq(args[0], "halt") ? "Halt" :
4020 streq(args[0], "poweroff") ? "PowerOff" :
4021 streq(args[0], "reboot") ? "Reboot" :
4022 streq(args[0], "kexec") ? "KExec" :
4023 streq(args[0], "exit") ? "Exit" :
4024 /* "daemon-reload" */ "Reload";
4027 r = bus_method_call_with_reply(
4029 "org.freedesktop.systemd1",
4030 "/org/freedesktop/systemd1",
4031 "org.freedesktop.systemd1.Manager",
4037 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4038 /* There's always a fallback possible for
4039 * legacy actions. */
4041 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4042 /* On reexecution, we expect a disconnect, not a
4046 log_error("Failed to issue method call: %s", bus_error_message(&error));
4048 dbus_error_free(&error);
4052 static int reset_failed(DBusConnection *bus, char **args) {
4056 if (strv_length(args) <= 1)
4057 return daemon_reload(bus, args);
4059 STRV_FOREACH(name, args+1) {
4060 _cleanup_free_ char *n;
4062 n = unit_name_mangle(*name);
4066 r = bus_method_call_with_reply(
4068 "org.freedesktop.systemd1",
4069 "/org/freedesktop/systemd1",
4070 "org.freedesktop.systemd1.Manager",
4074 DBUS_TYPE_STRING, &n,
4083 static int show_enviroment(DBusConnection *bus, char **args) {
4084 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4085 DBusMessageIter iter, sub, sub2;
4088 *interface = "org.freedesktop.systemd1.Manager",
4089 *property = "Environment";
4091 pager_open_if_enabled();
4093 r = bus_method_call_with_reply(
4095 "org.freedesktop.systemd1",
4096 "/org/freedesktop/systemd1",
4097 "org.freedesktop.DBus.Properties",
4101 DBUS_TYPE_STRING, &interface,
4102 DBUS_TYPE_STRING, &property,
4107 if (!dbus_message_iter_init(reply, &iter) ||
4108 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
4109 log_error("Failed to parse reply.");
4113 dbus_message_iter_recurse(&iter, &sub);
4115 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
4116 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
4117 log_error("Failed to parse reply.");
4121 dbus_message_iter_recurse(&sub, &sub2);
4123 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
4126 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
4127 log_error("Failed to parse reply.");
4131 dbus_message_iter_get_basic(&sub2, &text);
4134 dbus_message_iter_next(&sub2);
4140 static int switch_root(DBusConnection *bus, char **args) {
4143 _cleanup_free_ char *init = NULL;
4145 l = strv_length(args);
4146 if (l < 2 || l > 3) {
4147 log_error("Wrong number of arguments.");
4154 init = strdup(args[2]);
4156 parse_env_file("/proc/cmdline", WHITESPACE,
4166 log_debug("switching root - root: %s; init: %s", root, init);
4168 return bus_method_call_with_reply(
4170 "org.freedesktop.systemd1",
4171 "/org/freedesktop/systemd1",
4172 "org.freedesktop.systemd1.Manager",
4176 DBUS_TYPE_STRING, &root,
4177 DBUS_TYPE_STRING, &init,
4181 static int set_environment(DBusConnection *bus, char **args) {
4182 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4185 DBusMessageIter iter;
4191 dbus_error_init(&error);
4193 method = streq(args[0], "set-environment")
4195 : "UnsetEnvironment";
4197 m = dbus_message_new_method_call(
4198 "org.freedesktop.systemd1",
4199 "/org/freedesktop/systemd1",
4200 "org.freedesktop.systemd1.Manager",
4205 dbus_message_iter_init_append(m, &iter);
4207 r = bus_append_strv_iter(&iter, args + 1);
4211 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4213 log_error("Failed to issue method call: %s", bus_error_message(&error));
4214 dbus_error_free(&error);
4221 static int enable_sysv_units(const char *verb, char **args) {
4224 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4225 unsigned f = 1, t = 1;
4226 LookupPaths paths = {};
4228 if (arg_scope != UNIT_FILE_SYSTEM)
4231 if (!streq(verb, "enable") &&
4232 !streq(verb, "disable") &&
4233 !streq(verb, "is-enabled"))
4236 /* Processes all SysV units, and reshuffles the array so that
4237 * afterwards only the native units remain */
4239 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4244 for (f = 0; args[f]; f++) {
4246 _cleanup_free_ char *p = NULL, *q = NULL;
4247 bool found_native = false, found_sysv;
4249 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4257 if (!endswith(name, ".service"))
4260 if (path_is_absolute(name))
4263 STRV_FOREACH(k, paths.unit_path) {
4264 if (!isempty(arg_root))
4265 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4267 asprintf(&p, "%s/%s", *k, name);
4274 found_native = access(p, F_OK) >= 0;
4285 if (!isempty(arg_root))
4286 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4288 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4294 p[strlen(p) - sizeof(".service") + 1] = 0;
4295 found_sysv = access(p, F_OK) >= 0;
4300 /* Mark this entry, so that we don't try enabling it as native unit */
4301 args[f] = (char*) "";
4303 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4305 if (!isempty(arg_root))
4306 argv[c++] = q = strappend("--root=", arg_root);
4308 argv[c++] = path_get_file_name(p);
4310 streq(verb, "enable") ? "on" :
4311 streq(verb, "disable") ? "off" : "--level=5";
4314 l = strv_join((char**)argv, " ");
4320 log_info("Executing %s", l);
4325 log_error("Failed to fork: %m");
4328 } else if (pid == 0) {
4331 execv(argv[0], (char**) argv);
4332 _exit(EXIT_FAILURE);
4335 j = wait_for_terminate(pid, &status);
4337 log_error("Failed to wait for child: %s", strerror(-r));
4342 if (status.si_code == CLD_EXITED) {
4343 if (streq(verb, "is-enabled")) {
4344 if (status.si_status == 0) {
4353 } else if (status.si_status != 0) {
4364 lookup_paths_free(&paths);
4366 /* Drop all SysV units */
4367 for (f = 0, t = 0; args[f]; f++) {
4369 if (isempty(args[f]))
4372 args[t++] = args[f];
4381 static int mangle_names(char **original_names, char ***mangled_names) {
4382 char **i, **l, **name;
4384 l = new(char*, strv_length(original_names) + 1);
4389 STRV_FOREACH(name, original_names) {
4391 /* When enabling units qualified path names are OK,
4392 * too, hence allow them explicitly. */
4397 *i = unit_name_mangle(*name);
4413 static int enable_unit(DBusConnection *bus, char **args) {
4414 const char *verb = args[0];
4415 UnitFileChange *changes = NULL;
4416 unsigned n_changes = 0, i;
4417 int carries_install_info = -1;
4418 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4420 _cleanup_dbus_error_free_ DBusError error;
4421 _cleanup_strv_free_ char **mangled_names = NULL;
4423 dbus_error_init(&error);
4428 r = mangle_names(args+1, &mangled_names);
4432 r = enable_sysv_units(verb, mangled_names);
4436 if (!bus || avoid_bus()) {
4437 if (streq(verb, "enable")) {
4438 r = unit_file_enable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4439 carries_install_info = r;
4440 } else if (streq(verb, "disable"))
4441 r = unit_file_disable(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4442 else if (streq(verb, "reenable")) {
4443 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4444 carries_install_info = r;
4445 } else if (streq(verb, "link"))
4446 r = unit_file_link(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4447 else if (streq(verb, "preset")) {
4448 r = unit_file_preset(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4449 carries_install_info = r;
4450 } else if (streq(verb, "mask"))
4451 r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4452 else if (streq(verb, "unmask"))
4453 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4454 else if (streq(verb, "set-default"))
4455 r = unit_file_set_default(arg_scope, arg_root, args[1], &changes, &n_changes);
4457 assert_not_reached("Unknown verb");
4460 log_error("Operation failed: %s", strerror(-r));
4465 for (i = 0; i < n_changes; i++) {
4466 if (changes[i].type == UNIT_FILE_SYMLINK)
4467 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4469 log_info("rm '%s'", changes[i].path);
4476 bool send_force = true, expect_carries_install_info = false;
4478 DBusMessageIter iter, sub, sub2;
4480 if (streq(verb, "enable")) {
4481 method = "EnableUnitFiles";
4482 expect_carries_install_info = true;
4483 } else if (streq(verb, "disable")) {
4484 method = "DisableUnitFiles";
4486 } else if (streq(verb, "reenable")) {
4487 method = "ReenableUnitFiles";
4488 expect_carries_install_info = true;
4489 } else if (streq(verb, "link"))
4490 method = "LinkUnitFiles";
4491 else if (streq(verb, "preset")) {
4492 method = "PresetUnitFiles";
4493 expect_carries_install_info = true;
4494 } else if (streq(verb, "mask"))
4495 method = "MaskUnitFiles";
4496 else if (streq(verb, "unmask")) {
4497 method = "UnmaskUnitFiles";
4499 } else if (streq(verb, "set-default")) {
4500 method = "SetDefaultTarget";
4502 assert_not_reached("Unknown verb");
4504 m = dbus_message_new_method_call(
4505 "org.freedesktop.systemd1",
4506 "/org/freedesktop/systemd1",
4507 "org.freedesktop.systemd1.Manager",
4514 dbus_message_iter_init_append(m, &iter);
4516 r = bus_append_strv_iter(&iter, mangled_names);
4518 log_error("Failed to append unit files.");
4523 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4524 log_error("Failed to append runtime boolean.");
4532 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4533 log_error("Failed to append force boolean.");
4539 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4541 log_error("Failed to issue method call: %s", bus_error_message(&error));
4546 if (!dbus_message_iter_init(reply, &iter)) {
4547 log_error("Failed to initialize iterator.");
4551 if (expect_carries_install_info) {
4552 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4554 log_error("Failed to parse reply.");
4558 carries_install_info = b;
4561 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4562 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4563 log_error("Failed to parse reply.");
4568 dbus_message_iter_recurse(&iter, &sub);
4569 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4570 const char *type, *path, *source;
4572 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4573 log_error("Failed to parse reply.");
4578 dbus_message_iter_recurse(&sub, &sub2);
4580 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4581 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4582 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4583 log_error("Failed to parse reply.");
4589 if (streq(type, "symlink"))
4590 log_info("ln -s '%s' '%s'", source, path);
4592 log_info("rm '%s'", path);
4595 dbus_message_iter_next(&sub);
4598 /* Try to reload if enabeld */
4600 r = daemon_reload(bus, args);
4603 if (carries_install_info == 0)
4604 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4605 "using systemctl.\n"
4606 "Possible reasons for having this kind of units are:\n"
4607 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4608 " .wants/ or .requires/ directory.\n"
4609 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4610 " a requirement dependency on it.\n"
4611 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4612 " D-Bus, udev, scripted systemctl call, ...).\n");
4615 unit_file_changes_free(changes, n_changes);
4620 static int unit_is_enabled(DBusConnection *bus, char **args) {
4621 _cleanup_dbus_error_free_ DBusError error;
4623 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4626 _cleanup_strv_free_ char **mangled_names = NULL;
4628 dbus_error_init(&error);
4630 r = mangle_names(args+1, &mangled_names);
4634 r = enable_sysv_units(args[0], mangled_names);
4640 if (!bus || avoid_bus()) {
4642 STRV_FOREACH(name, mangled_names) {
4643 UnitFileState state;
4645 state = unit_file_get_state(arg_scope, arg_root, *name);
4650 if (state == UNIT_FILE_ENABLED ||
4651 state == UNIT_FILE_ENABLED_RUNTIME ||
4652 state == UNIT_FILE_STATIC)
4656 puts(unit_file_state_to_string(state));
4660 STRV_FOREACH(name, mangled_names) {
4663 r = bus_method_call_with_reply (
4665 "org.freedesktop.systemd1",
4666 "/org/freedesktop/systemd1",
4667 "org.freedesktop.systemd1.Manager",
4671 DBUS_TYPE_STRING, name,
4677 if (!dbus_message_get_args(reply, &error,
4678 DBUS_TYPE_STRING, &s,
4679 DBUS_TYPE_INVALID)) {
4680 log_error("Failed to parse reply: %s", bus_error_message(&error));
4684 dbus_message_unref(reply);
4687 if (streq(s, "enabled") ||
4688 streq(s, "enabled-runtime") ||
4697 return enabled ? 0 : 1;
4700 static int systemctl_help(void) {
4702 pager_open_if_enabled();
4704 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4705 "Query or send control commands to the systemd manager.\n\n"
4706 " -h --help Show this help\n"
4707 " --version Show package version\n"
4708 " -t --type=TYPE List only units of a particular type\n"
4709 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
4710 " -p --property=NAME Show only properties by this name\n"
4711 " -a --all Show all loaded units/properties, including dead/empty\n"
4712 " ones. To list all units installed on the system, use\n"
4713 " the 'list-unit-files' command instead.\n"
4714 " --reverse Show reverse dependencies with 'list-dependencies'\n"
4715 " -l --full Don't ellipsize unit names on output\n"
4716 " --fail When queueing a new job, fail if conflicting jobs are\n"
4718 " --irreversible When queueing a new job, make sure it cannot be implicitly\n"
4720 " --ignore-dependencies\n"
4721 " When queueing a new job, ignore all its dependencies\n"
4722 " --show-types When showing sockets, explicitly show their type\n"
4723 " -i --ignore-inhibitors\n"
4724 " When shutting down or sleeping, ignore inhibitors\n"
4725 " --kill-who=WHO Who to send signal to\n"
4726 " -s --signal=SIGNAL Which signal to send\n"
4727 " -H --host=[USER@]HOST\n"
4728 " Show information for remote host\n"
4729 " -P --privileged Acquire privileges before execution\n"
4730 " -q --quiet Suppress output\n"
4731 " --no-block Do not wait until operation finished\n"
4732 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4733 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4735 " --no-legend Do not print a legend (column headers and hints)\n"
4736 " --no-pager Do not pipe output into a pager\n"
4737 " --no-ask-password\n"
4738 " Do not ask for system passwords\n"
4739 " --system Connect to system manager\n"
4740 " --user Connect to user service manager\n"
4741 " --global Enable/disable unit files globally\n"
4742 " --runtime Enable unit files only temporarily until next reboot\n"
4743 " -f --force When enabling unit files, override existing symlinks\n"
4744 " When shutting down, execute action immediately\n"
4745 " --root=PATH Enable unit files in the specified root directory\n"
4746 " -n --lines=INTEGER Numer of journal entries to show\n"
4747 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4748 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4750 " list-units List loaded units\n"
4751 " list-sockets List loaded sockets ordered by address\n"
4752 " start [NAME...] Start (activate) one or more units\n"
4753 " stop [NAME...] Stop (deactivate) one or more units\n"
4754 " reload [NAME...] Reload one or more units\n"
4755 " restart [NAME...] Start or restart one or more units\n"
4756 " try-restart [NAME...] Restart one or more units if active\n"
4757 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4758 " otherwise start or restart\n"
4759 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4760 " otherwise restart if active\n"
4761 " isolate [NAME] Start one unit and stop all others\n"
4762 " kill [NAME...] Send signal to processes of a unit\n"
4763 " is-active [NAME...] Check whether units are active\n"
4764 " is-failed [NAME...] Check whether units are failed\n"
4765 " status [NAME...|PID...] Show runtime status of one or more units\n"
4766 " show [NAME...|JOB...] Show properties of one or more\n"
4767 " units/jobs or the manager\n"
4768 " set-property [NAME] [ASSIGNMENT...]\n"
4769 " Sets one or more properties of a unit\n"
4770 " help [NAME...|PID...] Show manual for one or more units\n"
4771 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4773 " list-dependencies [NAME] Recursively show units which are required\n"
4774 " or wanted by this unit or by which this\n"
4775 " unit is required or wanted\n\n"
4776 "Unit File Commands:\n"
4777 " list-unit-files List installed unit files\n"
4778 " enable [NAME...] Enable one or more unit files\n"
4779 " disable [NAME...] Disable one or more unit files\n"
4780 " reenable [NAME...] Reenable one or more unit files\n"
4781 " preset [NAME...] Enable/disable one or more unit files\n"
4782 " based on preset configuration\n"
4783 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4784 " mask [NAME...] Mask one or more units\n"
4785 " unmask [NAME...] Unmask one or more units\n"
4786 " link [PATH...] Link one or more units files into\n"
4787 " the search path\n"
4788 " get-default Get the name of the default target\n"
4789 " set-default NAME Set the default target\n\n"
4791 " list-jobs List jobs\n"
4792 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4793 "Snapshot Commands:\n"
4794 " snapshot [NAME] Create a snapshot\n"
4795 " delete [NAME...] Remove one or more snapshots\n\n"
4796 "Environment Commands:\n"
4797 " show-environment Dump environment\n"
4798 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4799 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4800 "Manager Lifecycle Commands:\n"
4801 " daemon-reload Reload systemd manager configuration\n"
4802 " daemon-reexec Reexecute systemd manager\n\n"
4803 "System Commands:\n"
4804 " default Enter system default mode\n"
4805 " rescue Enter system rescue mode\n"
4806 " emergency Enter system emergency mode\n"
4807 " halt Shut down and halt the system\n"
4808 " poweroff Shut down and power-off the system\n"
4809 " reboot Shut down and reboot the system\n"
4810 " kexec Shut down and reboot the system with kexec\n"
4811 " exit Request user instance exit\n"
4812 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4813 " suspend Suspend the system\n"
4814 " hibernate Hibernate the system\n"
4815 " hybrid-sleep Hibernate and suspend the system\n",
4816 program_invocation_short_name);
4821 static int halt_help(void) {
4823 printf("%s [OPTIONS...]\n\n"
4824 "%s the system.\n\n"
4825 " --help Show this help\n"
4826 " --halt Halt the machine\n"
4827 " -p --poweroff Switch off the machine\n"
4828 " --reboot Reboot the machine\n"
4829 " -f --force Force immediate halt/power-off/reboot\n"
4830 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4831 " -d --no-wtmp Don't write wtmp record\n"
4832 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4833 program_invocation_short_name,
4834 arg_action == ACTION_REBOOT ? "Reboot" :
4835 arg_action == ACTION_POWEROFF ? "Power off" :
4841 static int shutdown_help(void) {
4843 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4844 "Shut down the system.\n\n"
4845 " --help Show this help\n"
4846 " -H --halt Halt the machine\n"
4847 " -P --poweroff Power-off the machine\n"
4848 " -r --reboot Reboot the machine\n"
4849 " -h Equivalent to --poweroff, overridden by --halt\n"
4850 " -k Don't halt/power-off/reboot, just send warnings\n"
4851 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4852 " -c Cancel a pending shutdown\n",
4853 program_invocation_short_name);
4858 static int telinit_help(void) {
4860 printf("%s [OPTIONS...] {COMMAND}\n\n"
4861 "Send control commands to the init daemon.\n\n"
4862 " --help Show this help\n"
4863 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4865 " 0 Power-off the machine\n"
4866 " 6 Reboot the machine\n"
4867 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4868 " 1, s, S Enter rescue mode\n"
4869 " q, Q Reload init daemon configuration\n"
4870 " u, U Reexecute init daemon\n",
4871 program_invocation_short_name);
4876 static int runlevel_help(void) {
4878 printf("%s [OPTIONS...]\n\n"
4879 "Prints the previous and current runlevel of the init system.\n\n"
4880 " --help Show this help\n",
4881 program_invocation_short_name);
4886 static int help_types(void) {
4890 puts("Available unit types:");
4891 for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4892 t = unit_type_to_string(i);
4900 static int systemctl_parse_argv(int argc, char *argv[]) {
4909 ARG_IGNORE_DEPENDENCIES,
4921 ARG_NO_ASK_PASSWORD,
4929 static const struct option options[] = {
4930 { "help", no_argument, NULL, 'h' },
4931 { "version", no_argument, NULL, ARG_VERSION },
4932 { "type", required_argument, NULL, 't' },
4933 { "property", required_argument, NULL, 'p' },
4934 { "all", no_argument, NULL, 'a' },
4935 { "reverse", no_argument, NULL, ARG_REVERSE },
4936 { "after", no_argument, NULL, ARG_AFTER },
4937 { "before", no_argument, NULL, ARG_BEFORE },
4938 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
4939 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
4940 { "full", no_argument, NULL, 'l' },
4941 { "fail", no_argument, NULL, ARG_FAIL },
4942 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4943 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4944 { "ignore-inhibitors", no_argument, NULL, 'i' },
4945 { "user", no_argument, NULL, ARG_USER },
4946 { "system", no_argument, NULL, ARG_SYSTEM },
4947 { "global", no_argument, NULL, ARG_GLOBAL },
4948 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4949 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4950 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4951 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4952 { "quiet", no_argument, NULL, 'q' },
4953 { "root", required_argument, NULL, ARG_ROOT },
4954 { "force", no_argument, NULL, ARG_FORCE },
4955 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4956 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4957 { "signal", required_argument, NULL, 's' },
4958 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4959 { "host", required_argument, NULL, 'H' },
4960 { "privileged", no_argument, NULL, 'P' },
4961 { "runtime", no_argument, NULL, ARG_RUNTIME },
4962 { "lines", required_argument, NULL, 'n' },
4963 { "output", required_argument, NULL, 'o' },
4964 { "plain", no_argument, NULL, ARG_PLAIN },
4965 { "state", required_argument, NULL, ARG_STATE },
4966 { NULL, 0, NULL, 0 }
4974 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:Pn:o:i", options, NULL)) >= 0) {
4983 puts(PACKAGE_STRING);
4984 puts(SYSTEMD_FEATURES);
4991 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4992 _cleanup_free_ char *type;
4994 type = strndup(word, size);
4998 if (streq(type, "help")) {
5003 if (unit_type_from_string(type) >= 0) {
5004 if (strv_push(&arg_types, type))
5010 /* It's much nicer to use --state= for
5011 * load states, but let's support this
5012 * in --types= too for compatibility
5013 * with old versions */
5014 if (unit_load_state_from_string(optarg) >= 0) {
5015 if (strv_push(&arg_states, type) < 0)
5021 log_error("Unknown unit type or load state '%s'.", type);
5022 log_info("Use -t help to see a list of allowed values.");
5030 /* Make sure that if the empty property list
5031 was specified, we won't show any properties. */
5032 if (isempty(optarg) && !arg_properties) {
5033 arg_properties = strv_new(NULL, NULL);
5034 if (!arg_properties)
5040 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5043 prop = strndup(word, size);
5047 if (strv_push(&arg_properties, prop) < 0) {
5054 /* If the user asked for a particular
5055 * property, show it to him, even if it is
5067 arg_dependency = DEPENDENCY_REVERSE;
5071 arg_dependency = DEPENDENCY_AFTER;
5075 arg_dependency = DEPENDENCY_BEFORE;
5078 case ARG_SHOW_TYPES:
5079 arg_show_types = true;
5083 arg_job_mode = "fail";
5086 case ARG_IRREVERSIBLE:
5087 arg_job_mode = "replace-irreversibly";
5090 case ARG_IGNORE_DEPENDENCIES:
5091 arg_job_mode = "ignore-dependencies";
5095 arg_scope = UNIT_FILE_USER;
5099 arg_scope = UNIT_FILE_SYSTEM;
5103 arg_scope = UNIT_FILE_GLOBAL;
5107 arg_no_block = true;
5111 arg_no_legend = true;
5115 arg_no_pager = true;
5131 if (strv_extend(&arg_states, "failed") < 0)
5149 arg_no_reload = true;
5153 arg_kill_who = optarg;
5157 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5158 log_error("Failed to parse signal string %s.", optarg);
5163 case ARG_NO_ASK_PASSWORD:
5164 arg_ask_password = false;
5168 arg_transport = TRANSPORT_POLKIT;
5172 arg_transport = TRANSPORT_SSH;
5173 parse_user_at_host(optarg, &arg_user, &arg_host);
5181 if (safe_atou(optarg, &arg_lines) < 0) {
5182 log_error("Failed to parse lines '%s'", optarg);
5188 arg_output = output_mode_from_string(optarg);
5189 if (arg_output < 0) {
5190 log_error("Unknown output '%s'.", optarg);
5196 arg_ignore_inhibitors = true;
5207 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5210 s = strndup(word, size);
5214 if (strv_push(&arg_states, s) < 0) {
5226 log_error("Unknown option code '%c'.", c);
5231 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
5232 log_error("Cannot access user instance remotely.");
5239 static int halt_parse_argv(int argc, char *argv[]) {
5248 static const struct option options[] = {
5249 { "help", no_argument, NULL, ARG_HELP },
5250 { "halt", no_argument, NULL, ARG_HALT },
5251 { "poweroff", no_argument, NULL, 'p' },
5252 { "reboot", no_argument, NULL, ARG_REBOOT },
5253 { "force", no_argument, NULL, 'f' },
5254 { "wtmp-only", no_argument, NULL, 'w' },
5255 { "no-wtmp", no_argument, NULL, 'd' },
5256 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5257 { NULL, 0, NULL, 0 }
5265 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5266 if (runlevel == '0' || runlevel == '6')
5269 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5277 arg_action = ACTION_HALT;
5281 if (arg_action != ACTION_REBOOT)
5282 arg_action = ACTION_POWEROFF;
5286 arg_action = ACTION_REBOOT;
5308 /* Compatibility nops */
5315 log_error("Unknown option code '%c'.", c);
5320 if (optind < argc) {
5321 log_error("Too many arguments.");
5328 static int parse_time_spec(const char *t, usec_t *_u) {
5332 if (streq(t, "now"))
5334 else if (!strchr(t, ':')) {
5337 if (safe_atou64(t, &u) < 0)
5340 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5349 hour = strtol(t, &e, 10);
5350 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5353 minute = strtol(e+1, &e, 10);
5354 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5357 n = now(CLOCK_REALTIME);
5358 s = (time_t) (n / USEC_PER_SEC);
5360 assert_se(localtime_r(&s, &tm));
5362 tm.tm_hour = (int) hour;
5363 tm.tm_min = (int) minute;
5366 assert_se(s = mktime(&tm));
5368 *_u = (usec_t) s * USEC_PER_SEC;
5371 *_u += USEC_PER_DAY;
5377 static int shutdown_parse_argv(int argc, char *argv[]) {
5384 static const struct option options[] = {
5385 { "help", no_argument, NULL, ARG_HELP },
5386 { "halt", no_argument, NULL, 'H' },
5387 { "poweroff", no_argument, NULL, 'P' },
5388 { "reboot", no_argument, NULL, 'r' },
5389 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5390 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5391 { NULL, 0, NULL, 0 }
5399 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5407 arg_action = ACTION_HALT;
5411 arg_action = ACTION_POWEROFF;
5416 arg_action = ACTION_KEXEC;
5418 arg_action = ACTION_REBOOT;
5422 arg_action = ACTION_KEXEC;
5426 if (arg_action != ACTION_HALT)
5427 arg_action = ACTION_POWEROFF;
5440 /* Compatibility nops */
5444 arg_action = ACTION_CANCEL_SHUTDOWN;
5451 log_error("Unknown option code '%c'.", c);
5456 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5457 r = parse_time_spec(argv[optind], &arg_when);
5459 log_error("Failed to parse time specification: %s", argv[optind]);
5463 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5465 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5466 /* No time argument for shutdown cancel */
5467 arg_wall = argv + optind;
5468 else if (argc > optind + 1)
5469 /* We skip the time argument */
5470 arg_wall = argv + optind + 1;
5477 static int telinit_parse_argv(int argc, char *argv[]) {
5484 static const struct option options[] = {
5485 { "help", no_argument, NULL, ARG_HELP },
5486 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5487 { NULL, 0, NULL, 0 }
5490 static const struct {
5494 { '0', ACTION_POWEROFF },
5495 { '6', ACTION_REBOOT },
5496 { '1', ACTION_RESCUE },
5497 { '2', ACTION_RUNLEVEL2 },
5498 { '3', ACTION_RUNLEVEL3 },
5499 { '4', ACTION_RUNLEVEL4 },
5500 { '5', ACTION_RUNLEVEL5 },
5501 { 's', ACTION_RESCUE },
5502 { 'S', ACTION_RESCUE },
5503 { 'q', ACTION_RELOAD },
5504 { 'Q', ACTION_RELOAD },
5505 { 'u', ACTION_REEXEC },
5506 { 'U', ACTION_REEXEC }
5515 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5530 log_error("Unknown option code '%c'.", c);
5535 if (optind >= argc) {
5540 if (optind + 1 < argc) {
5541 log_error("Too many arguments.");
5545 if (strlen(argv[optind]) != 1) {
5546 log_error("Expected single character argument.");
5550 for (i = 0; i < ELEMENTSOF(table); i++)
5551 if (table[i].from == argv[optind][0])
5554 if (i >= ELEMENTSOF(table)) {
5555 log_error("Unknown command '%s'.", argv[optind]);
5559 arg_action = table[i].to;
5566 static int runlevel_parse_argv(int argc, char *argv[]) {
5572 static const struct option options[] = {
5573 { "help", no_argument, NULL, ARG_HELP },
5574 { NULL, 0, NULL, 0 }
5582 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5593 log_error("Unknown option code '%c'.", c);
5598 if (optind < argc) {
5599 log_error("Too many arguments.");
5606 static int parse_argv(int argc, char *argv[]) {
5610 if (program_invocation_short_name) {
5612 if (strstr(program_invocation_short_name, "halt")) {
5613 arg_action = ACTION_HALT;
5614 return halt_parse_argv(argc, argv);
5615 } else if (strstr(program_invocation_short_name, "poweroff")) {
5616 arg_action = ACTION_POWEROFF;
5617 return halt_parse_argv(argc, argv);
5618 } else if (strstr(program_invocation_short_name, "reboot")) {
5620 arg_action = ACTION_KEXEC;
5622 arg_action = ACTION_REBOOT;
5623 return halt_parse_argv(argc, argv);
5624 } else if (strstr(program_invocation_short_name, "shutdown")) {
5625 arg_action = ACTION_POWEROFF;
5626 return shutdown_parse_argv(argc, argv);
5627 } else if (strstr(program_invocation_short_name, "init")) {
5629 if (sd_booted() > 0) {
5630 arg_action = ACTION_INVALID;
5631 return telinit_parse_argv(argc, argv);
5633 /* Hmm, so some other init system is
5634 * running, we need to forward this
5635 * request to it. For now we simply
5636 * guess that it is Upstart. */
5638 execv(TELINIT, argv);
5640 log_error("Couldn't find an alternative telinit implementation to spawn.");
5644 } else if (strstr(program_invocation_short_name, "runlevel")) {
5645 arg_action = ACTION_RUNLEVEL;
5646 return runlevel_parse_argv(argc, argv);
5650 arg_action = ACTION_SYSTEMCTL;
5651 return systemctl_parse_argv(argc, argv);
5654 _pure_ static int action_to_runlevel(void) {
5656 static const char table[_ACTION_MAX] = {
5657 [ACTION_HALT] = '0',
5658 [ACTION_POWEROFF] = '0',
5659 [ACTION_REBOOT] = '6',
5660 [ACTION_RUNLEVEL2] = '2',
5661 [ACTION_RUNLEVEL3] = '3',
5662 [ACTION_RUNLEVEL4] = '4',
5663 [ACTION_RUNLEVEL5] = '5',
5664 [ACTION_RESCUE] = '1'
5667 assert(arg_action < _ACTION_MAX);
5669 return table[arg_action];
5672 static int talk_initctl(void) {
5673 struct init_request request = {};
5675 _cleanup_close_ int fd = -1;
5678 rl = action_to_runlevel();
5682 request.magic = INIT_MAGIC;
5683 request.sleeptime = 0;
5684 request.cmd = INIT_CMD_RUNLVL;
5685 request.runlevel = rl;
5687 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5689 if (errno == ENOENT)
5692 log_error("Failed to open "INIT_FIFO": %m");
5697 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5699 log_error("Failed to write to "INIT_FIFO": %m");
5700 return errno > 0 ? -errno : -EIO;
5706 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5708 static const struct {
5716 int (* const dispatch)(DBusConnection *bus, char **args);
5718 { "list-units", LESS, 1, list_units },
5719 { "list-unit-files", EQUAL, 1, list_unit_files },
5720 { "list-sockets", LESS, 1, list_sockets },
5721 { "list-jobs", EQUAL, 1, list_jobs },
5722 { "clear-jobs", EQUAL, 1, daemon_reload },
5723 { "cancel", MORE, 2, cancel_job },
5724 { "start", MORE, 2, start_unit },
5725 { "stop", MORE, 2, start_unit },
5726 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5727 { "reload", MORE, 2, start_unit },
5728 { "restart", MORE, 2, start_unit },
5729 { "try-restart", MORE, 2, start_unit },
5730 { "reload-or-restart", MORE, 2, start_unit },
5731 { "reload-or-try-restart", MORE, 2, start_unit },
5732 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5733 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5734 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5735 { "isolate", EQUAL, 2, start_unit },
5736 { "kill", MORE, 2, kill_unit },
5737 { "is-active", MORE, 2, check_unit_active },
5738 { "check", MORE, 2, check_unit_active },
5739 { "is-failed", MORE, 2, check_unit_failed },
5740 { "show", MORE, 1, show },
5741 { "status", MORE, 1, show },
5742 { "help", MORE, 2, show },
5743 { "snapshot", LESS, 2, snapshot },
5744 { "delete", MORE, 2, delete_snapshot },
5745 { "daemon-reload", EQUAL, 1, daemon_reload },
5746 { "daemon-reexec", EQUAL, 1, daemon_reload },
5747 { "show-environment", EQUAL, 1, show_enviroment },
5748 { "set-environment", MORE, 2, set_environment },
5749 { "unset-environment", MORE, 2, set_environment },
5750 { "halt", EQUAL, 1, start_special },
5751 { "poweroff", EQUAL, 1, start_special },
5752 { "reboot", EQUAL, 1, start_special },
5753 { "kexec", EQUAL, 1, start_special },
5754 { "suspend", EQUAL, 1, start_special },
5755 { "hibernate", EQUAL, 1, start_special },
5756 { "hybrid-sleep", EQUAL, 1, start_special },
5757 { "default", EQUAL, 1, start_special },
5758 { "rescue", EQUAL, 1, start_special },
5759 { "emergency", EQUAL, 1, start_special },
5760 { "exit", EQUAL, 1, start_special },
5761 { "reset-failed", MORE, 1, reset_failed },
5762 { "enable", MORE, 2, enable_unit },
5763 { "disable", MORE, 2, enable_unit },
5764 { "is-enabled", MORE, 2, unit_is_enabled },
5765 { "reenable", MORE, 2, enable_unit },
5766 { "preset", MORE, 2, enable_unit },
5767 { "mask", MORE, 2, enable_unit },
5768 { "unmask", MORE, 2, enable_unit },
5769 { "link", MORE, 2, enable_unit },
5770 { "switch-root", MORE, 2, switch_root },
5771 { "list-dependencies", LESS, 2, list_dependencies },
5772 { "set-default", EQUAL, 2, enable_unit },
5773 { "get-default", LESS, 1, get_default },
5774 { "set-property", MORE, 3, set_property },
5784 left = argc - optind;
5787 /* Special rule: no arguments means "list-units" */
5790 if (streq(argv[optind], "help") && !argv[optind+1]) {
5791 log_error("This command expects one or more "
5792 "unit names. Did you mean --help?");
5796 for (i = 0; i < ELEMENTSOF(verbs); i++)
5797 if (streq(argv[optind], verbs[i].verb))
5800 if (i >= ELEMENTSOF(verbs)) {
5801 log_error("Unknown operation '%s'.", argv[optind]);
5806 switch (verbs[i].argc_cmp) {
5809 if (left != verbs[i].argc) {
5810 log_error("Invalid number of arguments.");
5817 if (left < verbs[i].argc) {
5818 log_error("Too few arguments.");
5825 if (left > verbs[i].argc) {
5826 log_error("Too many arguments.");
5833 assert_not_reached("Unknown comparison operator.");
5836 /* Require a bus connection for all operations but
5838 if (!streq(verbs[i].verb, "enable") &&
5839 !streq(verbs[i].verb, "disable") &&
5840 !streq(verbs[i].verb, "is-enabled") &&
5841 !streq(verbs[i].verb, "list-unit-files") &&
5842 !streq(verbs[i].verb, "reenable") &&
5843 !streq(verbs[i].verb, "preset") &&
5844 !streq(verbs[i].verb, "mask") &&
5845 !streq(verbs[i].verb, "unmask") &&
5846 !streq(verbs[i].verb, "link") &&
5847 !streq(verbs[i].verb, "set-default") &&
5848 !streq(verbs[i].verb, "get-default")) {
5850 if (running_in_chroot() > 0) {
5851 log_info("Running in chroot, ignoring request.");
5855 if (((!streq(verbs[i].verb, "reboot") &&
5856 !streq(verbs[i].verb, "halt") &&
5857 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5858 log_error("Failed to get D-Bus connection: %s",
5859 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5865 if (!bus && !avoid_bus()) {
5866 log_error("Failed to get D-Bus connection: %s",
5867 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5872 return verbs[i].dispatch(bus, argv + optind);
5875 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5876 _cleanup_close_ int fd;
5877 struct sd_shutdown_command c = {
5883 union sockaddr_union sockaddr = {
5884 .un.sun_family = AF_UNIX,
5885 .un.sun_path = "/run/systemd/shutdownd",
5887 struct iovec iovec[2] = {
5888 {.iov_base = (char*) &c,
5889 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
5892 struct msghdr msghdr = {
5893 .msg_name = &sockaddr,
5894 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
5895 + sizeof("/run/systemd/shutdownd") - 1,
5900 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5904 if (!isempty(message)) {
5905 iovec[1].iov_base = (char*) message;
5906 iovec[1].iov_len = strlen(message);
5907 msghdr.msg_iovlen++;
5910 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5916 static int reload_with_fallback(DBusConnection *bus) {
5919 /* First, try systemd via D-Bus. */
5920 if (daemon_reload(bus, NULL) >= 0)
5924 /* Nothing else worked, so let's try signals */
5925 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5927 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5928 log_error("kill() failed: %m");
5935 static int start_with_fallback(DBusConnection *bus) {
5938 /* First, try systemd via D-Bus. */
5939 if (start_unit(bus, NULL) >= 0)
5943 /* Nothing else worked, so let's try
5945 if (talk_initctl() > 0)
5948 log_error("Failed to talk to init daemon.");
5952 warn_wall(arg_action);
5956 static _noreturn_ void halt_now(enum action a) {
5958 /* Make sure C-A-D is handled by the kernel from this
5960 reboot(RB_ENABLE_CAD);
5965 log_info("Halting.");
5966 reboot(RB_HALT_SYSTEM);
5969 case ACTION_POWEROFF:
5970 log_info("Powering off.");
5971 reboot(RB_POWER_OFF);
5975 log_info("Rebooting.");
5976 reboot(RB_AUTOBOOT);
5980 assert_not_reached("Unknown halt action.");
5983 assert_not_reached("Uh? This shouldn't happen.");
5986 static int halt_main(DBusConnection *bus) {
5989 r = check_inhibitors(bus, arg_action);
5993 if (geteuid() != 0) {
5994 /* Try logind if we are a normal user and no special
5995 * mode applies. Maybe PolicyKit allows us to shutdown
5998 if (arg_when <= 0 &&
6001 (arg_action == ACTION_POWEROFF ||
6002 arg_action == ACTION_REBOOT)) {
6003 r = reboot_with_logind(bus, arg_action);
6008 log_error("Must be root.");
6013 _cleanup_free_ char *m;
6015 m = strv_join(arg_wall, " ");
6016 r = send_shutdownd(arg_when,
6017 arg_action == ACTION_HALT ? 'H' :
6018 arg_action == ACTION_POWEROFF ? 'P' :
6019 arg_action == ACTION_KEXEC ? 'K' :
6026 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6028 char date[FORMAT_TIMESTAMP_MAX];
6030 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6031 format_timestamp(date, sizeof(date), arg_when));
6036 if (!arg_dry && !arg_force)
6037 return start_with_fallback(bus);
6040 if (sd_booted() > 0)
6041 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6043 r = utmp_put_shutdown();
6045 log_warning("Failed to write utmp record: %s", strerror(-r));
6052 halt_now(arg_action);
6053 /* We should never reach this. */
6057 static int runlevel_main(void) {
6058 int r, runlevel, previous;
6060 r = utmp_get_runlevel(&runlevel, &previous);
6067 previous <= 0 ? 'N' : previous,
6068 runlevel <= 0 ? 'N' : runlevel);
6073 int main(int argc, char*argv[]) {
6074 int r, retval = EXIT_FAILURE;
6075 DBusConnection *bus = NULL;
6076 _cleanup_dbus_error_free_ DBusError error;
6078 dbus_error_init(&error);
6080 setlocale(LC_ALL, "");
6081 log_parse_environment();
6084 /* Explicitly not on_tty() to avoid setting cached value.
6085 * This becomes relevant for piping output which might be
6087 original_stdout_is_tty = isatty(STDOUT_FILENO);
6089 r = parse_argv(argc, argv);
6093 retval = EXIT_SUCCESS;
6097 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6098 * let's shortcut this */
6099 if (arg_action == ACTION_RUNLEVEL) {
6100 r = runlevel_main();
6101 retval = r < 0 ? EXIT_FAILURE : r;
6105 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6106 log_info("Running in chroot, ignoring request.");
6112 if (arg_transport == TRANSPORT_NORMAL)
6113 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
6114 else if (arg_transport == TRANSPORT_POLKIT) {
6115 bus_connect_system_polkit(&bus, &error);
6116 private_bus = false;
6117 } else if (arg_transport == TRANSPORT_SSH) {
6118 bus_connect_system_ssh(arg_user, arg_host, &bus, &error);
6119 private_bus = false;
6121 assert_not_reached("Uh, invalid transport...");
6124 switch (arg_action) {
6126 case ACTION_SYSTEMCTL:
6127 r = systemctl_main(bus, argc, argv, &error);
6131 case ACTION_POWEROFF:
6137 case ACTION_RUNLEVEL2:
6138 case ACTION_RUNLEVEL3:
6139 case ACTION_RUNLEVEL4:
6140 case ACTION_RUNLEVEL5:
6142 case ACTION_EMERGENCY:
6143 case ACTION_DEFAULT:
6144 r = start_with_fallback(bus);
6149 r = reload_with_fallback(bus);
6152 case ACTION_CANCEL_SHUTDOWN: {
6156 m = strv_join(arg_wall, " ");
6158 retval = EXIT_FAILURE;
6162 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6164 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6169 case ACTION_INVALID:
6170 case ACTION_RUNLEVEL:
6172 assert_not_reached("Unknown action");
6175 retval = r < 0 ? EXIT_FAILURE : r;
6179 dbus_connection_flush(bus);
6180 dbus_connection_close(bus);
6181 dbus_connection_unref(bus);
6186 strv_free(arg_types);
6187 strv_free(arg_states);
6188 strv_free(arg_properties);
6191 ask_password_agent_close();
6192 polkit_agent_close();