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