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_safe(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_safe(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_safe(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(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(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_safe(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 _cleanup_lookup_paths_free_ 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 /* Drop all SysV units */
4365 for (f = 0, t = 0; args[f]; f++) {
4367 if (isempty(args[f]))
4370 args[t++] = args[f];
4379 static int mangle_names(char **original_names, char ***mangled_names) {
4380 char **i, **l, **name;
4382 l = new(char*, strv_length(original_names) + 1);
4387 STRV_FOREACH(name, original_names) {
4389 /* When enabling units qualified path names are OK,
4390 * too, hence allow them explicitly. */
4395 *i = unit_name_mangle(*name);
4411 static int enable_unit(DBusConnection *bus, char **args) {
4412 const char *verb = args[0];
4413 UnitFileChange *changes = NULL;
4414 unsigned n_changes = 0, i;
4415 int carries_install_info = -1;
4416 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4418 _cleanup_dbus_error_free_ DBusError error;
4419 _cleanup_strv_free_ char **mangled_names = NULL;
4421 dbus_error_init(&error);
4426 r = mangle_names(args+1, &mangled_names);
4430 r = enable_sysv_units(verb, mangled_names);
4434 if (!bus || avoid_bus()) {
4435 if (streq(verb, "enable")) {
4436 r = unit_file_enable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4437 carries_install_info = r;
4438 } else if (streq(verb, "disable"))
4439 r = unit_file_disable(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4440 else if (streq(verb, "reenable")) {
4441 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4442 carries_install_info = r;
4443 } else if (streq(verb, "link"))
4444 r = unit_file_link(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4445 else if (streq(verb, "preset")) {
4446 r = unit_file_preset(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4447 carries_install_info = r;
4448 } else if (streq(verb, "mask"))
4449 r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4450 else if (streq(verb, "unmask"))
4451 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4452 else if (streq(verb, "set-default"))
4453 r = unit_file_set_default(arg_scope, arg_root, args[1], &changes, &n_changes);
4455 assert_not_reached("Unknown verb");
4458 log_error("Operation failed: %s", strerror(-r));
4463 for (i = 0; i < n_changes; i++) {
4464 if (changes[i].type == UNIT_FILE_SYMLINK)
4465 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4467 log_info("rm '%s'", changes[i].path);
4474 bool send_force = true, expect_carries_install_info = false;
4476 DBusMessageIter iter, sub, sub2;
4478 if (streq(verb, "enable")) {
4479 method = "EnableUnitFiles";
4480 expect_carries_install_info = true;
4481 } else if (streq(verb, "disable")) {
4482 method = "DisableUnitFiles";
4484 } else if (streq(verb, "reenable")) {
4485 method = "ReenableUnitFiles";
4486 expect_carries_install_info = true;
4487 } else if (streq(verb, "link"))
4488 method = "LinkUnitFiles";
4489 else if (streq(verb, "preset")) {
4490 method = "PresetUnitFiles";
4491 expect_carries_install_info = true;
4492 } else if (streq(verb, "mask"))
4493 method = "MaskUnitFiles";
4494 else if (streq(verb, "unmask")) {
4495 method = "UnmaskUnitFiles";
4497 } else if (streq(verb, "set-default")) {
4498 method = "SetDefaultTarget";
4500 assert_not_reached("Unknown verb");
4502 m = dbus_message_new_method_call(
4503 "org.freedesktop.systemd1",
4504 "/org/freedesktop/systemd1",
4505 "org.freedesktop.systemd1.Manager",
4512 dbus_message_iter_init_append(m, &iter);
4514 r = bus_append_strv_iter(&iter, mangled_names);
4516 log_error("Failed to append unit files.");
4521 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4522 log_error("Failed to append runtime boolean.");
4530 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4531 log_error("Failed to append force boolean.");
4537 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4539 log_error("Failed to issue method call: %s", bus_error_message(&error));
4544 if (!dbus_message_iter_init(reply, &iter)) {
4545 log_error("Failed to initialize iterator.");
4549 if (expect_carries_install_info) {
4550 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4552 log_error("Failed to parse reply.");
4556 carries_install_info = b;
4559 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4560 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4561 log_error("Failed to parse reply.");
4566 dbus_message_iter_recurse(&iter, &sub);
4567 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4568 const char *type, *path, *source;
4570 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4571 log_error("Failed to parse reply.");
4576 dbus_message_iter_recurse(&sub, &sub2);
4578 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4579 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4580 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4581 log_error("Failed to parse reply.");
4587 if (streq(type, "symlink"))
4588 log_info("ln -s '%s' '%s'", source, path);
4590 log_info("rm '%s'", path);
4593 dbus_message_iter_next(&sub);
4596 /* Try to reload if enabeld */
4598 r = daemon_reload(bus, args);
4601 if (carries_install_info == 0)
4602 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4603 "using systemctl.\n"
4604 "Possible reasons for having this kind of units are:\n"
4605 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4606 " .wants/ or .requires/ directory.\n"
4607 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4608 " a requirement dependency on it.\n"
4609 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4610 " D-Bus, udev, scripted systemctl call, ...).\n");
4613 unit_file_changes_free(changes, n_changes);
4618 static int unit_is_enabled(DBusConnection *bus, char **args) {
4619 _cleanup_dbus_error_free_ DBusError error;
4621 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4624 _cleanup_strv_free_ char **mangled_names = NULL;
4626 dbus_error_init(&error);
4628 r = mangle_names(args+1, &mangled_names);
4632 r = enable_sysv_units(args[0], mangled_names);
4638 if (!bus || avoid_bus()) {
4640 STRV_FOREACH(name, mangled_names) {
4641 UnitFileState state;
4643 state = unit_file_get_state(arg_scope, arg_root, *name);
4648 if (state == UNIT_FILE_ENABLED ||
4649 state == UNIT_FILE_ENABLED_RUNTIME ||
4650 state == UNIT_FILE_STATIC)
4654 puts(unit_file_state_to_string(state));
4658 STRV_FOREACH(name, mangled_names) {
4661 r = bus_method_call_with_reply (
4663 "org.freedesktop.systemd1",
4664 "/org/freedesktop/systemd1",
4665 "org.freedesktop.systemd1.Manager",
4669 DBUS_TYPE_STRING, name,
4675 if (!dbus_message_get_args(reply, &error,
4676 DBUS_TYPE_STRING, &s,
4677 DBUS_TYPE_INVALID)) {
4678 log_error("Failed to parse reply: %s", bus_error_message(&error));
4682 dbus_message_unref(reply);
4685 if (streq(s, "enabled") ||
4686 streq(s, "enabled-runtime") ||
4695 return enabled ? 0 : 1;
4698 static int systemctl_help(void) {
4700 pager_open_if_enabled();
4702 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4703 "Query or send control commands to the systemd manager.\n\n"
4704 " -h --help Show this help\n"
4705 " --version Show package version\n"
4706 " -t --type=TYPE List only units of a particular type\n"
4707 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
4708 " -p --property=NAME Show only properties by this name\n"
4709 " -a --all Show all loaded units/properties, including dead/empty\n"
4710 " ones. To list all units installed on the system, use\n"
4711 " the 'list-unit-files' command instead.\n"
4712 " --reverse Show reverse dependencies with 'list-dependencies'\n"
4713 " -l --full Don't ellipsize unit names on output\n"
4714 " --fail When queueing a new job, fail if conflicting jobs are\n"
4716 " --irreversible When queueing a new job, make sure it cannot be implicitly\n"
4718 " --ignore-dependencies\n"
4719 " When queueing a new job, ignore all its dependencies\n"
4720 " --show-types When showing sockets, explicitly show their type\n"
4721 " -i --ignore-inhibitors\n"
4722 " When shutting down or sleeping, ignore inhibitors\n"
4723 " --kill-who=WHO Who to send signal to\n"
4724 " -s --signal=SIGNAL Which signal to send\n"
4725 " -H --host=[USER@]HOST\n"
4726 " Show information for remote host\n"
4727 " -P --privileged Acquire privileges before execution\n"
4728 " -q --quiet Suppress output\n"
4729 " --no-block Do not wait until operation finished\n"
4730 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4731 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4733 " --no-legend Do not print a legend (column headers and hints)\n"
4734 " --no-pager Do not pipe output into a pager\n"
4735 " --no-ask-password\n"
4736 " Do not ask for system passwords\n"
4737 " --system Connect to system manager\n"
4738 " --user Connect to user service manager\n"
4739 " --global Enable/disable unit files globally\n"
4740 " --runtime Enable unit files only temporarily until next reboot\n"
4741 " -f --force When enabling unit files, override existing symlinks\n"
4742 " When shutting down, execute action immediately\n"
4743 " --root=PATH Enable unit files in the specified root directory\n"
4744 " -n --lines=INTEGER Numer of journal entries to show\n"
4745 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4746 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4748 " list-units List loaded units\n"
4749 " list-sockets List loaded sockets ordered by address\n"
4750 " start [NAME...] Start (activate) one or more units\n"
4751 " stop [NAME...] Stop (deactivate) one or more units\n"
4752 " reload [NAME...] Reload one or more units\n"
4753 " restart [NAME...] Start or restart one or more units\n"
4754 " try-restart [NAME...] Restart one or more units if active\n"
4755 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4756 " otherwise start or restart\n"
4757 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4758 " otherwise restart if active\n"
4759 " isolate [NAME] Start one unit and stop all others\n"
4760 " kill [NAME...] Send signal to processes of a unit\n"
4761 " is-active [NAME...] Check whether units are active\n"
4762 " is-failed [NAME...] Check whether units are failed\n"
4763 " status [NAME...|PID...] Show runtime status of one or more units\n"
4764 " show [NAME...|JOB...] Show properties of one or more\n"
4765 " units/jobs or the manager\n"
4766 " set-property [NAME] [ASSIGNMENT...]\n"
4767 " Sets one or more properties of a unit\n"
4768 " help [NAME...|PID...] Show manual for one or more units\n"
4769 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4771 " list-dependencies [NAME] Recursively show units which are required\n"
4772 " or wanted by this unit or by which this\n"
4773 " unit is required or wanted\n\n"
4774 "Unit File Commands:\n"
4775 " list-unit-files List installed unit files\n"
4776 " enable [NAME...] Enable one or more unit files\n"
4777 " disable [NAME...] Disable one or more unit files\n"
4778 " reenable [NAME...] Reenable one or more unit files\n"
4779 " preset [NAME...] Enable/disable one or more unit files\n"
4780 " based on preset configuration\n"
4781 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4782 " mask [NAME...] Mask one or more units\n"
4783 " unmask [NAME...] Unmask one or more units\n"
4784 " link [PATH...] Link one or more units files into\n"
4785 " the search path\n"
4786 " get-default Get the name of the default target\n"
4787 " set-default NAME Set the default target\n\n"
4789 " list-jobs List jobs\n"
4790 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4791 "Snapshot Commands:\n"
4792 " snapshot [NAME] Create a snapshot\n"
4793 " delete [NAME...] Remove one or more snapshots\n\n"
4794 "Environment Commands:\n"
4795 " show-environment Dump environment\n"
4796 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4797 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4798 "Manager Lifecycle Commands:\n"
4799 " daemon-reload Reload systemd manager configuration\n"
4800 " daemon-reexec Reexecute systemd manager\n\n"
4801 "System Commands:\n"
4802 " default Enter system default mode\n"
4803 " rescue Enter system rescue mode\n"
4804 " emergency Enter system emergency mode\n"
4805 " halt Shut down and halt the system\n"
4806 " poweroff Shut down and power-off the system\n"
4807 " reboot Shut down and reboot the system\n"
4808 " kexec Shut down and reboot the system with kexec\n"
4809 " exit Request user instance exit\n"
4810 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4811 " suspend Suspend the system\n"
4812 " hibernate Hibernate the system\n"
4813 " hybrid-sleep Hibernate and suspend the system\n",
4814 program_invocation_short_name);
4819 static int halt_help(void) {
4821 printf("%s [OPTIONS...]\n\n"
4822 "%s the system.\n\n"
4823 " --help Show this help\n"
4824 " --halt Halt the machine\n"
4825 " -p --poweroff Switch off the machine\n"
4826 " --reboot Reboot the machine\n"
4827 " -f --force Force immediate halt/power-off/reboot\n"
4828 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4829 " -d --no-wtmp Don't write wtmp record\n"
4830 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4831 program_invocation_short_name,
4832 arg_action == ACTION_REBOOT ? "Reboot" :
4833 arg_action == ACTION_POWEROFF ? "Power off" :
4839 static int shutdown_help(void) {
4841 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4842 "Shut down the system.\n\n"
4843 " --help Show this help\n"
4844 " -H --halt Halt the machine\n"
4845 " -P --poweroff Power-off the machine\n"
4846 " -r --reboot Reboot the machine\n"
4847 " -h Equivalent to --poweroff, overridden by --halt\n"
4848 " -k Don't halt/power-off/reboot, just send warnings\n"
4849 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4850 " -c Cancel a pending shutdown\n",
4851 program_invocation_short_name);
4856 static int telinit_help(void) {
4858 printf("%s [OPTIONS...] {COMMAND}\n\n"
4859 "Send control commands to the init daemon.\n\n"
4860 " --help Show this help\n"
4861 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4863 " 0 Power-off the machine\n"
4864 " 6 Reboot the machine\n"
4865 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4866 " 1, s, S Enter rescue mode\n"
4867 " q, Q Reload init daemon configuration\n"
4868 " u, U Reexecute init daemon\n",
4869 program_invocation_short_name);
4874 static int runlevel_help(void) {
4876 printf("%s [OPTIONS...]\n\n"
4877 "Prints the previous and current runlevel of the init system.\n\n"
4878 " --help Show this help\n",
4879 program_invocation_short_name);
4884 static int help_types(void) {
4888 puts("Available unit types:");
4889 for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4890 t = unit_type_to_string(i);
4898 static int systemctl_parse_argv(int argc, char *argv[]) {
4907 ARG_IGNORE_DEPENDENCIES,
4919 ARG_NO_ASK_PASSWORD,
4927 static const struct option options[] = {
4928 { "help", no_argument, NULL, 'h' },
4929 { "version", no_argument, NULL, ARG_VERSION },
4930 { "type", required_argument, NULL, 't' },
4931 { "property", required_argument, NULL, 'p' },
4932 { "all", no_argument, NULL, 'a' },
4933 { "reverse", no_argument, NULL, ARG_REVERSE },
4934 { "after", no_argument, NULL, ARG_AFTER },
4935 { "before", no_argument, NULL, ARG_BEFORE },
4936 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
4937 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
4938 { "full", no_argument, NULL, 'l' },
4939 { "fail", no_argument, NULL, ARG_FAIL },
4940 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4941 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4942 { "ignore-inhibitors", no_argument, NULL, 'i' },
4943 { "user", no_argument, NULL, ARG_USER },
4944 { "system", no_argument, NULL, ARG_SYSTEM },
4945 { "global", no_argument, NULL, ARG_GLOBAL },
4946 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4947 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4948 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4949 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4950 { "quiet", no_argument, NULL, 'q' },
4951 { "root", required_argument, NULL, ARG_ROOT },
4952 { "force", no_argument, NULL, ARG_FORCE },
4953 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4954 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4955 { "signal", required_argument, NULL, 's' },
4956 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4957 { "host", required_argument, NULL, 'H' },
4958 { "privileged", no_argument, NULL, 'P' },
4959 { "runtime", no_argument, NULL, ARG_RUNTIME },
4960 { "lines", required_argument, NULL, 'n' },
4961 { "output", required_argument, NULL, 'o' },
4962 { "plain", no_argument, NULL, ARG_PLAIN },
4963 { "state", required_argument, NULL, ARG_STATE },
4964 { NULL, 0, NULL, 0 }
4972 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:Pn:o:i", options, NULL)) >= 0) {
4981 puts(PACKAGE_STRING);
4982 puts(SYSTEMD_FEATURES);
4989 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4990 _cleanup_free_ char *type;
4992 type = strndup(word, size);
4996 if (streq(type, "help")) {
5001 if (unit_type_from_string(type) >= 0) {
5002 if (strv_push(&arg_types, type))
5008 /* It's much nicer to use --state= for
5009 * load states, but let's support this
5010 * in --types= too for compatibility
5011 * with old versions */
5012 if (unit_load_state_from_string(optarg) >= 0) {
5013 if (strv_push(&arg_states, type) < 0)
5019 log_error("Unknown unit type or load state '%s'.", type);
5020 log_info("Use -t help to see a list of allowed values.");
5028 /* Make sure that if the empty property list
5029 was specified, we won't show any properties. */
5030 if (isempty(optarg) && !arg_properties) {
5031 arg_properties = strv_new(NULL, NULL);
5032 if (!arg_properties)
5038 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5041 prop = strndup(word, size);
5045 if (strv_push(&arg_properties, prop) < 0) {
5052 /* If the user asked for a particular
5053 * property, show it to him, even if it is
5065 arg_dependency = DEPENDENCY_REVERSE;
5069 arg_dependency = DEPENDENCY_AFTER;
5073 arg_dependency = DEPENDENCY_BEFORE;
5076 case ARG_SHOW_TYPES:
5077 arg_show_types = true;
5081 arg_job_mode = "fail";
5084 case ARG_IRREVERSIBLE:
5085 arg_job_mode = "replace-irreversibly";
5088 case ARG_IGNORE_DEPENDENCIES:
5089 arg_job_mode = "ignore-dependencies";
5093 arg_scope = UNIT_FILE_USER;
5097 arg_scope = UNIT_FILE_SYSTEM;
5101 arg_scope = UNIT_FILE_GLOBAL;
5105 arg_no_block = true;
5109 arg_no_legend = true;
5113 arg_no_pager = true;
5129 if (strv_extend(&arg_states, "failed") < 0)
5147 arg_no_reload = true;
5151 arg_kill_who = optarg;
5155 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5156 log_error("Failed to parse signal string %s.", optarg);
5161 case ARG_NO_ASK_PASSWORD:
5162 arg_ask_password = false;
5166 arg_transport = TRANSPORT_POLKIT;
5170 arg_transport = TRANSPORT_SSH;
5171 parse_user_at_host(optarg, &arg_user, &arg_host);
5179 if (safe_atou(optarg, &arg_lines) < 0) {
5180 log_error("Failed to parse lines '%s'", optarg);
5186 arg_output = output_mode_from_string(optarg);
5187 if (arg_output < 0) {
5188 log_error("Unknown output '%s'.", optarg);
5194 arg_ignore_inhibitors = true;
5205 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5208 s = strndup(word, size);
5212 if (strv_push(&arg_states, s) < 0) {
5224 log_error("Unknown option code '%c'.", c);
5229 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
5230 log_error("Cannot access user instance remotely.");
5237 static int halt_parse_argv(int argc, char *argv[]) {
5246 static const struct option options[] = {
5247 { "help", no_argument, NULL, ARG_HELP },
5248 { "halt", no_argument, NULL, ARG_HALT },
5249 { "poweroff", no_argument, NULL, 'p' },
5250 { "reboot", no_argument, NULL, ARG_REBOOT },
5251 { "force", no_argument, NULL, 'f' },
5252 { "wtmp-only", no_argument, NULL, 'w' },
5253 { "no-wtmp", no_argument, NULL, 'd' },
5254 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5255 { NULL, 0, NULL, 0 }
5263 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5264 if (runlevel == '0' || runlevel == '6')
5267 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5275 arg_action = ACTION_HALT;
5279 if (arg_action != ACTION_REBOOT)
5280 arg_action = ACTION_POWEROFF;
5284 arg_action = ACTION_REBOOT;
5306 /* Compatibility nops */
5313 log_error("Unknown option code '%c'.", c);
5318 if (optind < argc) {
5319 log_error("Too many arguments.");
5326 static int parse_time_spec(const char *t, usec_t *_u) {
5330 if (streq(t, "now"))
5332 else if (!strchr(t, ':')) {
5335 if (safe_atou64(t, &u) < 0)
5338 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5347 hour = strtol(t, &e, 10);
5348 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5351 minute = strtol(e+1, &e, 10);
5352 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5355 n = now(CLOCK_REALTIME);
5356 s = (time_t) (n / USEC_PER_SEC);
5358 assert_se(localtime_r(&s, &tm));
5360 tm.tm_hour = (int) hour;
5361 tm.tm_min = (int) minute;
5364 assert_se(s = mktime(&tm));
5366 *_u = (usec_t) s * USEC_PER_SEC;
5369 *_u += USEC_PER_DAY;
5375 static int shutdown_parse_argv(int argc, char *argv[]) {
5382 static const struct option options[] = {
5383 { "help", no_argument, NULL, ARG_HELP },
5384 { "halt", no_argument, NULL, 'H' },
5385 { "poweroff", no_argument, NULL, 'P' },
5386 { "reboot", no_argument, NULL, 'r' },
5387 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5388 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5389 { NULL, 0, NULL, 0 }
5397 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5405 arg_action = ACTION_HALT;
5409 arg_action = ACTION_POWEROFF;
5414 arg_action = ACTION_KEXEC;
5416 arg_action = ACTION_REBOOT;
5420 arg_action = ACTION_KEXEC;
5424 if (arg_action != ACTION_HALT)
5425 arg_action = ACTION_POWEROFF;
5438 /* Compatibility nops */
5442 arg_action = ACTION_CANCEL_SHUTDOWN;
5449 log_error("Unknown option code '%c'.", c);
5454 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5455 r = parse_time_spec(argv[optind], &arg_when);
5457 log_error("Failed to parse time specification: %s", argv[optind]);
5461 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5463 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5464 /* No time argument for shutdown cancel */
5465 arg_wall = argv + optind;
5466 else if (argc > optind + 1)
5467 /* We skip the time argument */
5468 arg_wall = argv + optind + 1;
5475 static int telinit_parse_argv(int argc, char *argv[]) {
5482 static const struct option options[] = {
5483 { "help", no_argument, NULL, ARG_HELP },
5484 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5485 { NULL, 0, NULL, 0 }
5488 static const struct {
5492 { '0', ACTION_POWEROFF },
5493 { '6', ACTION_REBOOT },
5494 { '1', ACTION_RESCUE },
5495 { '2', ACTION_RUNLEVEL2 },
5496 { '3', ACTION_RUNLEVEL3 },
5497 { '4', ACTION_RUNLEVEL4 },
5498 { '5', ACTION_RUNLEVEL5 },
5499 { 's', ACTION_RESCUE },
5500 { 'S', ACTION_RESCUE },
5501 { 'q', ACTION_RELOAD },
5502 { 'Q', ACTION_RELOAD },
5503 { 'u', ACTION_REEXEC },
5504 { 'U', ACTION_REEXEC }
5513 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5528 log_error("Unknown option code '%c'.", c);
5533 if (optind >= argc) {
5538 if (optind + 1 < argc) {
5539 log_error("Too many arguments.");
5543 if (strlen(argv[optind]) != 1) {
5544 log_error("Expected single character argument.");
5548 for (i = 0; i < ELEMENTSOF(table); i++)
5549 if (table[i].from == argv[optind][0])
5552 if (i >= ELEMENTSOF(table)) {
5553 log_error("Unknown command '%s'.", argv[optind]);
5557 arg_action = table[i].to;
5564 static int runlevel_parse_argv(int argc, char *argv[]) {
5570 static const struct option options[] = {
5571 { "help", no_argument, NULL, ARG_HELP },
5572 { NULL, 0, NULL, 0 }
5580 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5591 log_error("Unknown option code '%c'.", c);
5596 if (optind < argc) {
5597 log_error("Too many arguments.");
5604 static int parse_argv(int argc, char *argv[]) {
5608 if (program_invocation_short_name) {
5610 if (strstr(program_invocation_short_name, "halt")) {
5611 arg_action = ACTION_HALT;
5612 return halt_parse_argv(argc, argv);
5613 } else if (strstr(program_invocation_short_name, "poweroff")) {
5614 arg_action = ACTION_POWEROFF;
5615 return halt_parse_argv(argc, argv);
5616 } else if (strstr(program_invocation_short_name, "reboot")) {
5618 arg_action = ACTION_KEXEC;
5620 arg_action = ACTION_REBOOT;
5621 return halt_parse_argv(argc, argv);
5622 } else if (strstr(program_invocation_short_name, "shutdown")) {
5623 arg_action = ACTION_POWEROFF;
5624 return shutdown_parse_argv(argc, argv);
5625 } else if (strstr(program_invocation_short_name, "init")) {
5627 if (sd_booted() > 0) {
5628 arg_action = ACTION_INVALID;
5629 return telinit_parse_argv(argc, argv);
5631 /* Hmm, so some other init system is
5632 * running, we need to forward this
5633 * request to it. For now we simply
5634 * guess that it is Upstart. */
5636 execv(TELINIT, argv);
5638 log_error("Couldn't find an alternative telinit implementation to spawn.");
5642 } else if (strstr(program_invocation_short_name, "runlevel")) {
5643 arg_action = ACTION_RUNLEVEL;
5644 return runlevel_parse_argv(argc, argv);
5648 arg_action = ACTION_SYSTEMCTL;
5649 return systemctl_parse_argv(argc, argv);
5652 _pure_ static int action_to_runlevel(void) {
5654 static const char table[_ACTION_MAX] = {
5655 [ACTION_HALT] = '0',
5656 [ACTION_POWEROFF] = '0',
5657 [ACTION_REBOOT] = '6',
5658 [ACTION_RUNLEVEL2] = '2',
5659 [ACTION_RUNLEVEL3] = '3',
5660 [ACTION_RUNLEVEL4] = '4',
5661 [ACTION_RUNLEVEL5] = '5',
5662 [ACTION_RESCUE] = '1'
5665 assert(arg_action < _ACTION_MAX);
5667 return table[arg_action];
5670 static int talk_initctl(void) {
5671 struct init_request request = {};
5673 _cleanup_close_ int fd = -1;
5676 rl = action_to_runlevel();
5680 request.magic = INIT_MAGIC;
5681 request.sleeptime = 0;
5682 request.cmd = INIT_CMD_RUNLVL;
5683 request.runlevel = rl;
5685 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5687 if (errno == ENOENT)
5690 log_error("Failed to open "INIT_FIFO": %m");
5695 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5697 log_error("Failed to write to "INIT_FIFO": %m");
5698 return errno > 0 ? -errno : -EIO;
5704 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5706 static const struct {
5714 int (* const dispatch)(DBusConnection *bus, char **args);
5716 { "list-units", LESS, 1, list_units },
5717 { "list-unit-files", EQUAL, 1, list_unit_files },
5718 { "list-sockets", LESS, 1, list_sockets },
5719 { "list-jobs", EQUAL, 1, list_jobs },
5720 { "clear-jobs", EQUAL, 1, daemon_reload },
5721 { "cancel", MORE, 2, cancel_job },
5722 { "start", MORE, 2, start_unit },
5723 { "stop", MORE, 2, start_unit },
5724 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5725 { "reload", MORE, 2, start_unit },
5726 { "restart", MORE, 2, start_unit },
5727 { "try-restart", MORE, 2, start_unit },
5728 { "reload-or-restart", MORE, 2, start_unit },
5729 { "reload-or-try-restart", MORE, 2, start_unit },
5730 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5731 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5732 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5733 { "isolate", EQUAL, 2, start_unit },
5734 { "kill", MORE, 2, kill_unit },
5735 { "is-active", MORE, 2, check_unit_active },
5736 { "check", MORE, 2, check_unit_active },
5737 { "is-failed", MORE, 2, check_unit_failed },
5738 { "show", MORE, 1, show },
5739 { "status", MORE, 1, show },
5740 { "help", MORE, 2, show },
5741 { "snapshot", LESS, 2, snapshot },
5742 { "delete", MORE, 2, delete_snapshot },
5743 { "daemon-reload", EQUAL, 1, daemon_reload },
5744 { "daemon-reexec", EQUAL, 1, daemon_reload },
5745 { "show-environment", EQUAL, 1, show_enviroment },
5746 { "set-environment", MORE, 2, set_environment },
5747 { "unset-environment", MORE, 2, set_environment },
5748 { "halt", EQUAL, 1, start_special },
5749 { "poweroff", EQUAL, 1, start_special },
5750 { "reboot", EQUAL, 1, start_special },
5751 { "kexec", EQUAL, 1, start_special },
5752 { "suspend", EQUAL, 1, start_special },
5753 { "hibernate", EQUAL, 1, start_special },
5754 { "hybrid-sleep", EQUAL, 1, start_special },
5755 { "default", EQUAL, 1, start_special },
5756 { "rescue", EQUAL, 1, start_special },
5757 { "emergency", EQUAL, 1, start_special },
5758 { "exit", EQUAL, 1, start_special },
5759 { "reset-failed", MORE, 1, reset_failed },
5760 { "enable", MORE, 2, enable_unit },
5761 { "disable", MORE, 2, enable_unit },
5762 { "is-enabled", MORE, 2, unit_is_enabled },
5763 { "reenable", MORE, 2, enable_unit },
5764 { "preset", MORE, 2, enable_unit },
5765 { "mask", MORE, 2, enable_unit },
5766 { "unmask", MORE, 2, enable_unit },
5767 { "link", MORE, 2, enable_unit },
5768 { "switch-root", MORE, 2, switch_root },
5769 { "list-dependencies", LESS, 2, list_dependencies },
5770 { "set-default", EQUAL, 2, enable_unit },
5771 { "get-default", LESS, 1, get_default },
5772 { "set-property", MORE, 3, set_property },
5782 left = argc - optind;
5785 /* Special rule: no arguments means "list-units" */
5788 if (streq(argv[optind], "help") && !argv[optind+1]) {
5789 log_error("This command expects one or more "
5790 "unit names. Did you mean --help?");
5794 for (i = 0; i < ELEMENTSOF(verbs); i++)
5795 if (streq(argv[optind], verbs[i].verb))
5798 if (i >= ELEMENTSOF(verbs)) {
5799 log_error("Unknown operation '%s'.", argv[optind]);
5804 switch (verbs[i].argc_cmp) {
5807 if (left != verbs[i].argc) {
5808 log_error("Invalid number of arguments.");
5815 if (left < verbs[i].argc) {
5816 log_error("Too few arguments.");
5823 if (left > verbs[i].argc) {
5824 log_error("Too many arguments.");
5831 assert_not_reached("Unknown comparison operator.");
5834 /* Require a bus connection for all operations but
5836 if (!streq(verbs[i].verb, "enable") &&
5837 !streq(verbs[i].verb, "disable") &&
5838 !streq(verbs[i].verb, "is-enabled") &&
5839 !streq(verbs[i].verb, "list-unit-files") &&
5840 !streq(verbs[i].verb, "reenable") &&
5841 !streq(verbs[i].verb, "preset") &&
5842 !streq(verbs[i].verb, "mask") &&
5843 !streq(verbs[i].verb, "unmask") &&
5844 !streq(verbs[i].verb, "link") &&
5845 !streq(verbs[i].verb, "set-default") &&
5846 !streq(verbs[i].verb, "get-default")) {
5848 if (running_in_chroot() > 0) {
5849 log_info("Running in chroot, ignoring request.");
5853 if (((!streq(verbs[i].verb, "reboot") &&
5854 !streq(verbs[i].verb, "halt") &&
5855 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5856 log_error("Failed to get D-Bus connection: %s",
5857 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5863 if (!bus && !avoid_bus()) {
5864 log_error("Failed to get D-Bus connection: %s",
5865 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5870 return verbs[i].dispatch(bus, argv + optind);
5873 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5874 _cleanup_close_ int fd;
5875 struct sd_shutdown_command c = {
5881 union sockaddr_union sockaddr = {
5882 .un.sun_family = AF_UNIX,
5883 .un.sun_path = "/run/systemd/shutdownd",
5885 struct iovec iovec[2] = {
5886 {.iov_base = (char*) &c,
5887 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
5890 struct msghdr msghdr = {
5891 .msg_name = &sockaddr,
5892 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
5893 + sizeof("/run/systemd/shutdownd") - 1,
5898 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5902 if (!isempty(message)) {
5903 iovec[1].iov_base = (char*) message;
5904 iovec[1].iov_len = strlen(message);
5905 msghdr.msg_iovlen++;
5908 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5914 static int reload_with_fallback(DBusConnection *bus) {
5917 /* First, try systemd via D-Bus. */
5918 if (daemon_reload(bus, NULL) >= 0)
5922 /* Nothing else worked, so let's try signals */
5923 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5925 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5926 log_error("kill() failed: %m");
5933 static int start_with_fallback(DBusConnection *bus) {
5936 /* First, try systemd via D-Bus. */
5937 if (start_unit(bus, NULL) >= 0)
5941 /* Nothing else worked, so let's try
5943 if (talk_initctl() > 0)
5946 log_error("Failed to talk to init daemon.");
5950 warn_wall(arg_action);
5954 static _noreturn_ void halt_now(enum action a) {
5956 /* Make sure C-A-D is handled by the kernel from this
5958 reboot(RB_ENABLE_CAD);
5963 log_info("Halting.");
5964 reboot(RB_HALT_SYSTEM);
5967 case ACTION_POWEROFF:
5968 log_info("Powering off.");
5969 reboot(RB_POWER_OFF);
5973 log_info("Rebooting.");
5974 reboot(RB_AUTOBOOT);
5978 assert_not_reached("Unknown halt action.");
5981 assert_not_reached("Uh? This shouldn't happen.");
5984 static int halt_main(DBusConnection *bus) {
5987 r = check_inhibitors(bus, arg_action);
5991 if (geteuid() != 0) {
5992 /* Try logind if we are a normal user and no special
5993 * mode applies. Maybe PolicyKit allows us to shutdown
5996 if (arg_when <= 0 &&
5999 (arg_action == ACTION_POWEROFF ||
6000 arg_action == ACTION_REBOOT)) {
6001 r = reboot_with_logind(bus, arg_action);
6006 log_error("Must be root.");
6011 _cleanup_free_ char *m;
6013 m = strv_join(arg_wall, " ");
6014 r = send_shutdownd(arg_when,
6015 arg_action == ACTION_HALT ? 'H' :
6016 arg_action == ACTION_POWEROFF ? 'P' :
6017 arg_action == ACTION_KEXEC ? 'K' :
6024 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6026 char date[FORMAT_TIMESTAMP_MAX];
6028 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6029 format_timestamp(date, sizeof(date), arg_when));
6034 if (!arg_dry && !arg_force)
6035 return start_with_fallback(bus);
6038 if (sd_booted() > 0)
6039 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6041 r = utmp_put_shutdown();
6043 log_warning("Failed to write utmp record: %s", strerror(-r));
6050 halt_now(arg_action);
6051 /* We should never reach this. */
6055 static int runlevel_main(void) {
6056 int r, runlevel, previous;
6058 r = utmp_get_runlevel(&runlevel, &previous);
6065 previous <= 0 ? 'N' : previous,
6066 runlevel <= 0 ? 'N' : runlevel);
6071 int main(int argc, char*argv[]) {
6072 int r, retval = EXIT_FAILURE;
6073 DBusConnection *bus = NULL;
6074 _cleanup_dbus_error_free_ DBusError error;
6076 dbus_error_init(&error);
6078 setlocale(LC_ALL, "");
6079 log_parse_environment();
6082 /* Explicitly not on_tty() to avoid setting cached value.
6083 * This becomes relevant for piping output which might be
6085 original_stdout_is_tty = isatty(STDOUT_FILENO);
6087 r = parse_argv(argc, argv);
6091 retval = EXIT_SUCCESS;
6095 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6096 * let's shortcut this */
6097 if (arg_action == ACTION_RUNLEVEL) {
6098 r = runlevel_main();
6099 retval = r < 0 ? EXIT_FAILURE : r;
6103 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6104 log_info("Running in chroot, ignoring request.");
6110 if (arg_transport == TRANSPORT_NORMAL)
6111 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
6112 else if (arg_transport == TRANSPORT_POLKIT) {
6113 bus_connect_system_polkit(&bus, &error);
6114 private_bus = false;
6115 } else if (arg_transport == TRANSPORT_SSH) {
6116 bus_connect_system_ssh(arg_user, arg_host, &bus, &error);
6117 private_bus = false;
6119 assert_not_reached("Uh, invalid transport...");
6122 switch (arg_action) {
6124 case ACTION_SYSTEMCTL:
6125 r = systemctl_main(bus, argc, argv, &error);
6129 case ACTION_POWEROFF:
6135 case ACTION_RUNLEVEL2:
6136 case ACTION_RUNLEVEL3:
6137 case ACTION_RUNLEVEL4:
6138 case ACTION_RUNLEVEL5:
6140 case ACTION_EMERGENCY:
6141 case ACTION_DEFAULT:
6142 r = start_with_fallback(bus);
6147 r = reload_with_fallback(bus);
6150 case ACTION_CANCEL_SHUTDOWN: {
6154 m = strv_join(arg_wall, " ");
6156 retval = EXIT_FAILURE;
6160 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6162 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6167 case ACTION_INVALID:
6168 case ACTION_RUNLEVEL:
6170 assert_not_reached("Unknown action");
6173 retval = r < 0 ? EXIT_FAILURE : r;
6177 dbus_connection_flush(bus);
6178 dbus_connection_close(bus);
6179 dbus_connection_unref(bus);
6184 strv_free(arg_types);
6185 strv_free(arg_states);
6186 strv_free(arg_properties);
6189 ask_password_agent_close();
6190 polkit_agent_close();