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_load_states = NULL;
73 static char **arg_properties = NULL;
74 static bool arg_all = false;
75 static const char *arg_job_mode = "replace";
76 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
77 static bool arg_no_block = false;
78 static bool arg_no_legend = false;
79 static bool arg_no_pager = false;
80 static bool arg_no_wtmp = false;
81 static bool arg_no_wall = false;
82 static bool arg_no_reload = false;
83 static bool arg_show_types = false;
84 static bool arg_ignore_inhibitors = false;
85 static bool arg_dry = false;
86 static bool arg_quiet = false;
87 static bool arg_full = false;
88 static int arg_force = 0;
89 static bool arg_ask_password = true;
90 static bool arg_failed = false;
91 static bool arg_runtime = false;
92 static char **arg_wall = NULL;
93 static const char *arg_kill_who = NULL;
94 static int arg_signal = SIGTERM;
95 static const char *arg_root = NULL;
96 static usec_t arg_when = 0;
118 ACTION_CANCEL_SHUTDOWN,
120 } arg_action = ACTION_SYSTEMCTL;
121 static enum transport {
125 } arg_transport = TRANSPORT_NORMAL;
126 static const char *arg_host = NULL;
127 static unsigned arg_lines = 10;
128 static OutputMode arg_output = OUTPUT_SHORT;
130 static bool private_bus = false;
132 static int daemon_reload(DBusConnection *bus, char **args);
133 static void halt_now(enum action a);
135 static void pager_open_if_enabled(void) {
143 static void ask_password_agent_open_if_enabled(void) {
145 /* Open the password agent as a child process if necessary */
147 if (!arg_ask_password)
150 if (arg_scope != UNIT_FILE_SYSTEM)
153 ask_password_agent_open();
157 static void polkit_agent_open_if_enabled(void) {
159 /* Open the polkit agent as a child process if necessary */
161 if (!arg_ask_password)
164 if (arg_scope != UNIT_FILE_SYSTEM)
171 static const char *ansi_highlight(bool b) {
176 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
179 static const char *ansi_highlight_red(bool b) {
184 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
187 static const char *ansi_highlight_green(bool b) {
192 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
195 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
198 if (!dbus_error_is_set(error))
201 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
202 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
203 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
204 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
205 return EXIT_NOPERMISSION;
207 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
208 return EXIT_NOTINSTALLED;
210 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
211 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
212 return EXIT_NOTIMPLEMENTED;
214 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
215 return EXIT_NOTCONFIGURED;
223 static void warn_wall(enum action a) {
224 static const char *table[_ACTION_MAX] = {
225 [ACTION_HALT] = "The system is going down for system halt NOW!",
226 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
227 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
228 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
229 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
230 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
231 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
238 _cleanup_free_ char *p;
240 p = strv_join(arg_wall, " ");
255 utmp_wall(table[a], NULL);
258 static bool avoid_bus(void) {
260 if (running_in_chroot() > 0)
263 if (sd_booted() <= 0)
266 if (!isempty(arg_root))
269 if (arg_scope == UNIT_FILE_GLOBAL)
275 static int compare_unit_info(const void *a, const void *b) {
277 const struct unit_info *u = a, *v = b;
279 d1 = strrchr(u->id, '.');
280 d2 = strrchr(v->id, '.');
285 r = strcasecmp(d1, d2);
290 return strcasecmp(u->id, v->id);
293 static bool output_show_unit(const struct unit_info *u) {
297 return streq(u->active_state, "failed");
299 return (!arg_types || ((dot = strrchr(u->id, '.')) &&
300 strv_find(arg_types, dot+1))) &&
301 (!arg_load_states || strv_find(arg_load_states, u->load_state)) &&
302 (arg_all || !(streq(u->active_state, "inactive")
303 || u->following[0]) || u->job_id > 0);
306 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
307 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
308 const struct unit_info *u;
311 max_id_len = sizeof("UNIT")-1;
312 active_len = sizeof("ACTIVE")-1;
313 sub_len = sizeof("SUB")-1;
314 job_len = sizeof("JOB")-1;
317 for (u = unit_infos; u < unit_infos + c; u++) {
318 if (!output_show_unit(u))
321 max_id_len = MAX(max_id_len, strlen(u->id));
322 active_len = MAX(active_len, strlen(u->active_state));
323 sub_len = MAX(sub_len, strlen(u->sub_state));
324 if (u->job_id != 0) {
325 job_len = MAX(job_len, strlen(u->job_type));
332 id_len = MIN(max_id_len, 25u);
333 basic_len = 5 + id_len + 5 + active_len + sub_len;
335 basic_len += job_len + 1;
336 if (basic_len < (unsigned) columns()) {
337 unsigned extra_len, incr;
338 extra_len = columns() - basic_len;
339 /* Either UNIT already got 25, or is fully satisfied.
340 * Grant up to 25 to DESC now. */
341 incr = MIN(extra_len, 25u);
344 /* split the remaining space between UNIT and DESC,
345 * but do not give UNIT more than it needs. */
347 incr = MIN(extra_len / 2, max_id_len - id_len);
349 desc_len += extra_len - incr;
355 for (u = unit_infos; u < unit_infos + c; u++) {
356 _cleanup_free_ char *e = NULL;
357 const char *on_loaded, *off_loaded, *on = "";
358 const char *on_active, *off_active, *off = "";
360 if (!output_show_unit(u))
363 if (!n_shown && !arg_no_legend) {
364 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
365 active_len, "ACTIVE", sub_len, "SUB");
367 printf("%-*s ", job_len, "JOB");
368 if (!arg_full && arg_no_pager)
369 printf("%.*s\n", desc_len, "DESCRIPTION");
371 printf("%s\n", "DESCRIPTION");
376 if (streq(u->load_state, "error")) {
377 on_loaded = on = ansi_highlight_red(true);
378 off_loaded = off = ansi_highlight_red(false);
380 on_loaded = off_loaded = "";
382 if (streq(u->active_state, "failed")) {
383 on_active = on = ansi_highlight_red(true);
384 off_active = off = ansi_highlight_red(false);
386 on_active = off_active = "";
388 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
390 printf("%s%-*s%s %s%-6s%s %s%-*s %-*s%s %-*s",
391 on, id_len, e ? e : u->id, off,
392 on_loaded, u->load_state, off_loaded,
393 on_active, active_len, u->active_state,
394 sub_len, u->sub_state, off_active,
395 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
396 if (!arg_full && arg_no_pager)
397 printf("%.*s\n", desc_len, u->description);
399 printf("%s\n", u->description);
402 if (!arg_no_legend) {
403 const char *on, *off;
406 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
407 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
408 "SUB = The low-level unit activation state, values depend on unit type.\n");
410 printf("JOB = Pending job for the unit.\n");
412 on = ansi_highlight(true);
413 off = ansi_highlight(false);
415 on = ansi_highlight_red(true);
416 off = ansi_highlight_red(false);
420 printf("%s%u loaded units listed.%s\n"
421 "To show all installed unit files use 'systemctl list-unit-files'.\n",
424 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
425 "To show all installed unit files use 'systemctl list-unit-files'.\n",
430 static int get_unit_list(DBusConnection *bus, DBusMessage **reply,
431 struct unit_info **unit_infos, unsigned *c) {
432 DBusMessageIter iter, sub;
440 r = bus_method_call_with_reply(
442 "org.freedesktop.systemd1",
443 "/org/freedesktop/systemd1",
444 "org.freedesktop.systemd1.Manager",
452 if (!dbus_message_iter_init(*reply, &iter) ||
453 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
454 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
455 log_error("Failed to parse reply.");
459 dbus_message_iter_recurse(&iter, &sub);
461 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
462 if (!GREEDY_REALLOC(*unit_infos, size, *c + 1))
465 bus_parse_unit_info(&sub, *unit_infos + *c);
468 dbus_message_iter_next(&sub);
474 static int list_units(DBusConnection *bus, char **args) {
475 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
476 _cleanup_free_ struct unit_info *unit_infos = NULL;
480 pager_open_if_enabled();
482 r = get_unit_list(bus, &reply, &unit_infos, &c);
486 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
488 output_units_list(unit_infos, c);
493 static int get_triggered_units(DBusConnection *bus, const char* unit_path,
496 const char *interface = "org.freedesktop.systemd1.Unit",
497 *triggers_property = "Triggers";
498 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
499 DBusMessageIter iter, sub;
502 r = bus_method_call_with_reply(bus,
503 "org.freedesktop.systemd1",
505 "org.freedesktop.DBus.Properties",
509 DBUS_TYPE_STRING, &interface,
510 DBUS_TYPE_STRING, &triggers_property,
515 if (!dbus_message_iter_init(reply, &iter) ||
516 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
517 log_error("Failed to parse reply.");
521 dbus_message_iter_recurse(&iter, &sub);
522 dbus_message_iter_recurse(&sub, &iter);
525 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
528 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
529 log_error("Failed to parse reply.");
533 dbus_message_iter_get_basic(&sub, &unit);
534 r = strv_extend(triggered, unit);
538 dbus_message_iter_next(&sub);
544 static int get_listening(DBusConnection *bus, const char* unit_path,
545 char*** listen, unsigned *c)
547 const char *interface = "org.freedesktop.systemd1.Socket",
548 *listen_property = "Listen";
549 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
550 DBusMessageIter iter, sub;
553 r = bus_method_call_with_reply(bus,
554 "org.freedesktop.systemd1",
556 "org.freedesktop.DBus.Properties",
560 DBUS_TYPE_STRING, &interface,
561 DBUS_TYPE_STRING, &listen_property,
566 if (!dbus_message_iter_init(reply, &iter) ||
567 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
568 log_error("Failed to parse reply.");
572 dbus_message_iter_recurse(&iter, &sub);
573 dbus_message_iter_recurse(&sub, &iter);
576 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
577 DBusMessageIter sub2;
578 const char *type, *path;
580 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
581 log_error("Failed to parse reply.");
585 dbus_message_iter_recurse(&sub, &sub2);
587 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
588 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
589 r = strv_extend(listen, type);
593 r = strv_extend(listen, path);
600 dbus_message_iter_next(&sub);
612 /* Note: triggered is a list here, although it almost certainly
613 * will always be one unit. Nevertheless, dbus API allows for multiple
614 * values, so let's follow that.*/
617 /* The strv above is shared. free is set only in the first one. */
621 static int socket_info_compare(struct socket_info *a, struct socket_info *b) {
622 int o = strcmp(a->path, b->path);
624 o = strcmp(a->type, b->type);
628 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
629 struct socket_info *s;
630 unsigned pathlen = sizeof("LISTEN") - 1,
631 typelen = (sizeof("TYPE") - 1) * arg_show_types,
632 socklen = sizeof("UNIT") - 1,
633 servlen = sizeof("ACTIVATES") - 1;
634 const char *on, *off;
636 for (s = socket_infos; s < socket_infos + cs; s++) {
640 socklen = MAX(socklen, strlen(s->id));
642 typelen = MAX(typelen, strlen(s->type));
643 pathlen = MAX(pathlen, strlen(s->path));
645 STRV_FOREACH(a, s->triggered)
646 tmp += strlen(*a) + 2*(a != s->triggered);
647 servlen = MAX(servlen, tmp);
651 printf("%-*s %-*.*s%-*s %s\n",
653 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
657 for (s = socket_infos; s < socket_infos + cs; s++) {
661 printf("%-*s %-*s %-*s",
662 pathlen, s->path, typelen, s->type, socklen, s->id);
665 pathlen, s->path, socklen, s->id);
666 STRV_FOREACH(a, s->triggered)
668 a == s->triggered ? "" : ",", *a);
672 on = ansi_highlight(true);
673 off = ansi_highlight(false);
676 on = ansi_highlight_red(true);
677 off = ansi_highlight_red(false);
680 printf("%s%u sockets listed.%s\n", on, cs, off);
682 printf("Pass --all to see loaded but inactive sockets, too.\n");
687 static int list_sockets(DBusConnection *bus, char **args) {
688 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
689 _cleanup_free_ struct unit_info *unit_infos = NULL;
690 struct socket_info *socket_infos = NULL;
691 const struct unit_info *u;
692 struct socket_info *s;
693 unsigned cu = 0, cs = 0;
697 pager_open_if_enabled();
699 r = get_unit_list(bus, &reply, &unit_infos, &cu);
703 for (u = unit_infos; u < unit_infos + cu; u++) {
705 _cleanup_strv_free_ char **listen = NULL, **triggered = NULL;
708 if (!output_show_unit(u))
711 if ((dot = strrchr(u->id, '.')) && !streq(dot+1, "socket"))
714 r = get_triggered_units(bus, u->unit_path, &triggered);
718 r = get_listening(bus, u->unit_path, &listen, &c);
722 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
727 for (i = 0; i < c; i++)
728 socket_infos[cs + i] = (struct socket_info) {
731 .path = listen[i*2 + 1],
732 .triggered = triggered,
733 .own_triggered = i==0,
736 /* from this point on we will cleanup those socket_infos */
739 listen = triggered = NULL; /* avoid cleanup */
742 qsort(socket_infos, cs, sizeof(struct socket_info),
743 (__compar_fn_t) socket_info_compare);
745 output_sockets_list(socket_infos, cs);
748 assert(cs == 0 || socket_infos);
749 for (s = socket_infos; s < socket_infos + cs; s++) {
752 if (s->own_triggered)
753 strv_free(s->triggered);
760 static int compare_unit_file_list(const void *a, const void *b) {
762 const UnitFileList *u = a, *v = b;
764 d1 = strrchr(u->path, '.');
765 d2 = strrchr(v->path, '.');
770 r = strcasecmp(d1, d2);
775 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
778 static bool output_show_unit_file(const UnitFileList *u) {
781 return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
784 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
785 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
786 const UnitFileList *u;
788 max_id_len = sizeof("UNIT FILE")-1;
789 state_cols = sizeof("STATE")-1;
790 for (u = units; u < units + c; u++) {
791 if (!output_show_unit_file(u))
794 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
795 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
800 id_cols = MIN(max_id_len, 25u);
801 basic_cols = 1 + id_cols + state_cols;
802 if (basic_cols < (unsigned) columns())
803 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
805 id_cols = max_id_len;
808 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
810 for (u = units; u < units + c; u++) {
811 _cleanup_free_ char *e = NULL;
812 const char *on, *off;
815 if (!output_show_unit_file(u))
820 if (u->state == UNIT_FILE_MASKED ||
821 u->state == UNIT_FILE_MASKED_RUNTIME ||
822 u->state == UNIT_FILE_DISABLED ||
823 u->state == UNIT_FILE_INVALID) {
824 on = ansi_highlight_red(true);
825 off = ansi_highlight_red(false);
826 } else if (u->state == UNIT_FILE_ENABLED) {
827 on = ansi_highlight_green(true);
828 off = ansi_highlight_green(false);
832 id = path_get_file_name(u->path);
834 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
836 printf("%-*s %s%-*s%s\n",
838 on, state_cols, unit_file_state_to_string(u->state), off);
842 printf("\n%u unit files listed.\n", n_shown);
845 static int list_unit_files(DBusConnection *bus, char **args) {
846 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
847 _cleanup_free_ UnitFileList *units = NULL;
848 DBusMessageIter iter, sub, sub2;
849 unsigned c = 0, n_units = 0;
852 pager_open_if_enabled();
859 h = hashmap_new(string_hash_func, string_compare_func);
863 r = unit_file_get_list(arg_scope, arg_root, h);
865 unit_file_list_free(h);
866 log_error("Failed to get unit file list: %s", strerror(-r));
870 n_units = hashmap_size(h);
871 units = new(UnitFileList, n_units);
873 unit_file_list_free(h);
877 HASHMAP_FOREACH(u, h, i) {
878 memcpy(units + c++, u, sizeof(UnitFileList));
884 r = bus_method_call_with_reply(
886 "org.freedesktop.systemd1",
887 "/org/freedesktop/systemd1",
888 "org.freedesktop.systemd1.Manager",
896 if (!dbus_message_iter_init(reply, &iter) ||
897 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
898 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
899 log_error("Failed to parse reply.");
903 dbus_message_iter_recurse(&iter, &sub);
905 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
909 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
914 n_units = MAX(2*c, 16u);
915 w = realloc(units, sizeof(struct UnitFileList) * n_units);
924 dbus_message_iter_recurse(&sub, &sub2);
926 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
927 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
928 log_error("Failed to parse reply.");
932 u->state = unit_file_state_from_string(state);
934 dbus_message_iter_next(&sub);
940 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
941 output_unit_file_list(units, c);
947 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
949 _cleanup_free_ char *n = NULL;
951 size_t max_len = MAX(columns(),20u);
953 for (i = level - 1; i >= 0; i--) {
955 if(len > max_len - 3 && !arg_full) {
956 printf("%s...\n",max_len % 2 ? "" : " ");
959 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
962 if(len > max_len - 3 && !arg_full) {
963 printf("%s...\n",max_len % 2 ? "" : " ");
966 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
969 printf("%s\n", name);
973 n = ellipsize(name, max_len-len, 100);
981 static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
982 static const char dependencies[] =
984 "RequiresOverridable\0"
986 "RequisiteOverridable\0"
989 _cleanup_free_ char *path;
990 const char *interface = "org.freedesktop.systemd1.Unit";
992 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
993 DBusMessageIter iter, sub, sub2, sub3;
1002 path = unit_dbus_path_from_name(name);
1008 r = bus_method_call_with_reply(
1010 "org.freedesktop.systemd1",
1012 "org.freedesktop.DBus.Properties",
1016 DBUS_TYPE_STRING, &interface,
1021 if (!dbus_message_iter_init(reply, &iter) ||
1022 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1023 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
1024 log_error("Failed to parse reply.");
1029 dbus_message_iter_recurse(&iter, &sub);
1031 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1034 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
1035 dbus_message_iter_recurse(&sub, &sub2);
1037 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
1038 log_error("Failed to parse reply.");
1043 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
1044 log_error("Failed to parse reply.");
1049 dbus_message_iter_recurse(&sub2, &sub3);
1050 dbus_message_iter_next(&sub);
1052 if (!nulstr_contains(dependencies, prop))
1055 if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
1056 if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
1057 DBusMessageIter sub4;
1058 dbus_message_iter_recurse(&sub3, &sub4);
1060 while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
1063 assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
1064 dbus_message_iter_get_basic(&sub4, &s);
1066 r = strv_extend(&ret, s);
1072 dbus_message_iter_next(&sub4);
1085 static int list_dependencies_compare(const void *_a, const void *_b) {
1086 const char **a = (const char**) _a, **b = (const char**) _b;
1087 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1089 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1091 return strcasecmp(*a, *b);
1094 static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char **units, unsigned int branches) {
1095 _cleanup_strv_free_ char **deps = NULL, **u;
1099 u = strv_append(units, name);
1103 r = list_dependencies_get_dependencies(bus, name, &deps);
1107 qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1109 STRV_FOREACH(c, deps) {
1110 if (strv_contains(u, *c)) {
1111 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1117 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1121 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1122 r = list_dependencies_one(bus, *c, level + 1, u, (branches << 1) | (c[1] == NULL ? 0 : 1));
1131 static int list_dependencies(DBusConnection *bus, char **args) {
1132 _cleanup_free_ char *unit = NULL;
1138 unit = unit_name_mangle(args[1]);
1143 u = SPECIAL_DEFAULT_TARGET;
1145 pager_open_if_enabled();
1149 return list_dependencies_one(bus, u, 0, NULL, 0);
1154 char *name, *type, *state;
1157 static void list_jobs_print(struct job_info* jobs, size_t n) {
1160 const char *on, *off;
1161 bool shorten = false;
1163 assert(n == 0 || jobs);
1166 on = ansi_highlight_green(true);
1167 off = ansi_highlight_green(false);
1169 printf("%sNo jobs running.%s\n", on, off);
1173 pager_open_if_enabled();
1176 /* JOB UNIT TYPE STATE */
1177 unsigned l0 = 3, l1 = 4, l2 = 4, l3 = 5;
1179 for (i = 0, j = jobs; i < n; i++, j++) {
1180 assert(j->name && j->type && j->state);
1181 l0 = MAX(l0, DECIMAL_STR_WIDTH(j->id));
1182 l1 = MAX(l1, strlen(j->name));
1183 l2 = MAX(l2, strlen(j->type));
1184 l3 = MAX(l3, strlen(j->state));
1187 if (!arg_full && l0 + 1 + l1 + l2 + 1 + l3 > columns()) {
1188 l1 = MAX(33u, columns() - l0 - l2 - l3 - 3);
1193 printf("%*s %-*s %-*s %-*s\n",
1199 for (i = 0, j = jobs; i < n; i++, j++) {
1200 _cleanup_free_ char *e = NULL;
1202 if (streq(j->state, "running")) {
1203 on = ansi_highlight(true);
1204 off = ansi_highlight(false);
1208 e = shorten ? ellipsize(j->name, l1, 33) : NULL;
1209 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
1211 on, l1, e ? e : j->name, off,
1213 on, l3, j->state, off);
1217 on = ansi_highlight(true);
1218 off = ansi_highlight(false);
1221 printf("\n%s%zu jobs listed%s.\n", on, n, off);
1224 static int list_jobs(DBusConnection *bus, char **args) {
1225 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1226 DBusMessageIter iter, sub, sub2;
1228 struct job_info *jobs = NULL;
1229 size_t size = 0, used = 0;
1231 r = bus_method_call_with_reply(
1233 "org.freedesktop.systemd1",
1234 "/org/freedesktop/systemd1",
1235 "org.freedesktop.systemd1.Manager",
1243 if (!dbus_message_iter_init(reply, &iter) ||
1244 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1245 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1246 log_error("Failed to parse reply.");
1250 dbus_message_iter_recurse(&iter, &sub);
1252 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1253 const char *name, *type, *state, *job_path, *unit_path;
1256 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1257 log_error("Failed to parse reply.");
1261 dbus_message_iter_recurse(&sub, &sub2);
1263 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1264 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1265 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1266 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1267 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1268 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1269 log_error("Failed to parse reply.");
1274 if (!greedy_realloc((void**) &jobs, &size,
1275 sizeof(struct job_info) * (used + 1))) {
1280 jobs[used++] = (struct job_info) { id,
1284 if (!jobs[used-1].name || !jobs[used-1].type || !jobs[used-1].state) {
1289 dbus_message_iter_next(&sub);
1292 list_jobs_print(jobs, used);
1296 free(jobs[used].name);
1297 free(jobs[used].type);
1298 free(jobs[used].state);
1305 static int load_unit(DBusConnection *bus, char **args) {
1310 STRV_FOREACH(name, args+1) {
1311 _cleanup_free_ char *n = NULL;
1314 n = unit_name_mangle(*name);
1318 r = bus_method_call_with_reply(
1320 "org.freedesktop.systemd1",
1321 "/org/freedesktop/systemd1",
1322 "org.freedesktop.systemd1.Manager",
1326 DBUS_TYPE_STRING, &n,
1335 static int cancel_job(DBusConnection *bus, char **args) {
1340 if (strv_length(args) <= 1)
1341 return daemon_reload(bus, args);
1343 STRV_FOREACH(name, args+1) {
1347 r = safe_atou32(*name, &id);
1349 log_error("Failed to parse job id: %s", strerror(-r));
1353 r = bus_method_call_with_reply(
1355 "org.freedesktop.systemd1",
1356 "/org/freedesktop/systemd1",
1357 "org.freedesktop.systemd1.Manager",
1361 DBUS_TYPE_UINT32, &id,
1370 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1371 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1372 dbus_bool_t b = FALSE;
1373 DBusMessageIter iter, sub;
1375 *interface = "org.freedesktop.systemd1.Unit",
1376 *property = "NeedDaemonReload",
1378 _cleanup_free_ char *n = NULL;
1381 /* We ignore all errors here, since this is used to show a warning only */
1383 n = unit_name_mangle(unit);
1387 r = bus_method_call_with_reply(
1389 "org.freedesktop.systemd1",
1390 "/org/freedesktop/systemd1",
1391 "org.freedesktop.systemd1.Manager",
1395 DBUS_TYPE_STRING, &n,
1400 if (!dbus_message_get_args(reply, NULL,
1401 DBUS_TYPE_OBJECT_PATH, &path,
1405 dbus_message_unref(reply);
1408 r = bus_method_call_with_reply(
1410 "org.freedesktop.systemd1",
1412 "org.freedesktop.DBus.Properties",
1416 DBUS_TYPE_STRING, &interface,
1417 DBUS_TYPE_STRING, &property,
1422 if (!dbus_message_iter_init(reply, &iter) ||
1423 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1426 dbus_message_iter_recurse(&iter, &sub);
1427 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1430 dbus_message_iter_get_basic(&sub, &b);
1434 typedef struct WaitData {
1441 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1442 _cleanup_dbus_error_free_ DBusError error;
1445 dbus_error_init(&error);
1451 log_debug("Got D-Bus request: %s.%s() on %s",
1452 dbus_message_get_interface(message),
1453 dbus_message_get_member(message),
1454 dbus_message_get_path(message));
1456 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1457 log_error("Warning! D-Bus connection terminated.");
1458 dbus_connection_close(connection);
1460 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1462 const char *path, *result, *unit;
1464 if (dbus_message_get_args(message, &error,
1465 DBUS_TYPE_UINT32, &id,
1466 DBUS_TYPE_OBJECT_PATH, &path,
1467 DBUS_TYPE_STRING, &unit,
1468 DBUS_TYPE_STRING, &result,
1469 DBUS_TYPE_INVALID)) {
1471 free(set_remove(d->set, (char*) path));
1473 if (!isempty(result))
1474 d->result = strdup(result);
1477 d->name = strdup(unit);
1479 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1482 dbus_error_free(&error);
1483 if (dbus_message_get_args(message, &error,
1484 DBUS_TYPE_UINT32, &id,
1485 DBUS_TYPE_OBJECT_PATH, &path,
1486 DBUS_TYPE_STRING, &result,
1487 DBUS_TYPE_INVALID)) {
1488 /* Compatibility with older systemd versions <
1489 * 183 during upgrades. This should be dropped
1491 free(set_remove(d->set, (char*) path));
1494 d->result = strdup(result);
1496 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1500 log_error("Failed to parse message: %s", bus_error_message(&error));
1503 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1506 static int enable_wait_for_jobs(DBusConnection *bus) {
1514 dbus_error_init(&error);
1515 dbus_bus_add_match(bus,
1517 "sender='org.freedesktop.systemd1',"
1518 "interface='org.freedesktop.systemd1.Manager',"
1519 "member='JobRemoved',"
1520 "path='/org/freedesktop/systemd1'",
1523 if (dbus_error_is_set(&error)) {
1524 log_error("Failed to add match: %s", bus_error_message(&error));
1525 dbus_error_free(&error);
1529 /* This is slightly dirty, since we don't undo the match registrations. */
1533 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1535 WaitData d = { .set = s };
1540 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1543 while (!set_isempty(s)) {
1545 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1546 log_error("Disconnected from bus.");
1547 return -ECONNREFUSED;
1554 if (streq(d.result, "timeout"))
1555 log_error("Job for %s timed out.", strna(d.name));
1556 else if (streq(d.result, "canceled"))
1557 log_error("Job for %s canceled.", strna(d.name));
1558 else if (streq(d.result, "dependency"))
1559 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1560 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1561 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1564 if (streq_ptr(d.result, "timeout"))
1566 else if (streq_ptr(d.result, "canceled"))
1568 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1579 dbus_connection_remove_filter(bus, wait_filter, &d);
1583 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1584 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1585 _cleanup_free_ char *n = NULL;
1586 DBusMessageIter iter, sub;
1588 *interface = "org.freedesktop.systemd1.Unit",
1589 *property = "ActiveState";
1590 const char *state, *path;
1596 dbus_error_init(&error);
1598 n = unit_name_mangle(name);
1602 r = bus_method_call_with_reply (
1604 "org.freedesktop.systemd1",
1605 "/org/freedesktop/systemd1",
1606 "org.freedesktop.systemd1.Manager",
1610 DBUS_TYPE_STRING, &n,
1613 dbus_error_free(&error);
1620 if (!dbus_message_get_args(reply, NULL,
1621 DBUS_TYPE_OBJECT_PATH, &path,
1622 DBUS_TYPE_INVALID)) {
1623 log_error("Failed to parse reply.");
1627 dbus_message_unref(reply);
1630 r = bus_method_call_with_reply(
1632 "org.freedesktop.systemd1",
1634 "org.freedesktop.DBus.Properties",
1638 DBUS_TYPE_STRING, &interface,
1639 DBUS_TYPE_STRING, &property,
1647 if (!dbus_message_iter_init(reply, &iter) ||
1648 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1649 log_error("Failed to parse reply.");
1653 dbus_message_iter_recurse(&iter, &sub);
1655 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1656 log_error("Failed to parse reply.");
1660 dbus_message_iter_get_basic(&sub, &state);
1665 return strv_find(check_states, state) ? 1 : 0;
1668 static void check_triggering_units(
1669 DBusConnection *bus,
1670 const char *unit_name) {
1672 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1673 DBusMessageIter iter, sub;
1674 const char *interface = "org.freedesktop.systemd1.Unit",
1675 *load_state_property = "LoadState",
1676 *triggered_by_property = "TriggeredBy",
1678 _cleanup_free_ char *unit_path = NULL, *n = NULL;
1679 bool print_warning_label = true;
1682 n = unit_name_mangle(unit_name);
1688 unit_path = unit_dbus_path_from_name(n);
1694 r = bus_method_call_with_reply(
1696 "org.freedesktop.systemd1",
1698 "org.freedesktop.DBus.Properties",
1702 DBUS_TYPE_STRING, &interface,
1703 DBUS_TYPE_STRING, &load_state_property,
1708 if (!dbus_message_iter_init(reply, &iter) ||
1709 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1710 log_error("Failed to parse reply.");
1714 dbus_message_iter_recurse(&iter, &sub);
1716 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1717 log_error("Failed to parse reply.");
1721 dbus_message_iter_get_basic(&sub, &state);
1723 if (streq(state, "masked"))
1726 dbus_message_unref(reply);
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, &triggered_by_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);
1750 dbus_message_iter_recurse(&sub, &iter);
1753 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1754 const char * const check_states[] = {
1759 const char *service_trigger;
1761 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1762 log_error("Failed to parse reply.");
1766 dbus_message_iter_get_basic(&sub, &service_trigger);
1768 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1772 if (print_warning_label) {
1773 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1774 print_warning_label = false;
1777 log_warning(" %s", service_trigger);
1780 dbus_message_iter_next(&sub);
1784 static int start_unit_one(
1785 DBusConnection *bus,
1792 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1793 _cleanup_free_ char *n;
1802 n = unit_name_mangle(name);
1806 r = bus_method_call_with_reply(
1808 "org.freedesktop.systemd1",
1809 "/org/freedesktop/systemd1",
1810 "org.freedesktop.systemd1.Manager",
1814 DBUS_TYPE_STRING, &n,
1815 DBUS_TYPE_STRING, &mode,
1818 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1819 /* There's always a fallback possible for
1820 * legacy actions. */
1823 log_error("Failed to issue method call: %s", bus_error_message(error));
1828 if (!dbus_message_get_args(reply, error,
1829 DBUS_TYPE_OBJECT_PATH, &path,
1830 DBUS_TYPE_INVALID)) {
1831 log_error("Failed to parse reply: %s", bus_error_message(error));
1835 if (need_daemon_reload(bus, n))
1836 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1837 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1849 log_error("Failed to add path to set.");
1857 static const struct {
1861 } action_table[_ACTION_MAX] = {
1862 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
1863 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
1864 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
1865 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
1866 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
1867 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
1868 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
1869 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
1870 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
1871 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
1872 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
1873 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
1874 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
1875 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
1876 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1879 static enum action verb_to_action(const char *verb) {
1882 for (i = ACTION_INVALID; i < _ACTION_MAX; i++)
1883 if (action_table[i].verb && streq(verb, action_table[i].verb))
1885 return ACTION_INVALID;
1888 static int start_unit(DBusConnection *bus, char **args) {
1891 const char *method, *mode, *one_name;
1892 _cleanup_set_free_free_ Set *s = NULL;
1893 _cleanup_dbus_error_free_ DBusError error;
1896 dbus_error_init(&error);
1900 ask_password_agent_open_if_enabled();
1902 if (arg_action == ACTION_SYSTEMCTL) {
1905 streq(args[0], "stop") ||
1906 streq(args[0], "condstop") ? "StopUnit" :
1907 streq(args[0], "reload") ? "ReloadUnit" :
1908 streq(args[0], "restart") ? "RestartUnit" :
1910 streq(args[0], "try-restart") ||
1911 streq(args[0], "condrestart") ? "TryRestartUnit" :
1913 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1915 streq(args[0], "reload-or-try-restart") ||
1916 streq(args[0], "condreload") ||
1918 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1920 action = verb_to_action(args[0]);
1922 mode = streq(args[0], "isolate") ? "isolate" :
1923 action_table[action].mode ?: arg_job_mode;
1925 one_name = action_table[action].target;
1928 assert(arg_action < ELEMENTSOF(action_table));
1929 assert(action_table[arg_action].target);
1931 method = "StartUnit";
1933 mode = action_table[arg_action].mode;
1934 one_name = action_table[arg_action].target;
1937 if (!arg_no_block) {
1938 ret = enable_wait_for_jobs(bus);
1940 log_error("Could not watch jobs: %s", strerror(-ret));
1944 s = set_new(string_hash_func, string_compare_func);
1950 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1952 ret = translate_bus_error_to_exit_status(ret, &error);
1954 STRV_FOREACH(name, args+1) {
1955 r = start_unit_one(bus, method, *name, mode, &error, s);
1957 ret = translate_bus_error_to_exit_status(r, &error);
1958 dbus_error_free(&error);
1963 if (!arg_no_block) {
1964 r = wait_for_jobs(bus, s);
1968 /* When stopping units, warn if they can still be triggered by
1969 * another active unit (socket, path, timer) */
1970 if (!arg_quiet && streq(method, "StopUnit")) {
1972 check_triggering_units(bus, one_name);
1974 STRV_FOREACH(name, args+1)
1975 check_triggering_units(bus, *name);
1982 /* Ask systemd-logind, which might grant access to unprivileged users
1983 * through PolicyKit */
1984 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1987 dbus_bool_t interactive = true;
1992 polkit_agent_open_if_enabled();
2000 case ACTION_POWEROFF:
2001 method = "PowerOff";
2004 case ACTION_SUSPEND:
2008 case ACTION_HIBERNATE:
2009 method = "Hibernate";
2012 case ACTION_HYBRID_SLEEP:
2013 method = "HybridSleep";
2020 return bus_method_call_with_reply(
2022 "org.freedesktop.login1",
2023 "/org/freedesktop/login1",
2024 "org.freedesktop.login1.Manager",
2028 DBUS_TYPE_BOOLEAN, &interactive,
2035 static int check_inhibitors(DBusConnection *bus, enum action a) {
2037 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2038 DBusMessageIter iter, sub, sub2;
2041 _cleanup_strv_free_ char **sessions = NULL;
2047 if (arg_ignore_inhibitors || arg_force > 0)
2059 r = bus_method_call_with_reply(
2061 "org.freedesktop.login1",
2062 "/org/freedesktop/login1",
2063 "org.freedesktop.login1.Manager",
2069 /* If logind is not around, then there are no inhibitors... */
2072 if (!dbus_message_iter_init(reply, &iter) ||
2073 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2074 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
2075 log_error("Failed to parse reply.");
2079 dbus_message_iter_recurse(&iter, &sub);
2080 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2081 const char *what, *who, *why, *mode;
2083 _cleanup_strv_free_ char **sv = NULL;
2084 _cleanup_free_ char *comm = NULL, *user = NULL;
2086 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
2087 log_error("Failed to parse reply.");
2091 dbus_message_iter_recurse(&sub, &sub2);
2093 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
2094 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
2095 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
2096 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
2097 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
2098 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
2099 log_error("Failed to parse reply.");
2103 if (!streq(mode, "block"))
2106 sv = strv_split(what, ":");
2110 if (!strv_contains(sv,
2112 a == ACTION_POWEROFF ||
2113 a == ACTION_REBOOT ||
2114 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2117 get_process_comm(pid, &comm);
2118 user = uid_to_name(uid);
2119 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2120 who, (unsigned long) pid, strna(comm), strna(user), why);
2124 dbus_message_iter_next(&sub);
2127 dbus_message_iter_recurse(&iter, &sub);
2129 /* Check for current sessions */
2130 sd_get_sessions(&sessions);
2131 STRV_FOREACH(s, sessions) {
2133 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2135 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2138 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2141 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2144 sd_session_get_tty(*s, &tty);
2145 sd_session_get_seat(*s, &seat);
2146 sd_session_get_service(*s, &service);
2147 user = uid_to_name(uid);
2149 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2156 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2157 action_table[a].verb);
2165 static int start_special(DBusConnection *bus, char **args) {
2171 a = verb_to_action(args[0]);
2173 r = check_inhibitors(bus, a);
2177 if (arg_force >= 2 && geteuid() != 0) {
2178 log_error("Must be root.");
2182 if (arg_force >= 2 &&
2183 (a == ACTION_HALT ||
2184 a == ACTION_POWEROFF ||
2185 a == ACTION_REBOOT))
2188 if (arg_force >= 1 &&
2189 (a == ACTION_HALT ||
2190 a == ACTION_POWEROFF ||
2191 a == ACTION_REBOOT ||
2192 a == ACTION_KEXEC ||
2194 return daemon_reload(bus, args);
2196 /* first try logind, to allow authentication with polkit */
2197 if (geteuid() != 0 &&
2198 (a == ACTION_POWEROFF ||
2199 a == ACTION_REBOOT ||
2200 a == ACTION_SUSPEND ||
2201 a == ACTION_HIBERNATE ||
2202 a == ACTION_HYBRID_SLEEP)) {
2203 r = reboot_with_logind(bus, a);
2208 r = start_unit(bus, args);
2209 if (r == EXIT_SUCCESS)
2215 static int check_unit_active(DBusConnection *bus, char **args) {
2216 const char * const check_states[] = {
2223 int r = 3; /* According to LSB: "program is not running" */
2228 STRV_FOREACH(name, args+1) {
2231 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2241 static int check_unit_failed(DBusConnection *bus, char **args) {
2242 const char * const check_states[] = {
2253 STRV_FOREACH(name, args+1) {
2256 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2266 static int kill_unit(DBusConnection *bus, char **args) {
2274 arg_kill_who = "all";
2276 STRV_FOREACH(name, args+1) {
2277 _cleanup_free_ char *n = NULL;
2279 n = unit_name_mangle(*name);
2283 r = bus_method_call_with_reply(
2285 "org.freedesktop.systemd1",
2286 "/org/freedesktop/systemd1",
2287 "org.freedesktop.systemd1.Manager",
2291 DBUS_TYPE_STRING, &n,
2292 DBUS_TYPE_STRING, &arg_kill_who,
2293 DBUS_TYPE_INT32, &arg_signal,
2301 static int set_cgroup(DBusConnection *bus, char **args) {
2302 _cleanup_free_ char *n = NULL;
2303 const char *method, *runtime;
2311 streq(args[0], "set-cgroup") ? "SetUnitControlGroup" :
2312 streq(args[0], "unset-cgroup") ? "UnsetUnitControlGroup"
2313 : "UnsetUnitControlGroupAttribute";
2315 runtime = arg_runtime ? "runtime" : "persistent";
2317 n = unit_name_mangle(args[1]);
2321 STRV_FOREACH(argument, args + 2) {
2323 r = bus_method_call_with_reply(
2325 "org.freedesktop.systemd1",
2326 "/org/freedesktop/systemd1",
2327 "org.freedesktop.systemd1.Manager",
2331 DBUS_TYPE_STRING, &n,
2332 DBUS_TYPE_STRING, argument,
2333 DBUS_TYPE_STRING, &runtime,
2342 static int set_cgroup_attr(DBusConnection *bus, char **args) {
2343 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2345 DBusMessageIter iter;
2346 _cleanup_free_ char *n = NULL;
2347 const char *runtime;
2353 dbus_error_init(&error);
2355 runtime = arg_runtime ? "runtime" : "persistent";
2357 n = unit_name_mangle(args[1]);
2361 m = dbus_message_new_method_call(
2362 "org.freedesktop.systemd1",
2363 "/org/freedesktop/systemd1",
2364 "org.freedesktop.systemd1.Manager",
2365 "SetUnitControlGroupAttribute");
2369 dbus_message_iter_init_append(m, &iter);
2370 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2371 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[2]))
2374 r = bus_append_strv_iter(&iter, args + 3);
2378 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2381 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2383 log_error("Failed to issue method call: %s", bus_error_message(&error));
2384 dbus_error_free(&error);
2391 static int get_cgroup_attr(DBusConnection *bus, char **args) {
2392 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2393 _cleanup_free_ char *n = NULL;
2400 n = unit_name_mangle(args[1]);
2404 STRV_FOREACH(argument, args + 2) {
2405 _cleanup_strv_free_ char **list = NULL;
2406 DBusMessageIter iter;
2409 r = bus_method_call_with_reply(
2411 "org.freedesktop.systemd1",
2412 "/org/freedesktop/systemd1",
2413 "org.freedesktop.systemd1.Manager",
2414 "GetUnitControlGroupAttribute",
2417 DBUS_TYPE_STRING, &n,
2418 DBUS_TYPE_STRING, argument,
2423 if (!dbus_message_iter_init(reply, &iter)) {
2424 log_error("Failed to initialize iterator.");
2428 r = bus_parse_strv_iter(&iter, &list);
2430 log_error("Failed to parse value list.");
2434 STRV_FOREACH(a, list) {
2435 if (endswith(*a, "\n"))
2445 typedef struct ExecStatusInfo {
2453 usec_t start_timestamp;
2454 usec_t exit_timestamp;
2459 LIST_FIELDS(struct ExecStatusInfo, exec);
2462 static void exec_status_info_free(ExecStatusInfo *i) {
2471 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2472 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2473 DBusMessageIter sub2, sub3;
2477 int32_t code, status;
2483 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2486 dbus_message_iter_recurse(sub, &sub2);
2488 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2491 i->path = strdup(path);
2495 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2496 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2500 dbus_message_iter_recurse(&sub2, &sub3);
2501 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2502 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2503 dbus_message_iter_next(&sub3);
2507 i->argv = new0(char*, n+1);
2512 dbus_message_iter_recurse(&sub2, &sub3);
2513 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2516 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2517 dbus_message_iter_get_basic(&sub3, &s);
2518 dbus_message_iter_next(&sub3);
2520 i->argv[n] = strdup(s);
2527 if (!dbus_message_iter_next(&sub2) ||
2528 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2529 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2530 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2531 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2532 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2533 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2534 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2535 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2539 i->start_timestamp = (usec_t) start_timestamp;
2540 i->exit_timestamp = (usec_t) exit_timestamp;
2541 i->pid = (pid_t) pid;
2548 typedef struct UnitStatusInfo {
2550 const char *load_state;
2551 const char *active_state;
2552 const char *sub_state;
2553 const char *unit_file_state;
2555 const char *description;
2556 const char *following;
2558 char **documentation;
2560 const char *fragment_path;
2561 const char *source_path;
2562 const char *default_control_group;
2564 char **dropin_paths;
2566 const char *load_error;
2569 usec_t inactive_exit_timestamp;
2570 usec_t inactive_exit_timestamp_monotonic;
2571 usec_t active_enter_timestamp;
2572 usec_t active_exit_timestamp;
2573 usec_t inactive_enter_timestamp;
2575 bool need_daemon_reload;
2580 const char *status_text;
2583 usec_t start_timestamp;
2584 usec_t exit_timestamp;
2586 int exit_code, exit_status;
2588 usec_t condition_timestamp;
2589 bool condition_result;
2592 unsigned n_accepted;
2593 unsigned n_connections;
2596 /* Pairs of type, path */
2600 const char *sysfs_path;
2602 /* Mount, Automount */
2608 LIST_HEAD(ExecStatusInfo, exec);
2611 static void print_status_info(UnitStatusInfo *i) {
2613 const char *on, *off, *ss;
2615 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2616 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2619 arg_all * OUTPUT_SHOW_ALL |
2620 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2621 on_tty() * OUTPUT_COLOR |
2622 !arg_quiet * OUTPUT_WARN_CUTOFF |
2623 arg_full * OUTPUT_FULL_WIDTH;
2624 int maxlen = 8; /* a value that'll suffice most of the time */
2629 STRV_FOREACH_PAIR(t, t2, i->listen)
2630 maxlen = MAX(maxlen, (int)(sizeof("Listen") - 1 + strlen(*t)));
2632 maxlen = MAX(maxlen, (int)sizeof("Accept") - 1);
2633 if (i->main_pid > 0)
2634 maxlen = MAX(maxlen, (int)sizeof("Main PID") - 1);
2635 else if (i->control_pid > 0)
2636 maxlen = MAX(maxlen, (int)sizeof("Control") - 1);
2638 /* This shows pretty information about a unit. See
2639 * print_property() for a low-level property printer */
2641 printf("%s", strna(i->id));
2643 if (i->description && !streq_ptr(i->id, i->description))
2644 printf(" - %s", i->description);
2649 printf(" %*s: unit currently follows state of %s\n", maxlen, "Follow", i->following);
2651 if (streq_ptr(i->load_state, "error")) {
2652 on = ansi_highlight_red(true);
2653 off = ansi_highlight_red(false);
2657 path = i->source_path ? i->source_path : i->fragment_path;
2660 printf(" %*s: %s%s%s (Reason: %s)\n",
2661 maxlen, "Loaded", on, strna(i->load_state), off, i->load_error);
2662 else if (path && i->unit_file_state)
2663 printf(" %*s: %s%s%s (%s; %s)\n",
2664 maxlen, "Loaded", on, strna(i->load_state), off, path, i->unit_file_state);
2666 printf(" %*s: %s%s%s (%s)\n",
2667 maxlen, "Loaded", on, strna(i->load_state), off, path);
2669 printf(" %*s: %s%s%s\n",
2670 maxlen, "Loaded", on, strna(i->load_state), off);
2672 if (!strv_isempty(i->dropin_paths)) {
2677 STRV_FOREACH(dropin, i->dropin_paths) {
2678 if (! dir || last) {
2679 printf(" %*s ", maxlen, dir ? "" : "Drop-In:");
2683 if (path_get_parent(*dropin, &dir) < 0) {
2688 printf("%s\n %*s %s", dir, maxlen, "",
2689 draw_special_char(DRAW_TREE_RIGHT));
2692 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
2694 printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", ");
2700 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2702 if (streq_ptr(i->active_state, "failed")) {
2703 on = ansi_highlight_red(true);
2704 off = ansi_highlight_red(false);
2705 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2706 on = ansi_highlight_green(true);
2707 off = ansi_highlight_green(false);
2712 printf(" %*s: %s%s (%s)%s",
2713 maxlen, "Active", on, strna(i->active_state), ss, off);
2715 printf(" %*s: %s%s%s",
2716 maxlen, "Active", on, strna(i->active_state), off);
2718 if (!isempty(i->result) && !streq(i->result, "success"))
2719 printf(" (Result: %s)", i->result);
2721 timestamp = (streq_ptr(i->active_state, "active") ||
2722 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2723 (streq_ptr(i->active_state, "inactive") ||
2724 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2725 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2726 i->active_exit_timestamp;
2728 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2729 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2732 printf(" since %s; %s\n", s2, s1);
2734 printf(" since %s\n", s2);
2738 if (!i->condition_result && i->condition_timestamp > 0) {
2739 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2740 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2743 printf(" %*s start condition failed at %s; %s\n", maxlen, "", s2, s1);
2745 printf(" %*s start condition failed at %s\n", maxlen, "", s2);
2749 printf(" %*s: %s\n", maxlen, "Device", i->sysfs_path);
2751 printf(" %*s: %s\n", maxlen, "Where", i->where);
2753 printf(" %*s: %s\n", maxlen, "What", i->what);
2755 STRV_FOREACH(t, i->documentation)
2756 printf(" %*s %s\n", maxlen+1, t == i->documentation ? "Docs:" : "", *t);
2758 STRV_FOREACH_PAIR(t, t2, i->listen)
2759 printf(" %*s %s (%s)\n", maxlen+1, t == i->listen ? "Listen:" : "", *t2, *t);
2762 printf(" %*s: %u; Connected: %u\n", maxlen, "Accepted", i->n_accepted, i->n_connections);
2764 LIST_FOREACH(exec, p, i->exec) {
2765 _cleanup_free_ char *argv = NULL;
2768 /* Only show exited processes here */
2772 argv = strv_join(p->argv, " ");
2773 printf(" %*s: %u %s=%s ", maxlen, "Process", p->pid, p->name, strna(argv));
2775 good = is_clean_exit_lsb(p->code, p->status, NULL);
2777 on = ansi_highlight_red(true);
2778 off = ansi_highlight_red(false);
2782 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2784 if (p->code == CLD_EXITED) {
2787 printf("status=%i", p->status);
2789 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2794 printf("signal=%s", signal_to_string(p->status));
2796 printf(")%s\n", off);
2798 if (i->main_pid == p->pid &&
2799 i->start_timestamp == p->start_timestamp &&
2800 i->exit_timestamp == p->start_timestamp)
2801 /* Let's not show this twice */
2804 if (p->pid == i->control_pid)
2808 if (i->main_pid > 0 || i->control_pid > 0) {
2809 if (i->main_pid > 0) {
2810 printf(" %*s: %u", maxlen, "Main PID", (unsigned) i->main_pid);
2813 _cleanup_free_ char *comm = NULL;
2814 get_process_comm(i->main_pid, &comm);
2816 printf(" (%s)", comm);
2817 } else if (i->exit_code > 0) {
2818 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2820 if (i->exit_code == CLD_EXITED) {
2823 printf("status=%i", i->exit_status);
2825 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2830 printf("signal=%s", signal_to_string(i->exit_status));
2834 if (i->control_pid > 0)
2838 if (i->control_pid > 0) {
2839 _cleanup_free_ char *c = NULL;
2841 printf(" %*s: %u", i->main_pid ? 0 : maxlen, "Control", (unsigned) i->control_pid);
2843 get_process_comm(i->control_pid, &c);
2852 printf(" %*s: \"%s\"\n", maxlen, "Status", i->status_text);
2854 if (i->default_control_group &&
2855 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2858 printf(" %*s: %s\n", maxlen, "CGroup", i->default_control_group);
2860 if (arg_transport != TRANSPORT_SSH) {
2863 char prefix[maxlen + 4];
2864 memset(prefix, ' ', sizeof(prefix) - 1);
2865 prefix[sizeof(prefix) - 1] = '\0';
2868 if (c > sizeof(prefix) - 1)
2869 c -= sizeof(prefix) - 1;
2873 if (i->main_pid > 0)
2874 extra[k++] = i->main_pid;
2876 if (i->control_pid > 0)
2877 extra[k++] = i->control_pid;
2879 show_cgroup_and_extra_by_spec(i->default_control_group, prefix,
2880 c, false, extra, k, flags);
2884 if (i->id && arg_transport != TRANSPORT_SSH) {
2886 show_journal_by_unit(stdout,
2890 i->inactive_exit_timestamp_monotonic,
2894 arg_scope == UNIT_FILE_SYSTEM);
2897 if (i->need_daemon_reload)
2898 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2899 ansi_highlight_red(true),
2900 ansi_highlight_red(false),
2901 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2904 static void show_unit_help(UnitStatusInfo *i) {
2909 if (!i->documentation) {
2910 log_info("Documentation for %s not known.", i->id);
2914 STRV_FOREACH(p, i->documentation) {
2916 if (startswith(*p, "man:")) {
2919 _cleanup_free_ char *page = NULL, *section = NULL;
2920 const char *args[4] = { "man", NULL, NULL, NULL };
2925 if ((*p)[k-1] == ')')
2926 e = strrchr(*p, '(');
2929 page = strndup((*p) + 4, e - *p - 4);
2930 section = strndup(e + 1, *p + k - e - 2);
2931 if (!page || !section) {
2943 log_error("Failed to fork: %m");
2949 execvp(args[0], (char**) args);
2950 log_error("Failed to execute man: %m");
2951 _exit(EXIT_FAILURE);
2954 wait_for_terminate(pid, NULL);
2956 log_info("Can't show: %s", *p);
2960 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2966 switch (dbus_message_iter_get_arg_type(iter)) {
2968 case DBUS_TYPE_STRING: {
2971 dbus_message_iter_get_basic(iter, &s);
2974 if (streq(name, "Id"))
2976 else if (streq(name, "LoadState"))
2978 else if (streq(name, "ActiveState"))
2979 i->active_state = s;
2980 else if (streq(name, "SubState"))
2982 else if (streq(name, "Description"))
2984 else if (streq(name, "FragmentPath"))
2985 i->fragment_path = s;
2986 else if (streq(name, "SourcePath"))
2988 else if (streq(name, "DefaultControlGroup"))
2989 i->default_control_group = s;
2990 else if (streq(name, "StatusText"))
2992 else if (streq(name, "SysFSPath"))
2994 else if (streq(name, "Where"))
2996 else if (streq(name, "What"))
2998 else if (streq(name, "Following"))
3000 else if (streq(name, "UnitFileState"))
3001 i->unit_file_state = s;
3002 else if (streq(name, "Result"))
3009 case DBUS_TYPE_BOOLEAN: {
3012 dbus_message_iter_get_basic(iter, &b);
3014 if (streq(name, "Accept"))
3016 else if (streq(name, "NeedDaemonReload"))
3017 i->need_daemon_reload = b;
3018 else if (streq(name, "ConditionResult"))
3019 i->condition_result = b;
3024 case DBUS_TYPE_UINT32: {
3027 dbus_message_iter_get_basic(iter, &u);
3029 if (streq(name, "MainPID")) {
3031 i->main_pid = (pid_t) u;
3034 } else if (streq(name, "ControlPID"))
3035 i->control_pid = (pid_t) u;
3036 else if (streq(name, "ExecMainPID")) {
3038 i->main_pid = (pid_t) u;
3039 } else if (streq(name, "NAccepted"))
3041 else if (streq(name, "NConnections"))
3042 i->n_connections = u;
3047 case DBUS_TYPE_INT32: {
3050 dbus_message_iter_get_basic(iter, &j);
3052 if (streq(name, "ExecMainCode"))
3053 i->exit_code = (int) j;
3054 else if (streq(name, "ExecMainStatus"))
3055 i->exit_status = (int) j;
3060 case DBUS_TYPE_UINT64: {
3063 dbus_message_iter_get_basic(iter, &u);
3065 if (streq(name, "ExecMainStartTimestamp"))
3066 i->start_timestamp = (usec_t) u;
3067 else if (streq(name, "ExecMainExitTimestamp"))
3068 i->exit_timestamp = (usec_t) u;
3069 else if (streq(name, "ActiveEnterTimestamp"))
3070 i->active_enter_timestamp = (usec_t) u;
3071 else if (streq(name, "InactiveEnterTimestamp"))
3072 i->inactive_enter_timestamp = (usec_t) u;
3073 else if (streq(name, "InactiveExitTimestamp"))
3074 i->inactive_exit_timestamp = (usec_t) u;
3075 else if (streq(name, "InactiveExitTimestampMonotonic"))
3076 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3077 else if (streq(name, "ActiveExitTimestamp"))
3078 i->active_exit_timestamp = (usec_t) u;
3079 else if (streq(name, "ConditionTimestamp"))
3080 i->condition_timestamp = (usec_t) u;
3085 case DBUS_TYPE_ARRAY: {
3087 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3088 startswith(name, "Exec")) {
3089 DBusMessageIter sub;
3091 dbus_message_iter_recurse(iter, &sub);
3092 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3093 ExecStatusInfo *info;
3096 if (!(info = new0(ExecStatusInfo, 1)))
3099 if (!(info->name = strdup(name))) {
3104 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
3109 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
3111 dbus_message_iter_next(&sub);
3114 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3115 DBusMessageIter sub, sub2;
3117 dbus_message_iter_recurse(iter, &sub);
3118 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3119 const char *type, *path;
3121 dbus_message_iter_recurse(&sub, &sub2);
3123 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3124 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
3127 r = strv_extend(&i->listen, type);
3130 r = strv_extend(&i->listen, path);
3135 dbus_message_iter_next(&sub);
3140 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING && streq(name, "DropInPaths")) {
3141 int r = bus_parse_strv_iter(iter, &i->dropin_paths);
3145 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3146 streq(name, "Documentation")) {
3148 DBusMessageIter sub;
3150 dbus_message_iter_recurse(iter, &sub);
3151 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
3155 dbus_message_iter_get_basic(&sub, &s);
3157 r = strv_extend(&i->documentation, s);
3161 dbus_message_iter_next(&sub);
3168 case DBUS_TYPE_STRUCT: {
3170 if (streq(name, "LoadError")) {
3171 DBusMessageIter sub;
3172 const char *n, *message;
3175 dbus_message_iter_recurse(iter, &sub);
3177 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
3181 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
3185 if (!isempty(message))
3186 i->load_error = message;
3196 static int print_property(const char *name, DBusMessageIter *iter) {
3200 /* This is a low-level property printer, see
3201 * print_status_info() for the nicer output */
3203 if (arg_properties && !strv_find(arg_properties, name))
3206 switch (dbus_message_iter_get_arg_type(iter)) {
3208 case DBUS_TYPE_STRUCT: {
3209 DBusMessageIter sub;
3210 dbus_message_iter_recurse(iter, &sub);
3212 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
3215 dbus_message_iter_get_basic(&sub, &u);
3218 printf("%s=%u\n", name, (unsigned) u);
3220 printf("%s=\n", name);
3223 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
3226 dbus_message_iter_get_basic(&sub, &s);
3228 if (arg_all || s[0])
3229 printf("%s=%s\n", name, s);
3232 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
3233 const char *a = NULL, *b = NULL;
3235 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
3236 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
3238 if (arg_all || !isempty(a) || !isempty(b))
3239 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3247 case DBUS_TYPE_ARRAY:
3249 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
3250 DBusMessageIter sub, sub2;
3252 dbus_message_iter_recurse(iter, &sub);
3253 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3257 dbus_message_iter_recurse(&sub, &sub2);
3259 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3260 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3261 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3263 dbus_message_iter_next(&sub);
3268 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3269 DBusMessageIter sub, sub2;
3271 dbus_message_iter_recurse(iter, &sub);
3273 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3274 const char *type, *path;
3276 dbus_message_iter_recurse(&sub, &sub2);
3278 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3279 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3280 printf("%s=%s\n", type, path);
3282 dbus_message_iter_next(&sub);
3287 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3288 DBusMessageIter sub, sub2;
3290 dbus_message_iter_recurse(iter, &sub);
3291 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3292 const char *type, *path;
3294 dbus_message_iter_recurse(&sub, &sub2);
3296 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3297 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3298 printf("Listen%s=%s\n", type, path);
3300 dbus_message_iter_next(&sub);
3305 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3306 DBusMessageIter sub, sub2;
3308 dbus_message_iter_recurse(iter, &sub);
3309 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3311 uint64_t value, next_elapse;
3313 dbus_message_iter_recurse(&sub, &sub2);
3315 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3316 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3317 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3318 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3320 printf("%s={ value=%s ; next_elapse=%s }\n",
3322 format_timespan(timespan1, sizeof(timespan1), value, 0),
3323 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3326 dbus_message_iter_next(&sub);
3331 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
3332 DBusMessageIter sub, sub2;
3334 dbus_message_iter_recurse(iter, &sub);
3335 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3336 const char *controller, *attr, *value;
3338 dbus_message_iter_recurse(&sub, &sub2);
3340 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
3341 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
3342 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
3344 printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
3350 dbus_message_iter_next(&sub);
3355 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3356 DBusMessageIter sub;
3358 dbus_message_iter_recurse(iter, &sub);
3359 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3360 ExecStatusInfo info = {};
3362 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3363 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3364 _cleanup_free_ char *t;
3366 t = strv_join(info.argv, " ");
3368 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3372 yes_no(info.ignore),
3373 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3374 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3375 (unsigned) info. pid,
3376 sigchld_code_to_string(info.code),
3378 info.code == CLD_EXITED ? "" : "/",
3379 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3383 strv_free(info.argv);
3385 dbus_message_iter_next(&sub);
3394 if (generic_print_property(name, iter, arg_all) > 0)
3398 printf("%s=[unprintable]\n", name);
3403 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3404 _cleanup_free_ DBusMessage *reply = NULL;
3405 const char *interface = "";
3407 DBusMessageIter iter, sub, sub2, sub3;
3408 UnitStatusInfo info = {};
3414 r = bus_method_call_with_reply(
3416 "org.freedesktop.systemd1",
3418 "org.freedesktop.DBus.Properties",
3422 DBUS_TYPE_STRING, &interface,
3427 if (!dbus_message_iter_init(reply, &iter) ||
3428 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3429 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3430 log_error("Failed to parse reply.");
3434 dbus_message_iter_recurse(&iter, &sub);
3441 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3444 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3445 dbus_message_iter_recurse(&sub, &sub2);
3447 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3448 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3449 log_error("Failed to parse reply.");
3453 dbus_message_iter_recurse(&sub2, &sub3);
3455 if (show_properties)
3456 r = print_property(name, &sub3);
3458 r = status_property(name, &sub3, &info);
3460 log_error("Failed to parse reply.");
3464 dbus_message_iter_next(&sub);
3469 if (!show_properties) {
3470 if (streq(verb, "help"))
3471 show_unit_help(&info);
3473 print_status_info(&info);
3476 strv_free(info.documentation);
3477 strv_free(info.dropin_paths);
3478 strv_free(info.listen);
3480 if (!streq_ptr(info.active_state, "active") &&
3481 !streq_ptr(info.active_state, "reloading") &&
3482 streq(verb, "status"))
3483 /* According to LSB: "program not running" */
3486 while ((p = info.exec)) {
3487 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3488 exec_status_info_free(p);
3494 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3495 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3496 const char *path = NULL;
3497 _cleanup_dbus_error_free_ DBusError error;
3500 dbus_error_init(&error);
3502 r = bus_method_call_with_reply(
3504 "org.freedesktop.systemd1",
3505 "/org/freedesktop/systemd1",
3506 "org.freedesktop.systemd1.Manager",
3510 DBUS_TYPE_UINT32, &pid,
3515 if (!dbus_message_get_args(reply, &error,
3516 DBUS_TYPE_OBJECT_PATH, &path,
3517 DBUS_TYPE_INVALID)) {
3518 log_error("Failed to parse reply: %s", bus_error_message(&error));
3522 r = show_one(verb, bus, path, false, new_line);
3526 static int show_all(const char* verb, DBusConnection *bus, bool show_properties, bool *new_line) {
3527 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3528 _cleanup_free_ struct unit_info *unit_infos = NULL;
3530 const struct unit_info *u;
3533 r = get_unit_list(bus, &reply, &unit_infos, &c);
3537 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
3539 for (u = unit_infos; u < unit_infos + c; u++) {
3540 _cleanup_free_ char *p = NULL;
3542 if (!output_show_unit(u))
3545 p = unit_dbus_path_from_name(u->id);
3549 printf("%s -> '%s'\n", u->id, p);
3551 r = show_one(verb, bus, p, show_properties, new_line);
3559 static int show(DBusConnection *bus, char **args) {
3561 bool show_properties, show_status, new_line = false;
3567 show_properties = streq(args[0], "show");
3568 show_status = streq(args[0], "status");
3570 if (show_properties)
3571 pager_open_if_enabled();
3573 /* If no argument is specified inspect the manager itself */
3575 if (show_properties && strv_length(args) <= 1)
3576 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3578 if (show_status && strv_length(args) <= 1)
3579 return show_all(args[0], bus, false, &new_line);
3581 STRV_FOREACH(name, args+1) {
3584 if (safe_atou32(*name, &id) < 0) {
3585 _cleanup_free_ char *p = NULL, *n = NULL;
3586 /* Interpret as unit name */
3588 n = unit_name_mangle(*name);
3592 p = unit_dbus_path_from_name(n);
3596 r = show_one(args[0], bus, p, show_properties, &new_line);
3600 } else if (show_properties) {
3601 _cleanup_free_ char *p = NULL;
3603 /* Interpret as job id */
3604 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3607 r = show_one(args[0], bus, p, show_properties, &new_line);
3612 /* Interpret as PID */
3613 r = show_one_by_pid(args[0], bus, id, &new_line);
3622 static int dump(DBusConnection *bus, char **args) {
3623 _cleanup_free_ DBusMessage *reply = NULL;
3628 dbus_error_init(&error);
3630 pager_open_if_enabled();
3632 r = bus_method_call_with_reply(
3634 "org.freedesktop.systemd1",
3635 "/org/freedesktop/systemd1",
3636 "org.freedesktop.systemd1.Manager",
3644 if (!dbus_message_get_args(reply, &error,
3645 DBUS_TYPE_STRING, &text,
3646 DBUS_TYPE_INVALID)) {
3647 log_error("Failed to parse reply: %s", bus_error_message(&error));
3648 dbus_error_free(&error);
3652 fputs(text, stdout);
3656 static int snapshot(DBusConnection *bus, char **args) {
3657 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3660 dbus_bool_t cleanup = FALSE;
3661 DBusMessageIter iter, sub;
3664 *interface = "org.freedesktop.systemd1.Unit",
3666 _cleanup_free_ char *n = NULL;
3668 dbus_error_init(&error);
3670 if (strv_length(args) > 1)
3671 n = snapshot_name_mangle(args[1]);
3677 r = bus_method_call_with_reply (
3679 "org.freedesktop.systemd1",
3680 "/org/freedesktop/systemd1",
3681 "org.freedesktop.systemd1.Manager",
3685 DBUS_TYPE_STRING, &n,
3686 DBUS_TYPE_BOOLEAN, &cleanup,
3691 if (!dbus_message_get_args(reply, &error,
3692 DBUS_TYPE_OBJECT_PATH, &path,
3693 DBUS_TYPE_INVALID)) {
3694 log_error("Failed to parse reply: %s", bus_error_message(&error));
3695 dbus_error_free(&error);
3699 dbus_message_unref(reply);
3702 r = bus_method_call_with_reply (
3704 "org.freedesktop.systemd1",
3706 "org.freedesktop.DBus.Properties",
3710 DBUS_TYPE_STRING, &interface,
3711 DBUS_TYPE_STRING, &property,
3716 if (!dbus_message_iter_init(reply, &iter) ||
3717 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3718 log_error("Failed to parse reply.");
3722 dbus_message_iter_recurse(&iter, &sub);
3724 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3725 log_error("Failed to parse reply.");
3729 dbus_message_iter_get_basic(&sub, &id);
3737 static int delete_snapshot(DBusConnection *bus, char **args) {
3742 STRV_FOREACH(name, args+1) {
3743 _cleanup_free_ char *n = NULL;
3746 n = snapshot_name_mangle(*name);
3750 r = bus_method_call_with_reply(
3752 "org.freedesktop.systemd1",
3753 "/org/freedesktop/systemd1",
3754 "org.freedesktop.systemd1.Manager",
3758 DBUS_TYPE_STRING, &n,
3767 static int daemon_reload(DBusConnection *bus, char **args) {
3772 if (arg_action == ACTION_RELOAD)
3774 else if (arg_action == ACTION_REEXEC)
3775 method = "Reexecute";
3777 assert(arg_action == ACTION_SYSTEMCTL);
3780 streq(args[0], "clear-jobs") ||
3781 streq(args[0], "cancel") ? "ClearJobs" :
3782 streq(args[0], "daemon-reexec") ? "Reexecute" :
3783 streq(args[0], "reset-failed") ? "ResetFailed" :
3784 streq(args[0], "halt") ? "Halt" :
3785 streq(args[0], "poweroff") ? "PowerOff" :
3786 streq(args[0], "reboot") ? "Reboot" :
3787 streq(args[0], "kexec") ? "KExec" :
3788 streq(args[0], "exit") ? "Exit" :
3789 /* "daemon-reload" */ "Reload";
3792 r = bus_method_call_with_reply(
3794 "org.freedesktop.systemd1",
3795 "/org/freedesktop/systemd1",
3796 "org.freedesktop.systemd1.Manager",
3802 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3803 /* There's always a fallback possible for
3804 * legacy actions. */
3806 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3807 /* On reexecution, we expect a disconnect, not
3811 log_error("Failed to issue method call: %s", bus_error_message(&error));
3813 dbus_error_free(&error);
3817 static int reset_failed(DBusConnection *bus, char **args) {
3821 if (strv_length(args) <= 1)
3822 return daemon_reload(bus, args);
3824 STRV_FOREACH(name, args+1) {
3825 _cleanup_free_ char *n;
3827 n = unit_name_mangle(*name);
3831 r = bus_method_call_with_reply(
3833 "org.freedesktop.systemd1",
3834 "/org/freedesktop/systemd1",
3835 "org.freedesktop.systemd1.Manager",
3839 DBUS_TYPE_STRING, &n,
3848 static int show_enviroment(DBusConnection *bus, char **args) {
3849 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3850 DBusMessageIter iter, sub, sub2;
3853 *interface = "org.freedesktop.systemd1.Manager",
3854 *property = "Environment";
3856 pager_open_if_enabled();
3858 r = bus_method_call_with_reply(
3860 "org.freedesktop.systemd1",
3861 "/org/freedesktop/systemd1",
3862 "org.freedesktop.DBus.Properties",
3866 DBUS_TYPE_STRING, &interface,
3867 DBUS_TYPE_STRING, &property,
3872 if (!dbus_message_iter_init(reply, &iter) ||
3873 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3874 log_error("Failed to parse reply.");
3878 dbus_message_iter_recurse(&iter, &sub);
3880 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3881 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3882 log_error("Failed to parse reply.");
3886 dbus_message_iter_recurse(&sub, &sub2);
3888 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3891 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3892 log_error("Failed to parse reply.");
3896 dbus_message_iter_get_basic(&sub2, &text);
3899 dbus_message_iter_next(&sub2);
3905 static int switch_root(DBusConnection *bus, char **args) {
3908 _cleanup_free_ char *init = NULL;
3910 l = strv_length(args);
3911 if (l < 2 || l > 3) {
3912 log_error("Wrong number of arguments.");
3919 init = strdup(args[2]);
3921 parse_env_file("/proc/cmdline", WHITESPACE,
3931 log_debug("switching root - root: %s; init: %s", root, init);
3933 return bus_method_call_with_reply(
3935 "org.freedesktop.systemd1",
3936 "/org/freedesktop/systemd1",
3937 "org.freedesktop.systemd1.Manager",
3941 DBUS_TYPE_STRING, &root,
3942 DBUS_TYPE_STRING, &init,
3946 static int set_environment(DBusConnection *bus, char **args) {
3947 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3950 DBusMessageIter iter;
3956 dbus_error_init(&error);
3958 method = streq(args[0], "set-environment")
3960 : "UnsetEnvironment";
3962 m = dbus_message_new_method_call(
3963 "org.freedesktop.systemd1",
3964 "/org/freedesktop/systemd1",
3965 "org.freedesktop.systemd1.Manager",
3970 dbus_message_iter_init_append(m, &iter);
3972 r = bus_append_strv_iter(&iter, args + 1);
3976 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3978 log_error("Failed to issue method call: %s", bus_error_message(&error));
3979 dbus_error_free(&error);
3986 static int enable_sysv_units(char **args) {
3989 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3990 const char *verb = args[0];
3991 unsigned f = 1, t = 1;
3992 LookupPaths paths = {};
3994 if (arg_scope != UNIT_FILE_SYSTEM)
3997 if (!streq(verb, "enable") &&
3998 !streq(verb, "disable") &&
3999 !streq(verb, "is-enabled"))
4002 /* Processes all SysV units, and reshuffles the array so that
4003 * afterwards only the native units remain */
4005 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4010 for (f = 1; args[f]; f++) {
4012 _cleanup_free_ char *p = NULL, *q = NULL;
4013 bool found_native = false, found_sysv;
4015 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4023 if (!endswith(name, ".service"))
4026 if (path_is_absolute(name))
4029 STRV_FOREACH(k, paths.unit_path) {
4030 if (!isempty(arg_root))
4031 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4033 asprintf(&p, "%s/%s", *k, name);
4040 found_native = access(p, F_OK) >= 0;
4051 if (!isempty(arg_root))
4052 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4054 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4060 p[strlen(p) - sizeof(".service") + 1] = 0;
4061 found_sysv = access(p, F_OK) >= 0;
4066 /* Mark this entry, so that we don't try enabling it as native unit */
4067 args[f] = (char*) "";
4069 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4071 if (!isempty(arg_root))
4072 argv[c++] = q = strappend("--root=", arg_root);
4074 argv[c++] = path_get_file_name(p);
4076 streq(verb, "enable") ? "on" :
4077 streq(verb, "disable") ? "off" : "--level=5";
4080 l = strv_join((char**)argv, " ");
4086 log_info("Executing %s", l);
4091 log_error("Failed to fork: %m");
4094 } else if (pid == 0) {
4097 execv(argv[0], (char**) argv);
4098 _exit(EXIT_FAILURE);
4101 j = wait_for_terminate(pid, &status);
4103 log_error("Failed to wait for child: %s", strerror(-r));
4108 if (status.si_code == CLD_EXITED) {
4109 if (streq(verb, "is-enabled")) {
4110 if (status.si_status == 0) {
4119 } else if (status.si_status != 0) {
4130 lookup_paths_free(&paths);
4132 /* Drop all SysV units */
4133 for (f = 1, t = 1; args[f]; f++) {
4135 if (isempty(args[f]))
4138 args[t++] = args[f];
4147 static int mangle_names(char **original_names, char ***mangled_names) {
4148 char **i, **l, **name;
4150 l = new(char*, strv_length(original_names) + 1);
4155 STRV_FOREACH(name, original_names) {
4157 /* When enabling units qualified path names are OK,
4158 * too, hence allow them explicitly. */
4163 *i = unit_name_mangle(*name);
4179 static int enable_unit(DBusConnection *bus, char **args) {
4180 const char *verb = args[0];
4181 UnitFileChange *changes = NULL;
4182 unsigned n_changes = 0, i;
4183 int carries_install_info = -1;
4184 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4186 _cleanup_dbus_error_free_ DBusError error;
4187 _cleanup_strv_free_ char **mangled_names = NULL;
4189 dbus_error_init(&error);
4191 r = enable_sysv_units(args);
4198 if (!bus || avoid_bus()) {
4199 if (streq(verb, "enable")) {
4200 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4201 carries_install_info = r;
4202 } else if (streq(verb, "disable"))
4203 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
4204 else if (streq(verb, "reenable")) {
4205 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4206 carries_install_info = r;
4207 } else if (streq(verb, "link"))
4208 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4209 else if (streq(verb, "preset")) {
4210 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4211 carries_install_info = r;
4212 } else if (streq(verb, "mask"))
4213 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4214 else if (streq(verb, "unmask"))
4215 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
4217 assert_not_reached("Unknown verb");
4220 log_error("Operation failed: %s", strerror(-r));
4225 for (i = 0; i < n_changes; i++) {
4226 if (changes[i].type == UNIT_FILE_SYMLINK)
4227 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4229 log_info("rm '%s'", changes[i].path);
4236 bool send_force = true, expect_carries_install_info = false;
4238 DBusMessageIter iter, sub, sub2;
4240 if (streq(verb, "enable")) {
4241 method = "EnableUnitFiles";
4242 expect_carries_install_info = true;
4243 } else if (streq(verb, "disable")) {
4244 method = "DisableUnitFiles";
4246 } else if (streq(verb, "reenable")) {
4247 method = "ReenableUnitFiles";
4248 expect_carries_install_info = true;
4249 } else if (streq(verb, "link"))
4250 method = "LinkUnitFiles";
4251 else if (streq(verb, "preset")) {
4252 method = "PresetUnitFiles";
4253 expect_carries_install_info = true;
4254 } else if (streq(verb, "mask"))
4255 method = "MaskUnitFiles";
4256 else if (streq(verb, "unmask")) {
4257 method = "UnmaskUnitFiles";
4260 assert_not_reached("Unknown verb");
4262 m = dbus_message_new_method_call(
4263 "org.freedesktop.systemd1",
4264 "/org/freedesktop/systemd1",
4265 "org.freedesktop.systemd1.Manager",
4272 dbus_message_iter_init_append(m, &iter);
4274 r = mangle_names(args+1, &mangled_names);
4278 r = bus_append_strv_iter(&iter, mangled_names);
4280 log_error("Failed to append unit files.");
4285 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4286 log_error("Failed to append runtime boolean.");
4294 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4295 log_error("Failed to append force boolean.");
4301 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4303 log_error("Failed to issue method call: %s", bus_error_message(&error));
4308 if (!dbus_message_iter_init(reply, &iter)) {
4309 log_error("Failed to initialize iterator.");
4313 if (expect_carries_install_info) {
4314 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4316 log_error("Failed to parse reply.");
4320 carries_install_info = b;
4323 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4324 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4325 log_error("Failed to parse reply.");
4330 dbus_message_iter_recurse(&iter, &sub);
4331 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4332 const char *type, *path, *source;
4334 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4335 log_error("Failed to parse reply.");
4340 dbus_message_iter_recurse(&sub, &sub2);
4342 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4343 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4344 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4345 log_error("Failed to parse reply.");
4351 if (streq(type, "symlink"))
4352 log_info("ln -s '%s' '%s'", source, path);
4354 log_info("rm '%s'", path);
4357 dbus_message_iter_next(&sub);
4360 /* Try to reload if enabeld */
4362 r = daemon_reload(bus, args);
4365 if (carries_install_info == 0)
4366 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4367 "using systemctl.\n"
4368 "Possible reasons for having this kind of units are:\n"
4369 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4370 " .wants/ or .requires/ directory.\n"
4371 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4372 " a requirement dependency on it.\n"
4373 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4374 " D-Bus, udev, scripted systemctl call, ...).\n");
4377 unit_file_changes_free(changes, n_changes);
4382 static int unit_is_enabled(DBusConnection *bus, char **args) {
4383 _cleanup_dbus_error_free_ DBusError error;
4385 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4390 dbus_error_init(&error);
4392 r = enable_sysv_units(args);
4398 if (!bus || avoid_bus()) {
4400 STRV_FOREACH(name, args+1) {
4401 UnitFileState state;
4403 n = unit_name_mangle(*name);
4407 state = unit_file_get_state(arg_scope, arg_root, n);
4414 if (state == UNIT_FILE_ENABLED ||
4415 state == UNIT_FILE_ENABLED_RUNTIME ||
4416 state == UNIT_FILE_STATIC)
4420 puts(unit_file_state_to_string(state));
4424 STRV_FOREACH(name, args+1) {
4427 n = unit_name_mangle(*name);
4431 r = bus_method_call_with_reply (
4433 "org.freedesktop.systemd1",
4434 "/org/freedesktop/systemd1",
4435 "org.freedesktop.systemd1.Manager",
4439 DBUS_TYPE_STRING, &n,
4447 if (!dbus_message_get_args(reply, &error,
4448 DBUS_TYPE_STRING, &s,
4449 DBUS_TYPE_INVALID)) {
4450 log_error("Failed to parse reply: %s", bus_error_message(&error));
4454 dbus_message_unref(reply);
4457 if (streq(s, "enabled") ||
4458 streq(s, "enabled-runtime") ||
4467 return enabled ? 0 : 1;
4470 static int systemctl_help(void) {
4472 pager_open_if_enabled();
4474 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4475 "Query or send control commands to the systemd manager.\n\n"
4476 " -h --help Show this help\n"
4477 " --version Show package version\n"
4478 " -t --type=TYPE List only units of a particular type\n"
4479 " -p --property=NAME Show only properties by this name\n"
4480 " -a --all Show all loaded units/properties, including dead/empty\n"
4481 " ones. To list all units installed on the system, use\n"
4482 " the 'list-unit-files' command instead.\n"
4483 " --failed Show only failed units\n"
4484 " --full Don't ellipsize unit names on output\n"
4485 " --fail When queueing a new job, fail if conflicting jobs are\n"
4487 " --irreversible Create jobs which cannot be implicitly cancelled\n"
4488 " --show-types When showing sockets, explicitly show their type\n"
4489 " --ignore-dependencies\n"
4490 " When queueing a new job, ignore all its dependencies\n"
4491 " -i --ignore-inhibitors\n"
4492 " When shutting down or sleeping, ignore inhibitors\n"
4493 " --kill-who=WHO Who to send signal to\n"
4494 " -s --signal=SIGNAL Which signal to send\n"
4495 " -H --host=[USER@]HOST\n"
4496 " Show information for remote host\n"
4497 " -P --privileged Acquire privileges before execution\n"
4498 " -q --quiet Suppress output\n"
4499 " --no-block Do not wait until operation finished\n"
4500 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4501 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4503 " --no-legend Do not print a legend (column headers and hints)\n"
4504 " --no-pager Do not pipe output into a pager\n"
4505 " --no-ask-password\n"
4506 " Do not ask for system passwords\n"
4507 " --system Connect to system manager\n"
4508 " --user Connect to user service manager\n"
4509 " --global Enable/disable unit files globally\n"
4510 " -f --force When enabling unit files, override existing symlinks\n"
4511 " When shutting down, execute action immediately\n"
4512 " --root=PATH Enable unit files in the specified root directory\n"
4513 " --runtime Enable unit files only temporarily until next reboot\n"
4514 " -n --lines=INTEGER Journal entries to show\n"
4515 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4516 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4518 " list-units List loaded units\n"
4519 " start [NAME...] Start (activate) one or more units\n"
4520 " stop [NAME...] Stop (deactivate) one or more units\n"
4521 " reload [NAME...] Reload one or more units\n"
4522 " restart [NAME...] Start or restart one or more units\n"
4523 " try-restart [NAME...] Restart one or more units if active\n"
4524 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4525 " otherwise start or restart\n"
4526 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4527 " otherwise restart if active\n"
4528 " isolate [NAME] Start one unit and stop all others\n"
4529 " kill [NAME...] Send signal to processes of a unit\n"
4530 " is-active [NAME...] Check whether units are active\n"
4531 " is-failed [NAME...] Check whether units are failed\n"
4532 " status [NAME...|PID...] Show runtime status of one or more units\n"
4533 " show [NAME...|JOB...] Show properties of one or more\n"
4534 " units/jobs or the manager\n"
4535 " help [NAME...|PID...] Show manual for one or more units\n"
4536 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4538 " get-cgroup-attr [NAME] [ATTR] ...\n"
4539 " Get control group attrubute\n"
4540 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4541 " Set control group attribute\n"
4542 " unset-cgroup-attr [NAME] [ATTR...]\n"
4543 " Unset control group attribute\n"
4544 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4545 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4546 " load [NAME...] Load one or more units\n"
4547 " list-dependencies [NAME] Recursively show units which are required\n"
4548 " or wanted by this unit\n\n"
4549 "Unit File Commands:\n"
4550 " list-unit-files List installed unit files\n"
4551 " enable [NAME...] Enable one or more unit files\n"
4552 " disable [NAME...] Disable one or more unit files\n"
4553 " reenable [NAME...] Reenable one or more unit files\n"
4554 " preset [NAME...] Enable/disable one or more unit files\n"
4555 " based on preset configuration\n"
4556 " mask [NAME...] Mask one or more units\n"
4557 " unmask [NAME...] Unmask one or more units\n"
4558 " link [PATH...] Link one or more units files into\n"
4559 " the search path\n"
4560 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4562 " list-jobs List jobs\n"
4563 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4564 "Status Commands:\n"
4565 " dump Dump server status\n"
4566 "Snapshot Commands:\n"
4567 " snapshot [NAME] Create a snapshot\n"
4568 " delete [NAME...] Remove one or more snapshots\n\n"
4569 "Environment Commands:\n"
4570 " show-environment Dump environment\n"
4571 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4572 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4573 "Manager Lifecycle Commands:\n"
4574 " daemon-reload Reload systemd manager configuration\n"
4575 " daemon-reexec Reexecute systemd manager\n\n"
4576 "System Commands:\n"
4577 " default Enter system default mode\n"
4578 " rescue Enter system rescue mode\n"
4579 " emergency Enter system emergency mode\n"
4580 " halt Shut down and halt the system\n"
4581 " poweroff Shut down and power-off the system\n"
4582 " reboot Shut down and reboot the system\n"
4583 " kexec Shut down and reboot the system with kexec\n"
4584 " exit Request user instance exit\n"
4585 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4586 " suspend Suspend the system\n"
4587 " hibernate Hibernate the system\n"
4588 " hybrid-sleep Hibernate and suspend the system\n",
4589 program_invocation_short_name);
4594 static int halt_help(void) {
4596 printf("%s [OPTIONS...]\n\n"
4597 "%s the system.\n\n"
4598 " --help Show this help\n"
4599 " --halt Halt the machine\n"
4600 " -p --poweroff Switch off the machine\n"
4601 " --reboot Reboot the machine\n"
4602 " -f --force Force immediate halt/power-off/reboot\n"
4603 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4604 " -d --no-wtmp Don't write wtmp record\n"
4605 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4606 program_invocation_short_name,
4607 arg_action == ACTION_REBOOT ? "Reboot" :
4608 arg_action == ACTION_POWEROFF ? "Power off" :
4614 static int shutdown_help(void) {
4616 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4617 "Shut down the system.\n\n"
4618 " --help Show this help\n"
4619 " -H --halt Halt the machine\n"
4620 " -P --poweroff Power-off the machine\n"
4621 " -r --reboot Reboot the machine\n"
4622 " -h Equivalent to --poweroff, overridden by --halt\n"
4623 " -k Don't halt/power-off/reboot, just send warnings\n"
4624 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4625 " -c Cancel a pending shutdown\n",
4626 program_invocation_short_name);
4631 static int telinit_help(void) {
4633 printf("%s [OPTIONS...] {COMMAND}\n\n"
4634 "Send control commands to the init daemon.\n\n"
4635 " --help Show this help\n"
4636 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4638 " 0 Power-off the machine\n"
4639 " 6 Reboot the machine\n"
4640 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4641 " 1, s, S Enter rescue mode\n"
4642 " q, Q Reload init daemon configuration\n"
4643 " u, U Reexecute init daemon\n",
4644 program_invocation_short_name);
4649 static int runlevel_help(void) {
4651 printf("%s [OPTIONS...]\n\n"
4652 "Prints the previous and current runlevel of the init system.\n\n"
4653 " --help Show this help\n",
4654 program_invocation_short_name);
4659 static int help_types(void) {
4663 puts("Available unit types:");
4664 for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4665 t = unit_type_to_string(i);
4670 puts("\nAvailable unit load states: ");
4671 for(i = 0; i < _UNIT_LOAD_STATE_MAX; i++) {
4672 t = unit_load_state_to_string(i);
4680 static int systemctl_parse_argv(int argc, char *argv[]) {
4686 ARG_IGNORE_DEPENDENCIES,
4699 ARG_NO_ASK_PASSWORD,
4705 static const struct option options[] = {
4706 { "help", no_argument, NULL, 'h' },
4707 { "version", no_argument, NULL, ARG_VERSION },
4708 { "type", required_argument, NULL, 't' },
4709 { "property", required_argument, NULL, 'p' },
4710 { "all", no_argument, NULL, 'a' },
4711 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
4712 { "failed", no_argument, NULL, ARG_FAILED },
4713 { "full", no_argument, NULL, ARG_FULL },
4714 { "fail", no_argument, NULL, ARG_FAIL },
4715 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4716 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4717 { "ignore-inhibitors", no_argument, NULL, 'i' },
4718 { "user", no_argument, NULL, ARG_USER },
4719 { "system", no_argument, NULL, ARG_SYSTEM },
4720 { "global", no_argument, NULL, ARG_GLOBAL },
4721 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4722 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4723 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4724 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4725 { "quiet", no_argument, NULL, 'q' },
4726 { "root", required_argument, NULL, ARG_ROOT },
4727 { "force", no_argument, NULL, ARG_FORCE },
4728 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4729 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4730 { "signal", required_argument, NULL, 's' },
4731 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4732 { "host", required_argument, NULL, 'H' },
4733 { "privileged",no_argument, NULL, 'P' },
4734 { "runtime", no_argument, NULL, ARG_RUNTIME },
4735 { "lines", required_argument, NULL, 'n' },
4736 { "output", required_argument, NULL, 'o' },
4737 { NULL, 0, NULL, 0 }
4745 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4754 puts(PACKAGE_STRING);
4755 puts(SYSTEMD_FEATURES);
4762 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4763 _cleanup_free_ char *type;
4765 type = strndup(word, size);
4769 if (streq(type, "help")) {
4774 if (unit_type_from_string(type) >= 0) {
4775 if (strv_push(&arg_types, type))
4781 if (unit_load_state_from_string(optarg) >= 0) {
4782 if (strv_push(&arg_load_states, type))
4788 log_error("Unknown unit type or load state '%s'.", type);
4789 log_info("Use -t help to see a list of allowed values.");
4797 /* Make sure that if the empty property list
4798 was specified, we won't show any properties. */
4799 if (isempty(optarg) && !arg_properties) {
4800 arg_properties = strv_new(NULL, NULL);
4801 if (!arg_properties)
4807 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4810 prop = strndup(word, size);
4814 if (strv_push(&arg_properties, prop)) {
4821 /* If the user asked for a particular
4822 * property, show it to him, even if it is
4833 case ARG_SHOW_TYPES:
4834 arg_show_types = true;
4838 arg_job_mode = "fail";
4841 case ARG_IRREVERSIBLE:
4842 arg_job_mode = "replace-irreversibly";
4845 case ARG_IGNORE_DEPENDENCIES:
4846 arg_job_mode = "ignore-dependencies";
4850 arg_scope = UNIT_FILE_USER;
4854 arg_scope = UNIT_FILE_SYSTEM;
4858 arg_scope = UNIT_FILE_GLOBAL;
4862 arg_no_block = true;
4866 arg_no_legend = true;
4870 arg_no_pager = true;
4902 arg_no_reload = true;
4906 arg_kill_who = optarg;
4910 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4911 log_error("Failed to parse signal string %s.", optarg);
4916 case ARG_NO_ASK_PASSWORD:
4917 arg_ask_password = false;
4921 arg_transport = TRANSPORT_POLKIT;
4925 arg_transport = TRANSPORT_SSH;
4934 if (safe_atou(optarg, &arg_lines) < 0) {
4935 log_error("Failed to parse lines '%s'", optarg);
4941 arg_output = output_mode_from_string(optarg);
4942 if (arg_output < 0) {
4943 log_error("Unknown output '%s'.", optarg);
4949 arg_ignore_inhibitors = true;
4956 log_error("Unknown option code '%c'.", c);
4961 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4962 log_error("Cannot access user instance remotely.");
4969 static int halt_parse_argv(int argc, char *argv[]) {
4978 static const struct option options[] = {
4979 { "help", no_argument, NULL, ARG_HELP },
4980 { "halt", no_argument, NULL, ARG_HALT },
4981 { "poweroff", no_argument, NULL, 'p' },
4982 { "reboot", no_argument, NULL, ARG_REBOOT },
4983 { "force", no_argument, NULL, 'f' },
4984 { "wtmp-only", no_argument, NULL, 'w' },
4985 { "no-wtmp", no_argument, NULL, 'd' },
4986 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4987 { NULL, 0, NULL, 0 }
4995 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4996 if (runlevel == '0' || runlevel == '6')
4999 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5007 arg_action = ACTION_HALT;
5011 if (arg_action != ACTION_REBOOT)
5012 arg_action = ACTION_POWEROFF;
5016 arg_action = ACTION_REBOOT;
5038 /* Compatibility nops */
5045 log_error("Unknown option code '%c'.", c);
5050 if (optind < argc) {
5051 log_error("Too many arguments.");
5058 static int parse_time_spec(const char *t, usec_t *_u) {
5062 if (streq(t, "now"))
5064 else if (!strchr(t, ':')) {
5067 if (safe_atou64(t, &u) < 0)
5070 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5079 hour = strtol(t, &e, 10);
5080 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5083 minute = strtol(e+1, &e, 10);
5084 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5087 n = now(CLOCK_REALTIME);
5088 s = (time_t) (n / USEC_PER_SEC);
5090 assert_se(localtime_r(&s, &tm));
5092 tm.tm_hour = (int) hour;
5093 tm.tm_min = (int) minute;
5096 assert_se(s = mktime(&tm));
5098 *_u = (usec_t) s * USEC_PER_SEC;
5101 *_u += USEC_PER_DAY;
5107 static int shutdown_parse_argv(int argc, char *argv[]) {
5114 static const struct option options[] = {
5115 { "help", no_argument, NULL, ARG_HELP },
5116 { "halt", no_argument, NULL, 'H' },
5117 { "poweroff", no_argument, NULL, 'P' },
5118 { "reboot", no_argument, NULL, 'r' },
5119 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5120 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5121 { NULL, 0, NULL, 0 }
5129 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5137 arg_action = ACTION_HALT;
5141 arg_action = ACTION_POWEROFF;
5146 arg_action = ACTION_KEXEC;
5148 arg_action = ACTION_REBOOT;
5152 arg_action = ACTION_KEXEC;
5156 if (arg_action != ACTION_HALT)
5157 arg_action = ACTION_POWEROFF;
5170 /* Compatibility nops */
5174 arg_action = ACTION_CANCEL_SHUTDOWN;
5181 log_error("Unknown option code '%c'.", c);
5186 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5187 r = parse_time_spec(argv[optind], &arg_when);
5189 log_error("Failed to parse time specification: %s", argv[optind]);
5193 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5195 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5196 /* No time argument for shutdown cancel */
5197 arg_wall = argv + optind;
5198 else if (argc > optind + 1)
5199 /* We skip the time argument */
5200 arg_wall = argv + optind + 1;
5207 static int telinit_parse_argv(int argc, char *argv[]) {
5214 static const struct option options[] = {
5215 { "help", no_argument, NULL, ARG_HELP },
5216 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5217 { NULL, 0, NULL, 0 }
5220 static const struct {
5224 { '0', ACTION_POWEROFF },
5225 { '6', ACTION_REBOOT },
5226 { '1', ACTION_RESCUE },
5227 { '2', ACTION_RUNLEVEL2 },
5228 { '3', ACTION_RUNLEVEL3 },
5229 { '4', ACTION_RUNLEVEL4 },
5230 { '5', ACTION_RUNLEVEL5 },
5231 { 's', ACTION_RESCUE },
5232 { 'S', ACTION_RESCUE },
5233 { 'q', ACTION_RELOAD },
5234 { 'Q', ACTION_RELOAD },
5235 { 'u', ACTION_REEXEC },
5236 { 'U', ACTION_REEXEC }
5245 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5260 log_error("Unknown option code '%c'.", c);
5265 if (optind >= argc) {
5270 if (optind + 1 < argc) {
5271 log_error("Too many arguments.");
5275 if (strlen(argv[optind]) != 1) {
5276 log_error("Expected single character argument.");
5280 for (i = 0; i < ELEMENTSOF(table); i++)
5281 if (table[i].from == argv[optind][0])
5284 if (i >= ELEMENTSOF(table)) {
5285 log_error("Unknown command '%s'.", argv[optind]);
5289 arg_action = table[i].to;
5296 static int runlevel_parse_argv(int argc, char *argv[]) {
5302 static const struct option options[] = {
5303 { "help", no_argument, NULL, ARG_HELP },
5304 { NULL, 0, NULL, 0 }
5312 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5323 log_error("Unknown option code '%c'.", c);
5328 if (optind < argc) {
5329 log_error("Too many arguments.");
5336 static int parse_argv(int argc, char *argv[]) {
5340 if (program_invocation_short_name) {
5342 if (strstr(program_invocation_short_name, "halt")) {
5343 arg_action = ACTION_HALT;
5344 return halt_parse_argv(argc, argv);
5345 } else if (strstr(program_invocation_short_name, "poweroff")) {
5346 arg_action = ACTION_POWEROFF;
5347 return halt_parse_argv(argc, argv);
5348 } else if (strstr(program_invocation_short_name, "reboot")) {
5350 arg_action = ACTION_KEXEC;
5352 arg_action = ACTION_REBOOT;
5353 return halt_parse_argv(argc, argv);
5354 } else if (strstr(program_invocation_short_name, "shutdown")) {
5355 arg_action = ACTION_POWEROFF;
5356 return shutdown_parse_argv(argc, argv);
5357 } else if (strstr(program_invocation_short_name, "init")) {
5359 if (sd_booted() > 0) {
5360 arg_action = ACTION_INVALID;
5361 return telinit_parse_argv(argc, argv);
5363 /* Hmm, so some other init system is
5364 * running, we need to forward this
5365 * request to it. For now we simply
5366 * guess that it is Upstart. */
5368 execv(TELINIT, argv);
5370 log_error("Couldn't find an alternative telinit implementation to spawn.");
5374 } else if (strstr(program_invocation_short_name, "runlevel")) {
5375 arg_action = ACTION_RUNLEVEL;
5376 return runlevel_parse_argv(argc, argv);
5380 arg_action = ACTION_SYSTEMCTL;
5381 return systemctl_parse_argv(argc, argv);
5384 static int action_to_runlevel(void) {
5386 static const char table[_ACTION_MAX] = {
5387 [ACTION_HALT] = '0',
5388 [ACTION_POWEROFF] = '0',
5389 [ACTION_REBOOT] = '6',
5390 [ACTION_RUNLEVEL2] = '2',
5391 [ACTION_RUNLEVEL3] = '3',
5392 [ACTION_RUNLEVEL4] = '4',
5393 [ACTION_RUNLEVEL5] = '5',
5394 [ACTION_RESCUE] = '1'
5397 assert(arg_action < _ACTION_MAX);
5399 return table[arg_action];
5402 static int talk_upstart(void) {
5403 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
5404 _cleanup_dbus_error_free_ DBusError error;
5405 int previous, rl, r;
5407 env1_buf[] = "RUNLEVEL=X",
5408 env2_buf[] = "PREVLEVEL=X";
5409 char *env1 = env1_buf, *env2 = env2_buf;
5410 const char *emit = "runlevel";
5411 dbus_bool_t b_false = FALSE;
5412 DBusMessageIter iter, sub;
5413 DBusConnection *bus;
5415 dbus_error_init(&error);
5417 if (!(rl = action_to_runlevel()))
5420 if (utmp_get_runlevel(&previous, NULL) < 0)
5423 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5424 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5429 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5434 if ((r = bus_check_peercred(bus)) < 0) {
5435 log_error("Failed to verify owner of bus.");
5439 if (!(m = dbus_message_new_method_call(
5440 "com.ubuntu.Upstart",
5441 "/com/ubuntu/Upstart",
5442 "com.ubuntu.Upstart0_6",
5445 log_error("Could not allocate message.");
5450 dbus_message_iter_init_append(m, &iter);
5452 env1_buf[sizeof(env1_buf)-2] = rl;
5453 env2_buf[sizeof(env2_buf)-2] = previous;
5455 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5456 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5457 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5458 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5459 !dbus_message_iter_close_container(&iter, &sub) ||
5460 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5461 log_error("Could not append arguments to message.");
5466 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5468 if (bus_error_is_no_service(&error)) {
5473 log_error("Failed to issue method call: %s", bus_error_message(&error));
5482 dbus_connection_flush(bus);
5483 dbus_connection_close(bus);
5484 dbus_connection_unref(bus);
5490 static int talk_initctl(void) {
5491 struct init_request request = {};
5493 _cleanup_close_ int fd = -1;
5496 rl = action_to_runlevel();
5500 request.magic = INIT_MAGIC;
5501 request.sleeptime = 0;
5502 request.cmd = INIT_CMD_RUNLVL;
5503 request.runlevel = rl;
5505 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5507 if (errno == ENOENT)
5510 log_error("Failed to open "INIT_FIFO": %m");
5515 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5517 log_error("Failed to write to "INIT_FIFO": %m");
5518 return errno > 0 ? -errno : -EIO;
5524 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5526 static const struct {
5534 int (* const dispatch)(DBusConnection *bus, char **args);
5536 { "list-units", LESS, 1, list_units },
5537 { "list-unit-files", EQUAL, 1, list_unit_files },
5538 { "list-sockets", LESS, 1, list_sockets },
5539 { "list-jobs", EQUAL, 1, list_jobs },
5540 { "clear-jobs", EQUAL, 1, daemon_reload },
5541 { "load", MORE, 2, load_unit },
5542 { "cancel", MORE, 2, cancel_job },
5543 { "start", MORE, 2, start_unit },
5544 { "stop", MORE, 2, start_unit },
5545 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5546 { "reload", MORE, 2, start_unit },
5547 { "restart", MORE, 2, start_unit },
5548 { "try-restart", MORE, 2, start_unit },
5549 { "reload-or-restart", MORE, 2, start_unit },
5550 { "reload-or-try-restart", MORE, 2, start_unit },
5551 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5552 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5553 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5554 { "isolate", EQUAL, 2, start_unit },
5555 { "set-cgroup", MORE, 3, set_cgroup },
5556 { "unset-cgroup", MORE, 3, set_cgroup },
5557 { "get-cgroup-attr", MORE, 3, get_cgroup_attr },
5558 { "set-cgroup-attr", MORE, 4, set_cgroup_attr },
5559 { "unset-cgroup-attr", MORE, 3, set_cgroup },
5560 { "kill", MORE, 2, kill_unit },
5561 { "is-active", MORE, 2, check_unit_active },
5562 { "check", MORE, 2, check_unit_active },
5563 { "is-failed", MORE, 2, check_unit_failed },
5564 { "show", MORE, 1, show },
5565 { "status", MORE, 1, show },
5566 { "help", MORE, 2, show },
5567 { "dump", EQUAL, 1, dump },
5568 { "snapshot", LESS, 2, snapshot },
5569 { "delete", MORE, 2, delete_snapshot },
5570 { "daemon-reload", EQUAL, 1, daemon_reload },
5571 { "daemon-reexec", EQUAL, 1, daemon_reload },
5572 { "show-environment", EQUAL, 1, show_enviroment },
5573 { "set-environment", MORE, 2, set_environment },
5574 { "unset-environment", MORE, 2, set_environment },
5575 { "halt", EQUAL, 1, start_special },
5576 { "poweroff", EQUAL, 1, start_special },
5577 { "reboot", EQUAL, 1, start_special },
5578 { "kexec", EQUAL, 1, start_special },
5579 { "suspend", EQUAL, 1, start_special },
5580 { "hibernate", EQUAL, 1, start_special },
5581 { "hybrid-sleep", EQUAL, 1, start_special },
5582 { "default", EQUAL, 1, start_special },
5583 { "rescue", EQUAL, 1, start_special },
5584 { "emergency", EQUAL, 1, start_special },
5585 { "exit", EQUAL, 1, start_special },
5586 { "reset-failed", MORE, 1, reset_failed },
5587 { "enable", MORE, 2, enable_unit },
5588 { "disable", MORE, 2, enable_unit },
5589 { "is-enabled", MORE, 2, unit_is_enabled },
5590 { "reenable", MORE, 2, enable_unit },
5591 { "preset", MORE, 2, enable_unit },
5592 { "mask", MORE, 2, enable_unit },
5593 { "unmask", MORE, 2, enable_unit },
5594 { "link", MORE, 2, enable_unit },
5595 { "switch-root", MORE, 2, switch_root },
5596 { "list-dependencies", LESS, 2, list_dependencies },
5606 left = argc - optind;
5609 /* Special rule: no arguments means "list-units" */
5612 if (streq(argv[optind], "help") && !argv[optind+1]) {
5613 log_error("This command expects one or more "
5614 "unit names. Did you mean --help?");
5618 for (i = 0; i < ELEMENTSOF(verbs); i++)
5619 if (streq(argv[optind], verbs[i].verb))
5622 if (i >= ELEMENTSOF(verbs)) {
5623 log_error("Unknown operation '%s'.", argv[optind]);
5628 switch (verbs[i].argc_cmp) {
5631 if (left != verbs[i].argc) {
5632 log_error("Invalid number of arguments.");
5639 if (left < verbs[i].argc) {
5640 log_error("Too few arguments.");
5647 if (left > verbs[i].argc) {
5648 log_error("Too many arguments.");
5655 assert_not_reached("Unknown comparison operator.");
5658 /* Require a bus connection for all operations but
5660 if (!streq(verbs[i].verb, "enable") &&
5661 !streq(verbs[i].verb, "disable") &&
5662 !streq(verbs[i].verb, "is-enabled") &&
5663 !streq(verbs[i].verb, "list-unit-files") &&
5664 !streq(verbs[i].verb, "reenable") &&
5665 !streq(verbs[i].verb, "preset") &&
5666 !streq(verbs[i].verb, "mask") &&
5667 !streq(verbs[i].verb, "unmask") &&
5668 !streq(verbs[i].verb, "link")) {
5670 if (running_in_chroot() > 0) {
5671 log_info("Running in chroot, ignoring request.");
5675 if (((!streq(verbs[i].verb, "reboot") &&
5676 !streq(verbs[i].verb, "halt") &&
5677 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5678 log_error("Failed to get D-Bus connection: %s",
5679 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5685 if (!bus && !avoid_bus()) {
5686 log_error("Failed to get D-Bus connection: %s",
5687 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5692 return verbs[i].dispatch(bus, argv + optind);
5695 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5696 _cleanup_close_ int fd;
5697 struct sd_shutdown_command c = {
5703 union sockaddr_union sockaddr = {
5704 .un.sun_family = AF_UNIX,
5705 .un.sun_path = "/run/systemd/shutdownd",
5707 struct iovec iovec[2] = {
5708 {.iov_base = (char*) &c,
5709 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
5712 struct msghdr msghdr = {
5713 .msg_name = &sockaddr,
5714 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
5715 + sizeof("/run/systemd/shutdownd") - 1,
5720 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5724 if (!isempty(message)) {
5725 iovec[1].iov_base = (char*) message;
5726 iovec[1].iov_len = strlen(message);
5727 msghdr.msg_iovlen++;
5730 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5736 static int reload_with_fallback(DBusConnection *bus) {
5739 /* First, try systemd via D-Bus. */
5740 if (daemon_reload(bus, NULL) >= 0)
5744 /* Nothing else worked, so let's try signals */
5745 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5747 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5748 log_error("kill() failed: %m");
5755 static int start_with_fallback(DBusConnection *bus) {
5758 /* First, try systemd via D-Bus. */
5759 if (start_unit(bus, NULL) >= 0)
5763 /* Hmm, talking to systemd via D-Bus didn't work. Then
5764 * let's try to talk to Upstart via D-Bus. */
5765 if (talk_upstart() > 0)
5768 /* Nothing else worked, so let's try
5770 if (talk_initctl() > 0)
5773 log_error("Failed to talk to init daemon.");
5777 warn_wall(arg_action);
5781 static _noreturn_ void halt_now(enum action a) {
5783 /* Make sure C-A-D is handled by the kernel from this
5785 reboot(RB_ENABLE_CAD);
5790 log_info("Halting.");
5791 reboot(RB_HALT_SYSTEM);
5794 case ACTION_POWEROFF:
5795 log_info("Powering off.");
5796 reboot(RB_POWER_OFF);
5800 log_info("Rebooting.");
5801 reboot(RB_AUTOBOOT);
5805 assert_not_reached("Unknown halt action.");
5808 assert_not_reached("Uh? This shouldn't happen.");
5811 static int halt_main(DBusConnection *bus) {
5814 r = check_inhibitors(bus, arg_action);
5818 if (geteuid() != 0) {
5819 /* Try logind if we are a normal user and no special
5820 * mode applies. Maybe PolicyKit allows us to shutdown
5823 if (arg_when <= 0 &&
5826 (arg_action == ACTION_POWEROFF ||
5827 arg_action == ACTION_REBOOT)) {
5828 r = reboot_with_logind(bus, arg_action);
5833 log_error("Must be root.");
5838 _cleanup_free_ char *m;
5840 m = strv_join(arg_wall, " ");
5841 r = send_shutdownd(arg_when,
5842 arg_action == ACTION_HALT ? 'H' :
5843 arg_action == ACTION_POWEROFF ? 'P' :
5844 arg_action == ACTION_KEXEC ? 'K' :
5851 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5853 char date[FORMAT_TIMESTAMP_MAX];
5855 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5856 format_timestamp(date, sizeof(date), arg_when));
5861 if (!arg_dry && !arg_force)
5862 return start_with_fallback(bus);
5865 if (sd_booted() > 0)
5866 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5868 r = utmp_put_shutdown();
5870 log_warning("Failed to write utmp record: %s", strerror(-r));
5877 halt_now(arg_action);
5878 /* We should never reach this. */
5882 static int runlevel_main(void) {
5883 int r, runlevel, previous;
5885 r = utmp_get_runlevel(&runlevel, &previous);
5892 previous <= 0 ? 'N' : previous,
5893 runlevel <= 0 ? 'N' : runlevel);
5898 int main(int argc, char*argv[]) {
5899 int r, retval = EXIT_FAILURE;
5900 DBusConnection *bus = NULL;
5901 _cleanup_dbus_error_free_ DBusError error;
5903 dbus_error_init(&error);
5905 setlocale(LC_ALL, "");
5906 log_parse_environment();
5909 r = parse_argv(argc, argv);
5913 retval = EXIT_SUCCESS;
5917 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5918 * let's shortcut this */
5919 if (arg_action == ACTION_RUNLEVEL) {
5920 r = runlevel_main();
5921 retval = r < 0 ? EXIT_FAILURE : r;
5925 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5926 log_info("Running in chroot, ignoring request.");
5932 if (arg_transport == TRANSPORT_NORMAL)
5933 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5934 else if (arg_transport == TRANSPORT_POLKIT) {
5935 bus_connect_system_polkit(&bus, &error);
5936 private_bus = false;
5937 } else if (arg_transport == TRANSPORT_SSH) {
5938 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5939 private_bus = false;
5941 assert_not_reached("Uh, invalid transport...");
5944 switch (arg_action) {
5946 case ACTION_SYSTEMCTL:
5947 r = systemctl_main(bus, argc, argv, &error);
5951 case ACTION_POWEROFF:
5957 case ACTION_RUNLEVEL2:
5958 case ACTION_RUNLEVEL3:
5959 case ACTION_RUNLEVEL4:
5960 case ACTION_RUNLEVEL5:
5962 case ACTION_EMERGENCY:
5963 case ACTION_DEFAULT:
5964 r = start_with_fallback(bus);
5969 r = reload_with_fallback(bus);
5972 case ACTION_CANCEL_SHUTDOWN: {
5976 m = strv_join(arg_wall, " ");
5978 retval = EXIT_FAILURE;
5982 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5984 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5989 case ACTION_INVALID:
5990 case ACTION_RUNLEVEL:
5992 assert_not_reached("Unknown action");
5995 retval = r < 0 ? EXIT_FAILURE : r;
5999 dbus_connection_flush(bus);
6000 dbus_connection_close(bus);
6001 dbus_connection_unref(bus);
6006 strv_free(arg_types);
6007 strv_free(arg_load_states);
6008 strv_free(arg_properties);
6011 ask_password_agent_close();
6012 polkit_agent_close();