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 enum dependency {
80 } arg_dependency = DEPENDENCY_FORWARD;
81 static const char *arg_job_mode = "replace";
82 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
83 static bool arg_no_block = false;
84 static bool arg_no_legend = false;
85 static bool arg_no_pager = false;
86 static bool arg_no_wtmp = false;
87 static bool arg_no_wall = false;
88 static bool arg_no_reload = false;
89 static bool arg_show_types = false;
90 static bool arg_ignore_inhibitors = false;
91 static bool arg_dry = false;
92 static bool arg_quiet = false;
93 static bool arg_full = false;
94 static int arg_force = 0;
95 static bool arg_ask_password = true;
96 static bool arg_failed = false;
97 static bool arg_runtime = false;
98 static char **arg_wall = NULL;
99 static const char *arg_kill_who = NULL;
100 static int arg_signal = SIGTERM;
101 static const char *arg_root = NULL;
102 static usec_t arg_when = 0;
124 ACTION_CANCEL_SHUTDOWN,
126 } arg_action = ACTION_SYSTEMCTL;
127 static enum transport {
131 } arg_transport = TRANSPORT_NORMAL;
132 static const char *arg_host = NULL;
133 static unsigned arg_lines = 10;
134 static OutputMode arg_output = OUTPUT_SHORT;
136 static bool private_bus = false;
138 static int daemon_reload(DBusConnection *bus, char **args);
139 static void halt_now(enum action a);
141 static void pager_open_if_enabled(void) {
149 static void ask_password_agent_open_if_enabled(void) {
151 /* Open the password agent as a child process if necessary */
153 if (!arg_ask_password)
156 if (arg_scope != UNIT_FILE_SYSTEM)
159 ask_password_agent_open();
163 static void polkit_agent_open_if_enabled(void) {
165 /* Open the polkit agent as a child process if necessary */
167 if (!arg_ask_password)
170 if (arg_scope != UNIT_FILE_SYSTEM)
177 static const char *ansi_highlight(bool b) {
182 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
185 static const char *ansi_highlight_red(bool b) {
190 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
193 static const char *ansi_highlight_green(bool b) {
198 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
201 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
204 if (!dbus_error_is_set(error))
207 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
208 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
209 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
210 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
211 return EXIT_NOPERMISSION;
213 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
214 return EXIT_NOTINSTALLED;
216 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
217 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
218 return EXIT_NOTIMPLEMENTED;
220 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
221 return EXIT_NOTCONFIGURED;
229 static void warn_wall(enum action a) {
230 static const char *table[_ACTION_MAX] = {
231 [ACTION_HALT] = "The system is going down for system halt NOW!",
232 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
233 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
234 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
235 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
236 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
237 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
244 _cleanup_free_ char *p;
246 p = strv_join(arg_wall, " ");
261 utmp_wall(table[a], NULL);
264 static bool avoid_bus(void) {
266 if (running_in_chroot() > 0)
269 if (sd_booted() <= 0)
272 if (!isempty(arg_root))
275 if (arg_scope == UNIT_FILE_GLOBAL)
281 static int compare_unit_info(const void *a, const void *b) {
283 const struct unit_info *u = a, *v = b;
285 d1 = strrchr(u->id, '.');
286 d2 = strrchr(v->id, '.');
291 r = strcasecmp(d1, d2);
296 return strcasecmp(u->id, v->id);
299 static bool output_show_unit(const struct unit_info *u) {
303 return streq(u->active_state, "failed");
305 return (!arg_types || ((dot = strrchr(u->id, '.')) &&
306 strv_find(arg_types, dot+1))) &&
307 (!arg_load_states || strv_find(arg_load_states, u->load_state)) &&
308 (arg_all || !(streq(u->active_state, "inactive")
309 || u->following[0]) || u->job_id > 0);
312 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
313 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
314 const struct unit_info *u;
317 max_id_len = sizeof("UNIT")-1;
318 active_len = sizeof("ACTIVE")-1;
319 sub_len = sizeof("SUB")-1;
320 job_len = sizeof("JOB")-1;
323 for (u = unit_infos; u < unit_infos + c; u++) {
324 if (!output_show_unit(u))
327 max_id_len = MAX(max_id_len, strlen(u->id));
328 active_len = MAX(active_len, strlen(u->active_state));
329 sub_len = MAX(sub_len, strlen(u->sub_state));
330 if (u->job_id != 0) {
331 job_len = MAX(job_len, strlen(u->job_type));
338 id_len = MIN(max_id_len, 25u);
339 basic_len = 5 + id_len + 5 + active_len + sub_len;
341 basic_len += job_len + 1;
342 if (basic_len < (unsigned) columns()) {
343 unsigned extra_len, incr;
344 extra_len = columns() - basic_len;
345 /* Either UNIT already got 25, or is fully satisfied.
346 * Grant up to 25 to DESC now. */
347 incr = MIN(extra_len, 25u);
350 /* split the remaining space between UNIT and DESC,
351 * but do not give UNIT more than it needs. */
353 incr = MIN(extra_len / 2, max_id_len - id_len);
355 desc_len += extra_len - incr;
361 for (u = unit_infos; u < unit_infos + c; u++) {
362 _cleanup_free_ char *e = NULL;
363 const char *on_loaded, *off_loaded, *on = "";
364 const char *on_active, *off_active, *off = "";
366 if (!output_show_unit(u))
369 if (!n_shown && !arg_no_legend) {
370 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
371 active_len, "ACTIVE", sub_len, "SUB");
373 printf("%-*s ", job_len, "JOB");
374 if (!arg_full && arg_no_pager)
375 printf("%.*s\n", desc_len, "DESCRIPTION");
377 printf("%s\n", "DESCRIPTION");
382 if (streq(u->load_state, "error")) {
383 on_loaded = on = ansi_highlight_red(true);
384 off_loaded = off = ansi_highlight_red(false);
386 on_loaded = off_loaded = "";
388 if (streq(u->active_state, "failed")) {
389 on_active = on = ansi_highlight_red(true);
390 off_active = off = ansi_highlight_red(false);
392 on_active = off_active = "";
394 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
396 printf("%s%-*s%s %s%-6s%s %s%-*s %-*s%s %-*s",
397 on, id_len, e ? e : u->id, off,
398 on_loaded, u->load_state, off_loaded,
399 on_active, active_len, u->active_state,
400 sub_len, u->sub_state, off_active,
401 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
402 if (!arg_full && arg_no_pager)
403 printf("%.*s\n", desc_len, u->description);
405 printf("%s\n", u->description);
408 if (!arg_no_legend) {
409 const char *on, *off;
412 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
413 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
414 "SUB = The low-level unit activation state, values depend on unit type.\n");
416 printf("JOB = Pending job for the unit.\n");
418 on = ansi_highlight(true);
419 off = ansi_highlight(false);
421 on = ansi_highlight_red(true);
422 off = ansi_highlight_red(false);
426 printf("%s%u loaded units listed.%s\n"
427 "To show all installed unit files use 'systemctl list-unit-files'.\n",
430 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
431 "To show all installed unit files use 'systemctl list-unit-files'.\n",
436 static int get_unit_list(DBusConnection *bus, DBusMessage **reply,
437 struct unit_info **unit_infos, unsigned *c) {
438 DBusMessageIter iter, sub;
446 r = bus_method_call_with_reply(
448 "org.freedesktop.systemd1",
449 "/org/freedesktop/systemd1",
450 "org.freedesktop.systemd1.Manager",
458 if (!dbus_message_iter_init(*reply, &iter) ||
459 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
460 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
461 log_error("Failed to parse reply.");
465 dbus_message_iter_recurse(&iter, &sub);
467 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
468 if (!GREEDY_REALLOC(*unit_infos, size, *c + 1))
471 bus_parse_unit_info(&sub, *unit_infos + *c);
474 dbus_message_iter_next(&sub);
480 static int list_units(DBusConnection *bus, char **args) {
481 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
482 _cleanup_free_ struct unit_info *unit_infos = NULL;
486 pager_open_if_enabled();
488 r = get_unit_list(bus, &reply, &unit_infos, &c);
492 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
494 output_units_list(unit_infos, c);
499 static int get_triggered_units(DBusConnection *bus, const char* unit_path,
502 const char *interface = "org.freedesktop.systemd1.Unit",
503 *triggers_property = "Triggers";
504 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
505 DBusMessageIter iter, sub;
508 r = bus_method_call_with_reply(bus,
509 "org.freedesktop.systemd1",
511 "org.freedesktop.DBus.Properties",
515 DBUS_TYPE_STRING, &interface,
516 DBUS_TYPE_STRING, &triggers_property,
521 if (!dbus_message_iter_init(reply, &iter) ||
522 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
523 log_error("Failed to parse reply.");
527 dbus_message_iter_recurse(&iter, &sub);
528 dbus_message_iter_recurse(&sub, &iter);
531 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
534 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
535 log_error("Failed to parse reply.");
539 dbus_message_iter_get_basic(&sub, &unit);
540 r = strv_extend(triggered, unit);
544 dbus_message_iter_next(&sub);
550 static int get_listening(DBusConnection *bus, const char* unit_path,
551 char*** listen, unsigned *c)
553 const char *interface = "org.freedesktop.systemd1.Socket",
554 *listen_property = "Listen";
555 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
556 DBusMessageIter iter, sub;
559 r = bus_method_call_with_reply(bus,
560 "org.freedesktop.systemd1",
562 "org.freedesktop.DBus.Properties",
566 DBUS_TYPE_STRING, &interface,
567 DBUS_TYPE_STRING, &listen_property,
572 if (!dbus_message_iter_init(reply, &iter) ||
573 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
574 log_error("Failed to parse reply.");
578 dbus_message_iter_recurse(&iter, &sub);
579 dbus_message_iter_recurse(&sub, &iter);
582 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
583 DBusMessageIter sub2;
584 const char *type, *path;
586 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
587 log_error("Failed to parse reply.");
591 dbus_message_iter_recurse(&sub, &sub2);
593 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
594 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
595 r = strv_extend(listen, type);
599 r = strv_extend(listen, path);
606 dbus_message_iter_next(&sub);
618 /* Note: triggered is a list here, although it almost certainly
619 * will always be one unit. Nevertheless, dbus API allows for multiple
620 * values, so let's follow that.*/
623 /* The strv above is shared. free is set only in the first one. */
627 static int socket_info_compare(struct socket_info *a, struct socket_info *b) {
628 int o = strcmp(a->path, b->path);
630 o = strcmp(a->type, b->type);
634 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
635 struct socket_info *s;
636 unsigned pathlen = sizeof("LISTEN") - 1,
637 typelen = (sizeof("TYPE") - 1) * arg_show_types,
638 socklen = sizeof("UNIT") - 1,
639 servlen = sizeof("ACTIVATES") - 1;
640 const char *on, *off;
642 for (s = socket_infos; s < socket_infos + cs; s++) {
646 socklen = MAX(socklen, strlen(s->id));
648 typelen = MAX(typelen, strlen(s->type));
649 pathlen = MAX(pathlen, strlen(s->path));
651 STRV_FOREACH(a, s->triggered)
652 tmp += strlen(*a) + 2*(a != s->triggered);
653 servlen = MAX(servlen, tmp);
657 printf("%-*s %-*.*s%-*s %s\n",
659 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
663 for (s = socket_infos; s < socket_infos + cs; s++) {
667 printf("%-*s %-*s %-*s",
668 pathlen, s->path, typelen, s->type, socklen, s->id);
671 pathlen, s->path, socklen, s->id);
672 STRV_FOREACH(a, s->triggered)
674 a == s->triggered ? "" : ",", *a);
678 on = ansi_highlight(true);
679 off = ansi_highlight(false);
682 on = ansi_highlight_red(true);
683 off = ansi_highlight_red(false);
686 printf("%s%u sockets listed.%s\n", on, cs, off);
688 printf("Pass --all to see loaded but inactive sockets, too.\n");
693 static int list_sockets(DBusConnection *bus, char **args) {
694 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
695 _cleanup_free_ struct unit_info *unit_infos = NULL;
696 struct socket_info *socket_infos = NULL;
697 const struct unit_info *u;
698 struct socket_info *s;
699 unsigned cu = 0, cs = 0;
703 pager_open_if_enabled();
705 r = get_unit_list(bus, &reply, &unit_infos, &cu);
709 for (u = unit_infos; u < unit_infos + cu; u++) {
711 _cleanup_strv_free_ char **listen = NULL, **triggered = NULL;
714 if (!output_show_unit(u))
717 if ((dot = strrchr(u->id, '.')) && !streq(dot+1, "socket"))
720 r = get_triggered_units(bus, u->unit_path, &triggered);
724 r = get_listening(bus, u->unit_path, &listen, &c);
728 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
733 for (i = 0; i < c; i++)
734 socket_infos[cs + i] = (struct socket_info) {
737 .path = listen[i*2 + 1],
738 .triggered = triggered,
739 .own_triggered = i==0,
742 /* from this point on we will cleanup those socket_infos */
745 listen = triggered = NULL; /* avoid cleanup */
748 qsort(socket_infos, cs, sizeof(struct socket_info),
749 (__compar_fn_t) socket_info_compare);
751 output_sockets_list(socket_infos, cs);
754 assert(cs == 0 || socket_infos);
755 for (s = socket_infos; s < socket_infos + cs; s++) {
758 if (s->own_triggered)
759 strv_free(s->triggered);
766 static int compare_unit_file_list(const void *a, const void *b) {
768 const UnitFileList *u = a, *v = b;
770 d1 = strrchr(u->path, '.');
771 d2 = strrchr(v->path, '.');
776 r = strcasecmp(d1, d2);
781 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
784 static bool output_show_unit_file(const UnitFileList *u) {
787 return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
790 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
791 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
792 const UnitFileList *u;
794 max_id_len = sizeof("UNIT FILE")-1;
795 state_cols = sizeof("STATE")-1;
796 for (u = units; u < units + c; u++) {
797 if (!output_show_unit_file(u))
800 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
801 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
806 id_cols = MIN(max_id_len, 25u);
807 basic_cols = 1 + id_cols + state_cols;
808 if (basic_cols < (unsigned) columns())
809 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
811 id_cols = max_id_len;
814 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
816 for (u = units; u < units + c; u++) {
817 _cleanup_free_ char *e = NULL;
818 const char *on, *off;
821 if (!output_show_unit_file(u))
826 if (u->state == UNIT_FILE_MASKED ||
827 u->state == UNIT_FILE_MASKED_RUNTIME ||
828 u->state == UNIT_FILE_DISABLED ||
829 u->state == UNIT_FILE_INVALID) {
830 on = ansi_highlight_red(true);
831 off = ansi_highlight_red(false);
832 } else if (u->state == UNIT_FILE_ENABLED) {
833 on = ansi_highlight_green(true);
834 off = ansi_highlight_green(false);
838 id = path_get_file_name(u->path);
840 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
842 printf("%-*s %s%-*s%s\n",
844 on, state_cols, unit_file_state_to_string(u->state), off);
848 printf("\n%u unit files listed.\n", n_shown);
851 static int list_unit_files(DBusConnection *bus, char **args) {
852 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
853 _cleanup_free_ UnitFileList *units = NULL;
854 DBusMessageIter iter, sub, sub2;
855 unsigned c = 0, n_units = 0;
858 pager_open_if_enabled();
865 h = hashmap_new(string_hash_func, string_compare_func);
869 r = unit_file_get_list(arg_scope, arg_root, h);
871 unit_file_list_free(h);
872 log_error("Failed to get unit file list: %s", strerror(-r));
876 n_units = hashmap_size(h);
877 units = new(UnitFileList, n_units);
879 unit_file_list_free(h);
883 HASHMAP_FOREACH(u, h, i) {
884 memcpy(units + c++, u, sizeof(UnitFileList));
890 r = bus_method_call_with_reply(
892 "org.freedesktop.systemd1",
893 "/org/freedesktop/systemd1",
894 "org.freedesktop.systemd1.Manager",
902 if (!dbus_message_iter_init(reply, &iter) ||
903 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
904 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
905 log_error("Failed to parse reply.");
909 dbus_message_iter_recurse(&iter, &sub);
911 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
915 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
920 n_units = MAX(2*c, 16u);
921 w = realloc(units, sizeof(struct UnitFileList) * n_units);
930 dbus_message_iter_recurse(&sub, &sub2);
932 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
933 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
934 log_error("Failed to parse reply.");
938 u->state = unit_file_state_from_string(state);
940 dbus_message_iter_next(&sub);
946 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
947 output_unit_file_list(units, c);
953 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
955 _cleanup_free_ char *n = NULL;
957 size_t max_len = MAX(columns(),20u);
959 for (i = level - 1; i >= 0; i--) {
961 if(len > max_len - 3 && !arg_full) {
962 printf("%s...\n",max_len % 2 ? "" : " ");
965 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
968 if(len > max_len - 3 && !arg_full) {
969 printf("%s...\n",max_len % 2 ? "" : " ");
972 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
975 printf("%s\n", name);
979 n = ellipsize(name, max_len-len, 100);
987 static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
988 static const char *dependencies[] = {
989 [DEPENDENCY_FORWARD] = "Requires\0"
990 "RequiresOverridable\0"
992 "RequisiteOverridable\0"
994 [DEPENDENCY_REVERSE] = "RequiredBy\0"
995 "RequiredByOverridable\0"
998 [DEPENDENCY_AFTER] = "After\0",
999 [DEPENDENCY_BEFORE] = "Before\0",
1002 _cleanup_free_ char *path;
1003 const char *interface = "org.freedesktop.systemd1.Unit";
1005 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1006 DBusMessageIter iter, sub, sub2, sub3;
1015 path = unit_dbus_path_from_name(name);
1021 r = bus_method_call_with_reply(
1023 "org.freedesktop.systemd1",
1025 "org.freedesktop.DBus.Properties",
1029 DBUS_TYPE_STRING, &interface,
1034 if (!dbus_message_iter_init(reply, &iter) ||
1035 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1036 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
1037 log_error("Failed to parse reply.");
1042 dbus_message_iter_recurse(&iter, &sub);
1044 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1047 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
1048 dbus_message_iter_recurse(&sub, &sub2);
1050 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
1051 log_error("Failed to parse reply.");
1056 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
1057 log_error("Failed to parse reply.");
1062 dbus_message_iter_recurse(&sub2, &sub3);
1063 dbus_message_iter_next(&sub);
1065 assert(arg_dependency < ELEMENTSOF(dependencies));
1066 if (!nulstr_contains(dependencies[arg_dependency], prop))
1069 if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
1070 if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
1071 DBusMessageIter sub4;
1072 dbus_message_iter_recurse(&sub3, &sub4);
1074 while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
1077 assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
1078 dbus_message_iter_get_basic(&sub4, &s);
1080 r = strv_extend(&ret, s);
1086 dbus_message_iter_next(&sub4);
1099 static int list_dependencies_compare(const void *_a, const void *_b) {
1100 const char **a = (const char**) _a, **b = (const char**) _b;
1101 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1103 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1105 return strcasecmp(*a, *b);
1108 static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char **units, unsigned int branches) {
1109 _cleanup_strv_free_ char **deps = NULL, **u;
1113 u = strv_append(units, name);
1117 r = list_dependencies_get_dependencies(bus, name, &deps);
1121 qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1123 STRV_FOREACH(c, deps) {
1124 if (strv_contains(u, *c)) {
1125 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1131 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1135 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1136 r = list_dependencies_one(bus, *c, level + 1, u, (branches << 1) | (c[1] == NULL ? 0 : 1));
1145 static int list_dependencies(DBusConnection *bus, char **args) {
1146 _cleanup_free_ char *unit = NULL;
1152 unit = unit_name_mangle(args[1]);
1157 u = SPECIAL_DEFAULT_TARGET;
1159 pager_open_if_enabled();
1163 return list_dependencies_one(bus, u, 0, NULL, 0);
1168 char *name, *type, *state;
1171 static void list_jobs_print(struct job_info* jobs, size_t n) {
1174 const char *on, *off;
1175 bool shorten = false;
1177 assert(n == 0 || jobs);
1180 on = ansi_highlight_green(true);
1181 off = ansi_highlight_green(false);
1183 printf("%sNo jobs running.%s\n", on, off);
1187 pager_open_if_enabled();
1190 /* JOB UNIT TYPE STATE */
1191 unsigned l0 = 3, l1 = 4, l2 = 4, l3 = 5;
1193 for (i = 0, j = jobs; i < n; i++, j++) {
1194 assert(j->name && j->type && j->state);
1195 l0 = MAX(l0, DECIMAL_STR_WIDTH(j->id));
1196 l1 = MAX(l1, strlen(j->name));
1197 l2 = MAX(l2, strlen(j->type));
1198 l3 = MAX(l3, strlen(j->state));
1201 if (!arg_full && l0 + 1 + l1 + l2 + 1 + l3 > columns()) {
1202 l1 = MAX(33u, columns() - l0 - l2 - l3 - 3);
1207 printf("%*s %-*s %-*s %-*s\n",
1213 for (i = 0, j = jobs; i < n; i++, j++) {
1214 _cleanup_free_ char *e = NULL;
1216 if (streq(j->state, "running")) {
1217 on = ansi_highlight(true);
1218 off = ansi_highlight(false);
1222 e = shorten ? ellipsize(j->name, l1, 33) : NULL;
1223 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
1225 on, l1, e ? e : j->name, off,
1227 on, l3, j->state, off);
1231 on = ansi_highlight(true);
1232 off = ansi_highlight(false);
1235 printf("\n%s%zu jobs listed%s.\n", on, n, off);
1238 static int list_jobs(DBusConnection *bus, char **args) {
1239 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1240 DBusMessageIter iter, sub, sub2;
1242 struct job_info *jobs = NULL;
1243 size_t size = 0, used = 0;
1245 r = bus_method_call_with_reply(
1247 "org.freedesktop.systemd1",
1248 "/org/freedesktop/systemd1",
1249 "org.freedesktop.systemd1.Manager",
1257 if (!dbus_message_iter_init(reply, &iter) ||
1258 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1259 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1260 log_error("Failed to parse reply.");
1264 dbus_message_iter_recurse(&iter, &sub);
1266 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1267 const char *name, *type, *state, *job_path, *unit_path;
1270 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1271 log_error("Failed to parse reply.");
1275 dbus_message_iter_recurse(&sub, &sub2);
1277 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1278 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1279 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1280 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1281 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1282 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1283 log_error("Failed to parse reply.");
1288 if (!greedy_realloc((void**) &jobs, &size,
1289 sizeof(struct job_info) * (used + 1))) {
1294 jobs[used++] = (struct job_info) { id,
1298 if (!jobs[used-1].name || !jobs[used-1].type || !jobs[used-1].state) {
1303 dbus_message_iter_next(&sub);
1306 list_jobs_print(jobs, used);
1310 free(jobs[used].name);
1311 free(jobs[used].type);
1312 free(jobs[used].state);
1319 static int load_unit(DBusConnection *bus, char **args) {
1324 STRV_FOREACH(name, args+1) {
1325 _cleanup_free_ char *n = NULL;
1328 n = unit_name_mangle(*name);
1332 r = bus_method_call_with_reply(
1334 "org.freedesktop.systemd1",
1335 "/org/freedesktop/systemd1",
1336 "org.freedesktop.systemd1.Manager",
1340 DBUS_TYPE_STRING, &n,
1349 static int cancel_job(DBusConnection *bus, char **args) {
1354 if (strv_length(args) <= 1)
1355 return daemon_reload(bus, args);
1357 STRV_FOREACH(name, args+1) {
1361 r = safe_atou32(*name, &id);
1363 log_error("Failed to parse job id: %s", strerror(-r));
1367 r = bus_method_call_with_reply(
1369 "org.freedesktop.systemd1",
1370 "/org/freedesktop/systemd1",
1371 "org.freedesktop.systemd1.Manager",
1375 DBUS_TYPE_UINT32, &id,
1384 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1385 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1386 dbus_bool_t b = FALSE;
1387 DBusMessageIter iter, sub;
1389 *interface = "org.freedesktop.systemd1.Unit",
1390 *property = "NeedDaemonReload",
1392 _cleanup_free_ char *n = NULL;
1395 /* We ignore all errors here, since this is used to show a warning only */
1397 n = unit_name_mangle(unit);
1401 r = bus_method_call_with_reply(
1403 "org.freedesktop.systemd1",
1404 "/org/freedesktop/systemd1",
1405 "org.freedesktop.systemd1.Manager",
1409 DBUS_TYPE_STRING, &n,
1414 if (!dbus_message_get_args(reply, NULL,
1415 DBUS_TYPE_OBJECT_PATH, &path,
1419 dbus_message_unref(reply);
1422 r = bus_method_call_with_reply(
1424 "org.freedesktop.systemd1",
1426 "org.freedesktop.DBus.Properties",
1430 DBUS_TYPE_STRING, &interface,
1431 DBUS_TYPE_STRING, &property,
1436 if (!dbus_message_iter_init(reply, &iter) ||
1437 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1440 dbus_message_iter_recurse(&iter, &sub);
1441 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1444 dbus_message_iter_get_basic(&sub, &b);
1448 typedef struct WaitData {
1455 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1456 _cleanup_dbus_error_free_ DBusError error;
1459 dbus_error_init(&error);
1465 log_debug("Got D-Bus request: %s.%s() on %s",
1466 dbus_message_get_interface(message),
1467 dbus_message_get_member(message),
1468 dbus_message_get_path(message));
1470 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1471 log_error("Warning! D-Bus connection terminated.");
1472 dbus_connection_close(connection);
1474 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1476 const char *path, *result, *unit;
1478 if (dbus_message_get_args(message, &error,
1479 DBUS_TYPE_UINT32, &id,
1480 DBUS_TYPE_OBJECT_PATH, &path,
1481 DBUS_TYPE_STRING, &unit,
1482 DBUS_TYPE_STRING, &result,
1483 DBUS_TYPE_INVALID)) {
1485 free(set_remove(d->set, (char*) path));
1487 if (!isempty(result))
1488 d->result = strdup(result);
1491 d->name = strdup(unit);
1493 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1496 dbus_error_free(&error);
1497 if (dbus_message_get_args(message, &error,
1498 DBUS_TYPE_UINT32, &id,
1499 DBUS_TYPE_OBJECT_PATH, &path,
1500 DBUS_TYPE_STRING, &result,
1501 DBUS_TYPE_INVALID)) {
1502 /* Compatibility with older systemd versions <
1503 * 183 during upgrades. This should be dropped
1505 free(set_remove(d->set, (char*) path));
1508 d->result = strdup(result);
1510 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1514 log_error("Failed to parse message: %s", bus_error_message(&error));
1517 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1520 static int enable_wait_for_jobs(DBusConnection *bus) {
1528 dbus_error_init(&error);
1529 dbus_bus_add_match(bus,
1531 "sender='org.freedesktop.systemd1',"
1532 "interface='org.freedesktop.systemd1.Manager',"
1533 "member='JobRemoved',"
1534 "path='/org/freedesktop/systemd1'",
1537 if (dbus_error_is_set(&error)) {
1538 log_error("Failed to add match: %s", bus_error_message(&error));
1539 dbus_error_free(&error);
1543 /* This is slightly dirty, since we don't undo the match registrations. */
1547 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1549 WaitData d = { .set = s };
1554 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1557 while (!set_isempty(s)) {
1559 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1560 log_error("Disconnected from bus.");
1561 return -ECONNREFUSED;
1568 if (streq(d.result, "timeout"))
1569 log_error("Job for %s timed out.", strna(d.name));
1570 else if (streq(d.result, "canceled"))
1571 log_error("Job for %s canceled.", strna(d.name));
1572 else if (streq(d.result, "dependency"))
1573 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1574 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1575 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1578 if (streq_ptr(d.result, "timeout"))
1580 else if (streq_ptr(d.result, "canceled"))
1582 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1593 dbus_connection_remove_filter(bus, wait_filter, &d);
1597 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1598 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1599 _cleanup_free_ char *n = NULL;
1600 DBusMessageIter iter, sub;
1602 *interface = "org.freedesktop.systemd1.Unit",
1603 *property = "ActiveState";
1604 const char *state, *path;
1610 dbus_error_init(&error);
1612 n = unit_name_mangle(name);
1616 r = bus_method_call_with_reply (
1618 "org.freedesktop.systemd1",
1619 "/org/freedesktop/systemd1",
1620 "org.freedesktop.systemd1.Manager",
1624 DBUS_TYPE_STRING, &n,
1627 dbus_error_free(&error);
1634 if (!dbus_message_get_args(reply, NULL,
1635 DBUS_TYPE_OBJECT_PATH, &path,
1636 DBUS_TYPE_INVALID)) {
1637 log_error("Failed to parse reply.");
1641 dbus_message_unref(reply);
1644 r = bus_method_call_with_reply(
1646 "org.freedesktop.systemd1",
1648 "org.freedesktop.DBus.Properties",
1652 DBUS_TYPE_STRING, &interface,
1653 DBUS_TYPE_STRING, &property,
1661 if (!dbus_message_iter_init(reply, &iter) ||
1662 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1663 log_error("Failed to parse reply.");
1667 dbus_message_iter_recurse(&iter, &sub);
1669 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1670 log_error("Failed to parse reply.");
1674 dbus_message_iter_get_basic(&sub, &state);
1679 return strv_find(check_states, state) ? 1 : 0;
1682 static void check_triggering_units(
1683 DBusConnection *bus,
1684 const char *unit_name) {
1686 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1687 DBusMessageIter iter, sub;
1688 const char *interface = "org.freedesktop.systemd1.Unit",
1689 *load_state_property = "LoadState",
1690 *triggered_by_property = "TriggeredBy",
1692 _cleanup_free_ char *unit_path = NULL, *n = NULL;
1693 bool print_warning_label = true;
1696 n = unit_name_mangle(unit_name);
1702 unit_path = unit_dbus_path_from_name(n);
1708 r = bus_method_call_with_reply(
1710 "org.freedesktop.systemd1",
1712 "org.freedesktop.DBus.Properties",
1716 DBUS_TYPE_STRING, &interface,
1717 DBUS_TYPE_STRING, &load_state_property,
1722 if (!dbus_message_iter_init(reply, &iter) ||
1723 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1724 log_error("Failed to parse reply.");
1728 dbus_message_iter_recurse(&iter, &sub);
1730 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1731 log_error("Failed to parse reply.");
1735 dbus_message_iter_get_basic(&sub, &state);
1737 if (streq(state, "masked"))
1740 dbus_message_unref(reply);
1743 r = bus_method_call_with_reply(
1745 "org.freedesktop.systemd1",
1747 "org.freedesktop.DBus.Properties",
1751 DBUS_TYPE_STRING, &interface,
1752 DBUS_TYPE_STRING, &triggered_by_property,
1757 if (!dbus_message_iter_init(reply, &iter) ||
1758 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1759 log_error("Failed to parse reply.");
1763 dbus_message_iter_recurse(&iter, &sub);
1764 dbus_message_iter_recurse(&sub, &iter);
1767 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1768 const char * const check_states[] = {
1773 const char *service_trigger;
1775 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1776 log_error("Failed to parse reply.");
1780 dbus_message_iter_get_basic(&sub, &service_trigger);
1782 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1786 if (print_warning_label) {
1787 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1788 print_warning_label = false;
1791 log_warning(" %s", service_trigger);
1794 dbus_message_iter_next(&sub);
1798 static int start_unit_one(
1799 DBusConnection *bus,
1806 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1807 _cleanup_free_ char *n;
1816 n = unit_name_mangle(name);
1820 r = bus_method_call_with_reply(
1822 "org.freedesktop.systemd1",
1823 "/org/freedesktop/systemd1",
1824 "org.freedesktop.systemd1.Manager",
1828 DBUS_TYPE_STRING, &n,
1829 DBUS_TYPE_STRING, &mode,
1832 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1833 /* There's always a fallback possible for
1834 * legacy actions. */
1837 log_error("Failed to issue method call: %s", bus_error_message(error));
1842 if (!dbus_message_get_args(reply, error,
1843 DBUS_TYPE_OBJECT_PATH, &path,
1844 DBUS_TYPE_INVALID)) {
1845 log_error("Failed to parse reply: %s", bus_error_message(error));
1849 if (need_daemon_reload(bus, n))
1850 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1851 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1860 r = set_consume(s, p);
1862 log_error("Failed to add path to set.");
1870 static const struct {
1874 } action_table[_ACTION_MAX] = {
1875 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
1876 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
1877 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
1878 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
1879 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
1880 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
1881 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
1882 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
1883 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
1884 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
1885 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
1886 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
1887 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
1888 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
1889 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1892 static enum action verb_to_action(const char *verb) {
1895 for (i = ACTION_INVALID; i < _ACTION_MAX; i++)
1896 if (action_table[i].verb && streq(verb, action_table[i].verb))
1898 return ACTION_INVALID;
1901 static int start_unit(DBusConnection *bus, char **args) {
1904 const char *method, *mode, *one_name;
1905 _cleanup_set_free_free_ Set *s = NULL;
1906 _cleanup_dbus_error_free_ DBusError error;
1909 dbus_error_init(&error);
1913 ask_password_agent_open_if_enabled();
1915 if (arg_action == ACTION_SYSTEMCTL) {
1918 streq(args[0], "stop") ||
1919 streq(args[0], "condstop") ? "StopUnit" :
1920 streq(args[0], "reload") ? "ReloadUnit" :
1921 streq(args[0], "restart") ? "RestartUnit" :
1923 streq(args[0], "try-restart") ||
1924 streq(args[0], "condrestart") ? "TryRestartUnit" :
1926 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1928 streq(args[0], "reload-or-try-restart") ||
1929 streq(args[0], "condreload") ||
1931 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1933 action = verb_to_action(args[0]);
1935 mode = streq(args[0], "isolate") ? "isolate" :
1936 action_table[action].mode ?: arg_job_mode;
1938 one_name = action_table[action].target;
1941 assert(arg_action < ELEMENTSOF(action_table));
1942 assert(action_table[arg_action].target);
1944 method = "StartUnit";
1946 mode = action_table[arg_action].mode;
1947 one_name = action_table[arg_action].target;
1950 if (!arg_no_block) {
1951 ret = enable_wait_for_jobs(bus);
1953 log_error("Could not watch jobs: %s", strerror(-ret));
1957 s = set_new(string_hash_func, string_compare_func);
1963 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1965 ret = translate_bus_error_to_exit_status(ret, &error);
1967 STRV_FOREACH(name, args+1) {
1968 r = start_unit_one(bus, method, *name, mode, &error, s);
1970 ret = translate_bus_error_to_exit_status(r, &error);
1971 dbus_error_free(&error);
1976 if (!arg_no_block) {
1977 r = wait_for_jobs(bus, s);
1981 /* When stopping units, warn if they can still be triggered by
1982 * another active unit (socket, path, timer) */
1983 if (!arg_quiet && streq(method, "StopUnit")) {
1985 check_triggering_units(bus, one_name);
1987 STRV_FOREACH(name, args+1)
1988 check_triggering_units(bus, *name);
1995 /* Ask systemd-logind, which might grant access to unprivileged users
1996 * through PolicyKit */
1997 static int reboot_with_logind(DBusConnection *bus, enum action a) {
2000 dbus_bool_t interactive = true;
2005 polkit_agent_open_if_enabled();
2013 case ACTION_POWEROFF:
2014 method = "PowerOff";
2017 case ACTION_SUSPEND:
2021 case ACTION_HIBERNATE:
2022 method = "Hibernate";
2025 case ACTION_HYBRID_SLEEP:
2026 method = "HybridSleep";
2033 return bus_method_call_with_reply(
2035 "org.freedesktop.login1",
2036 "/org/freedesktop/login1",
2037 "org.freedesktop.login1.Manager",
2041 DBUS_TYPE_BOOLEAN, &interactive,
2048 static int check_inhibitors(DBusConnection *bus, enum action a) {
2050 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2051 DBusMessageIter iter, sub, sub2;
2054 _cleanup_strv_free_ char **sessions = NULL;
2060 if (arg_ignore_inhibitors || arg_force > 0)
2072 r = bus_method_call_with_reply(
2074 "org.freedesktop.login1",
2075 "/org/freedesktop/login1",
2076 "org.freedesktop.login1.Manager",
2082 /* If logind is not around, then there are no inhibitors... */
2085 if (!dbus_message_iter_init(reply, &iter) ||
2086 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2087 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
2088 log_error("Failed to parse reply.");
2092 dbus_message_iter_recurse(&iter, &sub);
2093 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2094 const char *what, *who, *why, *mode;
2096 _cleanup_strv_free_ char **sv = NULL;
2097 _cleanup_free_ char *comm = NULL, *user = NULL;
2099 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
2100 log_error("Failed to parse reply.");
2104 dbus_message_iter_recurse(&sub, &sub2);
2106 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
2107 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
2108 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
2109 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
2110 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
2111 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
2112 log_error("Failed to parse reply.");
2116 if (!streq(mode, "block"))
2119 sv = strv_split(what, ":");
2123 if (!strv_contains(sv,
2125 a == ACTION_POWEROFF ||
2126 a == ACTION_REBOOT ||
2127 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2130 get_process_comm(pid, &comm);
2131 user = uid_to_name(uid);
2132 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2133 who, (unsigned long) pid, strna(comm), strna(user), why);
2137 dbus_message_iter_next(&sub);
2140 dbus_message_iter_recurse(&iter, &sub);
2142 /* Check for current sessions */
2143 sd_get_sessions(&sessions);
2144 STRV_FOREACH(s, sessions) {
2146 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2148 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2151 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2154 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2157 sd_session_get_tty(*s, &tty);
2158 sd_session_get_seat(*s, &seat);
2159 sd_session_get_service(*s, &service);
2160 user = uid_to_name(uid);
2162 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2169 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2170 action_table[a].verb);
2178 static int start_special(DBusConnection *bus, char **args) {
2184 a = verb_to_action(args[0]);
2186 r = check_inhibitors(bus, a);
2190 if (arg_force >= 2 && geteuid() != 0) {
2191 log_error("Must be root.");
2195 if (arg_force >= 2 &&
2196 (a == ACTION_HALT ||
2197 a == ACTION_POWEROFF ||
2198 a == ACTION_REBOOT))
2201 if (arg_force >= 1 &&
2202 (a == ACTION_HALT ||
2203 a == ACTION_POWEROFF ||
2204 a == ACTION_REBOOT ||
2205 a == ACTION_KEXEC ||
2207 return daemon_reload(bus, args);
2209 /* first try logind, to allow authentication with polkit */
2210 if (geteuid() != 0 &&
2211 (a == ACTION_POWEROFF ||
2212 a == ACTION_REBOOT ||
2213 a == ACTION_SUSPEND ||
2214 a == ACTION_HIBERNATE ||
2215 a == ACTION_HYBRID_SLEEP)) {
2216 r = reboot_with_logind(bus, a);
2221 r = start_unit(bus, args);
2222 if (r == EXIT_SUCCESS)
2228 static int check_unit_active(DBusConnection *bus, char **args) {
2229 const char * const check_states[] = {
2236 int r = 3; /* According to LSB: "program is not running" */
2241 STRV_FOREACH(name, args+1) {
2244 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2254 static int check_unit_failed(DBusConnection *bus, char **args) {
2255 const char * const check_states[] = {
2266 STRV_FOREACH(name, args+1) {
2269 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2279 static int kill_unit(DBusConnection *bus, char **args) {
2287 arg_kill_who = "all";
2289 STRV_FOREACH(name, args+1) {
2290 _cleanup_free_ char *n = NULL;
2292 n = unit_name_mangle(*name);
2296 r = bus_method_call_with_reply(
2298 "org.freedesktop.systemd1",
2299 "/org/freedesktop/systemd1",
2300 "org.freedesktop.systemd1.Manager",
2304 DBUS_TYPE_STRING, &n,
2305 DBUS_TYPE_STRING, &arg_kill_who,
2306 DBUS_TYPE_INT32, &arg_signal,
2314 static int set_cgroup(DBusConnection *bus, char **args) {
2315 _cleanup_free_ char *n = NULL;
2316 const char *method, *runtime;
2324 streq(args[0], "set-cgroup") ? "SetUnitControlGroup" :
2325 streq(args[0], "unset-cgroup") ? "UnsetUnitControlGroup"
2326 : "UnsetUnitControlGroupAttribute";
2328 runtime = arg_runtime ? "runtime" : "persistent";
2330 n = unit_name_mangle(args[1]);
2334 STRV_FOREACH(argument, args + 2) {
2336 r = bus_method_call_with_reply(
2338 "org.freedesktop.systemd1",
2339 "/org/freedesktop/systemd1",
2340 "org.freedesktop.systemd1.Manager",
2344 DBUS_TYPE_STRING, &n,
2345 DBUS_TYPE_STRING, argument,
2346 DBUS_TYPE_STRING, &runtime,
2355 static int set_cgroup_attr(DBusConnection *bus, char **args) {
2356 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2358 DBusMessageIter iter;
2359 _cleanup_free_ char *n = NULL;
2360 const char *runtime;
2366 dbus_error_init(&error);
2368 runtime = arg_runtime ? "runtime" : "persistent";
2370 n = unit_name_mangle(args[1]);
2374 m = dbus_message_new_method_call(
2375 "org.freedesktop.systemd1",
2376 "/org/freedesktop/systemd1",
2377 "org.freedesktop.systemd1.Manager",
2378 "SetUnitControlGroupAttribute");
2382 dbus_message_iter_init_append(m, &iter);
2383 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2384 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[2]))
2387 r = bus_append_strv_iter(&iter, args + 3);
2391 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2394 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2396 log_error("Failed to issue method call: %s", bus_error_message(&error));
2397 dbus_error_free(&error);
2404 static int get_cgroup_attr(DBusConnection *bus, char **args) {
2405 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2406 _cleanup_free_ char *n = NULL;
2413 n = unit_name_mangle(args[1]);
2417 STRV_FOREACH(argument, args + 2) {
2418 _cleanup_strv_free_ char **list = NULL;
2419 DBusMessageIter iter;
2422 r = bus_method_call_with_reply(
2424 "org.freedesktop.systemd1",
2425 "/org/freedesktop/systemd1",
2426 "org.freedesktop.systemd1.Manager",
2427 "GetUnitControlGroupAttribute",
2430 DBUS_TYPE_STRING, &n,
2431 DBUS_TYPE_STRING, argument,
2436 if (!dbus_message_iter_init(reply, &iter)) {
2437 log_error("Failed to initialize iterator.");
2441 r = bus_parse_strv_iter(&iter, &list);
2443 log_error("Failed to parse value list.");
2447 STRV_FOREACH(a, list) {
2448 if (endswith(*a, "\n"))
2458 typedef struct ExecStatusInfo {
2466 usec_t start_timestamp;
2467 usec_t exit_timestamp;
2472 LIST_FIELDS(struct ExecStatusInfo, exec);
2475 static void exec_status_info_free(ExecStatusInfo *i) {
2484 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2485 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2486 DBusMessageIter sub2, sub3;
2490 int32_t code, status;
2496 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2499 dbus_message_iter_recurse(sub, &sub2);
2501 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2504 i->path = strdup(path);
2508 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2509 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2513 dbus_message_iter_recurse(&sub2, &sub3);
2514 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2515 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2516 dbus_message_iter_next(&sub3);
2520 i->argv = new0(char*, n+1);
2525 dbus_message_iter_recurse(&sub2, &sub3);
2526 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2529 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2530 dbus_message_iter_get_basic(&sub3, &s);
2531 dbus_message_iter_next(&sub3);
2533 i->argv[n] = strdup(s);
2540 if (!dbus_message_iter_next(&sub2) ||
2541 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2542 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2543 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2544 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2545 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2546 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2547 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2548 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2552 i->start_timestamp = (usec_t) start_timestamp;
2553 i->exit_timestamp = (usec_t) exit_timestamp;
2554 i->pid = (pid_t) pid;
2561 typedef struct UnitStatusInfo {
2563 const char *load_state;
2564 const char *active_state;
2565 const char *sub_state;
2566 const char *unit_file_state;
2568 const char *description;
2569 const char *following;
2571 char **documentation;
2573 const char *fragment_path;
2574 const char *source_path;
2575 const char *default_control_group;
2577 char **dropin_paths;
2579 const char *load_error;
2582 usec_t inactive_exit_timestamp;
2583 usec_t inactive_exit_timestamp_monotonic;
2584 usec_t active_enter_timestamp;
2585 usec_t active_exit_timestamp;
2586 usec_t inactive_enter_timestamp;
2588 bool need_daemon_reload;
2593 const char *status_text;
2596 usec_t start_timestamp;
2597 usec_t exit_timestamp;
2599 int exit_code, exit_status;
2601 usec_t condition_timestamp;
2602 bool condition_result;
2605 unsigned n_accepted;
2606 unsigned n_connections;
2609 /* Pairs of type, path */
2613 const char *sysfs_path;
2615 /* Mount, Automount */
2621 LIST_HEAD(ExecStatusInfo, exec);
2624 static void print_status_info(UnitStatusInfo *i) {
2626 const char *on, *off, *ss;
2628 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2629 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2632 arg_all * OUTPUT_SHOW_ALL |
2633 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2634 on_tty() * OUTPUT_COLOR |
2635 !arg_quiet * OUTPUT_WARN_CUTOFF |
2636 arg_full * OUTPUT_FULL_WIDTH;
2637 int maxlen = 8; /* a value that'll suffice most of the time */
2642 STRV_FOREACH_PAIR(t, t2, i->listen)
2643 maxlen = MAX(maxlen, (int)(sizeof("Listen") - 1 + strlen(*t)));
2645 maxlen = MAX(maxlen, (int)sizeof("Accept") - 1);
2646 if (i->main_pid > 0)
2647 maxlen = MAX(maxlen, (int)sizeof("Main PID") - 1);
2648 else if (i->control_pid > 0)
2649 maxlen = MAX(maxlen, (int)sizeof("Control") - 1);
2651 /* This shows pretty information about a unit. See
2652 * print_property() for a low-level property printer */
2654 printf("%s", strna(i->id));
2656 if (i->description && !streq_ptr(i->id, i->description))
2657 printf(" - %s", i->description);
2662 printf(" %*s: unit currently follows state of %s\n", maxlen, "Follow", i->following);
2664 if (streq_ptr(i->load_state, "error")) {
2665 on = ansi_highlight_red(true);
2666 off = ansi_highlight_red(false);
2670 path = i->source_path ? i->source_path : i->fragment_path;
2673 printf(" %*s: %s%s%s (Reason: %s)\n",
2674 maxlen, "Loaded", on, strna(i->load_state), off, i->load_error);
2675 else if (path && i->unit_file_state)
2676 printf(" %*s: %s%s%s (%s; %s)\n",
2677 maxlen, "Loaded", on, strna(i->load_state), off, path, i->unit_file_state);
2679 printf(" %*s: %s%s%s (%s)\n",
2680 maxlen, "Loaded", on, strna(i->load_state), off, path);
2682 printf(" %*s: %s%s%s\n",
2683 maxlen, "Loaded", on, strna(i->load_state), off);
2685 if (!strv_isempty(i->dropin_paths)) {
2690 STRV_FOREACH(dropin, i->dropin_paths) {
2691 if (! dir || last) {
2692 printf(" %*s ", maxlen, dir ? "" : "Drop-In:");
2696 if (path_get_parent(*dropin, &dir) < 0) {
2701 printf("%s\n %*s %s", dir, maxlen, "",
2702 draw_special_char(DRAW_TREE_RIGHT));
2705 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
2707 printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", ");
2713 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2715 if (streq_ptr(i->active_state, "failed")) {
2716 on = ansi_highlight_red(true);
2717 off = ansi_highlight_red(false);
2718 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2719 on = ansi_highlight_green(true);
2720 off = ansi_highlight_green(false);
2725 printf(" %*s: %s%s (%s)%s",
2726 maxlen, "Active", on, strna(i->active_state), ss, off);
2728 printf(" %*s: %s%s%s",
2729 maxlen, "Active", on, strna(i->active_state), off);
2731 if (!isempty(i->result) && !streq(i->result, "success"))
2732 printf(" (Result: %s)", i->result);
2734 timestamp = (streq_ptr(i->active_state, "active") ||
2735 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2736 (streq_ptr(i->active_state, "inactive") ||
2737 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2738 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2739 i->active_exit_timestamp;
2741 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2742 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2745 printf(" since %s; %s\n", s2, s1);
2747 printf(" since %s\n", s2);
2751 if (!i->condition_result && i->condition_timestamp > 0) {
2752 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2753 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2756 printf(" %*s start condition failed at %s; %s\n", maxlen, "", s2, s1);
2758 printf(" %*s start condition failed at %s\n", maxlen, "", s2);
2762 printf(" %*s: %s\n", maxlen, "Device", i->sysfs_path);
2764 printf(" %*s: %s\n", maxlen, "Where", i->where);
2766 printf(" %*s: %s\n", maxlen, "What", i->what);
2768 STRV_FOREACH(t, i->documentation)
2769 printf(" %*s %s\n", maxlen+1, t == i->documentation ? "Docs:" : "", *t);
2771 STRV_FOREACH_PAIR(t, t2, i->listen)
2772 printf(" %*s %s (%s)\n", maxlen+1, t == i->listen ? "Listen:" : "", *t2, *t);
2775 printf(" %*s: %u; Connected: %u\n", maxlen, "Accepted", i->n_accepted, i->n_connections);
2777 LIST_FOREACH(exec, p, i->exec) {
2778 _cleanup_free_ char *argv = NULL;
2781 /* Only show exited processes here */
2785 argv = strv_join(p->argv, " ");
2786 printf(" %*s: %u %s=%s ", maxlen, "Process", p->pid, p->name, strna(argv));
2788 good = is_clean_exit_lsb(p->code, p->status, NULL);
2790 on = ansi_highlight_red(true);
2791 off = ansi_highlight_red(false);
2795 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2797 if (p->code == CLD_EXITED) {
2800 printf("status=%i", p->status);
2802 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2807 printf("signal=%s", signal_to_string(p->status));
2809 printf(")%s\n", off);
2811 if (i->main_pid == p->pid &&
2812 i->start_timestamp == p->start_timestamp &&
2813 i->exit_timestamp == p->start_timestamp)
2814 /* Let's not show this twice */
2817 if (p->pid == i->control_pid)
2821 if (i->main_pid > 0 || i->control_pid > 0) {
2822 if (i->main_pid > 0) {
2823 printf(" %*s: %u", maxlen, "Main PID", (unsigned) i->main_pid);
2826 _cleanup_free_ char *comm = NULL;
2827 get_process_comm(i->main_pid, &comm);
2829 printf(" (%s)", comm);
2830 } else if (i->exit_code > 0) {
2831 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2833 if (i->exit_code == CLD_EXITED) {
2836 printf("status=%i", i->exit_status);
2838 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2843 printf("signal=%s", signal_to_string(i->exit_status));
2847 if (i->control_pid > 0)
2851 if (i->control_pid > 0) {
2852 _cleanup_free_ char *c = NULL;
2854 printf(" %*s: %u", i->main_pid ? 0 : maxlen, "Control", (unsigned) i->control_pid);
2856 get_process_comm(i->control_pid, &c);
2865 printf(" %*s: \"%s\"\n", maxlen, "Status", i->status_text);
2867 if (i->default_control_group &&
2868 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2871 printf(" %*s: %s\n", maxlen, "CGroup", i->default_control_group);
2873 if (arg_transport != TRANSPORT_SSH) {
2876 char prefix[maxlen + 4];
2877 memset(prefix, ' ', sizeof(prefix) - 1);
2878 prefix[sizeof(prefix) - 1] = '\0';
2881 if (c > sizeof(prefix) - 1)
2882 c -= sizeof(prefix) - 1;
2886 if (i->main_pid > 0)
2887 extra[k++] = i->main_pid;
2889 if (i->control_pid > 0)
2890 extra[k++] = i->control_pid;
2892 show_cgroup_and_extra_by_spec(i->default_control_group, prefix,
2893 c, false, extra, k, flags);
2897 if (i->id && arg_transport != TRANSPORT_SSH) {
2899 show_journal_by_unit(stdout,
2903 i->inactive_exit_timestamp_monotonic,
2907 arg_scope == UNIT_FILE_SYSTEM);
2910 if (i->need_daemon_reload)
2911 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2912 ansi_highlight_red(true),
2913 ansi_highlight_red(false),
2914 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2917 static void show_unit_help(UnitStatusInfo *i) {
2922 if (!i->documentation) {
2923 log_info("Documentation for %s not known.", i->id);
2927 STRV_FOREACH(p, i->documentation) {
2929 if (startswith(*p, "man:")) {
2932 _cleanup_free_ char *page = NULL, *section = NULL;
2933 const char *args[4] = { "man", NULL, NULL, NULL };
2938 if ((*p)[k-1] == ')')
2939 e = strrchr(*p, '(');
2942 page = strndup((*p) + 4, e - *p - 4);
2943 section = strndup(e + 1, *p + k - e - 2);
2944 if (!page || !section) {
2956 log_error("Failed to fork: %m");
2962 execvp(args[0], (char**) args);
2963 log_error("Failed to execute man: %m");
2964 _exit(EXIT_FAILURE);
2967 wait_for_terminate(pid, NULL);
2969 log_info("Can't show: %s", *p);
2973 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2979 switch (dbus_message_iter_get_arg_type(iter)) {
2981 case DBUS_TYPE_STRING: {
2984 dbus_message_iter_get_basic(iter, &s);
2987 if (streq(name, "Id"))
2989 else if (streq(name, "LoadState"))
2991 else if (streq(name, "ActiveState"))
2992 i->active_state = s;
2993 else if (streq(name, "SubState"))
2995 else if (streq(name, "Description"))
2997 else if (streq(name, "FragmentPath"))
2998 i->fragment_path = s;
2999 else if (streq(name, "SourcePath"))
3001 else if (streq(name, "DefaultControlGroup"))
3002 i->default_control_group = s;
3003 else if (streq(name, "StatusText"))
3005 else if (streq(name, "SysFSPath"))
3007 else if (streq(name, "Where"))
3009 else if (streq(name, "What"))
3011 else if (streq(name, "Following"))
3013 else if (streq(name, "UnitFileState"))
3014 i->unit_file_state = s;
3015 else if (streq(name, "Result"))
3022 case DBUS_TYPE_BOOLEAN: {
3025 dbus_message_iter_get_basic(iter, &b);
3027 if (streq(name, "Accept"))
3029 else if (streq(name, "NeedDaemonReload"))
3030 i->need_daemon_reload = b;
3031 else if (streq(name, "ConditionResult"))
3032 i->condition_result = b;
3037 case DBUS_TYPE_UINT32: {
3040 dbus_message_iter_get_basic(iter, &u);
3042 if (streq(name, "MainPID")) {
3044 i->main_pid = (pid_t) u;
3047 } else if (streq(name, "ControlPID"))
3048 i->control_pid = (pid_t) u;
3049 else if (streq(name, "ExecMainPID")) {
3051 i->main_pid = (pid_t) u;
3052 } else if (streq(name, "NAccepted"))
3054 else if (streq(name, "NConnections"))
3055 i->n_connections = u;
3060 case DBUS_TYPE_INT32: {
3063 dbus_message_iter_get_basic(iter, &j);
3065 if (streq(name, "ExecMainCode"))
3066 i->exit_code = (int) j;
3067 else if (streq(name, "ExecMainStatus"))
3068 i->exit_status = (int) j;
3073 case DBUS_TYPE_UINT64: {
3076 dbus_message_iter_get_basic(iter, &u);
3078 if (streq(name, "ExecMainStartTimestamp"))
3079 i->start_timestamp = (usec_t) u;
3080 else if (streq(name, "ExecMainExitTimestamp"))
3081 i->exit_timestamp = (usec_t) u;
3082 else if (streq(name, "ActiveEnterTimestamp"))
3083 i->active_enter_timestamp = (usec_t) u;
3084 else if (streq(name, "InactiveEnterTimestamp"))
3085 i->inactive_enter_timestamp = (usec_t) u;
3086 else if (streq(name, "InactiveExitTimestamp"))
3087 i->inactive_exit_timestamp = (usec_t) u;
3088 else if (streq(name, "InactiveExitTimestampMonotonic"))
3089 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3090 else if (streq(name, "ActiveExitTimestamp"))
3091 i->active_exit_timestamp = (usec_t) u;
3092 else if (streq(name, "ConditionTimestamp"))
3093 i->condition_timestamp = (usec_t) u;
3098 case DBUS_TYPE_ARRAY: {
3100 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3101 startswith(name, "Exec")) {
3102 DBusMessageIter sub;
3104 dbus_message_iter_recurse(iter, &sub);
3105 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3106 ExecStatusInfo *info;
3109 if (!(info = new0(ExecStatusInfo, 1)))
3112 if (!(info->name = strdup(name))) {
3117 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
3122 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
3124 dbus_message_iter_next(&sub);
3127 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3128 DBusMessageIter sub, sub2;
3130 dbus_message_iter_recurse(iter, &sub);
3131 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3132 const char *type, *path;
3134 dbus_message_iter_recurse(&sub, &sub2);
3136 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3137 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
3140 r = strv_extend(&i->listen, type);
3143 r = strv_extend(&i->listen, path);
3148 dbus_message_iter_next(&sub);
3153 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING && streq(name, "DropInPaths")) {
3154 int r = bus_parse_strv_iter(iter, &i->dropin_paths);
3158 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3159 streq(name, "Documentation")) {
3161 DBusMessageIter sub;
3163 dbus_message_iter_recurse(iter, &sub);
3164 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
3168 dbus_message_iter_get_basic(&sub, &s);
3170 r = strv_extend(&i->documentation, s);
3174 dbus_message_iter_next(&sub);
3181 case DBUS_TYPE_STRUCT: {
3183 if (streq(name, "LoadError")) {
3184 DBusMessageIter sub;
3185 const char *n, *message;
3188 dbus_message_iter_recurse(iter, &sub);
3190 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
3194 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
3198 if (!isempty(message))
3199 i->load_error = message;
3209 static int print_property(const char *name, DBusMessageIter *iter) {
3213 /* This is a low-level property printer, see
3214 * print_status_info() for the nicer output */
3216 if (arg_properties && !strv_find(arg_properties, name))
3219 switch (dbus_message_iter_get_arg_type(iter)) {
3221 case DBUS_TYPE_STRUCT: {
3222 DBusMessageIter sub;
3223 dbus_message_iter_recurse(iter, &sub);
3225 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
3228 dbus_message_iter_get_basic(&sub, &u);
3231 printf("%s=%u\n", name, (unsigned) u);
3233 printf("%s=\n", name);
3236 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
3239 dbus_message_iter_get_basic(&sub, &s);
3241 if (arg_all || s[0])
3242 printf("%s=%s\n", name, s);
3245 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
3246 const char *a = NULL, *b = NULL;
3248 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
3249 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
3251 if (arg_all || !isempty(a) || !isempty(b))
3252 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3260 case DBUS_TYPE_ARRAY:
3262 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
3263 DBusMessageIter sub, sub2;
3265 dbus_message_iter_recurse(iter, &sub);
3266 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3270 dbus_message_iter_recurse(&sub, &sub2);
3272 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3273 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3274 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3276 dbus_message_iter_next(&sub);
3281 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3282 DBusMessageIter sub, sub2;
3284 dbus_message_iter_recurse(iter, &sub);
3286 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3287 const char *type, *path;
3289 dbus_message_iter_recurse(&sub, &sub2);
3291 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3292 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3293 printf("%s=%s\n", type, path);
3295 dbus_message_iter_next(&sub);
3300 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3301 DBusMessageIter sub, sub2;
3303 dbus_message_iter_recurse(iter, &sub);
3304 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3305 const char *type, *path;
3307 dbus_message_iter_recurse(&sub, &sub2);
3309 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3310 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3311 printf("Listen%s=%s\n", type, path);
3313 dbus_message_iter_next(&sub);
3318 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3319 DBusMessageIter sub, sub2;
3321 dbus_message_iter_recurse(iter, &sub);
3322 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3324 uint64_t value, next_elapse;
3326 dbus_message_iter_recurse(&sub, &sub2);
3328 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3329 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3330 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3331 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3333 printf("%s={ value=%s ; next_elapse=%s }\n",
3335 format_timespan(timespan1, sizeof(timespan1), value, 0),
3336 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3339 dbus_message_iter_next(&sub);
3344 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
3345 DBusMessageIter sub, sub2;
3347 dbus_message_iter_recurse(iter, &sub);
3348 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3349 const char *controller, *attr, *value;
3351 dbus_message_iter_recurse(&sub, &sub2);
3353 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
3354 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
3355 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
3357 printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
3363 dbus_message_iter_next(&sub);
3368 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3369 DBusMessageIter sub;
3371 dbus_message_iter_recurse(iter, &sub);
3372 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3373 ExecStatusInfo info = {};
3375 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3376 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3377 _cleanup_free_ char *t;
3379 t = strv_join(info.argv, " ");
3381 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3385 yes_no(info.ignore),
3386 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3387 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3388 (unsigned) info. pid,
3389 sigchld_code_to_string(info.code),
3391 info.code == CLD_EXITED ? "" : "/",
3392 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3396 strv_free(info.argv);
3398 dbus_message_iter_next(&sub);
3407 if (generic_print_property(name, iter, arg_all) > 0)
3411 printf("%s=[unprintable]\n", name);
3416 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3417 _cleanup_free_ DBusMessage *reply = NULL;
3418 const char *interface = "";
3420 DBusMessageIter iter, sub, sub2, sub3;
3421 UnitStatusInfo info = {};
3427 r = bus_method_call_with_reply(
3429 "org.freedesktop.systemd1",
3431 "org.freedesktop.DBus.Properties",
3435 DBUS_TYPE_STRING, &interface,
3440 if (!dbus_message_iter_init(reply, &iter) ||
3441 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3442 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3443 log_error("Failed to parse reply.");
3447 dbus_message_iter_recurse(&iter, &sub);
3454 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3457 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3458 dbus_message_iter_recurse(&sub, &sub2);
3460 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3461 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3462 log_error("Failed to parse reply.");
3466 dbus_message_iter_recurse(&sub2, &sub3);
3468 if (show_properties)
3469 r = print_property(name, &sub3);
3471 r = status_property(name, &sub3, &info);
3473 log_error("Failed to parse reply.");
3477 dbus_message_iter_next(&sub);
3482 if (!show_properties) {
3483 if (streq(verb, "help"))
3484 show_unit_help(&info);
3486 print_status_info(&info);
3489 strv_free(info.documentation);
3490 strv_free(info.dropin_paths);
3491 strv_free(info.listen);
3493 if (!streq_ptr(info.active_state, "active") &&
3494 !streq_ptr(info.active_state, "reloading") &&
3495 streq(verb, "status"))
3496 /* According to LSB: "program not running" */
3499 while ((p = info.exec)) {
3500 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3501 exec_status_info_free(p);
3507 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3508 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3509 const char *path = NULL;
3510 _cleanup_dbus_error_free_ DBusError error;
3513 dbus_error_init(&error);
3515 r = bus_method_call_with_reply(
3517 "org.freedesktop.systemd1",
3518 "/org/freedesktop/systemd1",
3519 "org.freedesktop.systemd1.Manager",
3523 DBUS_TYPE_UINT32, &pid,
3528 if (!dbus_message_get_args(reply, &error,
3529 DBUS_TYPE_OBJECT_PATH, &path,
3530 DBUS_TYPE_INVALID)) {
3531 log_error("Failed to parse reply: %s", bus_error_message(&error));
3535 r = show_one(verb, bus, path, false, new_line);
3539 static int show_all(const char* verb, DBusConnection *bus, bool show_properties, bool *new_line) {
3540 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3541 _cleanup_free_ struct unit_info *unit_infos = NULL;
3543 const struct unit_info *u;
3546 r = get_unit_list(bus, &reply, &unit_infos, &c);
3550 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
3552 for (u = unit_infos; u < unit_infos + c; u++) {
3553 _cleanup_free_ char *p = NULL;
3555 if (!output_show_unit(u))
3558 p = unit_dbus_path_from_name(u->id);
3562 printf("%s -> '%s'\n", u->id, p);
3564 r = show_one(verb, bus, p, show_properties, new_line);
3572 static int show(DBusConnection *bus, char **args) {
3574 bool show_properties, show_status, new_line = false;
3580 show_properties = streq(args[0], "show");
3581 show_status = streq(args[0], "status");
3583 if (show_properties)
3584 pager_open_if_enabled();
3586 /* If no argument is specified inspect the manager itself */
3588 if (show_properties && strv_length(args) <= 1)
3589 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3591 if (show_status && strv_length(args) <= 1)
3592 return show_all(args[0], bus, false, &new_line);
3594 STRV_FOREACH(name, args+1) {
3597 if (safe_atou32(*name, &id) < 0) {
3598 _cleanup_free_ char *p = NULL, *n = NULL;
3599 /* Interpret as unit name */
3601 n = unit_name_mangle(*name);
3605 p = unit_dbus_path_from_name(n);
3609 r = show_one(args[0], bus, p, show_properties, &new_line);
3613 } else if (show_properties) {
3614 _cleanup_free_ char *p = NULL;
3616 /* Interpret as job id */
3617 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3620 r = show_one(args[0], bus, p, show_properties, &new_line);
3625 /* Interpret as PID */
3626 r = show_one_by_pid(args[0], bus, id, &new_line);
3635 static int dump(DBusConnection *bus, char **args) {
3636 _cleanup_free_ DBusMessage *reply = NULL;
3641 dbus_error_init(&error);
3643 pager_open_if_enabled();
3645 r = bus_method_call_with_reply(
3647 "org.freedesktop.systemd1",
3648 "/org/freedesktop/systemd1",
3649 "org.freedesktop.systemd1.Manager",
3657 if (!dbus_message_get_args(reply, &error,
3658 DBUS_TYPE_STRING, &text,
3659 DBUS_TYPE_INVALID)) {
3660 log_error("Failed to parse reply: %s", bus_error_message(&error));
3661 dbus_error_free(&error);
3665 fputs(text, stdout);
3669 static int snapshot(DBusConnection *bus, char **args) {
3670 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3673 dbus_bool_t cleanup = FALSE;
3674 DBusMessageIter iter, sub;
3677 *interface = "org.freedesktop.systemd1.Unit",
3679 _cleanup_free_ char *n = NULL;
3681 dbus_error_init(&error);
3683 if (strv_length(args) > 1)
3684 n = snapshot_name_mangle(args[1]);
3690 r = bus_method_call_with_reply (
3692 "org.freedesktop.systemd1",
3693 "/org/freedesktop/systemd1",
3694 "org.freedesktop.systemd1.Manager",
3698 DBUS_TYPE_STRING, &n,
3699 DBUS_TYPE_BOOLEAN, &cleanup,
3704 if (!dbus_message_get_args(reply, &error,
3705 DBUS_TYPE_OBJECT_PATH, &path,
3706 DBUS_TYPE_INVALID)) {
3707 log_error("Failed to parse reply: %s", bus_error_message(&error));
3708 dbus_error_free(&error);
3712 dbus_message_unref(reply);
3715 r = bus_method_call_with_reply (
3717 "org.freedesktop.systemd1",
3719 "org.freedesktop.DBus.Properties",
3723 DBUS_TYPE_STRING, &interface,
3724 DBUS_TYPE_STRING, &property,
3729 if (!dbus_message_iter_init(reply, &iter) ||
3730 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3731 log_error("Failed to parse reply.");
3735 dbus_message_iter_recurse(&iter, &sub);
3737 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3738 log_error("Failed to parse reply.");
3742 dbus_message_iter_get_basic(&sub, &id);
3750 static int delete_snapshot(DBusConnection *bus, char **args) {
3755 STRV_FOREACH(name, args+1) {
3756 _cleanup_free_ char *n = NULL;
3759 n = snapshot_name_mangle(*name);
3763 r = bus_method_call_with_reply(
3765 "org.freedesktop.systemd1",
3766 "/org/freedesktop/systemd1",
3767 "org.freedesktop.systemd1.Manager",
3771 DBUS_TYPE_STRING, &n,
3780 static int daemon_reload(DBusConnection *bus, char **args) {
3785 if (arg_action == ACTION_RELOAD)
3787 else if (arg_action == ACTION_REEXEC)
3788 method = "Reexecute";
3790 assert(arg_action == ACTION_SYSTEMCTL);
3793 streq(args[0], "clear-jobs") ||
3794 streq(args[0], "cancel") ? "ClearJobs" :
3795 streq(args[0], "daemon-reexec") ? "Reexecute" :
3796 streq(args[0], "reset-failed") ? "ResetFailed" :
3797 streq(args[0], "halt") ? "Halt" :
3798 streq(args[0], "poweroff") ? "PowerOff" :
3799 streq(args[0], "reboot") ? "Reboot" :
3800 streq(args[0], "kexec") ? "KExec" :
3801 streq(args[0], "exit") ? "Exit" :
3802 /* "daemon-reload" */ "Reload";
3805 r = bus_method_call_with_reply(
3807 "org.freedesktop.systemd1",
3808 "/org/freedesktop/systemd1",
3809 "org.freedesktop.systemd1.Manager",
3815 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3816 /* There's always a fallback possible for
3817 * legacy actions. */
3819 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3820 /* On reexecution, we expect a disconnect, not
3824 log_error("Failed to issue method call: %s", bus_error_message(&error));
3826 dbus_error_free(&error);
3830 static int reset_failed(DBusConnection *bus, char **args) {
3834 if (strv_length(args) <= 1)
3835 return daemon_reload(bus, args);
3837 STRV_FOREACH(name, args+1) {
3838 _cleanup_free_ char *n;
3840 n = unit_name_mangle(*name);
3844 r = bus_method_call_with_reply(
3846 "org.freedesktop.systemd1",
3847 "/org/freedesktop/systemd1",
3848 "org.freedesktop.systemd1.Manager",
3852 DBUS_TYPE_STRING, &n,
3861 static int show_enviroment(DBusConnection *bus, char **args) {
3862 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3863 DBusMessageIter iter, sub, sub2;
3866 *interface = "org.freedesktop.systemd1.Manager",
3867 *property = "Environment";
3869 pager_open_if_enabled();
3871 r = bus_method_call_with_reply(
3873 "org.freedesktop.systemd1",
3874 "/org/freedesktop/systemd1",
3875 "org.freedesktop.DBus.Properties",
3879 DBUS_TYPE_STRING, &interface,
3880 DBUS_TYPE_STRING, &property,
3885 if (!dbus_message_iter_init(reply, &iter) ||
3886 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3887 log_error("Failed to parse reply.");
3891 dbus_message_iter_recurse(&iter, &sub);
3893 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3894 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3895 log_error("Failed to parse reply.");
3899 dbus_message_iter_recurse(&sub, &sub2);
3901 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3904 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3905 log_error("Failed to parse reply.");
3909 dbus_message_iter_get_basic(&sub2, &text);
3912 dbus_message_iter_next(&sub2);
3918 static int switch_root(DBusConnection *bus, char **args) {
3921 _cleanup_free_ char *init = NULL;
3923 l = strv_length(args);
3924 if (l < 2 || l > 3) {
3925 log_error("Wrong number of arguments.");
3932 init = strdup(args[2]);
3934 parse_env_file("/proc/cmdline", WHITESPACE,
3944 log_debug("switching root - root: %s; init: %s", root, init);
3946 return bus_method_call_with_reply(
3948 "org.freedesktop.systemd1",
3949 "/org/freedesktop/systemd1",
3950 "org.freedesktop.systemd1.Manager",
3954 DBUS_TYPE_STRING, &root,
3955 DBUS_TYPE_STRING, &init,
3959 static int set_environment(DBusConnection *bus, char **args) {
3960 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3963 DBusMessageIter iter;
3969 dbus_error_init(&error);
3971 method = streq(args[0], "set-environment")
3973 : "UnsetEnvironment";
3975 m = dbus_message_new_method_call(
3976 "org.freedesktop.systemd1",
3977 "/org/freedesktop/systemd1",
3978 "org.freedesktop.systemd1.Manager",
3983 dbus_message_iter_init_append(m, &iter);
3985 r = bus_append_strv_iter(&iter, args + 1);
3989 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3991 log_error("Failed to issue method call: %s", bus_error_message(&error));
3992 dbus_error_free(&error);
3999 static int enable_sysv_units(char **args) {
4002 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4003 const char *verb = args[0];
4004 unsigned f = 1, t = 1;
4005 LookupPaths paths = {};
4007 if (arg_scope != UNIT_FILE_SYSTEM)
4010 if (!streq(verb, "enable") &&
4011 !streq(verb, "disable") &&
4012 !streq(verb, "is-enabled"))
4015 /* Processes all SysV units, and reshuffles the array so that
4016 * afterwards only the native units remain */
4018 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4023 for (f = 1; args[f]; f++) {
4025 _cleanup_free_ char *p = NULL, *q = NULL;
4026 bool found_native = false, found_sysv;
4028 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4036 if (!endswith(name, ".service"))
4039 if (path_is_absolute(name))
4042 STRV_FOREACH(k, paths.unit_path) {
4043 if (!isempty(arg_root))
4044 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4046 asprintf(&p, "%s/%s", *k, name);
4053 found_native = access(p, F_OK) >= 0;
4064 if (!isempty(arg_root))
4065 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4067 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4073 p[strlen(p) - sizeof(".service") + 1] = 0;
4074 found_sysv = access(p, F_OK) >= 0;
4079 /* Mark this entry, so that we don't try enabling it as native unit */
4080 args[f] = (char*) "";
4082 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4084 if (!isempty(arg_root))
4085 argv[c++] = q = strappend("--root=", arg_root);
4087 argv[c++] = path_get_file_name(p);
4089 streq(verb, "enable") ? "on" :
4090 streq(verb, "disable") ? "off" : "--level=5";
4093 l = strv_join((char**)argv, " ");
4099 log_info("Executing %s", l);
4104 log_error("Failed to fork: %m");
4107 } else if (pid == 0) {
4110 execv(argv[0], (char**) argv);
4111 _exit(EXIT_FAILURE);
4114 j = wait_for_terminate(pid, &status);
4116 log_error("Failed to wait for child: %s", strerror(-r));
4121 if (status.si_code == CLD_EXITED) {
4122 if (streq(verb, "is-enabled")) {
4123 if (status.si_status == 0) {
4132 } else if (status.si_status != 0) {
4143 lookup_paths_free(&paths);
4145 /* Drop all SysV units */
4146 for (f = 1, t = 1; args[f]; f++) {
4148 if (isempty(args[f]))
4151 args[t++] = args[f];
4160 static int mangle_names(char **original_names, char ***mangled_names) {
4161 char **i, **l, **name;
4163 l = new(char*, strv_length(original_names) + 1);
4168 STRV_FOREACH(name, original_names) {
4170 /* When enabling units qualified path names are OK,
4171 * too, hence allow them explicitly. */
4176 *i = unit_name_mangle(*name);
4192 static int enable_unit(DBusConnection *bus, char **args) {
4193 const char *verb = args[0];
4194 UnitFileChange *changes = NULL;
4195 unsigned n_changes = 0, i;
4196 int carries_install_info = -1;
4197 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4199 _cleanup_dbus_error_free_ DBusError error;
4200 _cleanup_strv_free_ char **mangled_names = NULL;
4202 dbus_error_init(&error);
4204 r = enable_sysv_units(args);
4211 if (!bus || avoid_bus()) {
4212 if (streq(verb, "enable")) {
4213 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4214 carries_install_info = r;
4215 } else if (streq(verb, "disable"))
4216 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
4217 else if (streq(verb, "reenable")) {
4218 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4219 carries_install_info = r;
4220 } else if (streq(verb, "link"))
4221 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4222 else if (streq(verb, "preset")) {
4223 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4224 carries_install_info = r;
4225 } else if (streq(verb, "mask"))
4226 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4227 else if (streq(verb, "unmask"))
4228 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
4230 assert_not_reached("Unknown verb");
4233 log_error("Operation failed: %s", strerror(-r));
4238 for (i = 0; i < n_changes; i++) {
4239 if (changes[i].type == UNIT_FILE_SYMLINK)
4240 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4242 log_info("rm '%s'", changes[i].path);
4249 bool send_force = true, expect_carries_install_info = false;
4251 DBusMessageIter iter, sub, sub2;
4253 if (streq(verb, "enable")) {
4254 method = "EnableUnitFiles";
4255 expect_carries_install_info = true;
4256 } else if (streq(verb, "disable")) {
4257 method = "DisableUnitFiles";
4259 } else if (streq(verb, "reenable")) {
4260 method = "ReenableUnitFiles";
4261 expect_carries_install_info = true;
4262 } else if (streq(verb, "link"))
4263 method = "LinkUnitFiles";
4264 else if (streq(verb, "preset")) {
4265 method = "PresetUnitFiles";
4266 expect_carries_install_info = true;
4267 } else if (streq(verb, "mask"))
4268 method = "MaskUnitFiles";
4269 else if (streq(verb, "unmask")) {
4270 method = "UnmaskUnitFiles";
4273 assert_not_reached("Unknown verb");
4275 m = dbus_message_new_method_call(
4276 "org.freedesktop.systemd1",
4277 "/org/freedesktop/systemd1",
4278 "org.freedesktop.systemd1.Manager",
4285 dbus_message_iter_init_append(m, &iter);
4287 r = mangle_names(args+1, &mangled_names);
4291 r = bus_append_strv_iter(&iter, mangled_names);
4293 log_error("Failed to append unit files.");
4298 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4299 log_error("Failed to append runtime boolean.");
4307 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4308 log_error("Failed to append force boolean.");
4314 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4316 log_error("Failed to issue method call: %s", bus_error_message(&error));
4321 if (!dbus_message_iter_init(reply, &iter)) {
4322 log_error("Failed to initialize iterator.");
4326 if (expect_carries_install_info) {
4327 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4329 log_error("Failed to parse reply.");
4333 carries_install_info = b;
4336 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4337 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4338 log_error("Failed to parse reply.");
4343 dbus_message_iter_recurse(&iter, &sub);
4344 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4345 const char *type, *path, *source;
4347 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4348 log_error("Failed to parse reply.");
4353 dbus_message_iter_recurse(&sub, &sub2);
4355 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4356 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4357 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4358 log_error("Failed to parse reply.");
4364 if (streq(type, "symlink"))
4365 log_info("ln -s '%s' '%s'", source, path);
4367 log_info("rm '%s'", path);
4370 dbus_message_iter_next(&sub);
4373 /* Try to reload if enabeld */
4375 r = daemon_reload(bus, args);
4378 if (carries_install_info == 0)
4379 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4380 "using systemctl.\n"
4381 "Possible reasons for having this kind of units are:\n"
4382 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4383 " .wants/ or .requires/ directory.\n"
4384 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4385 " a requirement dependency on it.\n"
4386 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4387 " D-Bus, udev, scripted systemctl call, ...).\n");
4390 unit_file_changes_free(changes, n_changes);
4395 static int unit_is_enabled(DBusConnection *bus, char **args) {
4396 _cleanup_dbus_error_free_ DBusError error;
4398 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4403 dbus_error_init(&error);
4405 r = enable_sysv_units(args);
4411 if (!bus || avoid_bus()) {
4413 STRV_FOREACH(name, args+1) {
4414 UnitFileState state;
4416 n = unit_name_mangle(*name);
4420 state = unit_file_get_state(arg_scope, arg_root, n);
4427 if (state == UNIT_FILE_ENABLED ||
4428 state == UNIT_FILE_ENABLED_RUNTIME ||
4429 state == UNIT_FILE_STATIC)
4433 puts(unit_file_state_to_string(state));
4437 STRV_FOREACH(name, args+1) {
4440 n = unit_name_mangle(*name);
4444 r = bus_method_call_with_reply (
4446 "org.freedesktop.systemd1",
4447 "/org/freedesktop/systemd1",
4448 "org.freedesktop.systemd1.Manager",
4452 DBUS_TYPE_STRING, &n,
4460 if (!dbus_message_get_args(reply, &error,
4461 DBUS_TYPE_STRING, &s,
4462 DBUS_TYPE_INVALID)) {
4463 log_error("Failed to parse reply: %s", bus_error_message(&error));
4467 dbus_message_unref(reply);
4470 if (streq(s, "enabled") ||
4471 streq(s, "enabled-runtime") ||
4480 return enabled ? 0 : 1;
4483 static int systemctl_help(void) {
4485 pager_open_if_enabled();
4487 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4488 "Query or send control commands to the systemd manager.\n\n"
4489 " -h --help Show this help\n"
4490 " --version Show package version\n"
4491 " -t --type=TYPE List only units of a particular type\n"
4492 " -p --property=NAME Show only properties by this name\n"
4493 " -a --all Show all loaded units/properties, including dead/empty\n"
4494 " ones. To list all units installed on the system, use\n"
4495 " the 'list-unit-files' command instead.\n"
4496 " --reverse Show reverse dependencies with 'list-dependencies'\n"
4497 " --failed Show only failed units\n"
4498 " --full Don't ellipsize unit names on output\n"
4499 " --fail When queueing a new job, fail if conflicting jobs are\n"
4501 " --irreversible Create jobs which cannot be implicitly cancelled\n"
4502 " --show-types When showing sockets, explicitly show their type\n"
4503 " --ignore-dependencies\n"
4504 " When queueing a new job, ignore all its dependencies\n"
4505 " -i --ignore-inhibitors\n"
4506 " When shutting down or sleeping, ignore inhibitors\n"
4507 " --kill-who=WHO Who to send signal to\n"
4508 " -s --signal=SIGNAL Which signal to send\n"
4509 " -H --host=[USER@]HOST\n"
4510 " Show information for remote host\n"
4511 " -P --privileged Acquire privileges before execution\n"
4512 " -q --quiet Suppress output\n"
4513 " --no-block Do not wait until operation finished\n"
4514 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4515 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4517 " --no-legend Do not print a legend (column headers and hints)\n"
4518 " --no-pager Do not pipe output into a pager\n"
4519 " --no-ask-password\n"
4520 " Do not ask for system passwords\n"
4521 " --system Connect to system manager\n"
4522 " --user Connect to user service manager\n"
4523 " --global Enable/disable unit files globally\n"
4524 " -f --force When enabling unit files, override existing symlinks\n"
4525 " When shutting down, execute action immediately\n"
4526 " --root=PATH Enable unit files in the specified root directory\n"
4527 " --runtime Enable unit files only temporarily until next reboot\n"
4528 " -n --lines=INTEGER Journal entries to show\n"
4529 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4530 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4532 " list-units List loaded units\n"
4533 " start [NAME...] Start (activate) one or more units\n"
4534 " stop [NAME...] Stop (deactivate) one or more units\n"
4535 " reload [NAME...] Reload one or more units\n"
4536 " restart [NAME...] Start or restart one or more units\n"
4537 " try-restart [NAME...] Restart one or more units if active\n"
4538 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4539 " otherwise start or restart\n"
4540 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4541 " otherwise restart if active\n"
4542 " isolate [NAME] Start one unit and stop all others\n"
4543 " kill [NAME...] Send signal to processes of a unit\n"
4544 " is-active [NAME...] Check whether units are active\n"
4545 " is-failed [NAME...] Check whether units are failed\n"
4546 " status [NAME...|PID...] Show runtime status of one or more units\n"
4547 " show [NAME...|JOB...] Show properties of one or more\n"
4548 " units/jobs or the manager\n"
4549 " help [NAME...|PID...] Show manual for one or more units\n"
4550 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4552 " get-cgroup-attr [NAME] [ATTR] ...\n"
4553 " Get control group attrubute\n"
4554 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4555 " Set control group attribute\n"
4556 " unset-cgroup-attr [NAME] [ATTR...]\n"
4557 " Unset control group attribute\n"
4558 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4559 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4560 " load [NAME...] Load one or more units\n"
4561 " list-dependencies [NAME] Recursively show units which are required\n"
4562 " or wanted by this unit or by which this\n"
4563 " unit is required or wanted\n\n"
4564 "Unit File Commands:\n"
4565 " list-unit-files List installed unit files\n"
4566 " enable [NAME...] Enable one or more unit files\n"
4567 " disable [NAME...] Disable one or more unit files\n"
4568 " reenable [NAME...] Reenable one or more unit files\n"
4569 " preset [NAME...] Enable/disable one or more unit files\n"
4570 " based on preset configuration\n"
4571 " mask [NAME...] Mask one or more units\n"
4572 " unmask [NAME...] Unmask one or more units\n"
4573 " link [PATH...] Link one or more units files into\n"
4574 " the search path\n"
4575 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4577 " list-jobs List jobs\n"
4578 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4579 "Status Commands:\n"
4580 " dump Dump server status\n"
4581 "Snapshot Commands:\n"
4582 " snapshot [NAME] Create a snapshot\n"
4583 " delete [NAME...] Remove one or more snapshots\n\n"
4584 "Environment Commands:\n"
4585 " show-environment Dump environment\n"
4586 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4587 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4588 "Manager Lifecycle Commands:\n"
4589 " daemon-reload Reload systemd manager configuration\n"
4590 " daemon-reexec Reexecute systemd manager\n\n"
4591 "System Commands:\n"
4592 " default Enter system default mode\n"
4593 " rescue Enter system rescue mode\n"
4594 " emergency Enter system emergency mode\n"
4595 " halt Shut down and halt the system\n"
4596 " poweroff Shut down and power-off the system\n"
4597 " reboot Shut down and reboot the system\n"
4598 " kexec Shut down and reboot the system with kexec\n"
4599 " exit Request user instance exit\n"
4600 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4601 " suspend Suspend the system\n"
4602 " hibernate Hibernate the system\n"
4603 " hybrid-sleep Hibernate and suspend the system\n",
4604 program_invocation_short_name);
4609 static int halt_help(void) {
4611 printf("%s [OPTIONS...]\n\n"
4612 "%s the system.\n\n"
4613 " --help Show this help\n"
4614 " --halt Halt the machine\n"
4615 " -p --poweroff Switch off the machine\n"
4616 " --reboot Reboot the machine\n"
4617 " -f --force Force immediate halt/power-off/reboot\n"
4618 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4619 " -d --no-wtmp Don't write wtmp record\n"
4620 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4621 program_invocation_short_name,
4622 arg_action == ACTION_REBOOT ? "Reboot" :
4623 arg_action == ACTION_POWEROFF ? "Power off" :
4629 static int shutdown_help(void) {
4631 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4632 "Shut down the system.\n\n"
4633 " --help Show this help\n"
4634 " -H --halt Halt the machine\n"
4635 " -P --poweroff Power-off the machine\n"
4636 " -r --reboot Reboot the machine\n"
4637 " -h Equivalent to --poweroff, overridden by --halt\n"
4638 " -k Don't halt/power-off/reboot, just send warnings\n"
4639 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4640 " -c Cancel a pending shutdown\n",
4641 program_invocation_short_name);
4646 static int telinit_help(void) {
4648 printf("%s [OPTIONS...] {COMMAND}\n\n"
4649 "Send control commands to the init daemon.\n\n"
4650 " --help Show this help\n"
4651 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4653 " 0 Power-off the machine\n"
4654 " 6 Reboot the machine\n"
4655 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4656 " 1, s, S Enter rescue mode\n"
4657 " q, Q Reload init daemon configuration\n"
4658 " u, U Reexecute init daemon\n",
4659 program_invocation_short_name);
4664 static int runlevel_help(void) {
4666 printf("%s [OPTIONS...]\n\n"
4667 "Prints the previous and current runlevel of the init system.\n\n"
4668 " --help Show this help\n",
4669 program_invocation_short_name);
4674 static int help_types(void) {
4678 puts("Available unit types:");
4679 for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4680 t = unit_type_to_string(i);
4685 puts("\nAvailable unit load states: ");
4686 for(i = 0; i < _UNIT_LOAD_STATE_MAX; i++) {
4687 t = unit_load_state_to_string(i);
4695 static int systemctl_parse_argv(int argc, char *argv[]) {
4704 ARG_IGNORE_DEPENDENCIES,
4717 ARG_NO_ASK_PASSWORD,
4723 static const struct option options[] = {
4724 { "help", no_argument, NULL, 'h' },
4725 { "version", no_argument, NULL, ARG_VERSION },
4726 { "type", required_argument, NULL, 't' },
4727 { "property", required_argument, NULL, 'p' },
4728 { "all", no_argument, NULL, 'a' },
4729 { "reverse", no_argument, NULL, ARG_REVERSE },
4730 { "after", no_argument, NULL, ARG_AFTER },
4731 { "before", no_argument, NULL, ARG_BEFORE },
4732 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
4733 { "failed", no_argument, NULL, ARG_FAILED },
4734 { "full", no_argument, NULL, ARG_FULL },
4735 { "fail", no_argument, NULL, ARG_FAIL },
4736 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4737 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4738 { "ignore-inhibitors", no_argument, NULL, 'i' },
4739 { "user", no_argument, NULL, ARG_USER },
4740 { "system", no_argument, NULL, ARG_SYSTEM },
4741 { "global", no_argument, NULL, ARG_GLOBAL },
4742 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4743 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4744 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4745 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4746 { "quiet", no_argument, NULL, 'q' },
4747 { "root", required_argument, NULL, ARG_ROOT },
4748 { "force", no_argument, NULL, ARG_FORCE },
4749 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4750 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4751 { "signal", required_argument, NULL, 's' },
4752 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4753 { "host", required_argument, NULL, 'H' },
4754 { "privileged",no_argument, NULL, 'P' },
4755 { "runtime", no_argument, NULL, ARG_RUNTIME },
4756 { "lines", required_argument, NULL, 'n' },
4757 { "output", required_argument, NULL, 'o' },
4758 { NULL, 0, NULL, 0 }
4766 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4775 puts(PACKAGE_STRING);
4776 puts(SYSTEMD_FEATURES);
4783 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4784 _cleanup_free_ char *type;
4786 type = strndup(word, size);
4790 if (streq(type, "help")) {
4795 if (unit_type_from_string(type) >= 0) {
4796 if (strv_push(&arg_types, type))
4802 if (unit_load_state_from_string(optarg) >= 0) {
4803 if (strv_push(&arg_load_states, type))
4809 log_error("Unknown unit type or load state '%s'.", type);
4810 log_info("Use -t help to see a list of allowed values.");
4818 /* Make sure that if the empty property list
4819 was specified, we won't show any properties. */
4820 if (isempty(optarg) && !arg_properties) {
4821 arg_properties = strv_new(NULL, NULL);
4822 if (!arg_properties)
4828 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4831 prop = strndup(word, size);
4835 if (strv_push(&arg_properties, prop)) {
4842 /* If the user asked for a particular
4843 * property, show it to him, even if it is
4855 arg_dependency = DEPENDENCY_REVERSE;
4859 arg_dependency = DEPENDENCY_AFTER;
4863 arg_dependency = DEPENDENCY_BEFORE;
4866 case ARG_SHOW_TYPES:
4867 arg_show_types = true;
4871 arg_job_mode = "fail";
4874 case ARG_IRREVERSIBLE:
4875 arg_job_mode = "replace-irreversibly";
4878 case ARG_IGNORE_DEPENDENCIES:
4879 arg_job_mode = "ignore-dependencies";
4883 arg_scope = UNIT_FILE_USER;
4887 arg_scope = UNIT_FILE_SYSTEM;
4891 arg_scope = UNIT_FILE_GLOBAL;
4895 arg_no_block = true;
4899 arg_no_legend = true;
4903 arg_no_pager = true;
4935 arg_no_reload = true;
4939 arg_kill_who = optarg;
4943 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4944 log_error("Failed to parse signal string %s.", optarg);
4949 case ARG_NO_ASK_PASSWORD:
4950 arg_ask_password = false;
4954 arg_transport = TRANSPORT_POLKIT;
4958 arg_transport = TRANSPORT_SSH;
4967 if (safe_atou(optarg, &arg_lines) < 0) {
4968 log_error("Failed to parse lines '%s'", optarg);
4974 arg_output = output_mode_from_string(optarg);
4975 if (arg_output < 0) {
4976 log_error("Unknown output '%s'.", optarg);
4982 arg_ignore_inhibitors = true;
4989 log_error("Unknown option code '%c'.", c);
4994 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4995 log_error("Cannot access user instance remotely.");
5002 static int halt_parse_argv(int argc, char *argv[]) {
5011 static const struct option options[] = {
5012 { "help", no_argument, NULL, ARG_HELP },
5013 { "halt", no_argument, NULL, ARG_HALT },
5014 { "poweroff", no_argument, NULL, 'p' },
5015 { "reboot", no_argument, NULL, ARG_REBOOT },
5016 { "force", no_argument, NULL, 'f' },
5017 { "wtmp-only", no_argument, NULL, 'w' },
5018 { "no-wtmp", no_argument, NULL, 'd' },
5019 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5020 { NULL, 0, NULL, 0 }
5028 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5029 if (runlevel == '0' || runlevel == '6')
5032 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5040 arg_action = ACTION_HALT;
5044 if (arg_action != ACTION_REBOOT)
5045 arg_action = ACTION_POWEROFF;
5049 arg_action = ACTION_REBOOT;
5071 /* Compatibility nops */
5078 log_error("Unknown option code '%c'.", c);
5083 if (optind < argc) {
5084 log_error("Too many arguments.");
5091 static int parse_time_spec(const char *t, usec_t *_u) {
5095 if (streq(t, "now"))
5097 else if (!strchr(t, ':')) {
5100 if (safe_atou64(t, &u) < 0)
5103 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5112 hour = strtol(t, &e, 10);
5113 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5116 minute = strtol(e+1, &e, 10);
5117 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5120 n = now(CLOCK_REALTIME);
5121 s = (time_t) (n / USEC_PER_SEC);
5123 assert_se(localtime_r(&s, &tm));
5125 tm.tm_hour = (int) hour;
5126 tm.tm_min = (int) minute;
5129 assert_se(s = mktime(&tm));
5131 *_u = (usec_t) s * USEC_PER_SEC;
5134 *_u += USEC_PER_DAY;
5140 static int shutdown_parse_argv(int argc, char *argv[]) {
5147 static const struct option options[] = {
5148 { "help", no_argument, NULL, ARG_HELP },
5149 { "halt", no_argument, NULL, 'H' },
5150 { "poweroff", no_argument, NULL, 'P' },
5151 { "reboot", no_argument, NULL, 'r' },
5152 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5153 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5154 { NULL, 0, NULL, 0 }
5162 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5170 arg_action = ACTION_HALT;
5174 arg_action = ACTION_POWEROFF;
5179 arg_action = ACTION_KEXEC;
5181 arg_action = ACTION_REBOOT;
5185 arg_action = ACTION_KEXEC;
5189 if (arg_action != ACTION_HALT)
5190 arg_action = ACTION_POWEROFF;
5203 /* Compatibility nops */
5207 arg_action = ACTION_CANCEL_SHUTDOWN;
5214 log_error("Unknown option code '%c'.", c);
5219 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5220 r = parse_time_spec(argv[optind], &arg_when);
5222 log_error("Failed to parse time specification: %s", argv[optind]);
5226 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5228 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5229 /* No time argument for shutdown cancel */
5230 arg_wall = argv + optind;
5231 else if (argc > optind + 1)
5232 /* We skip the time argument */
5233 arg_wall = argv + optind + 1;
5240 static int telinit_parse_argv(int argc, char *argv[]) {
5247 static const struct option options[] = {
5248 { "help", no_argument, NULL, ARG_HELP },
5249 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5250 { NULL, 0, NULL, 0 }
5253 static const struct {
5257 { '0', ACTION_POWEROFF },
5258 { '6', ACTION_REBOOT },
5259 { '1', ACTION_RESCUE },
5260 { '2', ACTION_RUNLEVEL2 },
5261 { '3', ACTION_RUNLEVEL3 },
5262 { '4', ACTION_RUNLEVEL4 },
5263 { '5', ACTION_RUNLEVEL5 },
5264 { 's', ACTION_RESCUE },
5265 { 'S', ACTION_RESCUE },
5266 { 'q', ACTION_RELOAD },
5267 { 'Q', ACTION_RELOAD },
5268 { 'u', ACTION_REEXEC },
5269 { 'U', ACTION_REEXEC }
5278 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5293 log_error("Unknown option code '%c'.", c);
5298 if (optind >= argc) {
5303 if (optind + 1 < argc) {
5304 log_error("Too many arguments.");
5308 if (strlen(argv[optind]) != 1) {
5309 log_error("Expected single character argument.");
5313 for (i = 0; i < ELEMENTSOF(table); i++)
5314 if (table[i].from == argv[optind][0])
5317 if (i >= ELEMENTSOF(table)) {
5318 log_error("Unknown command '%s'.", argv[optind]);
5322 arg_action = table[i].to;
5329 static int runlevel_parse_argv(int argc, char *argv[]) {
5335 static const struct option options[] = {
5336 { "help", no_argument, NULL, ARG_HELP },
5337 { NULL, 0, NULL, 0 }
5345 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5356 log_error("Unknown option code '%c'.", c);
5361 if (optind < argc) {
5362 log_error("Too many arguments.");
5369 static int parse_argv(int argc, char *argv[]) {
5373 if (program_invocation_short_name) {
5375 if (strstr(program_invocation_short_name, "halt")) {
5376 arg_action = ACTION_HALT;
5377 return halt_parse_argv(argc, argv);
5378 } else if (strstr(program_invocation_short_name, "poweroff")) {
5379 arg_action = ACTION_POWEROFF;
5380 return halt_parse_argv(argc, argv);
5381 } else if (strstr(program_invocation_short_name, "reboot")) {
5383 arg_action = ACTION_KEXEC;
5385 arg_action = ACTION_REBOOT;
5386 return halt_parse_argv(argc, argv);
5387 } else if (strstr(program_invocation_short_name, "shutdown")) {
5388 arg_action = ACTION_POWEROFF;
5389 return shutdown_parse_argv(argc, argv);
5390 } else if (strstr(program_invocation_short_name, "init")) {
5392 if (sd_booted() > 0) {
5393 arg_action = ACTION_INVALID;
5394 return telinit_parse_argv(argc, argv);
5396 /* Hmm, so some other init system is
5397 * running, we need to forward this
5398 * request to it. For now we simply
5399 * guess that it is Upstart. */
5401 execv(TELINIT, argv);
5403 log_error("Couldn't find an alternative telinit implementation to spawn.");
5407 } else if (strstr(program_invocation_short_name, "runlevel")) {
5408 arg_action = ACTION_RUNLEVEL;
5409 return runlevel_parse_argv(argc, argv);
5413 arg_action = ACTION_SYSTEMCTL;
5414 return systemctl_parse_argv(argc, argv);
5417 static int action_to_runlevel(void) {
5419 static const char table[_ACTION_MAX] = {
5420 [ACTION_HALT] = '0',
5421 [ACTION_POWEROFF] = '0',
5422 [ACTION_REBOOT] = '6',
5423 [ACTION_RUNLEVEL2] = '2',
5424 [ACTION_RUNLEVEL3] = '3',
5425 [ACTION_RUNLEVEL4] = '4',
5426 [ACTION_RUNLEVEL5] = '5',
5427 [ACTION_RESCUE] = '1'
5430 assert(arg_action < _ACTION_MAX);
5432 return table[arg_action];
5435 static int talk_upstart(void) {
5436 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
5437 _cleanup_dbus_error_free_ DBusError error;
5438 int previous, rl, r;
5440 env1_buf[] = "RUNLEVEL=X",
5441 env2_buf[] = "PREVLEVEL=X";
5442 char *env1 = env1_buf, *env2 = env2_buf;
5443 const char *emit = "runlevel";
5444 dbus_bool_t b_false = FALSE;
5445 DBusMessageIter iter, sub;
5446 DBusConnection *bus;
5448 dbus_error_init(&error);
5450 if (!(rl = action_to_runlevel()))
5453 if (utmp_get_runlevel(&previous, NULL) < 0)
5456 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5457 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5462 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5467 if ((r = bus_check_peercred(bus)) < 0) {
5468 log_error("Failed to verify owner of bus.");
5472 if (!(m = dbus_message_new_method_call(
5473 "com.ubuntu.Upstart",
5474 "/com/ubuntu/Upstart",
5475 "com.ubuntu.Upstart0_6",
5478 log_error("Could not allocate message.");
5483 dbus_message_iter_init_append(m, &iter);
5485 env1_buf[sizeof(env1_buf)-2] = rl;
5486 env2_buf[sizeof(env2_buf)-2] = previous;
5488 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5489 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5490 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5491 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5492 !dbus_message_iter_close_container(&iter, &sub) ||
5493 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5494 log_error("Could not append arguments to message.");
5499 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5501 if (bus_error_is_no_service(&error)) {
5506 log_error("Failed to issue method call: %s", bus_error_message(&error));
5515 dbus_connection_flush(bus);
5516 dbus_connection_close(bus);
5517 dbus_connection_unref(bus);
5523 static int talk_initctl(void) {
5524 struct init_request request = {};
5526 _cleanup_close_ int fd = -1;
5529 rl = action_to_runlevel();
5533 request.magic = INIT_MAGIC;
5534 request.sleeptime = 0;
5535 request.cmd = INIT_CMD_RUNLVL;
5536 request.runlevel = rl;
5538 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5540 if (errno == ENOENT)
5543 log_error("Failed to open "INIT_FIFO": %m");
5548 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5550 log_error("Failed to write to "INIT_FIFO": %m");
5551 return errno > 0 ? -errno : -EIO;
5557 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5559 static const struct {
5567 int (* const dispatch)(DBusConnection *bus, char **args);
5569 { "list-units", LESS, 1, list_units },
5570 { "list-unit-files", EQUAL, 1, list_unit_files },
5571 { "list-sockets", LESS, 1, list_sockets },
5572 { "list-jobs", EQUAL, 1, list_jobs },
5573 { "clear-jobs", EQUAL, 1, daemon_reload },
5574 { "load", MORE, 2, load_unit },
5575 { "cancel", MORE, 2, cancel_job },
5576 { "start", MORE, 2, start_unit },
5577 { "stop", MORE, 2, start_unit },
5578 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5579 { "reload", MORE, 2, start_unit },
5580 { "restart", MORE, 2, start_unit },
5581 { "try-restart", MORE, 2, start_unit },
5582 { "reload-or-restart", MORE, 2, start_unit },
5583 { "reload-or-try-restart", MORE, 2, start_unit },
5584 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5585 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5586 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5587 { "isolate", EQUAL, 2, start_unit },
5588 { "set-cgroup", MORE, 3, set_cgroup },
5589 { "unset-cgroup", MORE, 3, set_cgroup },
5590 { "get-cgroup-attr", MORE, 3, get_cgroup_attr },
5591 { "set-cgroup-attr", MORE, 4, set_cgroup_attr },
5592 { "unset-cgroup-attr", MORE, 3, set_cgroup },
5593 { "kill", MORE, 2, kill_unit },
5594 { "is-active", MORE, 2, check_unit_active },
5595 { "check", MORE, 2, check_unit_active },
5596 { "is-failed", MORE, 2, check_unit_failed },
5597 { "show", MORE, 1, show },
5598 { "status", MORE, 1, show },
5599 { "help", MORE, 2, show },
5600 { "dump", EQUAL, 1, dump },
5601 { "snapshot", LESS, 2, snapshot },
5602 { "delete", MORE, 2, delete_snapshot },
5603 { "daemon-reload", EQUAL, 1, daemon_reload },
5604 { "daemon-reexec", EQUAL, 1, daemon_reload },
5605 { "show-environment", EQUAL, 1, show_enviroment },
5606 { "set-environment", MORE, 2, set_environment },
5607 { "unset-environment", MORE, 2, set_environment },
5608 { "halt", EQUAL, 1, start_special },
5609 { "poweroff", EQUAL, 1, start_special },
5610 { "reboot", EQUAL, 1, start_special },
5611 { "kexec", EQUAL, 1, start_special },
5612 { "suspend", EQUAL, 1, start_special },
5613 { "hibernate", EQUAL, 1, start_special },
5614 { "hybrid-sleep", EQUAL, 1, start_special },
5615 { "default", EQUAL, 1, start_special },
5616 { "rescue", EQUAL, 1, start_special },
5617 { "emergency", EQUAL, 1, start_special },
5618 { "exit", EQUAL, 1, start_special },
5619 { "reset-failed", MORE, 1, reset_failed },
5620 { "enable", MORE, 2, enable_unit },
5621 { "disable", MORE, 2, enable_unit },
5622 { "is-enabled", MORE, 2, unit_is_enabled },
5623 { "reenable", MORE, 2, enable_unit },
5624 { "preset", MORE, 2, enable_unit },
5625 { "mask", MORE, 2, enable_unit },
5626 { "unmask", MORE, 2, enable_unit },
5627 { "link", MORE, 2, enable_unit },
5628 { "switch-root", MORE, 2, switch_root },
5629 { "list-dependencies", LESS, 2, list_dependencies },
5639 left = argc - optind;
5642 /* Special rule: no arguments means "list-units" */
5645 if (streq(argv[optind], "help") && !argv[optind+1]) {
5646 log_error("This command expects one or more "
5647 "unit names. Did you mean --help?");
5651 for (i = 0; i < ELEMENTSOF(verbs); i++)
5652 if (streq(argv[optind], verbs[i].verb))
5655 if (i >= ELEMENTSOF(verbs)) {
5656 log_error("Unknown operation '%s'.", argv[optind]);
5661 switch (verbs[i].argc_cmp) {
5664 if (left != verbs[i].argc) {
5665 log_error("Invalid number of arguments.");
5672 if (left < verbs[i].argc) {
5673 log_error("Too few arguments.");
5680 if (left > verbs[i].argc) {
5681 log_error("Too many arguments.");
5688 assert_not_reached("Unknown comparison operator.");
5691 /* Require a bus connection for all operations but
5693 if (!streq(verbs[i].verb, "enable") &&
5694 !streq(verbs[i].verb, "disable") &&
5695 !streq(verbs[i].verb, "is-enabled") &&
5696 !streq(verbs[i].verb, "list-unit-files") &&
5697 !streq(verbs[i].verb, "reenable") &&
5698 !streq(verbs[i].verb, "preset") &&
5699 !streq(verbs[i].verb, "mask") &&
5700 !streq(verbs[i].verb, "unmask") &&
5701 !streq(verbs[i].verb, "link")) {
5703 if (running_in_chroot() > 0) {
5704 log_info("Running in chroot, ignoring request.");
5708 if (((!streq(verbs[i].verb, "reboot") &&
5709 !streq(verbs[i].verb, "halt") &&
5710 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5711 log_error("Failed to get D-Bus connection: %s",
5712 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5718 if (!bus && !avoid_bus()) {
5719 log_error("Failed to get D-Bus connection: %s",
5720 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5725 return verbs[i].dispatch(bus, argv + optind);
5728 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5729 _cleanup_close_ int fd;
5730 struct sd_shutdown_command c = {
5736 union sockaddr_union sockaddr = {
5737 .un.sun_family = AF_UNIX,
5738 .un.sun_path = "/run/systemd/shutdownd",
5740 struct iovec iovec[2] = {
5741 {.iov_base = (char*) &c,
5742 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
5745 struct msghdr msghdr = {
5746 .msg_name = &sockaddr,
5747 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
5748 + sizeof("/run/systemd/shutdownd") - 1,
5753 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5757 if (!isempty(message)) {
5758 iovec[1].iov_base = (char*) message;
5759 iovec[1].iov_len = strlen(message);
5760 msghdr.msg_iovlen++;
5763 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5769 static int reload_with_fallback(DBusConnection *bus) {
5772 /* First, try systemd via D-Bus. */
5773 if (daemon_reload(bus, NULL) >= 0)
5777 /* Nothing else worked, so let's try signals */
5778 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5780 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5781 log_error("kill() failed: %m");
5788 static int start_with_fallback(DBusConnection *bus) {
5791 /* First, try systemd via D-Bus. */
5792 if (start_unit(bus, NULL) >= 0)
5796 /* Hmm, talking to systemd via D-Bus didn't work. Then
5797 * let's try to talk to Upstart via D-Bus. */
5798 if (talk_upstart() > 0)
5801 /* Nothing else worked, so let's try
5803 if (talk_initctl() > 0)
5806 log_error("Failed to talk to init daemon.");
5810 warn_wall(arg_action);
5814 static _noreturn_ void halt_now(enum action a) {
5816 /* Make sure C-A-D is handled by the kernel from this
5818 reboot(RB_ENABLE_CAD);
5823 log_info("Halting.");
5824 reboot(RB_HALT_SYSTEM);
5827 case ACTION_POWEROFF:
5828 log_info("Powering off.");
5829 reboot(RB_POWER_OFF);
5833 log_info("Rebooting.");
5834 reboot(RB_AUTOBOOT);
5838 assert_not_reached("Unknown halt action.");
5841 assert_not_reached("Uh? This shouldn't happen.");
5844 static int halt_main(DBusConnection *bus) {
5847 r = check_inhibitors(bus, arg_action);
5851 if (geteuid() != 0) {
5852 /* Try logind if we are a normal user and no special
5853 * mode applies. Maybe PolicyKit allows us to shutdown
5856 if (arg_when <= 0 &&
5859 (arg_action == ACTION_POWEROFF ||
5860 arg_action == ACTION_REBOOT)) {
5861 r = reboot_with_logind(bus, arg_action);
5866 log_error("Must be root.");
5871 _cleanup_free_ char *m;
5873 m = strv_join(arg_wall, " ");
5874 r = send_shutdownd(arg_when,
5875 arg_action == ACTION_HALT ? 'H' :
5876 arg_action == ACTION_POWEROFF ? 'P' :
5877 arg_action == ACTION_KEXEC ? 'K' :
5884 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5886 char date[FORMAT_TIMESTAMP_MAX];
5888 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5889 format_timestamp(date, sizeof(date), arg_when));
5894 if (!arg_dry && !arg_force)
5895 return start_with_fallback(bus);
5898 if (sd_booted() > 0)
5899 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5901 r = utmp_put_shutdown();
5903 log_warning("Failed to write utmp record: %s", strerror(-r));
5910 halt_now(arg_action);
5911 /* We should never reach this. */
5915 static int runlevel_main(void) {
5916 int r, runlevel, previous;
5918 r = utmp_get_runlevel(&runlevel, &previous);
5925 previous <= 0 ? 'N' : previous,
5926 runlevel <= 0 ? 'N' : runlevel);
5931 int main(int argc, char*argv[]) {
5932 int r, retval = EXIT_FAILURE;
5933 DBusConnection *bus = NULL;
5934 _cleanup_dbus_error_free_ DBusError error;
5936 dbus_error_init(&error);
5938 setlocale(LC_ALL, "");
5939 log_parse_environment();
5942 r = parse_argv(argc, argv);
5946 retval = EXIT_SUCCESS;
5950 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5951 * let's shortcut this */
5952 if (arg_action == ACTION_RUNLEVEL) {
5953 r = runlevel_main();
5954 retval = r < 0 ? EXIT_FAILURE : r;
5958 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5959 log_info("Running in chroot, ignoring request.");
5965 if (arg_transport == TRANSPORT_NORMAL)
5966 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5967 else if (arg_transport == TRANSPORT_POLKIT) {
5968 bus_connect_system_polkit(&bus, &error);
5969 private_bus = false;
5970 } else if (arg_transport == TRANSPORT_SSH) {
5971 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5972 private_bus = false;
5974 assert_not_reached("Uh, invalid transport...");
5977 switch (arg_action) {
5979 case ACTION_SYSTEMCTL:
5980 r = systemctl_main(bus, argc, argv, &error);
5984 case ACTION_POWEROFF:
5990 case ACTION_RUNLEVEL2:
5991 case ACTION_RUNLEVEL3:
5992 case ACTION_RUNLEVEL4:
5993 case ACTION_RUNLEVEL5:
5995 case ACTION_EMERGENCY:
5996 case ACTION_DEFAULT:
5997 r = start_with_fallback(bus);
6002 r = reload_with_fallback(bus);
6005 case ACTION_CANCEL_SHUTDOWN: {
6009 m = strv_join(arg_wall, " ");
6011 retval = EXIT_FAILURE;
6015 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6017 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6022 case ACTION_INVALID:
6023 case ACTION_RUNLEVEL:
6025 assert_not_reached("Unknown action");
6028 retval = r < 0 ? EXIT_FAILURE : r;
6032 dbus_connection_flush(bus);
6033 dbus_connection_close(bus);
6034 dbus_connection_unref(bus);
6039 strv_free(arg_types);
6040 strv_free(arg_load_states);
6041 strv_free(arg_properties);
6044 ask_password_agent_close();
6045 polkit_agent_close();