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 enum dependency {
80 } arg_dependency = DEPENDENCY_FORWARD;
81 static const char *arg_job_mode = "replace";
82 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
83 static bool arg_no_block = false;
84 static bool arg_no_legend = false;
85 static bool arg_no_pager = false;
86 static bool arg_no_wtmp = false;
87 static bool arg_no_wall = false;
88 static bool arg_no_reload = false;
89 static bool arg_show_types = false;
90 static bool arg_ignore_inhibitors = false;
91 static bool arg_dry = false;
92 static bool arg_quiet = false;
93 static bool arg_full = false;
94 static int arg_force = 0;
95 static bool arg_ask_password = true;
96 static bool arg_runtime = false;
97 static char **arg_wall = NULL;
98 static const char *arg_kill_who = NULL;
99 static int arg_signal = SIGTERM;
100 static const char *arg_root = NULL;
101 static usec_t arg_when = 0;
123 ACTION_CANCEL_SHUTDOWN,
125 } arg_action = ACTION_SYSTEMCTL;
126 static enum transport {
130 } arg_transport = TRANSPORT_NORMAL;
131 static char *arg_host = NULL;
132 static char *arg_user = NULL;
133 static unsigned arg_lines = 10;
134 static OutputMode arg_output = OUTPUT_SHORT;
135 static bool arg_plain = false;
137 static bool private_bus = false;
139 static int daemon_reload(DBusConnection *bus, char **args);
140 static void halt_now(enum action a);
142 static void pager_open_if_enabled(void) {
150 static void ask_password_agent_open_if_enabled(void) {
152 /* Open the password agent as a child process if necessary */
154 if (!arg_ask_password)
157 if (arg_scope != UNIT_FILE_SYSTEM)
160 ask_password_agent_open();
164 static void polkit_agent_open_if_enabled(void) {
166 /* Open the polkit agent as a child process if necessary */
168 if (!arg_ask_password)
171 if (arg_scope != UNIT_FILE_SYSTEM)
178 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
181 if (!dbus_error_is_set(error))
184 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
185 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
186 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
187 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
188 return EXIT_NOPERMISSION;
190 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
191 return EXIT_NOTINSTALLED;
193 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
194 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
195 return EXIT_NOTIMPLEMENTED;
197 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
198 return EXIT_NOTCONFIGURED;
206 static void warn_wall(enum action a) {
207 static const char *table[_ACTION_MAX] = {
208 [ACTION_HALT] = "The system is going down for system halt NOW!",
209 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
210 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
211 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
212 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
213 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
214 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
221 _cleanup_free_ char *p;
223 p = strv_join(arg_wall, " ");
238 utmp_wall(table[a], NULL);
241 static bool avoid_bus(void) {
243 if (running_in_chroot() > 0)
246 if (sd_booted() <= 0)
249 if (!isempty(arg_root))
252 if (arg_scope == UNIT_FILE_GLOBAL)
258 static int compare_unit_info(const void *a, const void *b) {
260 const struct unit_info *u = a, *v = b;
262 d1 = strrchr(u->id, '.');
263 d2 = strrchr(v->id, '.');
268 r = strcasecmp(d1, d2);
273 return strcasecmp(u->id, v->id);
276 static bool output_show_unit(const struct unit_info *u) {
279 if (!strv_isempty(arg_states))
280 return strv_contains(arg_states, u->load_state) || strv_contains(arg_states, u->sub_state) || strv_contains(arg_states, u->active_state);
282 return (!arg_types || ((dot = strrchr(u->id, '.')) &&
283 strv_find(arg_types, dot+1))) &&
284 (arg_all || !(streq(u->active_state, "inactive")
285 || u->following[0]) || u->job_id > 0);
288 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
289 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
290 const struct unit_info *u;
293 max_id_len = sizeof("UNIT")-1;
294 active_len = sizeof("ACTIVE")-1;
295 sub_len = sizeof("SUB")-1;
296 job_len = sizeof("JOB")-1;
299 for (u = unit_infos; u < unit_infos + c; u++) {
300 if (!output_show_unit(u))
303 max_id_len = MAX(max_id_len, strlen(u->id));
304 active_len = MAX(active_len, strlen(u->active_state));
305 sub_len = MAX(sub_len, strlen(u->sub_state));
306 if (u->job_id != 0) {
307 job_len = MAX(job_len, strlen(u->job_type));
314 id_len = MIN(max_id_len, 25u);
315 basic_len = 5 + id_len + 5 + active_len + sub_len;
317 basic_len += job_len + 1;
318 if (basic_len < (unsigned) columns()) {
319 unsigned extra_len, incr;
320 extra_len = columns() - basic_len;
321 /* Either UNIT already got 25, or is fully satisfied.
322 * Grant up to 25 to DESC now. */
323 incr = MIN(extra_len, 25u);
326 /* split the remaining space between UNIT and DESC,
327 * but do not give UNIT more than it needs. */
329 incr = MIN(extra_len / 2, max_id_len - id_len);
331 desc_len += extra_len - incr;
337 for (u = unit_infos; u < unit_infos + c; u++) {
338 _cleanup_free_ char *e = NULL;
339 const char *on_loaded, *off_loaded, *on = "";
340 const char *on_active, *off_active, *off = "";
342 if (!output_show_unit(u))
345 if (!n_shown && !arg_no_legend) {
346 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
347 active_len, "ACTIVE", sub_len, "SUB");
349 printf("%-*s ", job_len, "JOB");
350 if (!arg_full && arg_no_pager)
351 printf("%.*s\n", desc_len, "DESCRIPTION");
353 printf("%s\n", "DESCRIPTION");
358 if (streq(u->load_state, "error") ||
359 streq(u->load_state, "not-found")) {
360 on_loaded = on = ansi_highlight_red();
361 off_loaded = off = ansi_highlight_off();
363 on_loaded = off_loaded = "";
365 if (streq(u->active_state, "failed")) {
366 on_active = on = ansi_highlight_red();
367 off_active = off = ansi_highlight_off();
369 on_active = off_active = "";
371 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
373 printf("%s%-*s%s %s%-6s%s %s%-*s %-*s%s %-*s",
374 on, id_len, e ? e : u->id, off,
375 on_loaded, u->load_state, off_loaded,
376 on_active, active_len, u->active_state,
377 sub_len, u->sub_state, off_active,
378 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
379 if (!arg_full && arg_no_pager)
380 printf("%.*s\n", desc_len, u->description);
382 printf("%s\n", u->description);
385 if (!arg_no_legend) {
386 const char *on, *off;
389 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
390 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
391 "SUB = The low-level unit activation state, values depend on unit type.\n");
393 printf("JOB = Pending job for the unit.\n");
395 on = ansi_highlight();
396 off = ansi_highlight_off();
398 on = ansi_highlight_red();
399 off = ansi_highlight_off();
403 printf("%s%u loaded units listed.%s\n"
404 "To show all installed unit files use 'systemctl list-unit-files'.\n",
407 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
408 "To show all installed unit files use 'systemctl list-unit-files'.\n",
413 static int get_unit_list(
416 struct unit_info **unit_infos,
419 DBusMessageIter iter, sub;
427 r = bus_method_call_with_reply(
429 "org.freedesktop.systemd1",
430 "/org/freedesktop/systemd1",
431 "org.freedesktop.systemd1.Manager",
439 if (!dbus_message_iter_init(*reply, &iter) ||
440 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
441 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
442 log_error("Failed to parse reply.");
446 dbus_message_iter_recurse(&iter, &sub);
448 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
449 if (!GREEDY_REALLOC(*unit_infos, size, *c + 1))
452 bus_parse_unit_info(&sub, *unit_infos + *c);
455 dbus_message_iter_next(&sub);
461 static int list_units(DBusConnection *bus, char **args) {
462 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
463 _cleanup_free_ struct unit_info *unit_infos = NULL;
467 pager_open_if_enabled();
469 r = get_unit_list(bus, &reply, &unit_infos, &c);
473 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
475 output_units_list(unit_infos, c);
480 static int get_triggered_units(
482 const char* unit_path,
485 const char *interface = "org.freedesktop.systemd1.Unit",
486 *triggers_property = "Triggers";
487 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
488 DBusMessageIter iter, sub;
491 r = bus_method_call_with_reply(bus,
492 "org.freedesktop.systemd1",
494 "org.freedesktop.DBus.Properties",
498 DBUS_TYPE_STRING, &interface,
499 DBUS_TYPE_STRING, &triggers_property,
504 if (!dbus_message_iter_init(reply, &iter) ||
505 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
506 log_error("Failed to parse reply.");
510 dbus_message_iter_recurse(&iter, &sub);
511 dbus_message_iter_recurse(&sub, &iter);
514 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
517 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
518 log_error("Failed to parse reply.");
522 dbus_message_iter_get_basic(&sub, &unit);
523 r = strv_extend(triggered, unit);
527 dbus_message_iter_next(&sub);
533 static int get_listening(DBusConnection *bus, const char* unit_path,
534 char*** listen, unsigned *c)
536 const char *interface = "org.freedesktop.systemd1.Socket",
537 *listen_property = "Listen";
538 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
539 DBusMessageIter iter, sub;
542 r = bus_method_call_with_reply(bus,
543 "org.freedesktop.systemd1",
545 "org.freedesktop.DBus.Properties",
549 DBUS_TYPE_STRING, &interface,
550 DBUS_TYPE_STRING, &listen_property,
555 if (!dbus_message_iter_init(reply, &iter) ||
556 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
557 log_error("Failed to parse reply.");
561 dbus_message_iter_recurse(&iter, &sub);
562 dbus_message_iter_recurse(&sub, &iter);
565 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
566 DBusMessageIter sub2;
567 const char *type, *path;
569 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
570 log_error("Failed to parse reply.");
574 dbus_message_iter_recurse(&sub, &sub2);
576 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
577 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
578 r = strv_extend(listen, type);
582 r = strv_extend(listen, path);
589 dbus_message_iter_next(&sub);
601 /* Note: triggered is a list here, although it almost certainly
602 * will always be one unit. Nevertheless, dbus API allows for multiple
603 * values, so let's follow that.*/
606 /* The strv above is shared. free is set only in the first one. */
610 static int socket_info_compare(struct socket_info *a, struct socket_info *b) {
611 int o = strcmp(a->path, b->path);
613 o = strcmp(a->type, b->type);
617 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
618 struct socket_info *s;
619 unsigned pathlen = sizeof("LISTEN") - 1,
620 typelen = (sizeof("TYPE") - 1) * arg_show_types,
621 socklen = sizeof("UNIT") - 1,
622 servlen = sizeof("ACTIVATES") - 1;
623 const char *on, *off;
625 for (s = socket_infos; s < socket_infos + cs; s++) {
629 socklen = MAX(socklen, strlen(s->id));
631 typelen = MAX(typelen, strlen(s->type));
632 pathlen = MAX(pathlen, strlen(s->path));
634 STRV_FOREACH(a, s->triggered)
635 tmp += strlen(*a) + 2*(a != s->triggered);
636 servlen = MAX(servlen, tmp);
641 printf("%-*s %-*.*s%-*s %s\n",
643 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
647 for (s = socket_infos; s < socket_infos + cs; s++) {
651 printf("%-*s %-*s %-*s",
652 pathlen, s->path, typelen, s->type, socklen, s->id);
655 pathlen, s->path, socklen, s->id);
656 STRV_FOREACH(a, s->triggered)
658 a == s->triggered ? "" : ",", *a);
662 on = ansi_highlight();
663 off = ansi_highlight_off();
667 on = ansi_highlight_red();
668 off = ansi_highlight_off();
671 if (!arg_no_legend) {
672 printf("%s%u sockets listed.%s\n", on, cs, off);
674 printf("Pass --all to see loaded but inactive sockets, too.\n");
680 static int list_sockets(DBusConnection *bus, char **args) {
681 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
682 _cleanup_free_ struct unit_info *unit_infos = NULL;
683 struct socket_info *socket_infos = NULL;
684 const struct unit_info *u;
685 struct socket_info *s;
686 unsigned cu = 0, cs = 0;
690 pager_open_if_enabled();
692 r = get_unit_list(bus, &reply, &unit_infos, &cu);
696 for (u = unit_infos; u < unit_infos + cu; u++) {
698 _cleanup_strv_free_ char **listen = NULL, **triggered = NULL;
701 if (!output_show_unit(u))
704 if ((dot = strrchr(u->id, '.')) && !streq(dot+1, "socket"))
707 r = get_triggered_units(bus, u->unit_path, &triggered);
711 r = get_listening(bus, u->unit_path, &listen, &c);
715 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
720 for (i = 0; i < c; i++)
721 socket_infos[cs + i] = (struct socket_info) {
724 .path = listen[i*2 + 1],
725 .triggered = triggered,
726 .own_triggered = i==0,
729 /* from this point on we will cleanup those socket_infos */
732 listen = triggered = NULL; /* avoid cleanup */
735 qsort(socket_infos, cs, sizeof(struct socket_info),
736 (__compar_fn_t) socket_info_compare);
738 output_sockets_list(socket_infos, cs);
741 assert(cs == 0 || socket_infos);
742 for (s = socket_infos; s < socket_infos + cs; s++) {
745 if (s->own_triggered)
746 strv_free(s->triggered);
753 static int compare_unit_file_list(const void *a, const void *b) {
755 const UnitFileList *u = a, *v = b;
757 d1 = strrchr(u->path, '.');
758 d2 = strrchr(v->path, '.');
763 r = strcasecmp(d1, d2);
768 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
771 static bool output_show_unit_file(const UnitFileList *u) {
774 return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
777 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
778 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
779 const UnitFileList *u;
781 max_id_len = sizeof("UNIT FILE")-1;
782 state_cols = sizeof("STATE")-1;
783 for (u = units; u < units + c; u++) {
784 if (!output_show_unit_file(u))
787 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
788 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
793 id_cols = MIN(max_id_len, 25u);
794 basic_cols = 1 + id_cols + state_cols;
795 if (basic_cols < (unsigned) columns())
796 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
798 id_cols = max_id_len;
801 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
803 for (u = units; u < units + c; u++) {
804 _cleanup_free_ char *e = NULL;
805 const char *on, *off;
808 if (!output_show_unit_file(u))
813 if (u->state == UNIT_FILE_MASKED ||
814 u->state == UNIT_FILE_MASKED_RUNTIME ||
815 u->state == UNIT_FILE_DISABLED ||
816 u->state == UNIT_FILE_INVALID) {
817 on = ansi_highlight_red();
818 off = ansi_highlight_off();
819 } else if (u->state == UNIT_FILE_ENABLED) {
820 on = ansi_highlight_green();
821 off = ansi_highlight_off();
825 id = path_get_file_name(u->path);
827 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
829 printf("%-*s %s%-*s%s\n",
831 on, state_cols, unit_file_state_to_string(u->state), off);
835 printf("\n%u unit files listed.\n", n_shown);
838 static int list_unit_files(DBusConnection *bus, char **args) {
839 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
840 _cleanup_free_ UnitFileList *units = NULL;
841 DBusMessageIter iter, sub, sub2;
842 unsigned c = 0, n_units = 0;
845 pager_open_if_enabled();
852 h = hashmap_new(string_hash_func, string_compare_func);
856 r = unit_file_get_list(arg_scope, arg_root, h);
858 unit_file_list_free(h);
859 log_error("Failed to get unit file list: %s", strerror(-r));
863 n_units = hashmap_size(h);
864 units = new(UnitFileList, n_units);
866 unit_file_list_free(h);
870 HASHMAP_FOREACH(u, h, i) {
871 memcpy(units + c++, u, sizeof(UnitFileList));
877 r = bus_method_call_with_reply(
879 "org.freedesktop.systemd1",
880 "/org/freedesktop/systemd1",
881 "org.freedesktop.systemd1.Manager",
889 if (!dbus_message_iter_init(reply, &iter) ||
890 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
891 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
892 log_error("Failed to parse reply.");
896 dbus_message_iter_recurse(&iter, &sub);
898 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
902 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
907 n_units = MAX(2*c, 16u);
908 w = realloc(units, sizeof(struct UnitFileList) * n_units);
917 dbus_message_iter_recurse(&sub, &sub2);
919 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
920 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
921 log_error("Failed to parse reply.");
925 u->state = unit_file_state_from_string(state);
927 dbus_message_iter_next(&sub);
933 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
934 output_unit_file_list(units, c);
940 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
942 _cleanup_free_ char *n = NULL;
944 size_t max_len = MAX(columns(),20u);
947 for (i = level - 1; i >= 0; i--) {
949 if(len > max_len - 3 && !arg_full) {
950 printf("%s...\n",max_len % 2 ? "" : " ");
953 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
956 if(len > max_len - 3 && !arg_full) {
957 printf("%s...\n",max_len % 2 ? "" : " ");
960 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
964 printf("%s\n", name);
968 n = ellipsize(name, max_len-len, 100);
976 static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
977 static const char *dependencies[] = {
978 [DEPENDENCY_FORWARD] = "Requires\0"
979 "RequiresOverridable\0"
981 "RequisiteOverridable\0"
983 [DEPENDENCY_REVERSE] = "RequiredBy\0"
984 "RequiredByOverridable\0"
987 [DEPENDENCY_AFTER] = "After\0",
988 [DEPENDENCY_BEFORE] = "Before\0",
991 _cleanup_free_ char *path;
992 const char *interface = "org.freedesktop.systemd1.Unit";
994 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
995 DBusMessageIter iter, sub, sub2, sub3;
1004 path = unit_dbus_path_from_name(name);
1010 r = bus_method_call_with_reply(
1012 "org.freedesktop.systemd1",
1014 "org.freedesktop.DBus.Properties",
1018 DBUS_TYPE_STRING, &interface,
1023 if (!dbus_message_iter_init(reply, &iter) ||
1024 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1025 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
1026 log_error("Failed to parse reply.");
1031 dbus_message_iter_recurse(&iter, &sub);
1033 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1036 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
1037 dbus_message_iter_recurse(&sub, &sub2);
1039 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
1040 log_error("Failed to parse reply.");
1045 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
1046 log_error("Failed to parse reply.");
1051 dbus_message_iter_recurse(&sub2, &sub3);
1052 dbus_message_iter_next(&sub);
1054 assert(arg_dependency < ELEMENTSOF(dependencies));
1055 if (!nulstr_contains(dependencies[arg_dependency], prop))
1058 if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
1059 if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
1060 DBusMessageIter sub4;
1061 dbus_message_iter_recurse(&sub3, &sub4);
1063 while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
1066 assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
1067 dbus_message_iter_get_basic(&sub4, &s);
1069 r = strv_extend(&ret, s);
1075 dbus_message_iter_next(&sub4);
1088 static int list_dependencies_compare(const void *_a, const void *_b) {
1089 const char **a = (const char**) _a, **b = (const char**) _b;
1090 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1092 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1094 return strcasecmp(*a, *b);
1097 static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char ***units, unsigned int branches) {
1098 _cleanup_strv_free_ char **deps = NULL, **u;
1102 u = strv_append(*units, name);
1106 r = list_dependencies_get_dependencies(bus, name, &deps);
1110 qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1112 STRV_FOREACH(c, deps) {
1113 if (strv_contains(u, *c)) {
1115 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1122 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1126 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1127 r = list_dependencies_one(bus, *c, level + 1, &u, (branches << 1) | (c[1] == NULL ? 0 : 1));
1140 static int list_dependencies(DBusConnection *bus, char **args) {
1141 _cleanup_free_ char *unit = NULL;
1142 _cleanup_strv_free_ char **units = NULL;
1148 unit = unit_name_mangle(args[1]);
1153 u = SPECIAL_DEFAULT_TARGET;
1155 pager_open_if_enabled();
1159 return list_dependencies_one(bus, u, 0, &units, 0);
1162 static int get_default(DBusConnection *bus, char **args) {
1164 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1166 _cleanup_dbus_error_free_ DBusError error;
1168 dbus_error_init(&error);
1170 if (!bus || avoid_bus()) {
1171 r = unit_file_get_default(arg_scope, arg_root, &path);
1174 log_error("Operation failed: %s", strerror(-r));
1180 r = bus_method_call_with_reply(
1182 "org.freedesktop.systemd1",
1183 "/org/freedesktop/systemd1",
1184 "org.freedesktop.systemd1.Manager",
1191 log_error("Operation failed: %s", strerror(-r));
1195 if (!dbus_message_get_args(reply, &error,
1196 DBUS_TYPE_STRING, &path,
1197 DBUS_TYPE_INVALID)) {
1198 log_error("Failed to parse reply: %s", bus_error_message(&error));
1199 dbus_error_free(&error);
1205 printf("%s\n", path);
1208 if ((!bus || avoid_bus()) && path)
1217 char *name, *type, *state;
1220 static void list_jobs_print(struct job_info* jobs, size_t n) {
1223 const char *on, *off;
1224 bool shorten = false;
1226 assert(n == 0 || jobs);
1229 on = ansi_highlight_green();
1230 off = ansi_highlight_off();
1232 printf("%sNo jobs running.%s\n", on, off);
1236 pager_open_if_enabled();
1239 /* JOB UNIT TYPE STATE */
1240 unsigned l0 = 3, l1 = 4, l2 = 4, l3 = 5;
1242 for (i = 0, j = jobs; i < n; i++, j++) {
1243 assert(j->name && j->type && j->state);
1244 l0 = MAX(l0, DECIMAL_STR_WIDTH(j->id));
1245 l1 = MAX(l1, strlen(j->name));
1246 l2 = MAX(l2, strlen(j->type));
1247 l3 = MAX(l3, strlen(j->state));
1250 if (!arg_full && l0 + 1 + l1 + l2 + 1 + l3 > columns()) {
1251 l1 = MAX(33u, columns() - l0 - l2 - l3 - 3);
1256 printf("%*s %-*s %-*s %-*s\n",
1262 for (i = 0, j = jobs; i < n; i++, j++) {
1263 _cleanup_free_ char *e = NULL;
1265 if (streq(j->state, "running")) {
1266 on = ansi_highlight();
1267 off = ansi_highlight_off();
1271 e = shorten ? ellipsize(j->name, l1, 33) : NULL;
1272 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
1274 on, l1, e ? e : j->name, off,
1276 on, l3, j->state, off);
1280 on = ansi_highlight();
1281 off = ansi_highlight_off();
1284 printf("\n%s%zu jobs listed%s.\n", on, n, off);
1287 static int list_jobs(DBusConnection *bus, char **args) {
1288 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1289 DBusMessageIter iter, sub, sub2;
1291 struct job_info *jobs = NULL;
1292 size_t size = 0, used = 0;
1294 r = bus_method_call_with_reply(
1296 "org.freedesktop.systemd1",
1297 "/org/freedesktop/systemd1",
1298 "org.freedesktop.systemd1.Manager",
1306 if (!dbus_message_iter_init(reply, &iter) ||
1307 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1308 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1309 log_error("Failed to parse reply.");
1313 dbus_message_iter_recurse(&iter, &sub);
1315 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1316 const char *name, *type, *state, *job_path, *unit_path;
1319 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1320 log_error("Failed to parse reply.");
1324 dbus_message_iter_recurse(&sub, &sub2);
1326 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1327 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1328 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1329 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1330 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1331 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1332 log_error("Failed to parse reply.");
1337 if (!GREEDY_REALLOC(jobs, size, used + 1)) {
1342 jobs[used++] = (struct job_info) { id,
1346 if (!jobs[used-1].name || !jobs[used-1].type || !jobs[used-1].state) {
1351 dbus_message_iter_next(&sub);
1354 list_jobs_print(jobs, used);
1358 free(jobs[used].name);
1359 free(jobs[used].type);
1360 free(jobs[used].state);
1367 static int cancel_job(DBusConnection *bus, char **args) {
1372 if (strv_length(args) <= 1)
1373 return daemon_reload(bus, args);
1375 STRV_FOREACH(name, args+1) {
1379 r = safe_atou32(*name, &id);
1381 log_error("Failed to parse job id: %s", strerror(-r));
1385 r = bus_method_call_with_reply(
1387 "org.freedesktop.systemd1",
1388 "/org/freedesktop/systemd1",
1389 "org.freedesktop.systemd1.Manager",
1393 DBUS_TYPE_UINT32, &id,
1402 static int need_daemon_reload(DBusConnection *bus, const char *unit) {
1403 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1404 _cleanup_dbus_error_free_ DBusError error;
1405 dbus_bool_t b = FALSE;
1406 DBusMessageIter iter, sub;
1408 *interface = "org.freedesktop.systemd1.Unit",
1409 *property = "NeedDaemonReload",
1411 _cleanup_free_ char *n = NULL;
1414 dbus_error_init(&error);
1416 /* We ignore all errors here, since this is used to show a warning only */
1418 n = unit_name_mangle(unit);
1422 r = bus_method_call_with_reply(
1424 "org.freedesktop.systemd1",
1425 "/org/freedesktop/systemd1",
1426 "org.freedesktop.systemd1.Manager",
1430 DBUS_TYPE_STRING, &n,
1435 if (!dbus_message_get_args(reply, NULL,
1436 DBUS_TYPE_OBJECT_PATH, &path,
1440 dbus_message_unref(reply);
1443 r = bus_method_call_with_reply(
1445 "org.freedesktop.systemd1",
1447 "org.freedesktop.DBus.Properties",
1451 DBUS_TYPE_STRING, &interface,
1452 DBUS_TYPE_STRING, &property,
1457 if (!dbus_message_iter_init(reply, &iter) ||
1458 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1461 dbus_message_iter_recurse(&iter, &sub);
1462 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1465 dbus_message_iter_get_basic(&sub, &b);
1469 typedef struct WaitData {
1476 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1477 _cleanup_dbus_error_free_ DBusError error;
1480 dbus_error_init(&error);
1486 log_debug("Got D-Bus request: %s.%s() on %s",
1487 dbus_message_get_interface(message),
1488 dbus_message_get_member(message),
1489 dbus_message_get_path(message));
1491 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1492 log_error("Warning! D-Bus connection terminated.");
1493 dbus_connection_close(connection);
1495 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1497 const char *path, *result, *unit;
1499 if (dbus_message_get_args(message, &error,
1500 DBUS_TYPE_UINT32, &id,
1501 DBUS_TYPE_OBJECT_PATH, &path,
1502 DBUS_TYPE_STRING, &unit,
1503 DBUS_TYPE_STRING, &result,
1504 DBUS_TYPE_INVALID)) {
1506 free(set_remove(d->set, (char*) path));
1508 if (!isempty(result))
1509 d->result = strdup(result);
1512 d->name = strdup(unit);
1514 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1517 dbus_error_free(&error);
1518 if (dbus_message_get_args(message, &error,
1519 DBUS_TYPE_UINT32, &id,
1520 DBUS_TYPE_OBJECT_PATH, &path,
1521 DBUS_TYPE_STRING, &result,
1522 DBUS_TYPE_INVALID)) {
1523 /* Compatibility with older systemd versions <
1524 * 183 during upgrades. This should be dropped
1526 free(set_remove(d->set, (char*) path));
1529 d->result = strdup(result);
1531 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1535 log_error("Failed to parse message: %s", bus_error_message(&error));
1538 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1541 static int enable_wait_for_jobs(DBusConnection *bus) {
1549 dbus_error_init(&error);
1550 dbus_bus_add_match(bus,
1552 "sender='org.freedesktop.systemd1',"
1553 "interface='org.freedesktop.systemd1.Manager',"
1554 "member='JobRemoved',"
1555 "path='/org/freedesktop/systemd1'",
1558 if (dbus_error_is_set(&error)) {
1559 log_error("Failed to add match: %s", bus_error_message(&error));
1560 dbus_error_free(&error);
1564 /* This is slightly dirty, since we don't undo the match registrations. */
1568 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1570 WaitData d = { .set = s };
1575 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1578 while (!set_isempty(s)) {
1580 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1581 log_error("Disconnected from bus.");
1582 return -ECONNREFUSED;
1589 if (streq(d.result, "timeout"))
1590 log_error("Job for %s timed out.", strna(d.name));
1591 else if (streq(d.result, "canceled"))
1592 log_error("Job for %s canceled.", strna(d.name));
1593 else if (streq(d.result, "dependency"))
1594 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1595 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1596 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1599 if (streq_ptr(d.result, "timeout"))
1601 else if (streq_ptr(d.result, "canceled"))
1603 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1614 dbus_connection_remove_filter(bus, wait_filter, &d);
1618 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1619 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1620 _cleanup_free_ char *n = NULL;
1621 DBusMessageIter iter, sub;
1623 *interface = "org.freedesktop.systemd1.Unit",
1624 *property = "ActiveState";
1625 const char *state, *path;
1631 dbus_error_init(&error);
1633 n = unit_name_mangle(name);
1637 r = bus_method_call_with_reply (
1639 "org.freedesktop.systemd1",
1640 "/org/freedesktop/systemd1",
1641 "org.freedesktop.systemd1.Manager",
1645 DBUS_TYPE_STRING, &n,
1648 dbus_error_free(&error);
1655 if (!dbus_message_get_args(reply, NULL,
1656 DBUS_TYPE_OBJECT_PATH, &path,
1657 DBUS_TYPE_INVALID)) {
1658 log_error("Failed to parse reply.");
1662 dbus_message_unref(reply);
1665 r = bus_method_call_with_reply(
1667 "org.freedesktop.systemd1",
1669 "org.freedesktop.DBus.Properties",
1673 DBUS_TYPE_STRING, &interface,
1674 DBUS_TYPE_STRING, &property,
1682 if (!dbus_message_iter_init(reply, &iter) ||
1683 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1684 log_error("Failed to parse reply.");
1688 dbus_message_iter_recurse(&iter, &sub);
1690 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1691 log_error("Failed to parse reply.");
1695 dbus_message_iter_get_basic(&sub, &state);
1700 return strv_find(check_states, state) ? 1 : 0;
1703 static void check_triggering_units(
1704 DBusConnection *bus,
1705 const char *unit_name) {
1707 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1708 DBusMessageIter iter, sub;
1709 const char *interface = "org.freedesktop.systemd1.Unit",
1710 *load_state_property = "LoadState",
1711 *triggered_by_property = "TriggeredBy",
1713 _cleanup_free_ char *unit_path = NULL, *n = NULL;
1714 bool print_warning_label = true;
1717 n = unit_name_mangle(unit_name);
1723 unit_path = unit_dbus_path_from_name(n);
1729 r = bus_method_call_with_reply(
1731 "org.freedesktop.systemd1",
1733 "org.freedesktop.DBus.Properties",
1737 DBUS_TYPE_STRING, &interface,
1738 DBUS_TYPE_STRING, &load_state_property,
1743 if (!dbus_message_iter_init(reply, &iter) ||
1744 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1745 log_error("Failed to parse reply.");
1749 dbus_message_iter_recurse(&iter, &sub);
1751 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1752 log_error("Failed to parse reply.");
1756 dbus_message_iter_get_basic(&sub, &state);
1758 if (streq(state, "masked"))
1761 dbus_message_unref(reply);
1764 r = bus_method_call_with_reply(
1766 "org.freedesktop.systemd1",
1768 "org.freedesktop.DBus.Properties",
1772 DBUS_TYPE_STRING, &interface,
1773 DBUS_TYPE_STRING, &triggered_by_property,
1778 if (!dbus_message_iter_init(reply, &iter) ||
1779 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1780 log_error("Failed to parse reply.");
1784 dbus_message_iter_recurse(&iter, &sub);
1785 dbus_message_iter_recurse(&sub, &iter);
1788 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1789 const char * const check_states[] = {
1794 const char *service_trigger;
1796 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1797 log_error("Failed to parse reply.");
1801 dbus_message_iter_get_basic(&sub, &service_trigger);
1803 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1807 if (print_warning_label) {
1808 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1809 print_warning_label = false;
1812 log_warning(" %s", service_trigger);
1815 dbus_message_iter_next(&sub);
1819 static int start_unit_one(
1820 DBusConnection *bus,
1827 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1828 _cleanup_free_ char *n;
1837 n = unit_name_mangle(name);
1841 r = bus_method_call_with_reply(
1843 "org.freedesktop.systemd1",
1844 "/org/freedesktop/systemd1",
1845 "org.freedesktop.systemd1.Manager",
1849 DBUS_TYPE_STRING, &n,
1850 DBUS_TYPE_STRING, &mode,
1853 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1854 /* There's always a fallback possible for
1855 * legacy actions. */
1858 log_error("Failed to issue method call: %s", bus_error_message(error));
1863 if (!dbus_message_get_args(reply, error,
1864 DBUS_TYPE_OBJECT_PATH, &path,
1865 DBUS_TYPE_INVALID)) {
1866 log_error("Failed to parse reply: %s", bus_error_message(error));
1870 if (need_daemon_reload(bus, n) > 0)
1871 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %sdaemon-reload' recommended.",
1872 n, arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
1881 r = set_consume(s, p);
1883 log_error("Failed to add path to set.");
1891 static const struct {
1895 } action_table[_ACTION_MAX] = {
1896 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
1897 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
1898 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
1899 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
1900 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
1901 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
1902 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
1903 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
1904 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
1905 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
1906 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
1907 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
1908 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
1909 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
1910 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1913 static enum action verb_to_action(const char *verb) {
1916 for (i = ACTION_INVALID; i < _ACTION_MAX; i++)
1917 if (action_table[i].verb && streq(verb, action_table[i].verb))
1919 return ACTION_INVALID;
1922 static int start_unit(DBusConnection *bus, char **args) {
1925 const char *method, *mode, *one_name;
1926 _cleanup_set_free_free_ Set *s = NULL;
1927 _cleanup_dbus_error_free_ DBusError error;
1930 dbus_error_init(&error);
1934 ask_password_agent_open_if_enabled();
1936 if (arg_action == ACTION_SYSTEMCTL) {
1939 streq(args[0], "stop") ||
1940 streq(args[0], "condstop") ? "StopUnit" :
1941 streq(args[0], "reload") ? "ReloadUnit" :
1942 streq(args[0], "restart") ? "RestartUnit" :
1944 streq(args[0], "try-restart") ||
1945 streq(args[0], "condrestart") ? "TryRestartUnit" :
1947 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1949 streq(args[0], "reload-or-try-restart") ||
1950 streq(args[0], "condreload") ||
1952 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1954 action = verb_to_action(args[0]);
1956 mode = streq(args[0], "isolate") ? "isolate" :
1957 action_table[action].mode ?: arg_job_mode;
1959 one_name = action_table[action].target;
1962 assert(arg_action < ELEMENTSOF(action_table));
1963 assert(action_table[arg_action].target);
1965 method = "StartUnit";
1967 mode = action_table[arg_action].mode;
1968 one_name = action_table[arg_action].target;
1971 if (!arg_no_block) {
1972 ret = enable_wait_for_jobs(bus);
1974 log_error("Could not watch jobs: %s", strerror(-ret));
1978 s = set_new(string_hash_func, string_compare_func);
1984 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1986 ret = translate_bus_error_to_exit_status(ret, &error);
1988 STRV_FOREACH(name, args+1) {
1989 r = start_unit_one(bus, method, *name, mode, &error, s);
1991 ret = translate_bus_error_to_exit_status(r, &error);
1992 dbus_error_free(&error);
1997 if (!arg_no_block) {
1998 r = wait_for_jobs(bus, s);
2002 /* When stopping units, warn if they can still be triggered by
2003 * another active unit (socket, path, timer) */
2004 if (!arg_quiet && streq(method, "StopUnit")) {
2006 check_triggering_units(bus, one_name);
2008 STRV_FOREACH(name, args+1)
2009 check_triggering_units(bus, *name);
2016 /* Ask systemd-logind, which might grant access to unprivileged users
2017 * through PolicyKit */
2018 static int reboot_with_logind(DBusConnection *bus, enum action a) {
2021 dbus_bool_t interactive = true;
2026 polkit_agent_open_if_enabled();
2034 case ACTION_POWEROFF:
2035 method = "PowerOff";
2038 case ACTION_SUSPEND:
2042 case ACTION_HIBERNATE:
2043 method = "Hibernate";
2046 case ACTION_HYBRID_SLEEP:
2047 method = "HybridSleep";
2054 return bus_method_call_with_reply(
2056 "org.freedesktop.login1",
2057 "/org/freedesktop/login1",
2058 "org.freedesktop.login1.Manager",
2062 DBUS_TYPE_BOOLEAN, &interactive,
2069 static int check_inhibitors(DBusConnection *bus, enum action a) {
2071 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2072 DBusMessageIter iter, sub, sub2;
2075 _cleanup_strv_free_ char **sessions = NULL;
2081 if (arg_ignore_inhibitors || arg_force > 0)
2093 r = bus_method_call_with_reply(
2095 "org.freedesktop.login1",
2096 "/org/freedesktop/login1",
2097 "org.freedesktop.login1.Manager",
2103 /* If logind is not around, then there are no inhibitors... */
2106 if (!dbus_message_iter_init(reply, &iter) ||
2107 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2108 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
2109 log_error("Failed to parse reply.");
2113 dbus_message_iter_recurse(&iter, &sub);
2114 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2115 const char *what, *who, *why, *mode;
2117 _cleanup_strv_free_ char **sv = NULL;
2118 _cleanup_free_ char *comm = NULL, *user = NULL;
2120 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
2121 log_error("Failed to parse reply.");
2125 dbus_message_iter_recurse(&sub, &sub2);
2127 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
2128 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
2129 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
2130 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
2131 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
2132 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
2133 log_error("Failed to parse reply.");
2137 if (!streq(mode, "block"))
2140 sv = strv_split(what, ":");
2144 if (!strv_contains(sv,
2146 a == ACTION_POWEROFF ||
2147 a == ACTION_REBOOT ||
2148 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2151 get_process_comm(pid, &comm);
2152 user = uid_to_name(uid);
2153 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2154 who, (unsigned long) pid, strna(comm), strna(user), why);
2158 dbus_message_iter_next(&sub);
2161 dbus_message_iter_recurse(&iter, &sub);
2163 /* Check for current sessions */
2164 sd_get_sessions(&sessions);
2165 STRV_FOREACH(s, sessions) {
2167 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2169 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2172 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2175 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2178 sd_session_get_tty(*s, &tty);
2179 sd_session_get_seat(*s, &seat);
2180 sd_session_get_service(*s, &service);
2181 user = uid_to_name(uid);
2183 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2190 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2191 action_table[a].verb);
2199 static int start_special(DBusConnection *bus, char **args) {
2205 a = verb_to_action(args[0]);
2207 r = check_inhibitors(bus, a);
2211 if (arg_force >= 2 && geteuid() != 0) {
2212 log_error("Must be root.");
2216 if (arg_force >= 2 &&
2217 (a == ACTION_HALT ||
2218 a == ACTION_POWEROFF ||
2219 a == ACTION_REBOOT))
2222 if (arg_force >= 1 &&
2223 (a == ACTION_HALT ||
2224 a == ACTION_POWEROFF ||
2225 a == ACTION_REBOOT ||
2226 a == ACTION_KEXEC ||
2228 return daemon_reload(bus, args);
2230 /* first try logind, to allow authentication with polkit */
2231 if (geteuid() != 0 &&
2232 (a == ACTION_POWEROFF ||
2233 a == ACTION_REBOOT ||
2234 a == ACTION_SUSPEND ||
2235 a == ACTION_HIBERNATE ||
2236 a == ACTION_HYBRID_SLEEP)) {
2237 r = reboot_with_logind(bus, a);
2242 r = start_unit(bus, args);
2243 if (r == EXIT_SUCCESS)
2249 static int check_unit_active(DBusConnection *bus, char **args) {
2250 const char * const check_states[] = {
2257 int r = 3; /* According to LSB: "program is not running" */
2262 STRV_FOREACH(name, args+1) {
2265 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2275 static int check_unit_failed(DBusConnection *bus, char **args) {
2276 const char * const check_states[] = {
2287 STRV_FOREACH(name, args+1) {
2290 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2300 static int kill_unit(DBusConnection *bus, char **args) {
2308 arg_kill_who = "all";
2310 STRV_FOREACH(name, args+1) {
2311 _cleanup_free_ char *n = NULL;
2313 n = unit_name_mangle(*name);
2317 r = bus_method_call_with_reply(
2319 "org.freedesktop.systemd1",
2320 "/org/freedesktop/systemd1",
2321 "org.freedesktop.systemd1.Manager",
2325 DBUS_TYPE_STRING, &n,
2326 DBUS_TYPE_STRING, &arg_kill_who,
2327 DBUS_TYPE_INT32, &arg_signal,
2335 typedef struct ExecStatusInfo {
2343 usec_t start_timestamp;
2344 usec_t exit_timestamp;
2349 LIST_FIELDS(struct ExecStatusInfo, exec);
2352 static void exec_status_info_free(ExecStatusInfo *i) {
2361 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2362 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2363 DBusMessageIter sub2, sub3;
2367 int32_t code, status;
2373 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2376 dbus_message_iter_recurse(sub, &sub2);
2378 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2381 i->path = strdup(path);
2385 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2386 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2390 dbus_message_iter_recurse(&sub2, &sub3);
2391 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2392 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2393 dbus_message_iter_next(&sub3);
2397 i->argv = new0(char*, n+1);
2402 dbus_message_iter_recurse(&sub2, &sub3);
2403 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2406 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2407 dbus_message_iter_get_basic(&sub3, &s);
2408 dbus_message_iter_next(&sub3);
2410 i->argv[n] = strdup(s);
2417 if (!dbus_message_iter_next(&sub2) ||
2418 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2419 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2420 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2421 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2422 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2423 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2424 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2425 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2429 i->start_timestamp = (usec_t) start_timestamp;
2430 i->exit_timestamp = (usec_t) exit_timestamp;
2431 i->pid = (pid_t) pid;
2438 typedef struct UnitStatusInfo {
2440 const char *load_state;
2441 const char *active_state;
2442 const char *sub_state;
2443 const char *unit_file_state;
2445 const char *description;
2446 const char *following;
2448 char **documentation;
2450 const char *fragment_path;
2451 const char *source_path;
2452 const char *control_group;
2454 char **dropin_paths;
2456 const char *load_error;
2459 usec_t inactive_exit_timestamp;
2460 usec_t inactive_exit_timestamp_monotonic;
2461 usec_t active_enter_timestamp;
2462 usec_t active_exit_timestamp;
2463 usec_t inactive_enter_timestamp;
2465 bool need_daemon_reload;
2470 const char *status_text;
2471 const char *pid_file;
2474 usec_t start_timestamp;
2475 usec_t exit_timestamp;
2477 int exit_code, exit_status;
2479 usec_t condition_timestamp;
2480 bool condition_result;
2481 bool failed_condition_trigger;
2482 bool failed_condition_negate;
2483 const char *failed_condition;
2484 const char *failed_condition_param;
2487 unsigned n_accepted;
2488 unsigned n_connections;
2491 /* Pairs of type, path */
2495 const char *sysfs_path;
2497 /* Mount, Automount */
2503 LIST_HEAD(ExecStatusInfo, exec);
2506 static void print_status_info(UnitStatusInfo *i,
2509 const char *on, *off, *ss;
2511 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2512 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2515 arg_all * OUTPUT_SHOW_ALL |
2516 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2517 on_tty() * OUTPUT_COLOR |
2518 !arg_quiet * OUTPUT_WARN_CUTOFF |
2519 arg_full * OUTPUT_FULL_WIDTH;
2524 /* This shows pretty information about a unit. See
2525 * print_property() for a low-level property printer */
2527 printf("%s", strna(i->id));
2529 if (i->description && !streq_ptr(i->id, i->description))
2530 printf(" - %s", i->description);
2535 printf(" Follow: unit currently follows state of %s\n", i->following);
2537 if (streq_ptr(i->load_state, "error")) {
2538 on = ansi_highlight_red();
2539 off = ansi_highlight_off();
2543 path = i->source_path ? i->source_path : i->fragment_path;
2546 printf(" Loaded: %s%s%s (Reason: %s)\n",
2547 on, strna(i->load_state), off, i->load_error);
2548 else if (path && i->unit_file_state)
2549 printf(" Loaded: %s%s%s (%s; %s)\n",
2550 on, strna(i->load_state), off, path, i->unit_file_state);
2552 printf(" Loaded: %s%s%s (%s)\n",
2553 on, strna(i->load_state), off, path);
2555 printf(" Loaded: %s%s%s\n",
2556 on, strna(i->load_state), off);
2558 if (!strv_isempty(i->dropin_paths)) {
2563 STRV_FOREACH(dropin, i->dropin_paths) {
2564 if (! dir || last) {
2565 printf(dir ? " " : " Drop-In: ");
2569 if (path_get_parent(*dropin, &dir) < 0) {
2574 printf("%s\n %s", dir,
2575 draw_special_char(DRAW_TREE_RIGHT));
2578 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
2580 printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", ");
2586 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2588 if (streq_ptr(i->active_state, "failed")) {
2589 on = ansi_highlight_red();
2590 off = ansi_highlight_off();
2591 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2592 on = ansi_highlight_green();
2593 off = ansi_highlight_off();
2598 printf(" Active: %s%s (%s)%s",
2599 on, strna(i->active_state), ss, off);
2601 printf(" Active: %s%s%s",
2602 on, strna(i->active_state), off);
2604 if (!isempty(i->result) && !streq(i->result, "success"))
2605 printf(" (Result: %s)", i->result);
2607 timestamp = (streq_ptr(i->active_state, "active") ||
2608 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2609 (streq_ptr(i->active_state, "inactive") ||
2610 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2611 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2612 i->active_exit_timestamp;
2614 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2615 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2618 printf(" since %s; %s\n", s2, s1);
2620 printf(" since %s\n", s2);
2624 if (!i->condition_result && i->condition_timestamp > 0) {
2625 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2626 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2628 printf(" start condition failed at %s%s%s\n",
2629 s2, s1 ? "; " : "", s1 ? s1 : "");
2630 if (i->failed_condition_trigger)
2631 printf(" none of the trigger conditions were met\n");
2632 else if (i->failed_condition)
2633 printf(" %s=%s%s was not met\n",
2634 i->failed_condition,
2635 i->failed_condition_negate ? "!" : "",
2636 i->failed_condition_param);
2640 printf(" Device: %s\n", i->sysfs_path);
2642 printf(" Where: %s\n", i->where);
2644 printf(" What: %s\n", i->what);
2646 STRV_FOREACH(t, i->documentation)
2647 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
2649 STRV_FOREACH_PAIR(t, t2, i->listen)
2650 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
2653 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2655 LIST_FOREACH(exec, p, i->exec) {
2656 _cleanup_free_ char *argv = NULL;
2659 /* Only show exited processes here */
2663 argv = strv_join(p->argv, " ");
2664 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
2666 good = is_clean_exit_lsb(p->code, p->status, NULL);
2668 on = ansi_highlight_red();
2669 off = ansi_highlight_off();
2673 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2675 if (p->code == CLD_EXITED) {
2678 printf("status=%i", p->status);
2680 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2685 printf("signal=%s", signal_to_string(p->status));
2687 printf(")%s\n", off);
2689 if (i->main_pid == p->pid &&
2690 i->start_timestamp == p->start_timestamp &&
2691 i->exit_timestamp == p->start_timestamp)
2692 /* Let's not show this twice */
2695 if (p->pid == i->control_pid)
2699 if (i->main_pid > 0 || i->control_pid > 0) {
2700 if (i->main_pid > 0) {
2701 printf(" Main PID: %u", (unsigned) i->main_pid);
2704 _cleanup_free_ char *comm = NULL;
2705 get_process_comm(i->main_pid, &comm);
2707 printf(" (%s)", comm);
2708 } else if (i->exit_code > 0) {
2709 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2711 if (i->exit_code == CLD_EXITED) {
2714 printf("status=%i", i->exit_status);
2716 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2721 printf("signal=%s", signal_to_string(i->exit_status));
2725 if (i->control_pid > 0)
2729 if (i->control_pid > 0) {
2730 _cleanup_free_ char *c = NULL;
2732 printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
2734 get_process_comm(i->control_pid, &c);
2743 printf(" Status: \"%s\"\n", i->status_text);
2745 if (i->control_group &&
2746 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, i->control_group, false) == 0)) {
2749 printf(" CGroup: %s\n", i->control_group);
2751 if (arg_transport != TRANSPORT_SSH) {
2754 char prefix[] = " ";
2757 if (c > sizeof(prefix) - 1)
2758 c -= sizeof(prefix) - 1;
2762 if (i->main_pid > 0)
2763 extra[k++] = i->main_pid;
2765 if (i->control_pid > 0)
2766 extra[k++] = i->control_pid;
2768 show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, i->control_group, prefix,
2769 c, false, extra, k, flags);
2773 if (i->id && arg_transport != TRANSPORT_SSH) {
2775 show_journal_by_unit(stdout,
2779 i->inactive_exit_timestamp_monotonic,
2783 arg_scope == UNIT_FILE_SYSTEM,
2787 if (i->need_daemon_reload)
2788 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
2789 ansi_highlight_red(),
2790 ansi_highlight_off(),
2791 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
2794 static void show_unit_help(UnitStatusInfo *i) {
2799 if (!i->documentation) {
2800 log_info("Documentation for %s not known.", i->id);
2804 STRV_FOREACH(p, i->documentation) {
2806 if (startswith(*p, "man:")) {
2809 _cleanup_free_ char *page = NULL, *section = NULL;
2810 const char *args[4] = { "man", NULL, NULL, NULL };
2815 if ((*p)[k-1] == ')')
2816 e = strrchr(*p, '(');
2819 page = strndup((*p) + 4, e - *p - 4);
2820 section = strndup(e + 1, *p + k - e - 2);
2821 if (!page || !section) {
2833 log_error("Failed to fork: %m");
2839 execvp(args[0], (char**) args);
2840 log_error("Failed to execute man: %m");
2841 _exit(EXIT_FAILURE);
2844 wait_for_terminate(pid, NULL);
2846 log_info("Can't show: %s", *p);
2850 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2856 switch (dbus_message_iter_get_arg_type(iter)) {
2858 case DBUS_TYPE_STRING: {
2861 dbus_message_iter_get_basic(iter, &s);
2864 if (streq(name, "Id"))
2866 else if (streq(name, "LoadState"))
2868 else if (streq(name, "ActiveState"))
2869 i->active_state = s;
2870 else if (streq(name, "SubState"))
2872 else if (streq(name, "Description"))
2874 else if (streq(name, "FragmentPath"))
2875 i->fragment_path = s;
2876 else if (streq(name, "SourcePath"))
2879 else if (streq(name, "DefaultControlGroup")) {
2881 e = startswith(s, SYSTEMD_CGROUP_CONTROLLER ":");
2883 i->control_group = e;
2886 else if (streq(name, "ControlGroup"))
2887 i->control_group = s;
2888 else if (streq(name, "StatusText"))
2890 else if (streq(name, "PIDFile"))
2892 else if (streq(name, "SysFSPath"))
2894 else if (streq(name, "Where"))
2896 else if (streq(name, "What"))
2898 else if (streq(name, "Following"))
2900 else if (streq(name, "UnitFileState"))
2901 i->unit_file_state = s;
2902 else if (streq(name, "Result"))
2909 case DBUS_TYPE_BOOLEAN: {
2912 dbus_message_iter_get_basic(iter, &b);
2914 if (streq(name, "Accept"))
2916 else if (streq(name, "NeedDaemonReload"))
2917 i->need_daemon_reload = b;
2918 else if (streq(name, "ConditionResult"))
2919 i->condition_result = b;
2924 case DBUS_TYPE_UINT32: {
2927 dbus_message_iter_get_basic(iter, &u);
2929 if (streq(name, "MainPID")) {
2931 i->main_pid = (pid_t) u;
2934 } else if (streq(name, "ControlPID"))
2935 i->control_pid = (pid_t) u;
2936 else if (streq(name, "ExecMainPID")) {
2938 i->main_pid = (pid_t) u;
2939 } else if (streq(name, "NAccepted"))
2941 else if (streq(name, "NConnections"))
2942 i->n_connections = u;
2947 case DBUS_TYPE_INT32: {
2950 dbus_message_iter_get_basic(iter, &j);
2952 if (streq(name, "ExecMainCode"))
2953 i->exit_code = (int) j;
2954 else if (streq(name, "ExecMainStatus"))
2955 i->exit_status = (int) j;
2960 case DBUS_TYPE_UINT64: {
2963 dbus_message_iter_get_basic(iter, &u);
2965 if (streq(name, "ExecMainStartTimestamp"))
2966 i->start_timestamp = (usec_t) u;
2967 else if (streq(name, "ExecMainExitTimestamp"))
2968 i->exit_timestamp = (usec_t) u;
2969 else if (streq(name, "ActiveEnterTimestamp"))
2970 i->active_enter_timestamp = (usec_t) u;
2971 else if (streq(name, "InactiveEnterTimestamp"))
2972 i->inactive_enter_timestamp = (usec_t) u;
2973 else if (streq(name, "InactiveExitTimestamp"))
2974 i->inactive_exit_timestamp = (usec_t) u;
2975 else if (streq(name, "InactiveExitTimestampMonotonic"))
2976 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2977 else if (streq(name, "ActiveExitTimestamp"))
2978 i->active_exit_timestamp = (usec_t) u;
2979 else if (streq(name, "ConditionTimestamp"))
2980 i->condition_timestamp = (usec_t) u;
2985 case DBUS_TYPE_ARRAY: {
2987 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2988 startswith(name, "Exec")) {
2989 DBusMessageIter sub;
2991 dbus_message_iter_recurse(iter, &sub);
2992 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2993 ExecStatusInfo *info;
2996 info = new0(ExecStatusInfo, 1);
3000 info->name = strdup(name);
3006 r = exec_status_info_deserialize(&sub, info);
3012 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
3014 dbus_message_iter_next(&sub);
3017 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3018 streq(name, "Listen")) {
3019 DBusMessageIter sub, sub2;
3021 dbus_message_iter_recurse(iter, &sub);
3022 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3023 const char *type, *path;
3025 dbus_message_iter_recurse(&sub, &sub2);
3027 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3028 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
3031 r = strv_extend(&i->listen, type);
3034 r = strv_extend(&i->listen, path);
3039 dbus_message_iter_next(&sub);
3044 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3045 streq(name, "DropInPaths")) {
3046 int r = bus_parse_strv_iter(iter, &i->dropin_paths);
3050 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3051 streq(name, "Documentation")) {
3053 DBusMessageIter sub;
3055 dbus_message_iter_recurse(iter, &sub);
3056 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
3060 dbus_message_iter_get_basic(&sub, &s);
3062 r = strv_extend(&i->documentation, s);
3066 dbus_message_iter_next(&sub);
3069 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3070 streq(name, "Conditions")) {
3071 DBusMessageIter sub, sub2;
3073 dbus_message_iter_recurse(iter, &sub);
3074 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3075 const char *cond, *param;
3076 dbus_bool_t trigger, negate;
3079 dbus_message_iter_recurse(&sub, &sub2);
3082 if(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &cond, true) >= 0 &&
3083 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &trigger, true) >= 0 &&
3084 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &negate, true) >= 0 &&
3085 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, ¶m, true) >= 0 &&
3086 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &state, false) >= 0) {
3087 log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
3088 if (state < 0 && (!trigger || !i->failed_condition)) {
3089 i->failed_condition = cond;
3090 i->failed_condition_trigger = trigger;
3091 i->failed_condition_negate = negate;
3092 i->failed_condition_param = param;
3096 dbus_message_iter_next(&sub);
3103 case DBUS_TYPE_STRUCT: {
3105 if (streq(name, "LoadError")) {
3106 DBusMessageIter sub;
3107 const char *n, *message;
3110 dbus_message_iter_recurse(iter, &sub);
3112 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
3116 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
3120 if (!isempty(message))
3121 i->load_error = message;
3131 static int print_property(const char *name, DBusMessageIter *iter) {
3135 /* This is a low-level property printer, see
3136 * print_status_info() for the nicer output */
3138 if (arg_properties && !strv_find(arg_properties, name))
3141 switch (dbus_message_iter_get_arg_type(iter)) {
3143 case DBUS_TYPE_STRUCT: {
3144 DBusMessageIter sub;
3145 dbus_message_iter_recurse(iter, &sub);
3147 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
3150 dbus_message_iter_get_basic(&sub, &u);
3153 printf("%s=%u\n", name, (unsigned) u);
3155 printf("%s=\n", name);
3158 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
3161 dbus_message_iter_get_basic(&sub, &s);
3163 if (arg_all || s[0])
3164 printf("%s=%s\n", name, s);
3167 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
3168 const char *a = NULL, *b = NULL;
3170 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
3171 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
3173 if (arg_all || !isempty(a) || !isempty(b))
3174 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3182 case DBUS_TYPE_ARRAY:
3184 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
3185 DBusMessageIter sub, sub2;
3187 dbus_message_iter_recurse(iter, &sub);
3188 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3192 dbus_message_iter_recurse(&sub, &sub2);
3194 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3195 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3196 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3198 dbus_message_iter_next(&sub);
3203 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3204 DBusMessageIter sub, sub2;
3206 dbus_message_iter_recurse(iter, &sub);
3208 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3209 const char *type, *path;
3211 dbus_message_iter_recurse(&sub, &sub2);
3213 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3214 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3215 printf("%s=%s\n", type, path);
3217 dbus_message_iter_next(&sub);
3222 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3223 DBusMessageIter sub, sub2;
3225 dbus_message_iter_recurse(iter, &sub);
3226 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3227 const char *type, *path;
3229 dbus_message_iter_recurse(&sub, &sub2);
3231 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3232 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3233 printf("Listen%s=%s\n", type, path);
3235 dbus_message_iter_next(&sub);
3240 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3241 DBusMessageIter sub, sub2;
3243 dbus_message_iter_recurse(iter, &sub);
3244 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3246 uint64_t value, next_elapse;
3248 dbus_message_iter_recurse(&sub, &sub2);
3250 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3251 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3252 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3253 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3255 printf("%s={ value=%s ; next_elapse=%s }\n",
3257 format_timespan(timespan1, sizeof(timespan1), value, 0),
3258 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3261 dbus_message_iter_next(&sub);
3266 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3267 DBusMessageIter sub;
3269 dbus_message_iter_recurse(iter, &sub);
3270 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3271 ExecStatusInfo info = {};
3273 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3274 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3275 _cleanup_free_ char *t;
3277 t = strv_join(info.argv, " ");
3279 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3283 yes_no(info.ignore),
3284 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3285 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3286 (unsigned) info. pid,
3287 sigchld_code_to_string(info.code),
3289 info.code == CLD_EXITED ? "" : "/",
3290 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3294 strv_free(info.argv);
3296 dbus_message_iter_next(&sub);
3301 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "DeviceAllow")) {
3302 DBusMessageIter sub, sub2;
3304 dbus_message_iter_recurse(iter, &sub);
3305 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3306 const char *path, *rwm;
3308 dbus_message_iter_recurse(&sub, &sub2);
3310 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3311 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &rwm, false) >= 0)
3312 printf("%s=%s %s\n", name, strna(path), strna(rwm));
3314 dbus_message_iter_next(&sub);
3318 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
3319 DBusMessageIter sub, sub2;
3321 dbus_message_iter_recurse(iter, &sub);
3322 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3326 dbus_message_iter_recurse(&sub, &sub2);
3328 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3329 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &bandwidth, false) >= 0)
3330 printf("%s=%s %" PRIu64 "\n", name, strna(path), bandwidth);
3332 dbus_message_iter_next(&sub);
3341 if (generic_print_property(name, iter, arg_all) > 0)
3345 printf("%s=[unprintable]\n", name);
3350 static int show_one(const char *verb,
3351 DBusConnection *bus,
3353 bool show_properties,
3356 _cleanup_free_ DBusMessage *reply = NULL;
3357 const char *interface = "";
3359 DBusMessageIter iter, sub, sub2, sub3;
3360 UnitStatusInfo info = {};
3366 r = bus_method_call_with_reply(
3368 "org.freedesktop.systemd1",
3370 "org.freedesktop.DBus.Properties",
3374 DBUS_TYPE_STRING, &interface,
3379 if (!dbus_message_iter_init(reply, &iter) ||
3380 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3381 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3382 log_error("Failed to parse reply.");
3386 dbus_message_iter_recurse(&iter, &sub);
3393 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3396 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3397 dbus_message_iter_recurse(&sub, &sub2);
3399 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3400 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3401 log_error("Failed to parse reply.");
3405 dbus_message_iter_recurse(&sub2, &sub3);
3407 if (show_properties)
3408 r = print_property(name, &sub3);
3410 r = status_property(name, &sub3, &info);
3412 log_error("Failed to parse reply.");
3416 dbus_message_iter_next(&sub);
3421 if (!show_properties) {
3422 if (streq(verb, "help"))
3423 show_unit_help(&info);
3425 print_status_info(&info, ellipsized);
3428 strv_free(info.documentation);
3429 strv_free(info.dropin_paths);
3430 strv_free(info.listen);
3432 if (!streq_ptr(info.active_state, "active") &&
3433 !streq_ptr(info.active_state, "reloading") &&
3434 streq(verb, "status")) {
3435 /* According to LSB: "program not running" */
3436 /* 0: program is running or service is OK
3437 * 1: program is dead and /var/run pid file exists
3438 * 2: program is dead and /var/lock lock file exists
3439 * 3: program is not running
3440 * 4: program or service status is unknown
3442 if (info.pid_file && access(info.pid_file, F_OK) == 0)
3448 while ((p = info.exec)) {
3449 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3450 exec_status_info_free(p);
3456 static int show_one_by_pid(const char *verb,
3457 DBusConnection *bus,
3461 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3462 const char *path = NULL;
3463 _cleanup_dbus_error_free_ DBusError error;
3466 dbus_error_init(&error);
3468 r = bus_method_call_with_reply(
3470 "org.freedesktop.systemd1",
3471 "/org/freedesktop/systemd1",
3472 "org.freedesktop.systemd1.Manager",
3476 DBUS_TYPE_UINT32, &pid,
3481 if (!dbus_message_get_args(reply, &error,
3482 DBUS_TYPE_OBJECT_PATH, &path,
3483 DBUS_TYPE_INVALID)) {
3484 log_error("Failed to parse reply: %s", bus_error_message(&error));
3488 r = show_one(verb, bus, path, false, new_line, ellipsized);
3492 static int show_all(const char* verb,
3493 DBusConnection *bus,
3494 bool show_properties,
3497 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3498 _cleanup_free_ struct unit_info *unit_infos = NULL;
3500 const struct unit_info *u;
3503 r = get_unit_list(bus, &reply, &unit_infos, &c);
3507 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
3509 for (u = unit_infos; u < unit_infos + c; u++) {
3510 _cleanup_free_ char *p = NULL;
3512 if (!output_show_unit(u))
3515 p = unit_dbus_path_from_name(u->id);
3519 printf("%s -> '%s'\n", u->id, p);
3521 r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
3529 static int show(DBusConnection *bus, char **args) {
3531 bool show_properties, show_status, new_line = false;
3533 bool ellipsized = false;
3538 show_properties = streq(args[0], "show");
3539 show_status = streq(args[0], "status");
3541 if (show_properties)
3542 pager_open_if_enabled();
3544 /* If no argument is specified inspect the manager itself */
3546 if (show_properties && strv_length(args) <= 1)
3547 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
3549 if (show_status && strv_length(args) <= 1)
3550 ret = show_all(args[0], bus, false, &new_line, &ellipsized);
3552 STRV_FOREACH(name, args+1) {
3555 if (safe_atou32(*name, &id) < 0) {
3556 _cleanup_free_ char *p = NULL, *n = NULL;
3557 /* Interpret as unit name */
3559 n = unit_name_mangle(*name);
3563 p = unit_dbus_path_from_name(n);
3567 r = show_one(args[0], bus, p, show_properties, &new_line, &ellipsized);
3571 } else if (show_properties) {
3572 _cleanup_free_ char *p = NULL;
3574 /* Interpret as job id */
3575 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3578 r = show_one(args[0], bus, p, show_properties, &new_line, &ellipsized);
3583 /* Interpret as PID */
3584 r = show_one_by_pid(args[0], bus, id, &new_line, &ellipsized);
3590 if (ellipsized && !arg_quiet)
3591 printf("Hint: Some lines were ellipsized, use -l to show in full.\n");
3596 static int append_assignment(DBusMessageIter *iter, const char *assignment) {
3599 DBusMessageIter sub;
3605 eq = strchr(assignment, '=');
3607 log_error("Not an assignment: %s", assignment);
3611 field = strndupa(assignment, eq - assignment);
3614 if (!dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &field))
3617 if (streq(field, "CPUAccounting") ||
3618 streq(field, "MemoryAccounting") ||
3619 streq(field, "BlockIOAccounting")) {
3622 r = parse_boolean(eq);
3624 log_error("Failed to parse boolean assignment %s.", assignment);
3629 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "b", &sub) ||
3630 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_BOOLEAN, &b))
3633 } else if (streq(field, "MemoryLimit") || streq(field, "MemorySoftLimit")) {
3637 r = parse_bytes(eq, &bytes);
3639 log_error("Failed to parse bytes specification %s", assignment);
3644 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
3645 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
3648 } else if (streq(field, "CPUShares") || streq(field, "BlockIOWeight")) {
3651 r = safe_atou64(eq, &u);
3653 log_error("Failed to parse %s value %s.", field, eq);
3657 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "t", &sub) ||
3658 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT64, &u))
3661 } else if (streq(field, "DevicePolicy")) {
3663 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "s", &sub) ||
3664 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &eq))
3667 } else if (streq(field, "DeviceAllow")) {
3668 DBusMessageIter sub2;
3670 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(ss)", &sub) ||
3671 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(ss)", &sub2))
3675 const char *path, *rwm;
3676 DBusMessageIter sub3;
3679 e = strchr(eq, ' ');
3681 path = strndupa(eq, e - eq);
3688 if (!path_startswith(path, "/dev")) {
3689 log_error("%s is not a device file in /dev.", path);
3693 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3694 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3695 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &rwm) ||
3696 !dbus_message_iter_close_container(&sub2, &sub3))
3700 if (!dbus_message_iter_close_container(&sub, &sub2))
3703 } else if (streq(field, "BlockIOReadBandwidth") || streq(field, "BlockIOWriteBandwidth")) {
3704 DBusMessageIter sub2;
3706 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a(st)", &sub) ||
3707 !dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "(st)", &sub2))
3711 const char *path, *bandwidth;
3712 DBusMessageIter sub3;
3717 e = strchr(eq, ' ');
3719 path = strndupa(eq, e - eq);
3722 log_error("Failed to parse %s value %s.", field, eq);
3726 if (!path_startswith(path, "/dev")) {
3727 log_error("%s is not a device file in /dev.", path);
3731 r = parse_bytes(bandwidth, &bytes);
3733 log_error("Failed to parse byte value %s.", bandwidth);
3737 u = (uint64_t) bytes;
3739 if (!dbus_message_iter_open_container(&sub2, DBUS_TYPE_STRUCT, NULL, &sub3) ||
3740 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &path) ||
3741 !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_UINT64, &u) ||
3742 !dbus_message_iter_close_container(&sub2, &sub3))
3746 if (!dbus_message_iter_close_container(&sub, &sub2))
3750 log_error("Unknown assignment %s.", assignment);
3754 if (!dbus_message_iter_close_container(iter, &sub))
3760 static int set_property(DBusConnection *bus, char **args) {
3762 _cleanup_free_ DBusMessage *m = NULL, *reply = NULL;
3763 DBusMessageIter iter, sub;
3764 dbus_bool_t runtime;
3769 dbus_error_init(&error);
3771 m = dbus_message_new_method_call(
3772 "org.freedesktop.systemd1",
3773 "/org/freedesktop/systemd1",
3774 "org.freedesktop.systemd1.Manager",
3775 "SetUnitProperties");
3779 dbus_message_iter_init_append(m, &iter);
3781 runtime = arg_runtime;
3783 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[1]) ||
3784 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &runtime) ||
3785 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sv)", &sub))
3788 STRV_FOREACH(i, args + 2) {
3789 DBusMessageIter sub2;
3791 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
3794 r = append_assignment(&sub2, *i);
3798 if (!dbus_message_iter_close_container(&sub, &sub2))
3803 if (!dbus_message_iter_close_container(&iter, &sub))
3806 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3808 log_error("Failed to issue method call: %s", bus_error_message(&error));
3809 dbus_error_free(&error);
3816 static int snapshot(DBusConnection *bus, char **args) {
3817 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3820 dbus_bool_t cleanup = FALSE;
3821 DBusMessageIter iter, sub;
3824 *interface = "org.freedesktop.systemd1.Unit",
3826 _cleanup_free_ char *n = NULL;
3828 dbus_error_init(&error);
3830 if (strv_length(args) > 1)
3831 n = unit_name_mangle_with_suffix(args[1], ".snapshot");
3837 r = bus_method_call_with_reply(
3839 "org.freedesktop.systemd1",
3840 "/org/freedesktop/systemd1",
3841 "org.freedesktop.systemd1.Manager",
3845 DBUS_TYPE_STRING, &n,
3846 DBUS_TYPE_BOOLEAN, &cleanup,
3851 if (!dbus_message_get_args(reply, &error,
3852 DBUS_TYPE_OBJECT_PATH, &path,
3853 DBUS_TYPE_INVALID)) {
3854 log_error("Failed to parse reply: %s", bus_error_message(&error));
3855 dbus_error_free(&error);
3859 dbus_message_unref(reply);
3862 r = bus_method_call_with_reply (
3864 "org.freedesktop.systemd1",
3866 "org.freedesktop.DBus.Properties",
3870 DBUS_TYPE_STRING, &interface,
3871 DBUS_TYPE_STRING, &property,
3876 if (!dbus_message_iter_init(reply, &iter) ||
3877 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3878 log_error("Failed to parse reply.");
3882 dbus_message_iter_recurse(&iter, &sub);
3884 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3885 log_error("Failed to parse reply.");
3889 dbus_message_iter_get_basic(&sub, &id);
3897 static int delete_snapshot(DBusConnection *bus, char **args) {
3902 STRV_FOREACH(name, args+1) {
3903 _cleanup_free_ char *n = NULL;
3906 n = unit_name_mangle_with_suffix(*name, ".snapshot");
3910 r = bus_method_call_with_reply(
3912 "org.freedesktop.systemd1",
3913 "/org/freedesktop/systemd1",
3914 "org.freedesktop.systemd1.Manager",
3918 DBUS_TYPE_STRING, &n,
3927 static int daemon_reload(DBusConnection *bus, char **args) {
3932 if (arg_action == ACTION_RELOAD)
3934 else if (arg_action == ACTION_REEXEC)
3935 method = "Reexecute";
3937 assert(arg_action == ACTION_SYSTEMCTL);
3940 streq(args[0], "clear-jobs") ||
3941 streq(args[0], "cancel") ? "ClearJobs" :
3942 streq(args[0], "daemon-reexec") ? "Reexecute" :
3943 streq(args[0], "reset-failed") ? "ResetFailed" :
3944 streq(args[0], "halt") ? "Halt" :
3945 streq(args[0], "poweroff") ? "PowerOff" :
3946 streq(args[0], "reboot") ? "Reboot" :
3947 streq(args[0], "kexec") ? "KExec" :
3948 streq(args[0], "exit") ? "Exit" :
3949 /* "daemon-reload" */ "Reload";
3952 r = bus_method_call_with_reply(
3954 "org.freedesktop.systemd1",
3955 "/org/freedesktop/systemd1",
3956 "org.freedesktop.systemd1.Manager",
3962 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3963 /* There's always a fallback possible for
3964 * legacy actions. */
3966 else if ((r == -ETIMEDOUT || r == -ECONNRESET) && streq(method, "Reexecute"))
3967 /* On reexecution, we expect a disconnect, not a
3971 log_error("Failed to issue method call: %s", bus_error_message(&error));
3973 dbus_error_free(&error);
3977 static int reset_failed(DBusConnection *bus, char **args) {
3981 if (strv_length(args) <= 1)
3982 return daemon_reload(bus, args);
3984 STRV_FOREACH(name, args+1) {
3985 _cleanup_free_ char *n;
3987 n = unit_name_mangle(*name);
3991 r = bus_method_call_with_reply(
3993 "org.freedesktop.systemd1",
3994 "/org/freedesktop/systemd1",
3995 "org.freedesktop.systemd1.Manager",
3999 DBUS_TYPE_STRING, &n,
4008 static int show_enviroment(DBusConnection *bus, char **args) {
4009 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4010 DBusMessageIter iter, sub, sub2;
4013 *interface = "org.freedesktop.systemd1.Manager",
4014 *property = "Environment";
4016 pager_open_if_enabled();
4018 r = bus_method_call_with_reply(
4020 "org.freedesktop.systemd1",
4021 "/org/freedesktop/systemd1",
4022 "org.freedesktop.DBus.Properties",
4026 DBUS_TYPE_STRING, &interface,
4027 DBUS_TYPE_STRING, &property,
4032 if (!dbus_message_iter_init(reply, &iter) ||
4033 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
4034 log_error("Failed to parse reply.");
4038 dbus_message_iter_recurse(&iter, &sub);
4040 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
4041 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
4042 log_error("Failed to parse reply.");
4046 dbus_message_iter_recurse(&sub, &sub2);
4048 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
4051 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
4052 log_error("Failed to parse reply.");
4056 dbus_message_iter_get_basic(&sub2, &text);
4059 dbus_message_iter_next(&sub2);
4065 static int switch_root(DBusConnection *bus, char **args) {
4068 _cleanup_free_ char *init = NULL;
4070 l = strv_length(args);
4071 if (l < 2 || l > 3) {
4072 log_error("Wrong number of arguments.");
4079 init = strdup(args[2]);
4081 parse_env_file("/proc/cmdline", WHITESPACE,
4091 log_debug("switching root - root: %s; init: %s", root, init);
4093 return bus_method_call_with_reply(
4095 "org.freedesktop.systemd1",
4096 "/org/freedesktop/systemd1",
4097 "org.freedesktop.systemd1.Manager",
4101 DBUS_TYPE_STRING, &root,
4102 DBUS_TYPE_STRING, &init,
4106 static int set_environment(DBusConnection *bus, char **args) {
4107 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4110 DBusMessageIter iter;
4116 dbus_error_init(&error);
4118 method = streq(args[0], "set-environment")
4120 : "UnsetEnvironment";
4122 m = dbus_message_new_method_call(
4123 "org.freedesktop.systemd1",
4124 "/org/freedesktop/systemd1",
4125 "org.freedesktop.systemd1.Manager",
4130 dbus_message_iter_init_append(m, &iter);
4132 r = bus_append_strv_iter(&iter, args + 1);
4136 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4138 log_error("Failed to issue method call: %s", bus_error_message(&error));
4139 dbus_error_free(&error);
4146 static int enable_sysv_units(char **args) {
4149 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4150 const char *verb = args[0];
4151 unsigned f = 1, t = 1;
4152 LookupPaths paths = {};
4154 if (arg_scope != UNIT_FILE_SYSTEM)
4157 if (!streq(verb, "enable") &&
4158 !streq(verb, "disable") &&
4159 !streq(verb, "is-enabled"))
4162 /* Processes all SysV units, and reshuffles the array so that
4163 * afterwards only the native units remain */
4165 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4170 for (f = 1; args[f]; f++) {
4172 _cleanup_free_ char *p = NULL, *q = NULL;
4173 bool found_native = false, found_sysv;
4175 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4183 if (!endswith(name, ".service"))
4186 if (path_is_absolute(name))
4189 STRV_FOREACH(k, paths.unit_path) {
4190 if (!isempty(arg_root))
4191 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4193 asprintf(&p, "%s/%s", *k, name);
4200 found_native = access(p, F_OK) >= 0;
4211 if (!isempty(arg_root))
4212 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4214 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4220 p[strlen(p) - sizeof(".service") + 1] = 0;
4221 found_sysv = access(p, F_OK) >= 0;
4226 /* Mark this entry, so that we don't try enabling it as native unit */
4227 args[f] = (char*) "";
4229 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4231 if (!isempty(arg_root))
4232 argv[c++] = q = strappend("--root=", arg_root);
4234 argv[c++] = path_get_file_name(p);
4236 streq(verb, "enable") ? "on" :
4237 streq(verb, "disable") ? "off" : "--level=5";
4240 l = strv_join((char**)argv, " ");
4246 log_info("Executing %s", l);
4251 log_error("Failed to fork: %m");
4254 } else if (pid == 0) {
4257 execv(argv[0], (char**) argv);
4258 _exit(EXIT_FAILURE);
4261 j = wait_for_terminate(pid, &status);
4263 log_error("Failed to wait for child: %s", strerror(-r));
4268 if (status.si_code == CLD_EXITED) {
4269 if (streq(verb, "is-enabled")) {
4270 if (status.si_status == 0) {
4279 } else if (status.si_status != 0) {
4290 lookup_paths_free(&paths);
4292 /* Drop all SysV units */
4293 for (f = 1, t = 1; args[f]; f++) {
4295 if (isempty(args[f]))
4298 args[t++] = args[f];
4307 static int mangle_names(char **original_names, char ***mangled_names) {
4308 char **i, **l, **name;
4310 l = new(char*, strv_length(original_names) + 1);
4315 STRV_FOREACH(name, original_names) {
4317 /* When enabling units qualified path names are OK,
4318 * too, hence allow them explicitly. */
4323 *i = unit_name_mangle(*name);
4339 static int enable_unit(DBusConnection *bus, char **args) {
4340 const char *verb = args[0];
4341 UnitFileChange *changes = NULL;
4342 unsigned n_changes = 0, i;
4343 int carries_install_info = -1;
4344 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4346 _cleanup_dbus_error_free_ DBusError error;
4347 _cleanup_strv_free_ char **mangled_names = NULL;
4349 dbus_error_init(&error);
4351 r = enable_sysv_units(args);
4358 r = mangle_names(args+1, &mangled_names);
4362 if (!bus || avoid_bus()) {
4363 if (streq(verb, "enable")) {
4364 r = unit_file_enable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4365 carries_install_info = r;
4366 } else if (streq(verb, "disable"))
4367 r = unit_file_disable(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4368 else if (streq(verb, "reenable")) {
4369 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4370 carries_install_info = r;
4371 } else if (streq(verb, "link"))
4372 r = unit_file_link(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4373 else if (streq(verb, "preset")) {
4374 r = unit_file_preset(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4375 carries_install_info = r;
4376 } else if (streq(verb, "mask"))
4377 r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4378 else if (streq(verb, "unmask"))
4379 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4380 else if (streq(verb, "set-default"))
4381 r = unit_file_set_default(arg_scope, arg_root, args[1], &changes, &n_changes);
4383 assert_not_reached("Unknown verb");
4386 log_error("Operation failed: %s", strerror(-r));
4391 for (i = 0; i < n_changes; i++) {
4392 if (changes[i].type == UNIT_FILE_SYMLINK)
4393 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4395 log_info("rm '%s'", changes[i].path);
4402 bool send_force = true, expect_carries_install_info = false;
4404 DBusMessageIter iter, sub, sub2;
4406 if (streq(verb, "enable")) {
4407 method = "EnableUnitFiles";
4408 expect_carries_install_info = true;
4409 } else if (streq(verb, "disable")) {
4410 method = "DisableUnitFiles";
4412 } else if (streq(verb, "reenable")) {
4413 method = "ReenableUnitFiles";
4414 expect_carries_install_info = true;
4415 } else if (streq(verb, "link"))
4416 method = "LinkUnitFiles";
4417 else if (streq(verb, "preset")) {
4418 method = "PresetUnitFiles";
4419 expect_carries_install_info = true;
4420 } else if (streq(verb, "mask"))
4421 method = "MaskUnitFiles";
4422 else if (streq(verb, "unmask")) {
4423 method = "UnmaskUnitFiles";
4425 } else if (streq(verb, "set-default")) {
4426 method = "SetDefaultTarget";
4428 assert_not_reached("Unknown verb");
4430 m = dbus_message_new_method_call(
4431 "org.freedesktop.systemd1",
4432 "/org/freedesktop/systemd1",
4433 "org.freedesktop.systemd1.Manager",
4440 dbus_message_iter_init_append(m, &iter);
4442 r = bus_append_strv_iter(&iter, mangled_names);
4444 log_error("Failed to append unit files.");
4449 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4450 log_error("Failed to append runtime boolean.");
4458 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4459 log_error("Failed to append force boolean.");
4465 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4467 log_error("Failed to issue method call: %s", bus_error_message(&error));
4472 if (!dbus_message_iter_init(reply, &iter)) {
4473 log_error("Failed to initialize iterator.");
4477 if (expect_carries_install_info) {
4478 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4480 log_error("Failed to parse reply.");
4484 carries_install_info = b;
4487 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4488 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4489 log_error("Failed to parse reply.");
4494 dbus_message_iter_recurse(&iter, &sub);
4495 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4496 const char *type, *path, *source;
4498 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4499 log_error("Failed to parse reply.");
4504 dbus_message_iter_recurse(&sub, &sub2);
4506 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4507 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4508 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4509 log_error("Failed to parse reply.");
4515 if (streq(type, "symlink"))
4516 log_info("ln -s '%s' '%s'", source, path);
4518 log_info("rm '%s'", path);
4521 dbus_message_iter_next(&sub);
4524 /* Try to reload if enabeld */
4526 r = daemon_reload(bus, args);
4529 if (carries_install_info == 0)
4530 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4531 "using systemctl.\n"
4532 "Possible reasons for having this kind of units are:\n"
4533 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4534 " .wants/ or .requires/ directory.\n"
4535 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4536 " a requirement dependency on it.\n"
4537 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4538 " D-Bus, udev, scripted systemctl call, ...).\n");
4541 unit_file_changes_free(changes, n_changes);
4546 static int unit_is_enabled(DBusConnection *bus, char **args) {
4547 _cleanup_dbus_error_free_ DBusError error;
4549 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4554 dbus_error_init(&error);
4556 r = enable_sysv_units(args);
4562 if (!bus || avoid_bus()) {
4564 STRV_FOREACH(name, args+1) {
4565 UnitFileState state;
4567 n = unit_name_mangle(*name);
4571 state = unit_file_get_state(arg_scope, arg_root, n);
4578 if (state == UNIT_FILE_ENABLED ||
4579 state == UNIT_FILE_ENABLED_RUNTIME ||
4580 state == UNIT_FILE_STATIC)
4584 puts(unit_file_state_to_string(state));
4588 STRV_FOREACH(name, args+1) {
4591 n = unit_name_mangle(*name);
4595 r = bus_method_call_with_reply (
4597 "org.freedesktop.systemd1",
4598 "/org/freedesktop/systemd1",
4599 "org.freedesktop.systemd1.Manager",
4603 DBUS_TYPE_STRING, &n,
4611 if (!dbus_message_get_args(reply, &error,
4612 DBUS_TYPE_STRING, &s,
4613 DBUS_TYPE_INVALID)) {
4614 log_error("Failed to parse reply: %s", bus_error_message(&error));
4618 dbus_message_unref(reply);
4621 if (streq(s, "enabled") ||
4622 streq(s, "enabled-runtime") ||
4631 return enabled ? 0 : 1;
4634 static int systemctl_help(void) {
4636 pager_open_if_enabled();
4638 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4639 "Query or send control commands to the systemd manager.\n\n"
4640 " -h --help Show this help\n"
4641 " --version Show package version\n"
4642 " -t --type=TYPE List only units of a particular type\n"
4643 " --state=STATE List only units with particular LOAD or SUB or ACTIVE state\n"
4644 " -p --property=NAME Show only properties by this name\n"
4645 " -a --all Show all loaded units/properties, including dead/empty\n"
4646 " ones. To list all units installed on the system, use\n"
4647 " the 'list-unit-files' command instead.\n"
4648 " --reverse Show reverse dependencies with 'list-dependencies'\n"
4649 " -l --full Don't ellipsize unit names on output\n"
4650 " --fail When queueing a new job, fail if conflicting jobs are\n"
4652 " --irreversible When queueing a new job, make sure it cannot be implicitly\n"
4654 " --ignore-dependencies\n"
4655 " When queueing a new job, ignore all its dependencies\n"
4656 " --show-types When showing sockets, explicitly show their type\n"
4657 " -i --ignore-inhibitors\n"
4658 " When shutting down or sleeping, ignore inhibitors\n"
4659 " --kill-who=WHO Who to send signal to\n"
4660 " -s --signal=SIGNAL Which signal to send\n"
4661 " -H --host=[USER@]HOST\n"
4662 " Show information for remote host\n"
4663 " -P --privileged Acquire privileges before execution\n"
4664 " -q --quiet Suppress output\n"
4665 " --no-block Do not wait until operation finished\n"
4666 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4667 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4669 " --no-legend Do not print a legend (column headers and hints)\n"
4670 " --no-pager Do not pipe output into a pager\n"
4671 " --no-ask-password\n"
4672 " Do not ask for system passwords\n"
4673 " --system Connect to system manager\n"
4674 " --user Connect to user service manager\n"
4675 " --global Enable/disable unit files globally\n"
4676 " --runtime Enable unit files only temporarily until next reboot\n"
4677 " -f --force When enabling unit files, override existing symlinks\n"
4678 " When shutting down, execute action immediately\n"
4679 " --root=PATH Enable unit files in the specified root directory\n"
4680 " -n --lines=INTEGER Numer of journal entries to show\n"
4681 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4682 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4684 " list-units List loaded units\n"
4685 " list-sockets List loaded sockets ordered by address\n"
4686 " start [NAME...] Start (activate) one or more units\n"
4687 " stop [NAME...] Stop (deactivate) one or more units\n"
4688 " reload [NAME...] Reload one or more units\n"
4689 " restart [NAME...] Start or restart one or more units\n"
4690 " try-restart [NAME...] Restart one or more units if active\n"
4691 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4692 " otherwise start or restart\n"
4693 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4694 " otherwise restart if active\n"
4695 " isolate [NAME] Start one unit and stop all others\n"
4696 " kill [NAME...] Send signal to processes of a unit\n"
4697 " is-active [NAME...] Check whether units are active\n"
4698 " is-failed [NAME...] Check whether units are failed\n"
4699 " status [NAME...|PID...] Show runtime status of one or more units\n"
4700 " show [NAME...|JOB...] Show properties of one or more\n"
4701 " units/jobs or the manager\n"
4702 " set-property [NAME] [ASSIGNMENT...]\n"
4703 " Sets one or more properties of a unit\n"
4704 " help [NAME...|PID...] Show manual for one or more units\n"
4705 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4707 " list-dependencies [NAME] Recursively show units which are required\n"
4708 " or wanted by this unit or by which this\n"
4709 " unit is required or wanted\n\n"
4710 "Unit File Commands:\n"
4711 " list-unit-files List installed unit files\n"
4712 " enable [NAME...] Enable one or more unit files\n"
4713 " disable [NAME...] Disable one or more unit files\n"
4714 " reenable [NAME...] Reenable one or more unit files\n"
4715 " preset [NAME...] Enable/disable one or more unit files\n"
4716 " based on preset configuration\n"
4717 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4718 " mask [NAME...] Mask one or more units\n"
4719 " unmask [NAME...] Unmask one or more units\n"
4720 " link [PATH...] Link one or more units files into\n"
4721 " the search path\n"
4722 " get-default Get the name of the default target\n"
4723 " set-default NAME Set the default target\n\n"
4725 " list-jobs List jobs\n"
4726 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4727 "Snapshot Commands:\n"
4728 " snapshot [NAME] Create a snapshot\n"
4729 " delete [NAME...] Remove one or more snapshots\n\n"
4730 "Environment Commands:\n"
4731 " show-environment Dump environment\n"
4732 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4733 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4734 "Manager Lifecycle Commands:\n"
4735 " daemon-reload Reload systemd manager configuration\n"
4736 " daemon-reexec Reexecute systemd manager\n\n"
4737 "System Commands:\n"
4738 " default Enter system default mode\n"
4739 " rescue Enter system rescue mode\n"
4740 " emergency Enter system emergency mode\n"
4741 " halt Shut down and halt the system\n"
4742 " poweroff Shut down and power-off the system\n"
4743 " reboot Shut down and reboot the system\n"
4744 " kexec Shut down and reboot the system with kexec\n"
4745 " exit Request user instance exit\n"
4746 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4747 " suspend Suspend the system\n"
4748 " hibernate Hibernate the system\n"
4749 " hybrid-sleep Hibernate and suspend the system\n",
4750 program_invocation_short_name);
4755 static int halt_help(void) {
4757 printf("%s [OPTIONS...]\n\n"
4758 "%s the system.\n\n"
4759 " --help Show this help\n"
4760 " --halt Halt the machine\n"
4761 " -p --poweroff Switch off the machine\n"
4762 " --reboot Reboot the machine\n"
4763 " -f --force Force immediate halt/power-off/reboot\n"
4764 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4765 " -d --no-wtmp Don't write wtmp record\n"
4766 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4767 program_invocation_short_name,
4768 arg_action == ACTION_REBOOT ? "Reboot" :
4769 arg_action == ACTION_POWEROFF ? "Power off" :
4775 static int shutdown_help(void) {
4777 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4778 "Shut down the system.\n\n"
4779 " --help Show this help\n"
4780 " -H --halt Halt the machine\n"
4781 " -P --poweroff Power-off the machine\n"
4782 " -r --reboot Reboot the machine\n"
4783 " -h Equivalent to --poweroff, overridden by --halt\n"
4784 " -k Don't halt/power-off/reboot, just send warnings\n"
4785 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4786 " -c Cancel a pending shutdown\n",
4787 program_invocation_short_name);
4792 static int telinit_help(void) {
4794 printf("%s [OPTIONS...] {COMMAND}\n\n"
4795 "Send control commands to the init daemon.\n\n"
4796 " --help Show this help\n"
4797 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4799 " 0 Power-off the machine\n"
4800 " 6 Reboot the machine\n"
4801 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4802 " 1, s, S Enter rescue mode\n"
4803 " q, Q Reload init daemon configuration\n"
4804 " u, U Reexecute init daemon\n",
4805 program_invocation_short_name);
4810 static int runlevel_help(void) {
4812 printf("%s [OPTIONS...]\n\n"
4813 "Prints the previous and current runlevel of the init system.\n\n"
4814 " --help Show this help\n",
4815 program_invocation_short_name);
4820 static int help_types(void) {
4824 puts("Available unit types:");
4825 for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4826 t = unit_type_to_string(i);
4834 static int systemctl_parse_argv(int argc, char *argv[]) {
4843 ARG_IGNORE_DEPENDENCIES,
4855 ARG_NO_ASK_PASSWORD,
4863 static const struct option options[] = {
4864 { "help", no_argument, NULL, 'h' },
4865 { "version", no_argument, NULL, ARG_VERSION },
4866 { "type", required_argument, NULL, 't' },
4867 { "property", required_argument, NULL, 'p' },
4868 { "all", no_argument, NULL, 'a' },
4869 { "reverse", no_argument, NULL, ARG_REVERSE },
4870 { "after", no_argument, NULL, ARG_AFTER },
4871 { "before", no_argument, NULL, ARG_BEFORE },
4872 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
4873 { "failed", no_argument, NULL, ARG_FAILED }, /* compatibility only */
4874 { "full", no_argument, NULL, 'l' },
4875 { "fail", no_argument, NULL, ARG_FAIL },
4876 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4877 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4878 { "ignore-inhibitors", no_argument, NULL, 'i' },
4879 { "user", no_argument, NULL, ARG_USER },
4880 { "system", no_argument, NULL, ARG_SYSTEM },
4881 { "global", no_argument, NULL, ARG_GLOBAL },
4882 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4883 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4884 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4885 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4886 { "quiet", no_argument, NULL, 'q' },
4887 { "root", required_argument, NULL, ARG_ROOT },
4888 { "force", no_argument, NULL, ARG_FORCE },
4889 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4890 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4891 { "signal", required_argument, NULL, 's' },
4892 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4893 { "host", required_argument, NULL, 'H' },
4894 { "privileged", no_argument, NULL, 'P' },
4895 { "runtime", no_argument, NULL, ARG_RUNTIME },
4896 { "lines", required_argument, NULL, 'n' },
4897 { "output", required_argument, NULL, 'o' },
4898 { "plain", no_argument, NULL, ARG_PLAIN },
4899 { "state", required_argument, NULL, ARG_STATE },
4900 { NULL, 0, NULL, 0 }
4908 while ((c = getopt_long(argc, argv, "ht:p:alqfs:H:Pn:o:i", options, NULL)) >= 0) {
4917 puts(PACKAGE_STRING);
4918 puts(SYSTEMD_FEATURES);
4925 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4926 _cleanup_free_ char *type;
4928 type = strndup(word, size);
4932 if (streq(type, "help")) {
4937 if (unit_type_from_string(type) >= 0) {
4938 if (strv_push(&arg_types, type))
4944 /* It's much nicer to use --state= for
4945 * load states, but let's support this
4946 * in --types= too for compatibility
4947 * with old versions */
4948 if (unit_load_state_from_string(optarg) >= 0) {
4949 if (strv_push(&arg_states, type) < 0)
4955 log_error("Unknown unit type or load state '%s'.", type);
4956 log_info("Use -t help to see a list of allowed values.");
4964 /* Make sure that if the empty property list
4965 was specified, we won't show any properties. */
4966 if (isempty(optarg) && !arg_properties) {
4967 arg_properties = strv_new(NULL, NULL);
4968 if (!arg_properties)
4974 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4977 prop = strndup(word, size);
4981 if (strv_push(&arg_properties, prop) < 0) {
4988 /* If the user asked for a particular
4989 * property, show it to him, even if it is
5001 arg_dependency = DEPENDENCY_REVERSE;
5005 arg_dependency = DEPENDENCY_AFTER;
5009 arg_dependency = DEPENDENCY_BEFORE;
5012 case ARG_SHOW_TYPES:
5013 arg_show_types = true;
5017 arg_job_mode = "fail";
5020 case ARG_IRREVERSIBLE:
5021 arg_job_mode = "replace-irreversibly";
5024 case ARG_IGNORE_DEPENDENCIES:
5025 arg_job_mode = "ignore-dependencies";
5029 arg_scope = UNIT_FILE_USER;
5033 arg_scope = UNIT_FILE_SYSTEM;
5037 arg_scope = UNIT_FILE_GLOBAL;
5041 arg_no_block = true;
5045 arg_no_legend = true;
5049 arg_no_pager = true;
5065 if (strv_extend(&arg_states, "failed") < 0)
5083 arg_no_reload = true;
5087 arg_kill_who = optarg;
5091 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5092 log_error("Failed to parse signal string %s.", optarg);
5097 case ARG_NO_ASK_PASSWORD:
5098 arg_ask_password = false;
5102 arg_transport = TRANSPORT_POLKIT;
5106 arg_transport = TRANSPORT_SSH;
5107 parse_user_at_host(optarg, &arg_user, &arg_host);
5115 if (safe_atou(optarg, &arg_lines) < 0) {
5116 log_error("Failed to parse lines '%s'", optarg);
5122 arg_output = output_mode_from_string(optarg);
5123 if (arg_output < 0) {
5124 log_error("Unknown output '%s'.", optarg);
5130 arg_ignore_inhibitors = true;
5141 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
5144 s = strndup(word, size);
5148 if (strv_push(&arg_states, s) < 0) {
5160 log_error("Unknown option code '%c'.", c);
5165 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
5166 log_error("Cannot access user instance remotely.");
5173 static int halt_parse_argv(int argc, char *argv[]) {
5182 static const struct option options[] = {
5183 { "help", no_argument, NULL, ARG_HELP },
5184 { "halt", no_argument, NULL, ARG_HALT },
5185 { "poweroff", no_argument, NULL, 'p' },
5186 { "reboot", no_argument, NULL, ARG_REBOOT },
5187 { "force", no_argument, NULL, 'f' },
5188 { "wtmp-only", no_argument, NULL, 'w' },
5189 { "no-wtmp", no_argument, NULL, 'd' },
5190 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5191 { NULL, 0, NULL, 0 }
5199 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5200 if (runlevel == '0' || runlevel == '6')
5203 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5211 arg_action = ACTION_HALT;
5215 if (arg_action != ACTION_REBOOT)
5216 arg_action = ACTION_POWEROFF;
5220 arg_action = ACTION_REBOOT;
5242 /* Compatibility nops */
5249 log_error("Unknown option code '%c'.", c);
5254 if (optind < argc) {
5255 log_error("Too many arguments.");
5262 static int parse_time_spec(const char *t, usec_t *_u) {
5266 if (streq(t, "now"))
5268 else if (!strchr(t, ':')) {
5271 if (safe_atou64(t, &u) < 0)
5274 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5283 hour = strtol(t, &e, 10);
5284 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5287 minute = strtol(e+1, &e, 10);
5288 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5291 n = now(CLOCK_REALTIME);
5292 s = (time_t) (n / USEC_PER_SEC);
5294 assert_se(localtime_r(&s, &tm));
5296 tm.tm_hour = (int) hour;
5297 tm.tm_min = (int) minute;
5300 assert_se(s = mktime(&tm));
5302 *_u = (usec_t) s * USEC_PER_SEC;
5305 *_u += USEC_PER_DAY;
5311 static int shutdown_parse_argv(int argc, char *argv[]) {
5318 static const struct option options[] = {
5319 { "help", no_argument, NULL, ARG_HELP },
5320 { "halt", no_argument, NULL, 'H' },
5321 { "poweroff", no_argument, NULL, 'P' },
5322 { "reboot", no_argument, NULL, 'r' },
5323 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5324 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5325 { NULL, 0, NULL, 0 }
5333 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5341 arg_action = ACTION_HALT;
5345 arg_action = ACTION_POWEROFF;
5350 arg_action = ACTION_KEXEC;
5352 arg_action = ACTION_REBOOT;
5356 arg_action = ACTION_KEXEC;
5360 if (arg_action != ACTION_HALT)
5361 arg_action = ACTION_POWEROFF;
5374 /* Compatibility nops */
5378 arg_action = ACTION_CANCEL_SHUTDOWN;
5385 log_error("Unknown option code '%c'.", c);
5390 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5391 r = parse_time_spec(argv[optind], &arg_when);
5393 log_error("Failed to parse time specification: %s", argv[optind]);
5397 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5399 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5400 /* No time argument for shutdown cancel */
5401 arg_wall = argv + optind;
5402 else if (argc > optind + 1)
5403 /* We skip the time argument */
5404 arg_wall = argv + optind + 1;
5411 static int telinit_parse_argv(int argc, char *argv[]) {
5418 static const struct option options[] = {
5419 { "help", no_argument, NULL, ARG_HELP },
5420 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5421 { NULL, 0, NULL, 0 }
5424 static const struct {
5428 { '0', ACTION_POWEROFF },
5429 { '6', ACTION_REBOOT },
5430 { '1', ACTION_RESCUE },
5431 { '2', ACTION_RUNLEVEL2 },
5432 { '3', ACTION_RUNLEVEL3 },
5433 { '4', ACTION_RUNLEVEL4 },
5434 { '5', ACTION_RUNLEVEL5 },
5435 { 's', ACTION_RESCUE },
5436 { 'S', ACTION_RESCUE },
5437 { 'q', ACTION_RELOAD },
5438 { 'Q', ACTION_RELOAD },
5439 { 'u', ACTION_REEXEC },
5440 { 'U', ACTION_REEXEC }
5449 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5464 log_error("Unknown option code '%c'.", c);
5469 if (optind >= argc) {
5474 if (optind + 1 < argc) {
5475 log_error("Too many arguments.");
5479 if (strlen(argv[optind]) != 1) {
5480 log_error("Expected single character argument.");
5484 for (i = 0; i < ELEMENTSOF(table); i++)
5485 if (table[i].from == argv[optind][0])
5488 if (i >= ELEMENTSOF(table)) {
5489 log_error("Unknown command '%s'.", argv[optind]);
5493 arg_action = table[i].to;
5500 static int runlevel_parse_argv(int argc, char *argv[]) {
5506 static const struct option options[] = {
5507 { "help", no_argument, NULL, ARG_HELP },
5508 { NULL, 0, NULL, 0 }
5516 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5527 log_error("Unknown option code '%c'.", c);
5532 if (optind < argc) {
5533 log_error("Too many arguments.");
5540 static int parse_argv(int argc, char *argv[]) {
5544 if (program_invocation_short_name) {
5546 if (strstr(program_invocation_short_name, "halt")) {
5547 arg_action = ACTION_HALT;
5548 return halt_parse_argv(argc, argv);
5549 } else if (strstr(program_invocation_short_name, "poweroff")) {
5550 arg_action = ACTION_POWEROFF;
5551 return halt_parse_argv(argc, argv);
5552 } else if (strstr(program_invocation_short_name, "reboot")) {
5554 arg_action = ACTION_KEXEC;
5556 arg_action = ACTION_REBOOT;
5557 return halt_parse_argv(argc, argv);
5558 } else if (strstr(program_invocation_short_name, "shutdown")) {
5559 arg_action = ACTION_POWEROFF;
5560 return shutdown_parse_argv(argc, argv);
5561 } else if (strstr(program_invocation_short_name, "init")) {
5563 if (sd_booted() > 0) {
5564 arg_action = ACTION_INVALID;
5565 return telinit_parse_argv(argc, argv);
5567 /* Hmm, so some other init system is
5568 * running, we need to forward this
5569 * request to it. For now we simply
5570 * guess that it is Upstart. */
5572 execv(TELINIT, argv);
5574 log_error("Couldn't find an alternative telinit implementation to spawn.");
5578 } else if (strstr(program_invocation_short_name, "runlevel")) {
5579 arg_action = ACTION_RUNLEVEL;
5580 return runlevel_parse_argv(argc, argv);
5584 arg_action = ACTION_SYSTEMCTL;
5585 return systemctl_parse_argv(argc, argv);
5588 _pure_ static int action_to_runlevel(void) {
5590 static const char table[_ACTION_MAX] = {
5591 [ACTION_HALT] = '0',
5592 [ACTION_POWEROFF] = '0',
5593 [ACTION_REBOOT] = '6',
5594 [ACTION_RUNLEVEL2] = '2',
5595 [ACTION_RUNLEVEL3] = '3',
5596 [ACTION_RUNLEVEL4] = '4',
5597 [ACTION_RUNLEVEL5] = '5',
5598 [ACTION_RESCUE] = '1'
5601 assert(arg_action < _ACTION_MAX);
5603 return table[arg_action];
5606 static int talk_upstart(void) {
5607 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
5608 _cleanup_dbus_error_free_ DBusError error;
5609 int previous, rl, r;
5611 env1_buf[] = "RUNLEVEL=X",
5612 env2_buf[] = "PREVLEVEL=X";
5613 char *env1 = env1_buf, *env2 = env2_buf;
5614 const char *emit = "runlevel";
5615 dbus_bool_t b_false = FALSE;
5616 DBusMessageIter iter, sub;
5617 DBusConnection *bus;
5619 dbus_error_init(&error);
5621 if (!(rl = action_to_runlevel()))
5624 if (utmp_get_runlevel(&previous, NULL) < 0)
5627 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5628 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5633 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5638 if ((r = bus_check_peercred(bus)) < 0) {
5639 log_error("Failed to verify owner of bus.");
5643 if (!(m = dbus_message_new_method_call(
5644 "com.ubuntu.Upstart",
5645 "/com/ubuntu/Upstart",
5646 "com.ubuntu.Upstart0_6",
5649 log_error("Could not allocate message.");
5654 dbus_message_iter_init_append(m, &iter);
5656 env1_buf[sizeof(env1_buf)-2] = rl;
5657 env2_buf[sizeof(env2_buf)-2] = previous;
5659 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5660 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5661 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5662 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5663 !dbus_message_iter_close_container(&iter, &sub) ||
5664 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5665 log_error("Could not append arguments to message.");
5670 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5672 if (bus_error_is_no_service(&error)) {
5677 log_error("Failed to issue method call: %s", bus_error_message(&error));
5686 dbus_connection_flush(bus);
5687 dbus_connection_close(bus);
5688 dbus_connection_unref(bus);
5694 static int talk_initctl(void) {
5695 struct init_request request = {};
5697 _cleanup_close_ int fd = -1;
5700 rl = action_to_runlevel();
5704 request.magic = INIT_MAGIC;
5705 request.sleeptime = 0;
5706 request.cmd = INIT_CMD_RUNLVL;
5707 request.runlevel = rl;
5709 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5711 if (errno == ENOENT)
5714 log_error("Failed to open "INIT_FIFO": %m");
5719 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5721 log_error("Failed to write to "INIT_FIFO": %m");
5722 return errno > 0 ? -errno : -EIO;
5728 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5730 static const struct {
5738 int (* const dispatch)(DBusConnection *bus, char **args);
5740 { "list-units", LESS, 1, list_units },
5741 { "list-unit-files", EQUAL, 1, list_unit_files },
5742 { "list-sockets", LESS, 1, list_sockets },
5743 { "list-jobs", EQUAL, 1, list_jobs },
5744 { "clear-jobs", EQUAL, 1, daemon_reload },
5745 { "cancel", MORE, 2, cancel_job },
5746 { "start", MORE, 2, start_unit },
5747 { "stop", MORE, 2, start_unit },
5748 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5749 { "reload", MORE, 2, start_unit },
5750 { "restart", MORE, 2, start_unit },
5751 { "try-restart", MORE, 2, start_unit },
5752 { "reload-or-restart", MORE, 2, start_unit },
5753 { "reload-or-try-restart", MORE, 2, start_unit },
5754 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5755 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5756 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5757 { "isolate", EQUAL, 2, start_unit },
5758 { "kill", MORE, 2, kill_unit },
5759 { "is-active", MORE, 2, check_unit_active },
5760 { "check", MORE, 2, check_unit_active },
5761 { "is-failed", MORE, 2, check_unit_failed },
5762 { "show", MORE, 1, show },
5763 { "status", MORE, 1, show },
5764 { "help", MORE, 2, show },
5765 { "snapshot", LESS, 2, snapshot },
5766 { "delete", MORE, 2, delete_snapshot },
5767 { "daemon-reload", EQUAL, 1, daemon_reload },
5768 { "daemon-reexec", EQUAL, 1, daemon_reload },
5769 { "show-environment", EQUAL, 1, show_enviroment },
5770 { "set-environment", MORE, 2, set_environment },
5771 { "unset-environment", MORE, 2, set_environment },
5772 { "halt", EQUAL, 1, start_special },
5773 { "poweroff", EQUAL, 1, start_special },
5774 { "reboot", EQUAL, 1, start_special },
5775 { "kexec", EQUAL, 1, start_special },
5776 { "suspend", EQUAL, 1, start_special },
5777 { "hibernate", EQUAL, 1, start_special },
5778 { "hybrid-sleep", EQUAL, 1, start_special },
5779 { "default", EQUAL, 1, start_special },
5780 { "rescue", EQUAL, 1, start_special },
5781 { "emergency", EQUAL, 1, start_special },
5782 { "exit", EQUAL, 1, start_special },
5783 { "reset-failed", MORE, 1, reset_failed },
5784 { "enable", MORE, 2, enable_unit },
5785 { "disable", MORE, 2, enable_unit },
5786 { "is-enabled", MORE, 2, unit_is_enabled },
5787 { "reenable", MORE, 2, enable_unit },
5788 { "preset", MORE, 2, enable_unit },
5789 { "mask", MORE, 2, enable_unit },
5790 { "unmask", MORE, 2, enable_unit },
5791 { "link", MORE, 2, enable_unit },
5792 { "switch-root", MORE, 2, switch_root },
5793 { "list-dependencies", LESS, 2, list_dependencies },
5794 { "set-default", EQUAL, 2, enable_unit },
5795 { "get-default", LESS, 1, get_default },
5796 { "set-property", MORE, 3, set_property },
5806 left = argc - optind;
5809 /* Special rule: no arguments means "list-units" */
5812 if (streq(argv[optind], "help") && !argv[optind+1]) {
5813 log_error("This command expects one or more "
5814 "unit names. Did you mean --help?");
5818 for (i = 0; i < ELEMENTSOF(verbs); i++)
5819 if (streq(argv[optind], verbs[i].verb))
5822 if (i >= ELEMENTSOF(verbs)) {
5823 log_error("Unknown operation '%s'.", argv[optind]);
5828 switch (verbs[i].argc_cmp) {
5831 if (left != verbs[i].argc) {
5832 log_error("Invalid number of arguments.");
5839 if (left < verbs[i].argc) {
5840 log_error("Too few arguments.");
5847 if (left > verbs[i].argc) {
5848 log_error("Too many arguments.");
5855 assert_not_reached("Unknown comparison operator.");
5858 /* Require a bus connection for all operations but
5860 if (!streq(verbs[i].verb, "enable") &&
5861 !streq(verbs[i].verb, "disable") &&
5862 !streq(verbs[i].verb, "is-enabled") &&
5863 !streq(verbs[i].verb, "list-unit-files") &&
5864 !streq(verbs[i].verb, "reenable") &&
5865 !streq(verbs[i].verb, "preset") &&
5866 !streq(verbs[i].verb, "mask") &&
5867 !streq(verbs[i].verb, "unmask") &&
5868 !streq(verbs[i].verb, "link") &&
5869 !streq(verbs[i].verb, "set-default") &&
5870 !streq(verbs[i].verb, "get-default")) {
5872 if (running_in_chroot() > 0) {
5873 log_info("Running in chroot, ignoring request.");
5877 if (((!streq(verbs[i].verb, "reboot") &&
5878 !streq(verbs[i].verb, "halt") &&
5879 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5880 log_error("Failed to get D-Bus connection: %s",
5881 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5887 if (!bus && !avoid_bus()) {
5888 log_error("Failed to get D-Bus connection: %s",
5889 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5894 return verbs[i].dispatch(bus, argv + optind);
5897 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5898 _cleanup_close_ int fd;
5899 struct sd_shutdown_command c = {
5905 union sockaddr_union sockaddr = {
5906 .un.sun_family = AF_UNIX,
5907 .un.sun_path = "/run/systemd/shutdownd",
5909 struct iovec iovec[2] = {
5910 {.iov_base = (char*) &c,
5911 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
5914 struct msghdr msghdr = {
5915 .msg_name = &sockaddr,
5916 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
5917 + sizeof("/run/systemd/shutdownd") - 1,
5922 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5926 if (!isempty(message)) {
5927 iovec[1].iov_base = (char*) message;
5928 iovec[1].iov_len = strlen(message);
5929 msghdr.msg_iovlen++;
5932 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5938 static int reload_with_fallback(DBusConnection *bus) {
5941 /* First, try systemd via D-Bus. */
5942 if (daemon_reload(bus, NULL) >= 0)
5946 /* Nothing else worked, so let's try signals */
5947 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5949 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5950 log_error("kill() failed: %m");
5957 static int start_with_fallback(DBusConnection *bus) {
5960 /* First, try systemd via D-Bus. */
5961 if (start_unit(bus, NULL) >= 0)
5965 /* Hmm, talking to systemd via D-Bus didn't work. Then
5966 * let's try to talk to Upstart via D-Bus. */
5967 if (talk_upstart() > 0)
5970 /* Nothing else worked, so let's try
5972 if (talk_initctl() > 0)
5975 log_error("Failed to talk to init daemon.");
5979 warn_wall(arg_action);
5983 static _noreturn_ void halt_now(enum action a) {
5985 /* Make sure C-A-D is handled by the kernel from this
5987 reboot(RB_ENABLE_CAD);
5992 log_info("Halting.");
5993 reboot(RB_HALT_SYSTEM);
5996 case ACTION_POWEROFF:
5997 log_info("Powering off.");
5998 reboot(RB_POWER_OFF);
6002 log_info("Rebooting.");
6003 reboot(RB_AUTOBOOT);
6007 assert_not_reached("Unknown halt action.");
6010 assert_not_reached("Uh? This shouldn't happen.");
6013 static int halt_main(DBusConnection *bus) {
6016 r = check_inhibitors(bus, arg_action);
6020 if (geteuid() != 0) {
6021 /* Try logind if we are a normal user and no special
6022 * mode applies. Maybe PolicyKit allows us to shutdown
6025 if (arg_when <= 0 &&
6028 (arg_action == ACTION_POWEROFF ||
6029 arg_action == ACTION_REBOOT)) {
6030 r = reboot_with_logind(bus, arg_action);
6035 log_error("Must be root.");
6040 _cleanup_free_ char *m;
6042 m = strv_join(arg_wall, " ");
6043 r = send_shutdownd(arg_when,
6044 arg_action == ACTION_HALT ? 'H' :
6045 arg_action == ACTION_POWEROFF ? 'P' :
6046 arg_action == ACTION_KEXEC ? 'K' :
6053 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6055 char date[FORMAT_TIMESTAMP_MAX];
6057 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6058 format_timestamp(date, sizeof(date), arg_when));
6063 if (!arg_dry && !arg_force)
6064 return start_with_fallback(bus);
6067 if (sd_booted() > 0)
6068 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6070 r = utmp_put_shutdown();
6072 log_warning("Failed to write utmp record: %s", strerror(-r));
6079 halt_now(arg_action);
6080 /* We should never reach this. */
6084 static int runlevel_main(void) {
6085 int r, runlevel, previous;
6087 r = utmp_get_runlevel(&runlevel, &previous);
6094 previous <= 0 ? 'N' : previous,
6095 runlevel <= 0 ? 'N' : runlevel);
6100 int main(int argc, char*argv[]) {
6101 int r, retval = EXIT_FAILURE;
6102 DBusConnection *bus = NULL;
6103 _cleanup_dbus_error_free_ DBusError error;
6105 dbus_error_init(&error);
6107 setlocale(LC_ALL, "");
6108 log_parse_environment();
6111 r = parse_argv(argc, argv);
6115 retval = EXIT_SUCCESS;
6119 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6120 * let's shortcut this */
6121 if (arg_action == ACTION_RUNLEVEL) {
6122 r = runlevel_main();
6123 retval = r < 0 ? EXIT_FAILURE : r;
6127 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6128 log_info("Running in chroot, ignoring request.");
6134 if (arg_transport == TRANSPORT_NORMAL)
6135 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
6136 else if (arg_transport == TRANSPORT_POLKIT) {
6137 bus_connect_system_polkit(&bus, &error);
6138 private_bus = false;
6139 } else if (arg_transport == TRANSPORT_SSH) {
6140 bus_connect_system_ssh(arg_user, arg_host, &bus, &error);
6141 private_bus = false;
6143 assert_not_reached("Uh, invalid transport...");
6146 switch (arg_action) {
6148 case ACTION_SYSTEMCTL:
6149 r = systemctl_main(bus, argc, argv, &error);
6153 case ACTION_POWEROFF:
6159 case ACTION_RUNLEVEL2:
6160 case ACTION_RUNLEVEL3:
6161 case ACTION_RUNLEVEL4:
6162 case ACTION_RUNLEVEL5:
6164 case ACTION_EMERGENCY:
6165 case ACTION_DEFAULT:
6166 r = start_with_fallback(bus);
6171 r = reload_with_fallback(bus);
6174 case ACTION_CANCEL_SHUTDOWN: {
6178 m = strv_join(arg_wall, " ");
6180 retval = EXIT_FAILURE;
6184 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6186 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6191 case ACTION_INVALID:
6192 case ACTION_RUNLEVEL:
6194 assert_not_reached("Unknown action");
6197 retval = r < 0 ? EXIT_FAILURE : r;
6201 dbus_connection_flush(bus);
6202 dbus_connection_close(bus);
6203 dbus_connection_unref(bus);
6208 strv_free(arg_types);
6209 strv_free(arg_states);
6210 strv_free(arg_properties);
6213 ask_password_agent_close();
6214 polkit_agent_close();