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_free_ DBusMessage *m = NULL, *reply = NULL;
3833 DBusMessageIter iter, sub;
3834 dbus_bool_t runtime;
3839 dbus_error_init(&error);
3841 m = dbus_message_new_method_call(
3842 "org.freedesktop.systemd1",
3843 "/org/freedesktop/systemd1",
3844 "org.freedesktop.systemd1.Manager",
3845 "SetUnitProperties");
3849 dbus_message_iter_init_append(m, &iter);
3851 runtime = arg_runtime;
3853 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[1]) ||
3854 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &runtime) ||
3855 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sv)", &sub))
3858 STRV_FOREACH(i, args + 2) {
3859 DBusMessageIter sub2;
3861 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
3864 r = append_assignment(&sub2, *i);
3868 if (!dbus_message_iter_close_container(&sub, &sub2))
3873 if (!dbus_message_iter_close_container(&iter, &sub))
3876 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3878 log_error("Failed to issue method call: %s", bus_error_message(&error));
3879 dbus_error_free(&error);
3886 static int snapshot(DBusConnection *bus, char **args) {
3887 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3890 dbus_bool_t cleanup = FALSE;
3891 DBusMessageIter iter, sub;
3894 *interface = "org.freedesktop.systemd1.Unit",
3896 _cleanup_free_ char *n = NULL;
3898 dbus_error_init(&error);
3900 if (strv_length(args) > 1)
3901 n = unit_name_mangle_with_suffix(args[1], ".snapshot");
3907 r = bus_method_call_with_reply(
3909 "org.freedesktop.systemd1",
3910 "/org/freedesktop/systemd1",
3911 "org.freedesktop.systemd1.Manager",
3915 DBUS_TYPE_STRING, &n,
3916 DBUS_TYPE_BOOLEAN, &cleanup,
3921 if (!dbus_message_get_args(reply, &error,
3922 DBUS_TYPE_OBJECT_PATH, &path,
3923 DBUS_TYPE_INVALID)) {
3924 log_error("Failed to parse reply: %s", bus_error_message(&error));
3925 dbus_error_free(&error);
3929 dbus_message_unref(reply);
3932 r = bus_method_call_with_reply (
3934 "org.freedesktop.systemd1",
3936 "org.freedesktop.DBus.Properties",
3940 DBUS_TYPE_STRING, &interface,
3941 DBUS_TYPE_STRING, &property,
3946 if (!dbus_message_iter_init(reply, &iter) ||
3947 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3948 log_error("Failed to parse reply.");
3952 dbus_message_iter_recurse(&iter, &sub);
3954 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3955 log_error("Failed to parse reply.");
3959 dbus_message_iter_get_basic(&sub, &id);
3967 static int delete_snapshot(DBusConnection *bus, char **args) {
3972 STRV_FOREACH(name, args+1) {
3973 _cleanup_free_ char *n = NULL;
3976 n = unit_name_mangle_with_suffix(*name, ".snapshot");
3980 r = bus_method_call_with_reply(
3982 "org.freedesktop.systemd1",
3983 "/org/freedesktop/systemd1",
3984 "org.freedesktop.systemd1.Manager",
3988 DBUS_TYPE_STRING, &n,
3997 static int daemon_reload(DBusConnection *bus, char **args) {
4002 if (arg_action == ACTION_RELOAD)
4004 else if (arg_action == ACTION_REEXEC)
4005 method = "Reexecute";
4007 assert(arg_action == ACTION_SYSTEMCTL);
4010 streq(args[0], "clear-jobs") ||
4011 streq(args[0], "cancel") ? "ClearJobs" :
4012 streq(args[0], "daemon-reexec") ? "Reexecute" :
4013 streq(args[0], "reset-failed") ? "ResetFailed" :
4014 streq(args[0], "halt") ? "Halt" :
4015 streq(args[0], "poweroff") ? "PowerOff" :
4016 streq(args[0], "reboot") ? "Reboot" :
4017 streq(args[0], "kexec") ? "KExec" :
4018 streq(args[0], "exit") ? "Exit" :
4019 /* "daemon-reload" */ "Reload";
4022 r = bus_method_call_with_reply(
4024 "org.freedesktop.systemd1",
4025 "/org/freedesktop/systemd1",
4026 "org.freedesktop.systemd1.Manager",
4032 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
4033 /* There's always a fallback possible for
4034 * legacy actions. */
4036 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
4037 /* On reexecution, we expect a disconnect, not a
4041 log_error("Failed to issue method call: %s", bus_error_message(&error));
4043 dbus_error_free(&error);
4047 static int reset_failed(DBusConnection *bus, char **args) {
4051 if (strv_length(args) <= 1)
4052 return daemon_reload(bus, args);
4054 STRV_FOREACH(name, args+1) {
4055 _cleanup_free_ char *n;
4057 n = unit_name_mangle(*name);
4061 r = bus_method_call_with_reply(
4063 "org.freedesktop.systemd1",
4064 "/org/freedesktop/systemd1",
4065 "org.freedesktop.systemd1.Manager",
4069 DBUS_TYPE_STRING, &n,
4078 static int show_enviroment(DBusConnection *bus, char **args) {
4079 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4080 DBusMessageIter iter, sub, sub2;
4083 *interface = "org.freedesktop.systemd1.Manager",
4084 *property = "Environment";
4086 pager_open_if_enabled();
4088 r = bus_method_call_with_reply(
4090 "org.freedesktop.systemd1",
4091 "/org/freedesktop/systemd1",
4092 "org.freedesktop.DBus.Properties",
4096 DBUS_TYPE_STRING, &interface,
4097 DBUS_TYPE_STRING, &property,
4102 if (!dbus_message_iter_init(reply, &iter) ||
4103 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
4104 log_error("Failed to parse reply.");
4108 dbus_message_iter_recurse(&iter, &sub);
4110 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
4111 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
4112 log_error("Failed to parse reply.");
4116 dbus_message_iter_recurse(&sub, &sub2);
4118 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
4121 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
4122 log_error("Failed to parse reply.");
4126 dbus_message_iter_get_basic(&sub2, &text);
4129 dbus_message_iter_next(&sub2);
4135 static int switch_root(DBusConnection *bus, char **args) {
4138 _cleanup_free_ char *init = NULL;
4140 l = strv_length(args);
4141 if (l < 2 || l > 3) {
4142 log_error("Wrong number of arguments.");
4149 init = strdup(args[2]);
4151 parse_env_file("/proc/cmdline", WHITESPACE,
4161 log_debug("switching root - root: %s; init: %s", root, init);
4163 return bus_method_call_with_reply(
4165 "org.freedesktop.systemd1",
4166 "/org/freedesktop/systemd1",
4167 "org.freedesktop.systemd1.Manager",
4171 DBUS_TYPE_STRING, &root,
4172 DBUS_TYPE_STRING, &init,
4176 static int set_environment(DBusConnection *bus, char **args) {
4177 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4180 DBusMessageIter iter;
4186 dbus_error_init(&error);
4188 method = streq(args[0], "set-environment")
4190 : "UnsetEnvironment";
4192 m = dbus_message_new_method_call(
4193 "org.freedesktop.systemd1",
4194 "/org/freedesktop/systemd1",
4195 "org.freedesktop.systemd1.Manager",
4200 dbus_message_iter_init_append(m, &iter);
4202 r = bus_append_strv_iter(&iter, args + 1);
4206 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4208 log_error("Failed to issue method call: %s", bus_error_message(&error));
4209 dbus_error_free(&error);
4216 static int enable_sysv_units(char **args) {
4219 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4220 const char *verb = args[0];
4221 unsigned f = 1, t = 1;
4222 LookupPaths paths = {};
4224 if (arg_scope != UNIT_FILE_SYSTEM)
4227 if (!streq(verb, "enable") &&
4228 !streq(verb, "disable") &&
4229 !streq(verb, "is-enabled"))
4232 /* Processes all SysV units, and reshuffles the array so that
4233 * afterwards only the native units remain */
4235 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4240 for (f = 1; args[f]; f++) {
4242 _cleanup_free_ char *p = NULL, *q = NULL;
4243 bool found_native = false, found_sysv;
4245 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4253 if (!endswith(name, ".service"))
4256 if (path_is_absolute(name))
4259 STRV_FOREACH(k, paths.unit_path) {
4260 if (!isempty(arg_root))
4261 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4263 asprintf(&p, "%s/%s", *k, name);
4270 found_native = access(p, F_OK) >= 0;
4281 if (!isempty(arg_root))
4282 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4284 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4290 p[strlen(p) - sizeof(".service") + 1] = 0;
4291 found_sysv = access(p, F_OK) >= 0;
4296 /* Mark this entry, so that we don't try enabling it as native unit */
4297 args[f] = (char*) "";
4299 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4301 if (!isempty(arg_root))
4302 argv[c++] = q = strappend("--root=", arg_root);
4304 argv[c++] = path_get_file_name(p);
4306 streq(verb, "enable") ? "on" :
4307 streq(verb, "disable") ? "off" : "--level=5";
4310 l = strv_join((char**)argv, " ");
4316 log_info("Executing %s", l);
4321 log_error("Failed to fork: %m");
4324 } else if (pid == 0) {
4327 execv(argv[0], (char**) argv);
4328 _exit(EXIT_FAILURE);
4331 j = wait_for_terminate(pid, &status);
4333 log_error("Failed to wait for child: %s", strerror(-r));
4338 if (status.si_code == CLD_EXITED) {
4339 if (streq(verb, "is-enabled")) {
4340 if (status.si_status == 0) {
4349 } else if (status.si_status != 0) {
4360 lookup_paths_free(&paths);
4362 /* Drop all SysV units */
4363 for (f = 1, t = 1; args[f]; f++) {
4365 if (isempty(args[f]))
4368 args[t++] = args[f];
4377 static int mangle_names(char **original_names, char ***mangled_names) {
4378 char **i, **l, **name;
4380 l = new(char*, strv_length(original_names) + 1);
4385 STRV_FOREACH(name, original_names) {
4387 /* When enabling units qualified path names are OK,
4388 * too, hence allow them explicitly. */
4393 *i = unit_name_mangle(*name);
4409 static int enable_unit(DBusConnection *bus, char **args) {
4410 const char *verb = args[0];
4411 UnitFileChange *changes = NULL;
4412 unsigned n_changes = 0, i;
4413 int carries_install_info = -1;
4414 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4416 _cleanup_dbus_error_free_ DBusError error;
4417 _cleanup_strv_free_ char **mangled_names = NULL;
4419 dbus_error_init(&error);
4421 r = enable_sysv_units(args);
4428 r = mangle_names(args+1, &mangled_names);
4432 if (!bus || avoid_bus()) {
4433 if (streq(verb, "enable")) {
4434 r = unit_file_enable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4435 carries_install_info = r;
4436 } else if (streq(verb, "disable"))
4437 r = unit_file_disable(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4438 else if (streq(verb, "reenable")) {
4439 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4440 carries_install_info = r;
4441 } else if (streq(verb, "link"))
4442 r = unit_file_link(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4443 else if (streq(verb, "preset")) {
4444 r = unit_file_preset(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4445 carries_install_info = r;
4446 } else if (streq(verb, "mask"))
4447 r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4448 else if (streq(verb, "unmask"))
4449 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4450 else if (streq(verb, "set-default"))
4451 r = unit_file_set_default(arg_scope, arg_root, args[1], &changes, &n_changes);
4453 assert_not_reached("Unknown verb");
4456 log_error("Operation failed: %s", strerror(-r));
4461 for (i = 0; i < n_changes; i++) {
4462 if (changes[i].type == UNIT_FILE_SYMLINK)
4463 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4465 log_info("rm '%s'", changes[i].path);
4472 bool send_force = true, expect_carries_install_info = false;
4474 DBusMessageIter iter, sub, sub2;
4476 if (streq(verb, "enable")) {
4477 method = "EnableUnitFiles";
4478 expect_carries_install_info = true;
4479 } else if (streq(verb, "disable")) {
4480 method = "DisableUnitFiles";
4482 } else if (streq(verb, "reenable")) {
4483 method = "ReenableUnitFiles";
4484 expect_carries_install_info = true;
4485 } else if (streq(verb, "link"))
4486 method = "LinkUnitFiles";
4487 else if (streq(verb, "preset")) {
4488 method = "PresetUnitFiles";
4489 expect_carries_install_info = true;
4490 } else if (streq(verb, "mask"))
4491 method = "MaskUnitFiles";
4492 else if (streq(verb, "unmask")) {
4493 method = "UnmaskUnitFiles";
4495 } else if (streq(verb, "set-default")) {
4496 method = "SetDefaultTarget";
4498 assert_not_reached("Unknown verb");
4500 m = dbus_message_new_method_call(
4501 "org.freedesktop.systemd1",
4502 "/org/freedesktop/systemd1",
4503 "org.freedesktop.systemd1.Manager",
4510 dbus_message_iter_init_append(m, &iter);
4512 r = bus_append_strv_iter(&iter, mangled_names);
4514 log_error("Failed to append unit files.");
4519 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4520 log_error("Failed to append runtime boolean.");
4528 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4529 log_error("Failed to append force boolean.");
4535 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4537 log_error("Failed to issue method call: %s", bus_error_message(&error));
4542 if (!dbus_message_iter_init(reply, &iter)) {
4543 log_error("Failed to initialize iterator.");
4547 if (expect_carries_install_info) {
4548 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4550 log_error("Failed to parse reply.");
4554 carries_install_info = b;
4557 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4558 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4559 log_error("Failed to parse reply.");
4564 dbus_message_iter_recurse(&iter, &sub);
4565 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4566 const char *type, *path, *source;
4568 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4569 log_error("Failed to parse reply.");
4574 dbus_message_iter_recurse(&sub, &sub2);
4576 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4577 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4578 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4579 log_error("Failed to parse reply.");
4585 if (streq(type, "symlink"))
4586 log_info("ln -s '%s' '%s'", source, path);
4588 log_info("rm '%s'", path);
4591 dbus_message_iter_next(&sub);
4594 /* Try to reload if enabeld */
4596 r = daemon_reload(bus, args);
4599 if (carries_install_info == 0)
4600 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4601 "using systemctl.\n"
4602 "Possible reasons for having this kind of units are:\n"
4603 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4604 " .wants/ or .requires/ directory.\n"
4605 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4606 " a requirement dependency on it.\n"
4607 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4608 " D-Bus, udev, scripted systemctl call, ...).\n");
4611 unit_file_changes_free(changes, n_changes);
4616 static int unit_is_enabled(DBusConnection *bus, char **args) {
4617 _cleanup_dbus_error_free_ DBusError error;
4619 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4624 dbus_error_init(&error);
4626 r = enable_sysv_units(args);
4632 if (!bus || avoid_bus()) {
4634 STRV_FOREACH(name, args+1) {
4635 UnitFileState state;
4637 n = unit_name_mangle(*name);
4641 state = unit_file_get_state(arg_scope, arg_root, n);
4648 if (state == UNIT_FILE_ENABLED ||
4649 state == UNIT_FILE_ENABLED_RUNTIME ||
4650 state == UNIT_FILE_STATIC)
4654 puts(unit_file_state_to_string(state));
4658 STRV_FOREACH(name, args+1) {
4661 n = unit_name_mangle(*name);
4665 r = bus_method_call_with_reply (
4667 "org.freedesktop.systemd1",
4668 "/org/freedesktop/systemd1",
4669 "org.freedesktop.systemd1.Manager",
4673 DBUS_TYPE_STRING, &n,
4681 if (!dbus_message_get_args(reply, &error,
4682 DBUS_TYPE_STRING, &s,
4683 DBUS_TYPE_INVALID)) {
4684 log_error("Failed to parse reply: %s", bus_error_message(&error));
4688 dbus_message_unref(reply);
4691 if (streq(s, "enabled") ||
4692 streq(s, "enabled-runtime") ||
4701 return enabled ? 0 : 1;
4704 static int systemctl_help(void) {
4706 pager_open_if_enabled();
4708 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4709 "Query or send control commands to the systemd manager.\n\n"
4710 " -h --help Show this help\n"
4711 " --version Show package version\n"
4712 " -t --type=TYPE List only units of a particular type\n"
4713 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
4714 " -p --property=NAME Show only properties by this name\n"
4715 " -a --all Show all loaded units/properties, including dead/empty\n"
4716 " ones. To list all units installed on the system, use\n"
4717 " the 'list-unit-files' command instead.\n"
4718 " --reverse Show reverse dependencies with 'list-dependencies'\n"
4719 " -l --full Don't ellipsize unit names on output\n"
4720 " --fail When queueing a new job, fail if conflicting jobs are\n"
4722 " --irreversible When queueing a new job, make sure it cannot be implicitly\n"
4724 " --ignore-dependencies\n"
4725 " When queueing a new job, ignore all its dependencies\n"
4726 " --show-types When showing sockets, explicitly show their type\n"
4727 " -i --ignore-inhibitors\n"
4728 " When shutting down or sleeping, ignore inhibitors\n"
4729 " --kill-who=WHO Who to send signal to\n"
4730 " -s --signal=SIGNAL Which signal to send\n"
4731 " -H --host=[USER@]HOST\n"
4732 " Show information for remote host\n"
4733 " -P --privileged Acquire privileges before execution\n"
4734 " -q --quiet Suppress output\n"
4735 " --no-block Do not wait until operation finished\n"
4736 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4737 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4739 " --no-legend Do not print a legend (column headers and hints)\n"
4740 " --no-pager Do not pipe output into a pager\n"
4741 " --no-ask-password\n"
4742 " Do not ask for system passwords\n"
4743 " --system Connect to system manager\n"
4744 " --user Connect to user service manager\n"
4745 " --global Enable/disable unit files globally\n"
4746 " --runtime Enable unit files only temporarily until next reboot\n"
4747 " -f --force When enabling unit files, override existing symlinks\n"
4748 " When shutting down, execute action immediately\n"
4749 " --root=PATH Enable unit files in the specified root directory\n"
4750 " -n --lines=INTEGER Numer of journal entries to show\n"
4751 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4752 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4754 " list-units List loaded units\n"
4755 " list-sockets List loaded sockets ordered by address\n"
4756 " start [NAME...] Start (activate) one or more units\n"
4757 " stop [NAME...] Stop (deactivate) one or more units\n"
4758 " reload [NAME...] Reload one or more units\n"
4759 " restart [NAME...] Start or restart one or more units\n"
4760 " try-restart [NAME...] Restart one or more units if active\n"
4761 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4762 " otherwise start or restart\n"
4763 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4764 " otherwise restart if active\n"
4765 " isolate [NAME] Start one unit and stop all others\n"
4766 " kill [NAME...] Send signal to processes of a unit\n"
4767 " is-active [NAME...] Check whether units are active\n"
4768 " is-failed [NAME...] Check whether units are failed\n"
4769 " status [NAME...|PID...] Show runtime status of one or more units\n"
4770 " show [NAME...|JOB...] Show properties of one or more\n"
4771 " units/jobs or the manager\n"
4772 " set-property [NAME] [ASSIGNMENT...]\n"
4773 " Sets one or more properties of a unit\n"
4774 " help [NAME...|PID...] Show manual for one or more units\n"
4775 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4777 " list-dependencies [NAME] Recursively show units which are required\n"
4778 " or wanted by this unit or by which this\n"
4779 " unit is required or wanted\n\n"
4780 "Unit File Commands:\n"
4781 " list-unit-files List installed unit files\n"
4782 " enable [NAME...] Enable one or more unit files\n"
4783 " disable [NAME...] Disable one or more unit files\n"
4784 " reenable [NAME...] Reenable one or more unit files\n"
4785 " preset [NAME...] Enable/disable one or more unit files\n"
4786 " based on preset configuration\n"
4787 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4788 " mask [NAME...] Mask one or more units\n"
4789 " unmask [NAME...] Unmask one or more units\n"
4790 " link [PATH...] Link one or more units files into\n"
4791 " the search path\n"
4792 " get-default Get the name of the default target\n"
4793 " set-default NAME Set the default target\n\n"
4795 " list-jobs List jobs\n"
4796 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4797 "Snapshot Commands:\n"
4798 " snapshot [NAME] Create a snapshot\n"
4799 " delete [NAME...] Remove one or more snapshots\n\n"
4800 "Environment Commands:\n"
4801 " show-environment Dump environment\n"
4802 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4803 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4804 "Manager Lifecycle Commands:\n"
4805 " daemon-reload Reload systemd manager configuration\n"
4806 " daemon-reexec Reexecute systemd manager\n\n"
4807 "System Commands:\n"
4808 " default Enter system default mode\n"
4809 " rescue Enter system rescue mode\n"
4810 " emergency Enter system emergency mode\n"
4811 " halt Shut down and halt the system\n"
4812 " poweroff Shut down and power-off the system\n"
4813 " reboot Shut down and reboot the system\n"
4814 " kexec Shut down and reboot the system with kexec\n"
4815 " exit Request user instance exit\n"
4816 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4817 " suspend Suspend the system\n"
4818 " hibernate Hibernate the system\n"
4819 " hybrid-sleep Hibernate and suspend the system\n",
4820 program_invocation_short_name);
4825 static int halt_help(void) {
4827 printf("%s [OPTIONS...]\n\n"
4828 "%s the system.\n\n"
4829 " --help Show this help\n"
4830 " --halt Halt the machine\n"
4831 " -p --poweroff Switch off the machine\n"
4832 " --reboot Reboot the machine\n"
4833 " -f --force Force immediate halt/power-off/reboot\n"
4834 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4835 " -d --no-wtmp Don't write wtmp record\n"
4836 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4837 program_invocation_short_name,
4838 arg_action == ACTION_REBOOT ? "Reboot" :
4839 arg_action == ACTION_POWEROFF ? "Power off" :
4845 static int shutdown_help(void) {
4847 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4848 "Shut down the system.\n\n"
4849 " --help Show this help\n"
4850 " -H --halt Halt the machine\n"
4851 " -P --poweroff Power-off the machine\n"
4852 " -r --reboot Reboot the machine\n"
4853 " -h Equivalent to --poweroff, overridden by --halt\n"
4854 " -k Don't halt/power-off/reboot, just send warnings\n"
4855 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4856 " -c Cancel a pending shutdown\n",
4857 program_invocation_short_name);
4862 static int telinit_help(void) {
4864 printf("%s [OPTIONS...] {COMMAND}\n\n"
4865 "Send control commands to the init daemon.\n\n"
4866 " --help Show this help\n"
4867 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4869 " 0 Power-off the machine\n"
4870 " 6 Reboot the machine\n"
4871 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4872 " 1, s, S Enter rescue mode\n"
4873 " q, Q Reload init daemon configuration\n"
4874 " u, U Reexecute init daemon\n",
4875 program_invocation_short_name);
4880 static int runlevel_help(void) {
4882 printf("%s [OPTIONS...]\n\n"
4883 "Prints the previous and current runlevel of the init system.\n\n"
4884 " --help Show this help\n",
4885 program_invocation_short_name);
4890 static int help_types(void) {
4894 puts("Available unit types:");
4895 for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4896 t = unit_type_to_string(i);
4904 static int systemctl_parse_argv(int argc, char *argv[]) {
4913 ARG_IGNORE_DEPENDENCIES,
4925 ARG_NO_ASK_PASSWORD,
4933 static const struct option options[] = {
4934 { "help", no_argument, NULL, 'h' },
4935 { "version", no_argument, NULL, ARG_VERSION },
4936 { "type", required_argument, NULL, 't' },
4937 { "property", required_argument, NULL, 'p' },
4938 { "all", no_argument, NULL, 'a' },
4939 { "reverse", no_argument, NULL, ARG_REVERSE },
4940 { "after", no_argument, NULL, ARG_AFTER },
4941 { "before", no_argument, NULL, ARG_BEFORE },
4942 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
4943 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
4944 { "full", no_argument, NULL, 'l' },
4945 { "fail", no_argument, NULL, ARG_FAIL },
4946 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4947 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4948 { "ignore-inhibitors", no_argument, NULL, 'i' },
4949 { "user", no_argument, NULL, ARG_USER },
4950 { "system", no_argument, NULL, ARG_SYSTEM },
4951 { "global", no_argument, NULL, ARG_GLOBAL },
4952 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4953 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4954 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4955 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4956 { "quiet", no_argument, NULL, 'q' },
4957 { "root", required_argument, NULL, ARG_ROOT },
4958 { "force", no_argument, NULL, ARG_FORCE },
4959 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4960 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4961 { "signal", required_argument, NULL, 's' },
4962 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4963 { "host", required_argument, NULL, 'H' },
4964 { "privileged", no_argument, NULL, 'P' },
4965 { "runtime", no_argument, NULL, ARG_RUNTIME },
4966 { "lines", required_argument, NULL, 'n' },
4967 { "output", required_argument, NULL, 'o' },
4968 { "plain", no_argument, NULL, ARG_PLAIN },
4969 { "state", required_argument, NULL, ARG_STATE },
4970 { NULL, 0, NULL, 0 }
4978 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:Pn:o:i", options, NULL)) >= 0) {
4987 puts(PACKAGE_STRING);
4988 puts(SYSTEMD_FEATURES);
4995 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4996 _cleanup_free_ char *type;
4998 type = strndup(word, size);
5002 if (streq(type, "help")) {
5007 if (unit_type_from_string(type) >= 0) {
5008 if (strv_push(&arg_types, type))
5014 /* It's much nicer to use --state= for
5015 * load states, but let's support this
5016 * in --types= too for compatibility
5017 * with old versions */
5018 if (unit_load_state_from_string(optarg) >= 0) {
5019 if (strv_push(&arg_states, type) < 0)
5025 log_error("Unknown unit type or load state '%s'.", type);
5026 log_info("Use -t help to see a list of allowed values.");
5034 /* Make sure that if the empty property list
5035 was specified, we won't show any properties. */
5036 if (isempty(optarg) && !arg_properties) {
5037 arg_properties = strv_new(NULL, NULL);
5038 if (!arg_properties)
5044 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5047 prop = strndup(word, size);
5051 if (strv_push(&arg_properties, prop) < 0) {
5058 /* If the user asked for a particular
5059 * property, show it to him, even if it is
5071 arg_dependency = DEPENDENCY_REVERSE;
5075 arg_dependency = DEPENDENCY_AFTER;
5079 arg_dependency = DEPENDENCY_BEFORE;
5082 case ARG_SHOW_TYPES:
5083 arg_show_types = true;
5087 arg_job_mode = "fail";
5090 case ARG_IRREVERSIBLE:
5091 arg_job_mode = "replace-irreversibly";
5094 case ARG_IGNORE_DEPENDENCIES:
5095 arg_job_mode = "ignore-dependencies";
5099 arg_scope = UNIT_FILE_USER;
5103 arg_scope = UNIT_FILE_SYSTEM;
5107 arg_scope = UNIT_FILE_GLOBAL;
5111 arg_no_block = true;
5115 arg_no_legend = true;
5119 arg_no_pager = true;
5135 if (strv_extend(&arg_states, "failed") < 0)
5153 arg_no_reload = true;
5157 arg_kill_who = optarg;
5161 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5162 log_error("Failed to parse signal string %s.", optarg);
5167 case ARG_NO_ASK_PASSWORD:
5168 arg_ask_password = false;
5172 arg_transport = TRANSPORT_POLKIT;
5176 arg_transport = TRANSPORT_SSH;
5177 parse_user_at_host(optarg, &arg_user, &arg_host);
5185 if (safe_atou(optarg, &arg_lines) < 0) {
5186 log_error("Failed to parse lines '%s'", optarg);
5192 arg_output = output_mode_from_string(optarg);
5193 if (arg_output < 0) {
5194 log_error("Unknown output '%s'.", optarg);
5200 arg_ignore_inhibitors = true;
5211 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5214 s = strndup(word, size);
5218 if (strv_push(&arg_states, s) < 0) {
5230 log_error("Unknown option code '%c'.", c);
5235 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
5236 log_error("Cannot access user instance remotely.");
5243 static int halt_parse_argv(int argc, char *argv[]) {
5252 static const struct option options[] = {
5253 { "help", no_argument, NULL, ARG_HELP },
5254 { "halt", no_argument, NULL, ARG_HALT },
5255 { "poweroff", no_argument, NULL, 'p' },
5256 { "reboot", no_argument, NULL, ARG_REBOOT },
5257 { "force", no_argument, NULL, 'f' },
5258 { "wtmp-only", no_argument, NULL, 'w' },
5259 { "no-wtmp", no_argument, NULL, 'd' },
5260 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5261 { NULL, 0, NULL, 0 }
5269 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5270 if (runlevel == '0' || runlevel == '6')
5273 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5281 arg_action = ACTION_HALT;
5285 if (arg_action != ACTION_REBOOT)
5286 arg_action = ACTION_POWEROFF;
5290 arg_action = ACTION_REBOOT;
5312 /* Compatibility nops */
5319 log_error("Unknown option code '%c'.", c);
5324 if (optind < argc) {
5325 log_error("Too many arguments.");
5332 static int parse_time_spec(const char *t, usec_t *_u) {
5336 if (streq(t, "now"))
5338 else if (!strchr(t, ':')) {
5341 if (safe_atou64(t, &u) < 0)
5344 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5353 hour = strtol(t, &e, 10);
5354 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5357 minute = strtol(e+1, &e, 10);
5358 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5361 n = now(CLOCK_REALTIME);
5362 s = (time_t) (n / USEC_PER_SEC);
5364 assert_se(localtime_r(&s, &tm));
5366 tm.tm_hour = (int) hour;
5367 tm.tm_min = (int) minute;
5370 assert_se(s = mktime(&tm));
5372 *_u = (usec_t) s * USEC_PER_SEC;
5375 *_u += USEC_PER_DAY;
5381 static int shutdown_parse_argv(int argc, char *argv[]) {
5388 static const struct option options[] = {
5389 { "help", no_argument, NULL, ARG_HELP },
5390 { "halt", no_argument, NULL, 'H' },
5391 { "poweroff", no_argument, NULL, 'P' },
5392 { "reboot", no_argument, NULL, 'r' },
5393 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5394 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5395 { NULL, 0, NULL, 0 }
5403 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5411 arg_action = ACTION_HALT;
5415 arg_action = ACTION_POWEROFF;
5420 arg_action = ACTION_KEXEC;
5422 arg_action = ACTION_REBOOT;
5426 arg_action = ACTION_KEXEC;
5430 if (arg_action != ACTION_HALT)
5431 arg_action = ACTION_POWEROFF;
5444 /* Compatibility nops */
5448 arg_action = ACTION_CANCEL_SHUTDOWN;
5455 log_error("Unknown option code '%c'.", c);
5460 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5461 r = parse_time_spec(argv[optind], &arg_when);
5463 log_error("Failed to parse time specification: %s", argv[optind]);
5467 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5469 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5470 /* No time argument for shutdown cancel */
5471 arg_wall = argv + optind;
5472 else if (argc > optind + 1)
5473 /* We skip the time argument */
5474 arg_wall = argv + optind + 1;
5481 static int telinit_parse_argv(int argc, char *argv[]) {
5488 static const struct option options[] = {
5489 { "help", no_argument, NULL, ARG_HELP },
5490 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5491 { NULL, 0, NULL, 0 }
5494 static const struct {
5498 { '0', ACTION_POWEROFF },
5499 { '6', ACTION_REBOOT },
5500 { '1', ACTION_RESCUE },
5501 { '2', ACTION_RUNLEVEL2 },
5502 { '3', ACTION_RUNLEVEL3 },
5503 { '4', ACTION_RUNLEVEL4 },
5504 { '5', ACTION_RUNLEVEL5 },
5505 { 's', ACTION_RESCUE },
5506 { 'S', ACTION_RESCUE },
5507 { 'q', ACTION_RELOAD },
5508 { 'Q', ACTION_RELOAD },
5509 { 'u', ACTION_REEXEC },
5510 { 'U', ACTION_REEXEC }
5519 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5534 log_error("Unknown option code '%c'.", c);
5539 if (optind >= argc) {
5544 if (optind + 1 < argc) {
5545 log_error("Too many arguments.");
5549 if (strlen(argv[optind]) != 1) {
5550 log_error("Expected single character argument.");
5554 for (i = 0; i < ELEMENTSOF(table); i++)
5555 if (table[i].from == argv[optind][0])
5558 if (i >= ELEMENTSOF(table)) {
5559 log_error("Unknown command '%s'.", argv[optind]);
5563 arg_action = table[i].to;
5570 static int runlevel_parse_argv(int argc, char *argv[]) {
5576 static const struct option options[] = {
5577 { "help", no_argument, NULL, ARG_HELP },
5578 { NULL, 0, NULL, 0 }
5586 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5597 log_error("Unknown option code '%c'.", c);
5602 if (optind < argc) {
5603 log_error("Too many arguments.");
5610 static int parse_argv(int argc, char *argv[]) {
5614 if (program_invocation_short_name) {
5616 if (strstr(program_invocation_short_name, "halt")) {
5617 arg_action = ACTION_HALT;
5618 return halt_parse_argv(argc, argv);
5619 } else if (strstr(program_invocation_short_name, "poweroff")) {
5620 arg_action = ACTION_POWEROFF;
5621 return halt_parse_argv(argc, argv);
5622 } else if (strstr(program_invocation_short_name, "reboot")) {
5624 arg_action = ACTION_KEXEC;
5626 arg_action = ACTION_REBOOT;
5627 return halt_parse_argv(argc, argv);
5628 } else if (strstr(program_invocation_short_name, "shutdown")) {
5629 arg_action = ACTION_POWEROFF;
5630 return shutdown_parse_argv(argc, argv);
5631 } else if (strstr(program_invocation_short_name, "init")) {
5633 if (sd_booted() > 0) {
5634 arg_action = ACTION_INVALID;
5635 return telinit_parse_argv(argc, argv);
5637 /* Hmm, so some other init system is
5638 * running, we need to forward this
5639 * request to it. For now we simply
5640 * guess that it is Upstart. */
5642 execv(TELINIT, argv);
5644 log_error("Couldn't find an alternative telinit implementation to spawn.");
5648 } else if (strstr(program_invocation_short_name, "runlevel")) {
5649 arg_action = ACTION_RUNLEVEL;
5650 return runlevel_parse_argv(argc, argv);
5654 arg_action = ACTION_SYSTEMCTL;
5655 return systemctl_parse_argv(argc, argv);
5658 _pure_ static int action_to_runlevel(void) {
5660 static const char table[_ACTION_MAX] = {
5661 [ACTION_HALT] = '0',
5662 [ACTION_POWEROFF] = '0',
5663 [ACTION_REBOOT] = '6',
5664 [ACTION_RUNLEVEL2] = '2',
5665 [ACTION_RUNLEVEL3] = '3',
5666 [ACTION_RUNLEVEL4] = '4',
5667 [ACTION_RUNLEVEL5] = '5',
5668 [ACTION_RESCUE] = '1'
5671 assert(arg_action < _ACTION_MAX);
5673 return table[arg_action];
5676 static int talk_upstart(void) {
5677 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
5678 _cleanup_dbus_error_free_ DBusError error;
5679 int previous, rl, r;
5681 env1_buf[] = "RUNLEVEL=X",
5682 env2_buf[] = "PREVLEVEL=X";
5683 char *env1 = env1_buf, *env2 = env2_buf;
5684 const char *emit = "runlevel";
5685 dbus_bool_t b_false = FALSE;
5686 DBusMessageIter iter, sub;
5687 DBusConnection *bus;
5689 dbus_error_init(&error);
5691 if (!(rl = action_to_runlevel()))
5694 if (utmp_get_runlevel(&previous, NULL) < 0)
5697 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5698 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5703 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5708 if ((r = bus_check_peercred(bus)) < 0) {
5709 log_error("Failed to verify owner of bus.");
5713 if (!(m = dbus_message_new_method_call(
5714 "com.ubuntu.Upstart",
5715 "/com/ubuntu/Upstart",
5716 "com.ubuntu.Upstart0_6",
5719 log_error("Could not allocate message.");
5724 dbus_message_iter_init_append(m, &iter);
5726 env1_buf[sizeof(env1_buf)-2] = rl;
5727 env2_buf[sizeof(env2_buf)-2] = previous;
5729 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5730 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5731 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5732 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5733 !dbus_message_iter_close_container(&iter, &sub) ||
5734 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5735 log_error("Could not append arguments to message.");
5740 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5742 if (bus_error_is_no_service(&error)) {
5747 log_error("Failed to issue method call: %s", bus_error_message(&error));
5756 dbus_connection_flush(bus);
5757 dbus_connection_close(bus);
5758 dbus_connection_unref(bus);
5764 static int talk_initctl(void) {
5765 struct init_request request = {};
5767 _cleanup_close_ int fd = -1;
5770 rl = action_to_runlevel();
5774 request.magic = INIT_MAGIC;
5775 request.sleeptime = 0;
5776 request.cmd = INIT_CMD_RUNLVL;
5777 request.runlevel = rl;
5779 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5781 if (errno == ENOENT)
5784 log_error("Failed to open "INIT_FIFO": %m");
5789 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5791 log_error("Failed to write to "INIT_FIFO": %m");
5792 return errno > 0 ? -errno : -EIO;
5798 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5800 static const struct {
5808 int (* const dispatch)(DBusConnection *bus, char **args);
5810 { "list-units", LESS, 1, list_units },
5811 { "list-unit-files", EQUAL, 1, list_unit_files },
5812 { "list-sockets", LESS, 1, list_sockets },
5813 { "list-jobs", EQUAL, 1, list_jobs },
5814 { "clear-jobs", EQUAL, 1, daemon_reload },
5815 { "cancel", MORE, 2, cancel_job },
5816 { "start", MORE, 2, start_unit },
5817 { "stop", MORE, 2, start_unit },
5818 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5819 { "reload", MORE, 2, start_unit },
5820 { "restart", MORE, 2, start_unit },
5821 { "try-restart", MORE, 2, start_unit },
5822 { "reload-or-restart", MORE, 2, start_unit },
5823 { "reload-or-try-restart", MORE, 2, start_unit },
5824 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5825 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5826 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5827 { "isolate", EQUAL, 2, start_unit },
5828 { "kill", MORE, 2, kill_unit },
5829 { "is-active", MORE, 2, check_unit_active },
5830 { "check", MORE, 2, check_unit_active },
5831 { "is-failed", MORE, 2, check_unit_failed },
5832 { "show", MORE, 1, show },
5833 { "status", MORE, 1, show },
5834 { "help", MORE, 2, show },
5835 { "snapshot", LESS, 2, snapshot },
5836 { "delete", MORE, 2, delete_snapshot },
5837 { "daemon-reload", EQUAL, 1, daemon_reload },
5838 { "daemon-reexec", EQUAL, 1, daemon_reload },
5839 { "show-environment", EQUAL, 1, show_enviroment },
5840 { "set-environment", MORE, 2, set_environment },
5841 { "unset-environment", MORE, 2, set_environment },
5842 { "halt", EQUAL, 1, start_special },
5843 { "poweroff", EQUAL, 1, start_special },
5844 { "reboot", EQUAL, 1, start_special },
5845 { "kexec", EQUAL, 1, start_special },
5846 { "suspend", EQUAL, 1, start_special },
5847 { "hibernate", EQUAL, 1, start_special },
5848 { "hybrid-sleep", EQUAL, 1, start_special },
5849 { "default", EQUAL, 1, start_special },
5850 { "rescue", EQUAL, 1, start_special },
5851 { "emergency", EQUAL, 1, start_special },
5852 { "exit", EQUAL, 1, start_special },
5853 { "reset-failed", MORE, 1, reset_failed },
5854 { "enable", MORE, 2, enable_unit },
5855 { "disable", MORE, 2, enable_unit },
5856 { "is-enabled", MORE, 2, unit_is_enabled },
5857 { "reenable", MORE, 2, enable_unit },
5858 { "preset", MORE, 2, enable_unit },
5859 { "mask", MORE, 2, enable_unit },
5860 { "unmask", MORE, 2, enable_unit },
5861 { "link", MORE, 2, enable_unit },
5862 { "switch-root", MORE, 2, switch_root },
5863 { "list-dependencies", LESS, 2, list_dependencies },
5864 { "set-default", EQUAL, 2, enable_unit },
5865 { "get-default", LESS, 1, get_default },
5866 { "set-property", MORE, 3, set_property },
5876 left = argc - optind;
5879 /* Special rule: no arguments means "list-units" */
5882 if (streq(argv[optind], "help") && !argv[optind+1]) {
5883 log_error("This command expects one or more "
5884 "unit names. Did you mean --help?");
5888 for (i = 0; i < ELEMENTSOF(verbs); i++)
5889 if (streq(argv[optind], verbs[i].verb))
5892 if (i >= ELEMENTSOF(verbs)) {
5893 log_error("Unknown operation '%s'.", argv[optind]);
5898 switch (verbs[i].argc_cmp) {
5901 if (left != verbs[i].argc) {
5902 log_error("Invalid number of arguments.");
5909 if (left < verbs[i].argc) {
5910 log_error("Too few arguments.");
5917 if (left > verbs[i].argc) {
5918 log_error("Too many arguments.");
5925 assert_not_reached("Unknown comparison operator.");
5928 /* Require a bus connection for all operations but
5930 if (!streq(verbs[i].verb, "enable") &&
5931 !streq(verbs[i].verb, "disable") &&
5932 !streq(verbs[i].verb, "is-enabled") &&
5933 !streq(verbs[i].verb, "list-unit-files") &&
5934 !streq(verbs[i].verb, "reenable") &&
5935 !streq(verbs[i].verb, "preset") &&
5936 !streq(verbs[i].verb, "mask") &&
5937 !streq(verbs[i].verb, "unmask") &&
5938 !streq(verbs[i].verb, "link") &&
5939 !streq(verbs[i].verb, "set-default") &&
5940 !streq(verbs[i].verb, "get-default")) {
5942 if (running_in_chroot() > 0) {
5943 log_info("Running in chroot, ignoring request.");
5947 if (((!streq(verbs[i].verb, "reboot") &&
5948 !streq(verbs[i].verb, "halt") &&
5949 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5950 log_error("Failed to get D-Bus connection: %s",
5951 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5957 if (!bus && !avoid_bus()) {
5958 log_error("Failed to get D-Bus connection: %s",
5959 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5964 return verbs[i].dispatch(bus, argv + optind);
5967 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5968 _cleanup_close_ int fd;
5969 struct sd_shutdown_command c = {
5975 union sockaddr_union sockaddr = {
5976 .un.sun_family = AF_UNIX,
5977 .un.sun_path = "/run/systemd/shutdownd",
5979 struct iovec iovec[2] = {
5980 {.iov_base = (char*) &c,
5981 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
5984 struct msghdr msghdr = {
5985 .msg_name = &sockaddr,
5986 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
5987 + sizeof("/run/systemd/shutdownd") - 1,
5992 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5996 if (!isempty(message)) {
5997 iovec[1].iov_base = (char*) message;
5998 iovec[1].iov_len = strlen(message);
5999 msghdr.msg_iovlen++;
6002 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
6008 static int reload_with_fallback(DBusConnection *bus) {
6011 /* First, try systemd via D-Bus. */
6012 if (daemon_reload(bus, NULL) >= 0)
6016 /* Nothing else worked, so let's try signals */
6017 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
6019 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
6020 log_error("kill() failed: %m");
6027 static int start_with_fallback(DBusConnection *bus) {
6030 /* First, try systemd via D-Bus. */
6031 if (start_unit(bus, NULL) >= 0)
6035 /* Hmm, talking to systemd via D-Bus didn't work. Then
6036 * let's try to talk to Upstart via D-Bus. */
6037 if (talk_upstart() > 0)
6040 /* Nothing else worked, so let's try
6042 if (talk_initctl() > 0)
6045 log_error("Failed to talk to init daemon.");
6049 warn_wall(arg_action);
6053 static _noreturn_ void halt_now(enum action a) {
6055 /* Make sure C-A-D is handled by the kernel from this
6057 reboot(RB_ENABLE_CAD);
6062 log_info("Halting.");
6063 reboot(RB_HALT_SYSTEM);
6066 case ACTION_POWEROFF:
6067 log_info("Powering off.");
6068 reboot(RB_POWER_OFF);
6072 log_info("Rebooting.");
6073 reboot(RB_AUTOBOOT);
6077 assert_not_reached("Unknown halt action.");
6080 assert_not_reached("Uh? This shouldn't happen.");
6083 static int halt_main(DBusConnection *bus) {
6086 r = check_inhibitors(bus, arg_action);
6090 if (geteuid() != 0) {
6091 /* Try logind if we are a normal user and no special
6092 * mode applies. Maybe PolicyKit allows us to shutdown
6095 if (arg_when <= 0 &&
6098 (arg_action == ACTION_POWEROFF ||
6099 arg_action == ACTION_REBOOT)) {
6100 r = reboot_with_logind(bus, arg_action);
6105 log_error("Must be root.");
6110 _cleanup_free_ char *m;
6112 m = strv_join(arg_wall, " ");
6113 r = send_shutdownd(arg_when,
6114 arg_action == ACTION_HALT ? 'H' :
6115 arg_action == ACTION_POWEROFF ? 'P' :
6116 arg_action == ACTION_KEXEC ? 'K' :
6123 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6125 char date[FORMAT_TIMESTAMP_MAX];
6127 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6128 format_timestamp(date, sizeof(date), arg_when));
6133 if (!arg_dry && !arg_force)
6134 return start_with_fallback(bus);
6137 if (sd_booted() > 0)
6138 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6140 r = utmp_put_shutdown();
6142 log_warning("Failed to write utmp record: %s", strerror(-r));
6149 halt_now(arg_action);
6150 /* We should never reach this. */
6154 static int runlevel_main(void) {
6155 int r, runlevel, previous;
6157 r = utmp_get_runlevel(&runlevel, &previous);
6164 previous <= 0 ? 'N' : previous,
6165 runlevel <= 0 ? 'N' : runlevel);
6170 int main(int argc, char*argv[]) {
6171 int r, retval = EXIT_FAILURE;
6172 DBusConnection *bus = NULL;
6173 _cleanup_dbus_error_free_ DBusError error;
6175 dbus_error_init(&error);
6177 setlocale(LC_ALL, "");
6178 log_parse_environment();
6181 /* Explicitly not on_tty() to avoid setting cached value.
6182 * This becomes relevant for piping output which might be
6184 original_stdout_is_tty = isatty(STDOUT_FILENO);
6186 r = parse_argv(argc, argv);
6190 retval = EXIT_SUCCESS;
6194 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6195 * let's shortcut this */
6196 if (arg_action == ACTION_RUNLEVEL) {
6197 r = runlevel_main();
6198 retval = r < 0 ? EXIT_FAILURE : r;
6202 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6203 log_info("Running in chroot, ignoring request.");
6209 if (arg_transport == TRANSPORT_NORMAL)
6210 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
6211 else if (arg_transport == TRANSPORT_POLKIT) {
6212 bus_connect_system_polkit(&bus, &error);
6213 private_bus = false;
6214 } else if (arg_transport == TRANSPORT_SSH) {
6215 bus_connect_system_ssh(arg_user, arg_host, &bus, &error);
6216 private_bus = false;
6218 assert_not_reached("Uh, invalid transport...");
6221 switch (arg_action) {
6223 case ACTION_SYSTEMCTL:
6224 r = systemctl_main(bus, argc, argv, &error);
6228 case ACTION_POWEROFF:
6234 case ACTION_RUNLEVEL2:
6235 case ACTION_RUNLEVEL3:
6236 case ACTION_RUNLEVEL4:
6237 case ACTION_RUNLEVEL5:
6239 case ACTION_EMERGENCY:
6240 case ACTION_DEFAULT:
6241 r = start_with_fallback(bus);
6246 r = reload_with_fallback(bus);
6249 case ACTION_CANCEL_SHUTDOWN: {
6253 m = strv_join(arg_wall, " ");
6255 retval = EXIT_FAILURE;
6259 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6261 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6266 case ACTION_INVALID:
6267 case ACTION_RUNLEVEL:
6269 assert_not_reached("Unknown action");
6272 retval = r < 0 ? EXIT_FAILURE : r;
6276 dbus_connection_flush(bus);
6277 dbus_connection_close(bus);
6278 dbus_connection_unref(bus);
6283 strv_free(arg_types);
6284 strv_free(arg_states);
6285 strv_free(arg_properties);
6288 ask_password_agent_close();
6289 polkit_agent_close();