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;
135 static bool arg_plain = false;
137 static bool private_bus = false;
139 static int daemon_reload(DBusConnection *bus, char **args);
140 static void halt_now(enum action a);
142 static void pager_open_if_enabled(void) {
150 static void ask_password_agent_open_if_enabled(void) {
152 /* Open the password agent as a child process if necessary */
154 if (!arg_ask_password)
157 if (arg_scope != UNIT_FILE_SYSTEM)
160 ask_password_agent_open();
164 static void polkit_agent_open_if_enabled(void) {
166 /* Open the polkit agent as a child process if necessary */
168 if (!arg_ask_password)
171 if (arg_scope != UNIT_FILE_SYSTEM)
178 static const char *ansi_highlight(bool b) {
183 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
186 static const char *ansi_highlight_red(bool b) {
191 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
194 static const char *ansi_highlight_green(bool b) {
199 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
202 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
205 if (!dbus_error_is_set(error))
208 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
209 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
210 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
211 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
212 return EXIT_NOPERMISSION;
214 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
215 return EXIT_NOTINSTALLED;
217 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
218 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
219 return EXIT_NOTIMPLEMENTED;
221 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
222 return EXIT_NOTCONFIGURED;
230 static void warn_wall(enum action a) {
231 static const char *table[_ACTION_MAX] = {
232 [ACTION_HALT] = "The system is going down for system halt NOW!",
233 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
234 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
235 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
236 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
237 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
238 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
245 _cleanup_free_ char *p;
247 p = strv_join(arg_wall, " ");
262 utmp_wall(table[a], NULL);
265 static bool avoid_bus(void) {
267 if (running_in_chroot() > 0)
270 if (sd_booted() <= 0)
273 if (!isempty(arg_root))
276 if (arg_scope == UNIT_FILE_GLOBAL)
282 static int compare_unit_info(const void *a, const void *b) {
284 const struct unit_info *u = a, *v = b;
286 d1 = strrchr(u->id, '.');
287 d2 = strrchr(v->id, '.');
292 r = strcasecmp(d1, d2);
297 return strcasecmp(u->id, v->id);
300 static bool output_show_unit(const struct unit_info *u) {
304 return streq(u->active_state, "failed");
306 return (!arg_types || ((dot = strrchr(u->id, '.')) &&
307 strv_find(arg_types, dot+1))) &&
308 (!arg_load_states || strv_find(arg_load_states, u->load_state)) &&
309 (arg_all || !(streq(u->active_state, "inactive")
310 || u->following[0]) || u->job_id > 0);
313 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
314 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
315 const struct unit_info *u;
318 max_id_len = sizeof("UNIT")-1;
319 active_len = sizeof("ACTIVE")-1;
320 sub_len = sizeof("SUB")-1;
321 job_len = sizeof("JOB")-1;
324 for (u = unit_infos; u < unit_infos + c; u++) {
325 if (!output_show_unit(u))
328 max_id_len = MAX(max_id_len, strlen(u->id));
329 active_len = MAX(active_len, strlen(u->active_state));
330 sub_len = MAX(sub_len, strlen(u->sub_state));
331 if (u->job_id != 0) {
332 job_len = MAX(job_len, strlen(u->job_type));
339 id_len = MIN(max_id_len, 25u);
340 basic_len = 5 + id_len + 5 + active_len + sub_len;
342 basic_len += job_len + 1;
343 if (basic_len < (unsigned) columns()) {
344 unsigned extra_len, incr;
345 extra_len = columns() - basic_len;
346 /* Either UNIT already got 25, or is fully satisfied.
347 * Grant up to 25 to DESC now. */
348 incr = MIN(extra_len, 25u);
351 /* split the remaining space between UNIT and DESC,
352 * but do not give UNIT more than it needs. */
354 incr = MIN(extra_len / 2, max_id_len - id_len);
356 desc_len += extra_len - incr;
362 for (u = unit_infos; u < unit_infos + c; u++) {
363 _cleanup_free_ char *e = NULL;
364 const char *on_loaded, *off_loaded, *on = "";
365 const char *on_active, *off_active, *off = "";
367 if (!output_show_unit(u))
370 if (!n_shown && !arg_no_legend) {
371 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
372 active_len, "ACTIVE", sub_len, "SUB");
374 printf("%-*s ", job_len, "JOB");
375 if (!arg_full && arg_no_pager)
376 printf("%.*s\n", desc_len, "DESCRIPTION");
378 printf("%s\n", "DESCRIPTION");
383 if (streq(u->load_state, "error")) {
384 on_loaded = on = ansi_highlight_red(true);
385 off_loaded = off = ansi_highlight_red(false);
387 on_loaded = off_loaded = "";
389 if (streq(u->active_state, "failed")) {
390 on_active = on = ansi_highlight_red(true);
391 off_active = off = ansi_highlight_red(false);
393 on_active = off_active = "";
395 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
397 printf("%s%-*s%s %s%-6s%s %s%-*s %-*s%s %-*s",
398 on, id_len, e ? e : u->id, off,
399 on_loaded, u->load_state, off_loaded,
400 on_active, active_len, u->active_state,
401 sub_len, u->sub_state, off_active,
402 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
403 if (!arg_full && arg_no_pager)
404 printf("%.*s\n", desc_len, u->description);
406 printf("%s\n", u->description);
409 if (!arg_no_legend) {
410 const char *on, *off;
413 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
414 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
415 "SUB = The low-level unit activation state, values depend on unit type.\n");
417 printf("JOB = Pending job for the unit.\n");
419 on = ansi_highlight(true);
420 off = ansi_highlight(false);
422 on = ansi_highlight_red(true);
423 off = ansi_highlight_red(false);
427 printf("%s%u loaded units listed.%s\n"
428 "To show all installed unit files use 'systemctl list-unit-files'.\n",
431 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
432 "To show all installed unit files use 'systemctl list-unit-files'.\n",
437 static int get_unit_list(DBusConnection *bus, DBusMessage **reply,
438 struct unit_info **unit_infos, unsigned *c) {
439 DBusMessageIter iter, sub;
447 r = bus_method_call_with_reply(
449 "org.freedesktop.systemd1",
450 "/org/freedesktop/systemd1",
451 "org.freedesktop.systemd1.Manager",
459 if (!dbus_message_iter_init(*reply, &iter) ||
460 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
461 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
462 log_error("Failed to parse reply.");
466 dbus_message_iter_recurse(&iter, &sub);
468 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
469 if (!GREEDY_REALLOC(*unit_infos, size, *c + 1))
472 bus_parse_unit_info(&sub, *unit_infos + *c);
475 dbus_message_iter_next(&sub);
481 static int list_units(DBusConnection *bus, char **args) {
482 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
483 _cleanup_free_ struct unit_info *unit_infos = NULL;
487 pager_open_if_enabled();
489 r = get_unit_list(bus, &reply, &unit_infos, &c);
493 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
495 output_units_list(unit_infos, c);
500 static int get_triggered_units(DBusConnection *bus, const char* unit_path,
503 const char *interface = "org.freedesktop.systemd1.Unit",
504 *triggers_property = "Triggers";
505 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
506 DBusMessageIter iter, sub;
509 r = bus_method_call_with_reply(bus,
510 "org.freedesktop.systemd1",
512 "org.freedesktop.DBus.Properties",
516 DBUS_TYPE_STRING, &interface,
517 DBUS_TYPE_STRING, &triggers_property,
522 if (!dbus_message_iter_init(reply, &iter) ||
523 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
524 log_error("Failed to parse reply.");
528 dbus_message_iter_recurse(&iter, &sub);
529 dbus_message_iter_recurse(&sub, &iter);
532 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
535 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
536 log_error("Failed to parse reply.");
540 dbus_message_iter_get_basic(&sub, &unit);
541 r = strv_extend(triggered, unit);
545 dbus_message_iter_next(&sub);
551 static int get_listening(DBusConnection *bus, const char* unit_path,
552 char*** listen, unsigned *c)
554 const char *interface = "org.freedesktop.systemd1.Socket",
555 *listen_property = "Listen";
556 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
557 DBusMessageIter iter, sub;
560 r = bus_method_call_with_reply(bus,
561 "org.freedesktop.systemd1",
563 "org.freedesktop.DBus.Properties",
567 DBUS_TYPE_STRING, &interface,
568 DBUS_TYPE_STRING, &listen_property,
573 if (!dbus_message_iter_init(reply, &iter) ||
574 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
575 log_error("Failed to parse reply.");
579 dbus_message_iter_recurse(&iter, &sub);
580 dbus_message_iter_recurse(&sub, &iter);
583 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
584 DBusMessageIter sub2;
585 const char *type, *path;
587 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
588 log_error("Failed to parse reply.");
592 dbus_message_iter_recurse(&sub, &sub2);
594 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
595 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
596 r = strv_extend(listen, type);
600 r = strv_extend(listen, path);
607 dbus_message_iter_next(&sub);
619 /* Note: triggered is a list here, although it almost certainly
620 * will always be one unit. Nevertheless, dbus API allows for multiple
621 * values, so let's follow that.*/
624 /* The strv above is shared. free is set only in the first one. */
628 static int socket_info_compare(struct socket_info *a, struct socket_info *b) {
629 int o = strcmp(a->path, b->path);
631 o = strcmp(a->type, b->type);
635 static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) {
636 struct socket_info *s;
637 unsigned pathlen = sizeof("LISTEN") - 1,
638 typelen = (sizeof("TYPE") - 1) * arg_show_types,
639 socklen = sizeof("UNIT") - 1,
640 servlen = sizeof("ACTIVATES") - 1;
641 const char *on, *off;
643 for (s = socket_infos; s < socket_infos + cs; s++) {
647 socklen = MAX(socklen, strlen(s->id));
649 typelen = MAX(typelen, strlen(s->type));
650 pathlen = MAX(pathlen, strlen(s->path));
652 STRV_FOREACH(a, s->triggered)
653 tmp += strlen(*a) + 2*(a != s->triggered);
654 servlen = MAX(servlen, tmp);
659 printf("%-*s %-*.*s%-*s %s\n",
661 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
665 for (s = socket_infos; s < socket_infos + cs; s++) {
669 printf("%-*s %-*s %-*s",
670 pathlen, s->path, typelen, s->type, socklen, s->id);
673 pathlen, s->path, socklen, s->id);
674 STRV_FOREACH(a, s->triggered)
676 a == s->triggered ? "" : ",", *a);
680 on = ansi_highlight(true);
681 off = ansi_highlight(false);
685 on = ansi_highlight_red(true);
686 off = ansi_highlight_red(false);
689 if (!arg_no_legend) {
690 printf("%s%u sockets listed.%s\n", on, cs, off);
692 printf("Pass --all to see loaded but inactive sockets, too.\n");
698 static int list_sockets(DBusConnection *bus, char **args) {
699 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
700 _cleanup_free_ struct unit_info *unit_infos = NULL;
701 struct socket_info *socket_infos = NULL;
702 const struct unit_info *u;
703 struct socket_info *s;
704 unsigned cu = 0, cs = 0;
708 pager_open_if_enabled();
710 r = get_unit_list(bus, &reply, &unit_infos, &cu);
714 for (u = unit_infos; u < unit_infos + cu; u++) {
716 _cleanup_strv_free_ char **listen = NULL, **triggered = NULL;
719 if (!output_show_unit(u))
722 if ((dot = strrchr(u->id, '.')) && !streq(dot+1, "socket"))
725 r = get_triggered_units(bus, u->unit_path, &triggered);
729 r = get_listening(bus, u->unit_path, &listen, &c);
733 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
738 for (i = 0; i < c; i++)
739 socket_infos[cs + i] = (struct socket_info) {
742 .path = listen[i*2 + 1],
743 .triggered = triggered,
744 .own_triggered = i==0,
747 /* from this point on we will cleanup those socket_infos */
750 listen = triggered = NULL; /* avoid cleanup */
753 qsort(socket_infos, cs, sizeof(struct socket_info),
754 (__compar_fn_t) socket_info_compare);
756 output_sockets_list(socket_infos, cs);
759 assert(cs == 0 || socket_infos);
760 for (s = socket_infos; s < socket_infos + cs; s++) {
763 if (s->own_triggered)
764 strv_free(s->triggered);
771 static int compare_unit_file_list(const void *a, const void *b) {
773 const UnitFileList *u = a, *v = b;
775 d1 = strrchr(u->path, '.');
776 d2 = strrchr(v->path, '.');
781 r = strcasecmp(d1, d2);
786 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
789 static bool output_show_unit_file(const UnitFileList *u) {
792 return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
795 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
796 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
797 const UnitFileList *u;
799 max_id_len = sizeof("UNIT FILE")-1;
800 state_cols = sizeof("STATE")-1;
801 for (u = units; u < units + c; u++) {
802 if (!output_show_unit_file(u))
805 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
806 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
811 id_cols = MIN(max_id_len, 25u);
812 basic_cols = 1 + id_cols + state_cols;
813 if (basic_cols < (unsigned) columns())
814 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
816 id_cols = max_id_len;
819 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
821 for (u = units; u < units + c; u++) {
822 _cleanup_free_ char *e = NULL;
823 const char *on, *off;
826 if (!output_show_unit_file(u))
831 if (u->state == UNIT_FILE_MASKED ||
832 u->state == UNIT_FILE_MASKED_RUNTIME ||
833 u->state == UNIT_FILE_DISABLED ||
834 u->state == UNIT_FILE_INVALID) {
835 on = ansi_highlight_red(true);
836 off = ansi_highlight_red(false);
837 } else if (u->state == UNIT_FILE_ENABLED) {
838 on = ansi_highlight_green(true);
839 off = ansi_highlight_green(false);
843 id = path_get_file_name(u->path);
845 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
847 printf("%-*s %s%-*s%s\n",
849 on, state_cols, unit_file_state_to_string(u->state), off);
853 printf("\n%u unit files listed.\n", n_shown);
856 static int list_unit_files(DBusConnection *bus, char **args) {
857 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
858 _cleanup_free_ UnitFileList *units = NULL;
859 DBusMessageIter iter, sub, sub2;
860 unsigned c = 0, n_units = 0;
863 pager_open_if_enabled();
870 h = hashmap_new(string_hash_func, string_compare_func);
874 r = unit_file_get_list(arg_scope, arg_root, h);
876 unit_file_list_free(h);
877 log_error("Failed to get unit file list: %s", strerror(-r));
881 n_units = hashmap_size(h);
882 units = new(UnitFileList, n_units);
884 unit_file_list_free(h);
888 HASHMAP_FOREACH(u, h, i) {
889 memcpy(units + c++, u, sizeof(UnitFileList));
895 r = bus_method_call_with_reply(
897 "org.freedesktop.systemd1",
898 "/org/freedesktop/systemd1",
899 "org.freedesktop.systemd1.Manager",
907 if (!dbus_message_iter_init(reply, &iter) ||
908 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
909 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
910 log_error("Failed to parse reply.");
914 dbus_message_iter_recurse(&iter, &sub);
916 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
920 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
925 n_units = MAX(2*c, 16u);
926 w = realloc(units, sizeof(struct UnitFileList) * n_units);
935 dbus_message_iter_recurse(&sub, &sub2);
937 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
938 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
939 log_error("Failed to parse reply.");
943 u->state = unit_file_state_from_string(state);
945 dbus_message_iter_next(&sub);
951 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
952 output_unit_file_list(units, c);
958 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
960 _cleanup_free_ char *n = NULL;
962 size_t max_len = MAX(columns(),20u);
965 for (i = level - 1; i >= 0; i--) {
967 if(len > max_len - 3 && !arg_full) {
968 printf("%s...\n",max_len % 2 ? "" : " ");
971 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
974 if(len > max_len - 3 && !arg_full) {
975 printf("%s...\n",max_len % 2 ? "" : " ");
978 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
982 printf("%s\n", name);
986 n = ellipsize(name, max_len-len, 100);
994 static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
995 static const char *dependencies[] = {
996 [DEPENDENCY_FORWARD] = "Requires\0"
997 "RequiresOverridable\0"
999 "RequisiteOverridable\0"
1001 [DEPENDENCY_REVERSE] = "RequiredBy\0"
1002 "RequiredByOverridable\0"
1005 [DEPENDENCY_AFTER] = "After\0",
1006 [DEPENDENCY_BEFORE] = "Before\0",
1009 _cleanup_free_ char *path;
1010 const char *interface = "org.freedesktop.systemd1.Unit";
1012 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1013 DBusMessageIter iter, sub, sub2, sub3;
1022 path = unit_dbus_path_from_name(name);
1028 r = bus_method_call_with_reply(
1030 "org.freedesktop.systemd1",
1032 "org.freedesktop.DBus.Properties",
1036 DBUS_TYPE_STRING, &interface,
1041 if (!dbus_message_iter_init(reply, &iter) ||
1042 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1043 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
1044 log_error("Failed to parse reply.");
1049 dbus_message_iter_recurse(&iter, &sub);
1051 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1054 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
1055 dbus_message_iter_recurse(&sub, &sub2);
1057 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
1058 log_error("Failed to parse reply.");
1063 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
1064 log_error("Failed to parse reply.");
1069 dbus_message_iter_recurse(&sub2, &sub3);
1070 dbus_message_iter_next(&sub);
1072 assert(arg_dependency < ELEMENTSOF(dependencies));
1073 if (!nulstr_contains(dependencies[arg_dependency], prop))
1076 if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
1077 if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
1078 DBusMessageIter sub4;
1079 dbus_message_iter_recurse(&sub3, &sub4);
1081 while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
1084 assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
1085 dbus_message_iter_get_basic(&sub4, &s);
1087 r = strv_extend(&ret, s);
1093 dbus_message_iter_next(&sub4);
1106 static int list_dependencies_compare(const void *_a, const void *_b) {
1107 const char **a = (const char**) _a, **b = (const char**) _b;
1108 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1110 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1112 return strcasecmp(*a, *b);
1115 static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char ***units, unsigned int branches) {
1116 _cleanup_strv_free_ char **deps = NULL, **u;
1120 u = strv_append(*units, name);
1124 r = list_dependencies_get_dependencies(bus, name, &deps);
1128 qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1130 STRV_FOREACH(c, deps) {
1131 if (strv_contains(u, *c)) {
1133 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1140 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1144 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1145 r = list_dependencies_one(bus, *c, level + 1, &u, (branches << 1) | (c[1] == NULL ? 0 : 1));
1158 static int list_dependencies(DBusConnection *bus, char **args) {
1159 _cleanup_free_ char *unit = NULL;
1160 _cleanup_strv_free_ char **units = NULL;
1166 unit = unit_name_mangle(args[1]);
1171 u = SPECIAL_DEFAULT_TARGET;
1173 pager_open_if_enabled();
1177 return list_dependencies_one(bus, u, 0, &units, 0);
1182 char *name, *type, *state;
1185 static void list_jobs_print(struct job_info* jobs, size_t n) {
1188 const char *on, *off;
1189 bool shorten = false;
1191 assert(n == 0 || jobs);
1194 on = ansi_highlight_green(true);
1195 off = ansi_highlight_green(false);
1197 printf("%sNo jobs running.%s\n", on, off);
1201 pager_open_if_enabled();
1204 /* JOB UNIT TYPE STATE */
1205 unsigned l0 = 3, l1 = 4, l2 = 4, l3 = 5;
1207 for (i = 0, j = jobs; i < n; i++, j++) {
1208 assert(j->name && j->type && j->state);
1209 l0 = MAX(l0, DECIMAL_STR_WIDTH(j->id));
1210 l1 = MAX(l1, strlen(j->name));
1211 l2 = MAX(l2, strlen(j->type));
1212 l3 = MAX(l3, strlen(j->state));
1215 if (!arg_full && l0 + 1 + l1 + l2 + 1 + l3 > columns()) {
1216 l1 = MAX(33u, columns() - l0 - l2 - l3 - 3);
1221 printf("%*s %-*s %-*s %-*s\n",
1227 for (i = 0, j = jobs; i < n; i++, j++) {
1228 _cleanup_free_ char *e = NULL;
1230 if (streq(j->state, "running")) {
1231 on = ansi_highlight(true);
1232 off = ansi_highlight(false);
1236 e = shorten ? ellipsize(j->name, l1, 33) : NULL;
1237 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
1239 on, l1, e ? e : j->name, off,
1241 on, l3, j->state, off);
1245 on = ansi_highlight(true);
1246 off = ansi_highlight(false);
1249 printf("\n%s%zu jobs listed%s.\n", on, n, off);
1252 static int list_jobs(DBusConnection *bus, char **args) {
1253 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1254 DBusMessageIter iter, sub, sub2;
1256 struct job_info *jobs = NULL;
1257 size_t size = 0, used = 0;
1259 r = bus_method_call_with_reply(
1261 "org.freedesktop.systemd1",
1262 "/org/freedesktop/systemd1",
1263 "org.freedesktop.systemd1.Manager",
1271 if (!dbus_message_iter_init(reply, &iter) ||
1272 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1273 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1274 log_error("Failed to parse reply.");
1278 dbus_message_iter_recurse(&iter, &sub);
1280 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1281 const char *name, *type, *state, *job_path, *unit_path;
1284 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1285 log_error("Failed to parse reply.");
1289 dbus_message_iter_recurse(&sub, &sub2);
1291 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1292 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1293 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1294 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1295 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1296 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1297 log_error("Failed to parse reply.");
1302 if (!GREEDY_REALLOC(jobs, size, used + 1)) {
1307 jobs[used++] = (struct job_info) { id,
1311 if (!jobs[used-1].name || !jobs[used-1].type || !jobs[used-1].state) {
1316 dbus_message_iter_next(&sub);
1319 list_jobs_print(jobs, used);
1323 free(jobs[used].name);
1324 free(jobs[used].type);
1325 free(jobs[used].state);
1332 static int load_unit(DBusConnection *bus, char **args) {
1337 STRV_FOREACH(name, args+1) {
1338 _cleanup_free_ char *n = NULL;
1341 n = unit_name_mangle(*name);
1345 r = bus_method_call_with_reply(
1347 "org.freedesktop.systemd1",
1348 "/org/freedesktop/systemd1",
1349 "org.freedesktop.systemd1.Manager",
1353 DBUS_TYPE_STRING, &n,
1362 static int cancel_job(DBusConnection *bus, char **args) {
1367 if (strv_length(args) <= 1)
1368 return daemon_reload(bus, args);
1370 STRV_FOREACH(name, args+1) {
1374 r = safe_atou32(*name, &id);
1376 log_error("Failed to parse job id: %s", strerror(-r));
1380 r = bus_method_call_with_reply(
1382 "org.freedesktop.systemd1",
1383 "/org/freedesktop/systemd1",
1384 "org.freedesktop.systemd1.Manager",
1388 DBUS_TYPE_UINT32, &id,
1397 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1398 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1399 dbus_bool_t b = FALSE;
1400 DBusMessageIter iter, sub;
1402 *interface = "org.freedesktop.systemd1.Unit",
1403 *property = "NeedDaemonReload",
1405 _cleanup_free_ char *n = NULL;
1408 /* We ignore all errors here, since this is used to show a warning only */
1410 n = unit_name_mangle(unit);
1414 r = bus_method_call_with_reply(
1416 "org.freedesktop.systemd1",
1417 "/org/freedesktop/systemd1",
1418 "org.freedesktop.systemd1.Manager",
1422 DBUS_TYPE_STRING, &n,
1427 if (!dbus_message_get_args(reply, NULL,
1428 DBUS_TYPE_OBJECT_PATH, &path,
1432 dbus_message_unref(reply);
1435 r = bus_method_call_with_reply(
1437 "org.freedesktop.systemd1",
1439 "org.freedesktop.DBus.Properties",
1443 DBUS_TYPE_STRING, &interface,
1444 DBUS_TYPE_STRING, &property,
1449 if (!dbus_message_iter_init(reply, &iter) ||
1450 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1453 dbus_message_iter_recurse(&iter, &sub);
1454 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1457 dbus_message_iter_get_basic(&sub, &b);
1461 typedef struct WaitData {
1468 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1469 _cleanup_dbus_error_free_ DBusError error;
1472 dbus_error_init(&error);
1478 log_debug("Got D-Bus request: %s.%s() on %s",
1479 dbus_message_get_interface(message),
1480 dbus_message_get_member(message),
1481 dbus_message_get_path(message));
1483 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1484 log_error("Warning! D-Bus connection terminated.");
1485 dbus_connection_close(connection);
1487 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1489 const char *path, *result, *unit;
1491 if (dbus_message_get_args(message, &error,
1492 DBUS_TYPE_UINT32, &id,
1493 DBUS_TYPE_OBJECT_PATH, &path,
1494 DBUS_TYPE_STRING, &unit,
1495 DBUS_TYPE_STRING, &result,
1496 DBUS_TYPE_INVALID)) {
1498 free(set_remove(d->set, (char*) path));
1500 if (!isempty(result))
1501 d->result = strdup(result);
1504 d->name = strdup(unit);
1506 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1509 dbus_error_free(&error);
1510 if (dbus_message_get_args(message, &error,
1511 DBUS_TYPE_UINT32, &id,
1512 DBUS_TYPE_OBJECT_PATH, &path,
1513 DBUS_TYPE_STRING, &result,
1514 DBUS_TYPE_INVALID)) {
1515 /* Compatibility with older systemd versions <
1516 * 183 during upgrades. This should be dropped
1518 free(set_remove(d->set, (char*) path));
1521 d->result = strdup(result);
1523 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1527 log_error("Failed to parse message: %s", bus_error_message(&error));
1530 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1533 static int enable_wait_for_jobs(DBusConnection *bus) {
1541 dbus_error_init(&error);
1542 dbus_bus_add_match(bus,
1544 "sender='org.freedesktop.systemd1',"
1545 "interface='org.freedesktop.systemd1.Manager',"
1546 "member='JobRemoved',"
1547 "path='/org/freedesktop/systemd1'",
1550 if (dbus_error_is_set(&error)) {
1551 log_error("Failed to add match: %s", bus_error_message(&error));
1552 dbus_error_free(&error);
1556 /* This is slightly dirty, since we don't undo the match registrations. */
1560 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1562 WaitData d = { .set = s };
1567 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1570 while (!set_isempty(s)) {
1572 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1573 log_error("Disconnected from bus.");
1574 return -ECONNREFUSED;
1581 if (streq(d.result, "timeout"))
1582 log_error("Job for %s timed out.", strna(d.name));
1583 else if (streq(d.result, "canceled"))
1584 log_error("Job for %s canceled.", strna(d.name));
1585 else if (streq(d.result, "dependency"))
1586 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1587 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1588 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1591 if (streq_ptr(d.result, "timeout"))
1593 else if (streq_ptr(d.result, "canceled"))
1595 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1606 dbus_connection_remove_filter(bus, wait_filter, &d);
1610 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1611 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1612 _cleanup_free_ char *n = NULL;
1613 DBusMessageIter iter, sub;
1615 *interface = "org.freedesktop.systemd1.Unit",
1616 *property = "ActiveState";
1617 const char *state, *path;
1623 dbus_error_init(&error);
1625 n = unit_name_mangle(name);
1629 r = bus_method_call_with_reply (
1631 "org.freedesktop.systemd1",
1632 "/org/freedesktop/systemd1",
1633 "org.freedesktop.systemd1.Manager",
1637 DBUS_TYPE_STRING, &n,
1640 dbus_error_free(&error);
1647 if (!dbus_message_get_args(reply, NULL,
1648 DBUS_TYPE_OBJECT_PATH, &path,
1649 DBUS_TYPE_INVALID)) {
1650 log_error("Failed to parse reply.");
1654 dbus_message_unref(reply);
1657 r = bus_method_call_with_reply(
1659 "org.freedesktop.systemd1",
1661 "org.freedesktop.DBus.Properties",
1665 DBUS_TYPE_STRING, &interface,
1666 DBUS_TYPE_STRING, &property,
1674 if (!dbus_message_iter_init(reply, &iter) ||
1675 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1676 log_error("Failed to parse reply.");
1680 dbus_message_iter_recurse(&iter, &sub);
1682 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1683 log_error("Failed to parse reply.");
1687 dbus_message_iter_get_basic(&sub, &state);
1692 return strv_find(check_states, state) ? 1 : 0;
1695 static void check_triggering_units(
1696 DBusConnection *bus,
1697 const char *unit_name) {
1699 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1700 DBusMessageIter iter, sub;
1701 const char *interface = "org.freedesktop.systemd1.Unit",
1702 *load_state_property = "LoadState",
1703 *triggered_by_property = "TriggeredBy",
1705 _cleanup_free_ char *unit_path = NULL, *n = NULL;
1706 bool print_warning_label = true;
1709 n = unit_name_mangle(unit_name);
1715 unit_path = unit_dbus_path_from_name(n);
1721 r = bus_method_call_with_reply(
1723 "org.freedesktop.systemd1",
1725 "org.freedesktop.DBus.Properties",
1729 DBUS_TYPE_STRING, &interface,
1730 DBUS_TYPE_STRING, &load_state_property,
1735 if (!dbus_message_iter_init(reply, &iter) ||
1736 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1737 log_error("Failed to parse reply.");
1741 dbus_message_iter_recurse(&iter, &sub);
1743 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1744 log_error("Failed to parse reply.");
1748 dbus_message_iter_get_basic(&sub, &state);
1750 if (streq(state, "masked"))
1753 dbus_message_unref(reply);
1756 r = bus_method_call_with_reply(
1758 "org.freedesktop.systemd1",
1760 "org.freedesktop.DBus.Properties",
1764 DBUS_TYPE_STRING, &interface,
1765 DBUS_TYPE_STRING, &triggered_by_property,
1770 if (!dbus_message_iter_init(reply, &iter) ||
1771 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1772 log_error("Failed to parse reply.");
1776 dbus_message_iter_recurse(&iter, &sub);
1777 dbus_message_iter_recurse(&sub, &iter);
1780 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1781 const char * const check_states[] = {
1786 const char *service_trigger;
1788 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1789 log_error("Failed to parse reply.");
1793 dbus_message_iter_get_basic(&sub, &service_trigger);
1795 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1799 if (print_warning_label) {
1800 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1801 print_warning_label = false;
1804 log_warning(" %s", service_trigger);
1807 dbus_message_iter_next(&sub);
1811 static int start_unit_one(
1812 DBusConnection *bus,
1819 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1820 _cleanup_free_ char *n;
1829 n = unit_name_mangle(name);
1833 r = bus_method_call_with_reply(
1835 "org.freedesktop.systemd1",
1836 "/org/freedesktop/systemd1",
1837 "org.freedesktop.systemd1.Manager",
1841 DBUS_TYPE_STRING, &n,
1842 DBUS_TYPE_STRING, &mode,
1845 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1846 /* There's always a fallback possible for
1847 * legacy actions. */
1850 log_error("Failed to issue method call: %s", bus_error_message(error));
1855 if (!dbus_message_get_args(reply, error,
1856 DBUS_TYPE_OBJECT_PATH, &path,
1857 DBUS_TYPE_INVALID)) {
1858 log_error("Failed to parse reply: %s", bus_error_message(error));
1862 if (need_daemon_reload(bus, n))
1863 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1864 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1873 r = set_consume(s, p);
1875 log_error("Failed to add path to set.");
1883 static const struct {
1887 } action_table[_ACTION_MAX] = {
1888 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
1889 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
1890 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
1891 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
1892 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
1893 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
1894 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
1895 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
1896 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
1897 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
1898 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
1899 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
1900 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
1901 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
1902 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1905 static enum action verb_to_action(const char *verb) {
1908 for (i = ACTION_INVALID; i < _ACTION_MAX; i++)
1909 if (action_table[i].verb && streq(verb, action_table[i].verb))
1911 return ACTION_INVALID;
1914 static int start_unit(DBusConnection *bus, char **args) {
1917 const char *method, *mode, *one_name;
1918 _cleanup_set_free_free_ Set *s = NULL;
1919 _cleanup_dbus_error_free_ DBusError error;
1922 dbus_error_init(&error);
1926 ask_password_agent_open_if_enabled();
1928 if (arg_action == ACTION_SYSTEMCTL) {
1931 streq(args[0], "stop") ||
1932 streq(args[0], "condstop") ? "StopUnit" :
1933 streq(args[0], "reload") ? "ReloadUnit" :
1934 streq(args[0], "restart") ? "RestartUnit" :
1936 streq(args[0], "try-restart") ||
1937 streq(args[0], "condrestart") ? "TryRestartUnit" :
1939 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1941 streq(args[0], "reload-or-try-restart") ||
1942 streq(args[0], "condreload") ||
1944 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1946 action = verb_to_action(args[0]);
1948 mode = streq(args[0], "isolate") ? "isolate" :
1949 action_table[action].mode ?: arg_job_mode;
1951 one_name = action_table[action].target;
1954 assert(arg_action < ELEMENTSOF(action_table));
1955 assert(action_table[arg_action].target);
1957 method = "StartUnit";
1959 mode = action_table[arg_action].mode;
1960 one_name = action_table[arg_action].target;
1963 if (!arg_no_block) {
1964 ret = enable_wait_for_jobs(bus);
1966 log_error("Could not watch jobs: %s", strerror(-ret));
1970 s = set_new(string_hash_func, string_compare_func);
1976 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1978 ret = translate_bus_error_to_exit_status(ret, &error);
1980 STRV_FOREACH(name, args+1) {
1981 r = start_unit_one(bus, method, *name, mode, &error, s);
1983 ret = translate_bus_error_to_exit_status(r, &error);
1984 dbus_error_free(&error);
1989 if (!arg_no_block) {
1990 r = wait_for_jobs(bus, s);
1994 /* When stopping units, warn if they can still be triggered by
1995 * another active unit (socket, path, timer) */
1996 if (!arg_quiet && streq(method, "StopUnit")) {
1998 check_triggering_units(bus, one_name);
2000 STRV_FOREACH(name, args+1)
2001 check_triggering_units(bus, *name);
2008 /* Ask systemd-logind, which might grant access to unprivileged users
2009 * through PolicyKit */
2010 static int reboot_with_logind(DBusConnection *bus, enum action a) {
2013 dbus_bool_t interactive = true;
2018 polkit_agent_open_if_enabled();
2026 case ACTION_POWEROFF:
2027 method = "PowerOff";
2030 case ACTION_SUSPEND:
2034 case ACTION_HIBERNATE:
2035 method = "Hibernate";
2038 case ACTION_HYBRID_SLEEP:
2039 method = "HybridSleep";
2046 return bus_method_call_with_reply(
2048 "org.freedesktop.login1",
2049 "/org/freedesktop/login1",
2050 "org.freedesktop.login1.Manager",
2054 DBUS_TYPE_BOOLEAN, &interactive,
2061 static int check_inhibitors(DBusConnection *bus, enum action a) {
2063 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2064 DBusMessageIter iter, sub, sub2;
2067 _cleanup_strv_free_ char **sessions = NULL;
2073 if (arg_ignore_inhibitors || arg_force > 0)
2085 r = bus_method_call_with_reply(
2087 "org.freedesktop.login1",
2088 "/org/freedesktop/login1",
2089 "org.freedesktop.login1.Manager",
2095 /* If logind is not around, then there are no inhibitors... */
2098 if (!dbus_message_iter_init(reply, &iter) ||
2099 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2100 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
2101 log_error("Failed to parse reply.");
2105 dbus_message_iter_recurse(&iter, &sub);
2106 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2107 const char *what, *who, *why, *mode;
2109 _cleanup_strv_free_ char **sv = NULL;
2110 _cleanup_free_ char *comm = NULL, *user = NULL;
2112 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
2113 log_error("Failed to parse reply.");
2117 dbus_message_iter_recurse(&sub, &sub2);
2119 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
2120 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
2121 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
2122 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
2123 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
2124 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
2125 log_error("Failed to parse reply.");
2129 if (!streq(mode, "block"))
2132 sv = strv_split(what, ":");
2136 if (!strv_contains(sv,
2138 a == ACTION_POWEROFF ||
2139 a == ACTION_REBOOT ||
2140 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2143 get_process_comm(pid, &comm);
2144 user = uid_to_name(uid);
2145 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2146 who, (unsigned long) pid, strna(comm), strna(user), why);
2150 dbus_message_iter_next(&sub);
2153 dbus_message_iter_recurse(&iter, &sub);
2155 /* Check for current sessions */
2156 sd_get_sessions(&sessions);
2157 STRV_FOREACH(s, sessions) {
2159 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2161 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2164 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2167 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2170 sd_session_get_tty(*s, &tty);
2171 sd_session_get_seat(*s, &seat);
2172 sd_session_get_service(*s, &service);
2173 user = uid_to_name(uid);
2175 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2182 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2183 action_table[a].verb);
2191 static int start_special(DBusConnection *bus, char **args) {
2197 a = verb_to_action(args[0]);
2199 r = check_inhibitors(bus, a);
2203 if (arg_force >= 2 && geteuid() != 0) {
2204 log_error("Must be root.");
2208 if (arg_force >= 2 &&
2209 (a == ACTION_HALT ||
2210 a == ACTION_POWEROFF ||
2211 a == ACTION_REBOOT))
2214 if (arg_force >= 1 &&
2215 (a == ACTION_HALT ||
2216 a == ACTION_POWEROFF ||
2217 a == ACTION_REBOOT ||
2218 a == ACTION_KEXEC ||
2220 return daemon_reload(bus, args);
2222 /* first try logind, to allow authentication with polkit */
2223 if (geteuid() != 0 &&
2224 (a == ACTION_POWEROFF ||
2225 a == ACTION_REBOOT ||
2226 a == ACTION_SUSPEND ||
2227 a == ACTION_HIBERNATE ||
2228 a == ACTION_HYBRID_SLEEP)) {
2229 r = reboot_with_logind(bus, a);
2234 r = start_unit(bus, args);
2235 if (r == EXIT_SUCCESS)
2241 static int check_unit_active(DBusConnection *bus, char **args) {
2242 const char * const check_states[] = {
2249 int r = 3; /* According to LSB: "program is not running" */
2254 STRV_FOREACH(name, args+1) {
2257 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2267 static int check_unit_failed(DBusConnection *bus, char **args) {
2268 const char * const check_states[] = {
2279 STRV_FOREACH(name, args+1) {
2282 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2292 static int kill_unit(DBusConnection *bus, char **args) {
2300 arg_kill_who = "all";
2302 STRV_FOREACH(name, args+1) {
2303 _cleanup_free_ char *n = NULL;
2305 n = unit_name_mangle(*name);
2309 r = bus_method_call_with_reply(
2311 "org.freedesktop.systemd1",
2312 "/org/freedesktop/systemd1",
2313 "org.freedesktop.systemd1.Manager",
2317 DBUS_TYPE_STRING, &n,
2318 DBUS_TYPE_STRING, &arg_kill_who,
2319 DBUS_TYPE_INT32, &arg_signal,
2327 static int set_cgroup(DBusConnection *bus, char **args) {
2328 _cleanup_free_ char *n = NULL;
2329 const char *method, *runtime;
2337 streq(args[0], "set-cgroup") ? "SetUnitControlGroup" :
2338 streq(args[0], "unset-cgroup") ? "UnsetUnitControlGroup"
2339 : "UnsetUnitControlGroupAttribute";
2341 runtime = arg_runtime ? "runtime" : "persistent";
2343 n = unit_name_mangle(args[1]);
2347 STRV_FOREACH(argument, args + 2) {
2349 r = bus_method_call_with_reply(
2351 "org.freedesktop.systemd1",
2352 "/org/freedesktop/systemd1",
2353 "org.freedesktop.systemd1.Manager",
2357 DBUS_TYPE_STRING, &n,
2358 DBUS_TYPE_STRING, argument,
2359 DBUS_TYPE_STRING, &runtime,
2368 static int set_cgroup_attr(DBusConnection *bus, char **args) {
2369 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2371 DBusMessageIter iter;
2372 _cleanup_free_ char *n = NULL;
2373 const char *runtime;
2379 dbus_error_init(&error);
2381 runtime = arg_runtime ? "runtime" : "persistent";
2383 n = unit_name_mangle(args[1]);
2387 m = dbus_message_new_method_call(
2388 "org.freedesktop.systemd1",
2389 "/org/freedesktop/systemd1",
2390 "org.freedesktop.systemd1.Manager",
2391 "SetUnitControlGroupAttribute");
2395 dbus_message_iter_init_append(m, &iter);
2396 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2397 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[2]))
2400 r = bus_append_strv_iter(&iter, args + 3);
2404 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2407 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2409 log_error("Failed to issue method call: %s", bus_error_message(&error));
2410 dbus_error_free(&error);
2417 static int get_cgroup_attr(DBusConnection *bus, char **args) {
2418 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2419 _cleanup_free_ char *n = NULL;
2426 n = unit_name_mangle(args[1]);
2430 STRV_FOREACH(argument, args + 2) {
2431 _cleanup_strv_free_ char **list = NULL;
2432 DBusMessageIter iter;
2435 r = bus_method_call_with_reply(
2437 "org.freedesktop.systemd1",
2438 "/org/freedesktop/systemd1",
2439 "org.freedesktop.systemd1.Manager",
2440 "GetUnitControlGroupAttribute",
2443 DBUS_TYPE_STRING, &n,
2444 DBUS_TYPE_STRING, argument,
2449 if (!dbus_message_iter_init(reply, &iter)) {
2450 log_error("Failed to initialize iterator.");
2454 r = bus_parse_strv_iter(&iter, &list);
2456 log_error("Failed to parse value list.");
2460 STRV_FOREACH(a, list) {
2461 if (endswith(*a, "\n"))
2471 typedef struct ExecStatusInfo {
2479 usec_t start_timestamp;
2480 usec_t exit_timestamp;
2485 LIST_FIELDS(struct ExecStatusInfo, exec);
2488 static void exec_status_info_free(ExecStatusInfo *i) {
2497 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2498 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2499 DBusMessageIter sub2, sub3;
2503 int32_t code, status;
2509 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2512 dbus_message_iter_recurse(sub, &sub2);
2514 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2517 i->path = strdup(path);
2521 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2522 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2526 dbus_message_iter_recurse(&sub2, &sub3);
2527 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2528 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2529 dbus_message_iter_next(&sub3);
2533 i->argv = new0(char*, n+1);
2538 dbus_message_iter_recurse(&sub2, &sub3);
2539 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2542 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2543 dbus_message_iter_get_basic(&sub3, &s);
2544 dbus_message_iter_next(&sub3);
2546 i->argv[n] = strdup(s);
2553 if (!dbus_message_iter_next(&sub2) ||
2554 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2555 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2556 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2557 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2558 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2559 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2560 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2561 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2565 i->start_timestamp = (usec_t) start_timestamp;
2566 i->exit_timestamp = (usec_t) exit_timestamp;
2567 i->pid = (pid_t) pid;
2574 typedef struct UnitStatusInfo {
2576 const char *load_state;
2577 const char *active_state;
2578 const char *sub_state;
2579 const char *unit_file_state;
2581 const char *description;
2582 const char *following;
2584 char **documentation;
2586 const char *fragment_path;
2587 const char *source_path;
2588 const char *default_control_group;
2590 char **dropin_paths;
2592 const char *load_error;
2595 usec_t inactive_exit_timestamp;
2596 usec_t inactive_exit_timestamp_monotonic;
2597 usec_t active_enter_timestamp;
2598 usec_t active_exit_timestamp;
2599 usec_t inactive_enter_timestamp;
2601 bool need_daemon_reload;
2606 const char *status_text;
2609 usec_t start_timestamp;
2610 usec_t exit_timestamp;
2612 int exit_code, exit_status;
2614 usec_t condition_timestamp;
2615 bool condition_result;
2618 unsigned n_accepted;
2619 unsigned n_connections;
2622 /* Pairs of type, path */
2626 const char *sysfs_path;
2628 /* Mount, Automount */
2634 LIST_HEAD(ExecStatusInfo, exec);
2637 static void print_status_info(UnitStatusInfo *i) {
2639 const char *on, *off, *ss;
2641 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2642 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2645 arg_all * OUTPUT_SHOW_ALL |
2646 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2647 on_tty() * OUTPUT_COLOR |
2648 !arg_quiet * OUTPUT_WARN_CUTOFF |
2649 arg_full * OUTPUT_FULL_WIDTH;
2650 int maxlen = 8; /* a value that'll suffice most of the time */
2655 STRV_FOREACH_PAIR(t, t2, i->listen)
2656 maxlen = MAX(maxlen, (int)(sizeof("Listen") - 1 + strlen(*t)));
2658 maxlen = MAX(maxlen, (int)sizeof("Accept") - 1);
2659 if (i->main_pid > 0)
2660 maxlen = MAX(maxlen, (int)sizeof("Main PID") - 1);
2661 else if (i->control_pid > 0)
2662 maxlen = MAX(maxlen, (int)sizeof("Control") - 1);
2664 /* This shows pretty information about a unit. See
2665 * print_property() for a low-level property printer */
2667 printf("%s", strna(i->id));
2669 if (i->description && !streq_ptr(i->id, i->description))
2670 printf(" - %s", i->description);
2675 printf(" %*s: unit currently follows state of %s\n", maxlen, "Follow", i->following);
2677 if (streq_ptr(i->load_state, "error")) {
2678 on = ansi_highlight_red(true);
2679 off = ansi_highlight_red(false);
2683 path = i->source_path ? i->source_path : i->fragment_path;
2686 printf(" %*s: %s%s%s (Reason: %s)\n",
2687 maxlen, "Loaded", on, strna(i->load_state), off, i->load_error);
2688 else if (path && i->unit_file_state)
2689 printf(" %*s: %s%s%s (%s; %s)\n",
2690 maxlen, "Loaded", on, strna(i->load_state), off, path, i->unit_file_state);
2692 printf(" %*s: %s%s%s (%s)\n",
2693 maxlen, "Loaded", on, strna(i->load_state), off, path);
2695 printf(" %*s: %s%s%s\n",
2696 maxlen, "Loaded", on, strna(i->load_state), off);
2698 if (!strv_isempty(i->dropin_paths)) {
2703 STRV_FOREACH(dropin, i->dropin_paths) {
2704 if (! dir || last) {
2705 printf(" %*s ", maxlen, dir ? "" : "Drop-In:");
2709 if (path_get_parent(*dropin, &dir) < 0) {
2714 printf("%s\n %*s %s", dir, maxlen, "",
2715 draw_special_char(DRAW_TREE_RIGHT));
2718 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
2720 printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", ");
2726 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2728 if (streq_ptr(i->active_state, "failed")) {
2729 on = ansi_highlight_red(true);
2730 off = ansi_highlight_red(false);
2731 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2732 on = ansi_highlight_green(true);
2733 off = ansi_highlight_green(false);
2738 printf(" %*s: %s%s (%s)%s",
2739 maxlen, "Active", on, strna(i->active_state), ss, off);
2741 printf(" %*s: %s%s%s",
2742 maxlen, "Active", on, strna(i->active_state), off);
2744 if (!isempty(i->result) && !streq(i->result, "success"))
2745 printf(" (Result: %s)", i->result);
2747 timestamp = (streq_ptr(i->active_state, "active") ||
2748 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2749 (streq_ptr(i->active_state, "inactive") ||
2750 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2751 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2752 i->active_exit_timestamp;
2754 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2755 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2758 printf(" since %s; %s\n", s2, s1);
2760 printf(" since %s\n", s2);
2764 if (!i->condition_result && i->condition_timestamp > 0) {
2765 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2766 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2769 printf(" %*s start condition failed at %s; %s\n", maxlen, "", s2, s1);
2771 printf(" %*s start condition failed at %s\n", maxlen, "", s2);
2775 printf(" %*s: %s\n", maxlen, "Device", i->sysfs_path);
2777 printf(" %*s: %s\n", maxlen, "Where", i->where);
2779 printf(" %*s: %s\n", maxlen, "What", i->what);
2781 STRV_FOREACH(t, i->documentation)
2782 printf(" %*s %s\n", maxlen+1, t == i->documentation ? "Docs:" : "", *t);
2784 STRV_FOREACH_PAIR(t, t2, i->listen)
2785 printf(" %*s %s (%s)\n", maxlen+1, t == i->listen ? "Listen:" : "", *t2, *t);
2788 printf(" %*s: %u; Connected: %u\n", maxlen, "Accepted", i->n_accepted, i->n_connections);
2790 LIST_FOREACH(exec, p, i->exec) {
2791 _cleanup_free_ char *argv = NULL;
2794 /* Only show exited processes here */
2798 argv = strv_join(p->argv, " ");
2799 printf(" %*s: %u %s=%s ", maxlen, "Process", p->pid, p->name, strna(argv));
2801 good = is_clean_exit_lsb(p->code, p->status, NULL);
2803 on = ansi_highlight_red(true);
2804 off = ansi_highlight_red(false);
2808 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2810 if (p->code == CLD_EXITED) {
2813 printf("status=%i", p->status);
2815 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2820 printf("signal=%s", signal_to_string(p->status));
2822 printf(")%s\n", off);
2824 if (i->main_pid == p->pid &&
2825 i->start_timestamp == p->start_timestamp &&
2826 i->exit_timestamp == p->start_timestamp)
2827 /* Let's not show this twice */
2830 if (p->pid == i->control_pid)
2834 if (i->main_pid > 0 || i->control_pid > 0) {
2835 if (i->main_pid > 0) {
2836 printf(" %*s: %u", maxlen, "Main PID", (unsigned) i->main_pid);
2839 _cleanup_free_ char *comm = NULL;
2840 get_process_comm(i->main_pid, &comm);
2842 printf(" (%s)", comm);
2843 } else if (i->exit_code > 0) {
2844 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2846 if (i->exit_code == CLD_EXITED) {
2849 printf("status=%i", i->exit_status);
2851 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2856 printf("signal=%s", signal_to_string(i->exit_status));
2860 if (i->control_pid > 0)
2864 if (i->control_pid > 0) {
2865 _cleanup_free_ char *c = NULL;
2867 printf(" %*s: %u", i->main_pid ? 0 : maxlen, "Control", (unsigned) i->control_pid);
2869 get_process_comm(i->control_pid, &c);
2878 printf(" %*s: \"%s\"\n", maxlen, "Status", i->status_text);
2880 if (i->default_control_group &&
2881 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2884 printf(" %*s: %s\n", maxlen, "CGroup", i->default_control_group);
2886 if (arg_transport != TRANSPORT_SSH) {
2889 char prefix[maxlen + 4];
2890 memset(prefix, ' ', sizeof(prefix) - 1);
2891 prefix[sizeof(prefix) - 1] = '\0';
2894 if (c > sizeof(prefix) - 1)
2895 c -= sizeof(prefix) - 1;
2899 if (i->main_pid > 0)
2900 extra[k++] = i->main_pid;
2902 if (i->control_pid > 0)
2903 extra[k++] = i->control_pid;
2905 show_cgroup_and_extra_by_spec(i->default_control_group, prefix,
2906 c, false, extra, k, flags);
2910 if (i->id && arg_transport != TRANSPORT_SSH) {
2912 show_journal_by_unit(stdout,
2916 i->inactive_exit_timestamp_monotonic,
2920 arg_scope == UNIT_FILE_SYSTEM);
2923 if (i->need_daemon_reload)
2924 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2925 ansi_highlight_red(true),
2926 ansi_highlight_red(false),
2927 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2930 static void show_unit_help(UnitStatusInfo *i) {
2935 if (!i->documentation) {
2936 log_info("Documentation for %s not known.", i->id);
2940 STRV_FOREACH(p, i->documentation) {
2942 if (startswith(*p, "man:")) {
2945 _cleanup_free_ char *page = NULL, *section = NULL;
2946 const char *args[4] = { "man", NULL, NULL, NULL };
2951 if ((*p)[k-1] == ')')
2952 e = strrchr(*p, '(');
2955 page = strndup((*p) + 4, e - *p - 4);
2956 section = strndup(e + 1, *p + k - e - 2);
2957 if (!page || !section) {
2969 log_error("Failed to fork: %m");
2975 execvp(args[0], (char**) args);
2976 log_error("Failed to execute man: %m");
2977 _exit(EXIT_FAILURE);
2980 wait_for_terminate(pid, NULL);
2982 log_info("Can't show: %s", *p);
2986 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2992 switch (dbus_message_iter_get_arg_type(iter)) {
2994 case DBUS_TYPE_STRING: {
2997 dbus_message_iter_get_basic(iter, &s);
3000 if (streq(name, "Id"))
3002 else if (streq(name, "LoadState"))
3004 else if (streq(name, "ActiveState"))
3005 i->active_state = s;
3006 else if (streq(name, "SubState"))
3008 else if (streq(name, "Description"))
3010 else if (streq(name, "FragmentPath"))
3011 i->fragment_path = s;
3012 else if (streq(name, "SourcePath"))
3014 else if (streq(name, "DefaultControlGroup"))
3015 i->default_control_group = s;
3016 else if (streq(name, "StatusText"))
3018 else if (streq(name, "SysFSPath"))
3020 else if (streq(name, "Where"))
3022 else if (streq(name, "What"))
3024 else if (streq(name, "Following"))
3026 else if (streq(name, "UnitFileState"))
3027 i->unit_file_state = s;
3028 else if (streq(name, "Result"))
3035 case DBUS_TYPE_BOOLEAN: {
3038 dbus_message_iter_get_basic(iter, &b);
3040 if (streq(name, "Accept"))
3042 else if (streq(name, "NeedDaemonReload"))
3043 i->need_daemon_reload = b;
3044 else if (streq(name, "ConditionResult"))
3045 i->condition_result = b;
3050 case DBUS_TYPE_UINT32: {
3053 dbus_message_iter_get_basic(iter, &u);
3055 if (streq(name, "MainPID")) {
3057 i->main_pid = (pid_t) u;
3060 } else if (streq(name, "ControlPID"))
3061 i->control_pid = (pid_t) u;
3062 else if (streq(name, "ExecMainPID")) {
3064 i->main_pid = (pid_t) u;
3065 } else if (streq(name, "NAccepted"))
3067 else if (streq(name, "NConnections"))
3068 i->n_connections = u;
3073 case DBUS_TYPE_INT32: {
3076 dbus_message_iter_get_basic(iter, &j);
3078 if (streq(name, "ExecMainCode"))
3079 i->exit_code = (int) j;
3080 else if (streq(name, "ExecMainStatus"))
3081 i->exit_status = (int) j;
3086 case DBUS_TYPE_UINT64: {
3089 dbus_message_iter_get_basic(iter, &u);
3091 if (streq(name, "ExecMainStartTimestamp"))
3092 i->start_timestamp = (usec_t) u;
3093 else if (streq(name, "ExecMainExitTimestamp"))
3094 i->exit_timestamp = (usec_t) u;
3095 else if (streq(name, "ActiveEnterTimestamp"))
3096 i->active_enter_timestamp = (usec_t) u;
3097 else if (streq(name, "InactiveEnterTimestamp"))
3098 i->inactive_enter_timestamp = (usec_t) u;
3099 else if (streq(name, "InactiveExitTimestamp"))
3100 i->inactive_exit_timestamp = (usec_t) u;
3101 else if (streq(name, "InactiveExitTimestampMonotonic"))
3102 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3103 else if (streq(name, "ActiveExitTimestamp"))
3104 i->active_exit_timestamp = (usec_t) u;
3105 else if (streq(name, "ConditionTimestamp"))
3106 i->condition_timestamp = (usec_t) u;
3111 case DBUS_TYPE_ARRAY: {
3113 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3114 startswith(name, "Exec")) {
3115 DBusMessageIter sub;
3117 dbus_message_iter_recurse(iter, &sub);
3118 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3119 ExecStatusInfo *info;
3122 if (!(info = new0(ExecStatusInfo, 1)))
3125 if (!(info->name = strdup(name))) {
3130 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
3135 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
3137 dbus_message_iter_next(&sub);
3140 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3141 DBusMessageIter sub, sub2;
3143 dbus_message_iter_recurse(iter, &sub);
3144 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3145 const char *type, *path;
3147 dbus_message_iter_recurse(&sub, &sub2);
3149 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3150 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
3153 r = strv_extend(&i->listen, type);
3156 r = strv_extend(&i->listen, path);
3161 dbus_message_iter_next(&sub);
3166 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING && streq(name, "DropInPaths")) {
3167 int r = bus_parse_strv_iter(iter, &i->dropin_paths);
3171 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3172 streq(name, "Documentation")) {
3174 DBusMessageIter sub;
3176 dbus_message_iter_recurse(iter, &sub);
3177 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
3181 dbus_message_iter_get_basic(&sub, &s);
3183 r = strv_extend(&i->documentation, s);
3187 dbus_message_iter_next(&sub);
3194 case DBUS_TYPE_STRUCT: {
3196 if (streq(name, "LoadError")) {
3197 DBusMessageIter sub;
3198 const char *n, *message;
3201 dbus_message_iter_recurse(iter, &sub);
3203 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
3207 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
3211 if (!isempty(message))
3212 i->load_error = message;
3222 static int print_property(const char *name, DBusMessageIter *iter) {
3226 /* This is a low-level property printer, see
3227 * print_status_info() for the nicer output */
3229 if (arg_properties && !strv_find(arg_properties, name))
3232 switch (dbus_message_iter_get_arg_type(iter)) {
3234 case DBUS_TYPE_STRUCT: {
3235 DBusMessageIter sub;
3236 dbus_message_iter_recurse(iter, &sub);
3238 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
3241 dbus_message_iter_get_basic(&sub, &u);
3244 printf("%s=%u\n", name, (unsigned) u);
3246 printf("%s=\n", name);
3249 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
3252 dbus_message_iter_get_basic(&sub, &s);
3254 if (arg_all || s[0])
3255 printf("%s=%s\n", name, s);
3258 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
3259 const char *a = NULL, *b = NULL;
3261 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
3262 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
3264 if (arg_all || !isempty(a) || !isempty(b))
3265 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3273 case DBUS_TYPE_ARRAY:
3275 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
3276 DBusMessageIter sub, sub2;
3278 dbus_message_iter_recurse(iter, &sub);
3279 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3283 dbus_message_iter_recurse(&sub, &sub2);
3285 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3286 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3287 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3289 dbus_message_iter_next(&sub);
3294 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3295 DBusMessageIter sub, sub2;
3297 dbus_message_iter_recurse(iter, &sub);
3299 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3300 const char *type, *path;
3302 dbus_message_iter_recurse(&sub, &sub2);
3304 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3305 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3306 printf("%s=%s\n", type, path);
3308 dbus_message_iter_next(&sub);
3313 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3314 DBusMessageIter sub, sub2;
3316 dbus_message_iter_recurse(iter, &sub);
3317 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3318 const char *type, *path;
3320 dbus_message_iter_recurse(&sub, &sub2);
3322 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3323 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3324 printf("Listen%s=%s\n", type, path);
3326 dbus_message_iter_next(&sub);
3331 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3332 DBusMessageIter sub, sub2;
3334 dbus_message_iter_recurse(iter, &sub);
3335 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3337 uint64_t value, next_elapse;
3339 dbus_message_iter_recurse(&sub, &sub2);
3341 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3342 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3343 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3344 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3346 printf("%s={ value=%s ; next_elapse=%s }\n",
3348 format_timespan(timespan1, sizeof(timespan1), value, 0),
3349 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3352 dbus_message_iter_next(&sub);
3357 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
3358 DBusMessageIter sub, sub2;
3360 dbus_message_iter_recurse(iter, &sub);
3361 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3362 const char *controller, *attr, *value;
3364 dbus_message_iter_recurse(&sub, &sub2);
3366 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
3367 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
3368 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
3370 printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
3376 dbus_message_iter_next(&sub);
3381 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3382 DBusMessageIter sub;
3384 dbus_message_iter_recurse(iter, &sub);
3385 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3386 ExecStatusInfo info = {};
3388 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3389 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3390 _cleanup_free_ char *t;
3392 t = strv_join(info.argv, " ");
3394 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3398 yes_no(info.ignore),
3399 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3400 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3401 (unsigned) info. pid,
3402 sigchld_code_to_string(info.code),
3404 info.code == CLD_EXITED ? "" : "/",
3405 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3409 strv_free(info.argv);
3411 dbus_message_iter_next(&sub);
3420 if (generic_print_property(name, iter, arg_all) > 0)
3424 printf("%s=[unprintable]\n", name);
3429 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3430 _cleanup_free_ DBusMessage *reply = NULL;
3431 const char *interface = "";
3433 DBusMessageIter iter, sub, sub2, sub3;
3434 UnitStatusInfo info = {};
3440 r = bus_method_call_with_reply(
3442 "org.freedesktop.systemd1",
3444 "org.freedesktop.DBus.Properties",
3448 DBUS_TYPE_STRING, &interface,
3453 if (!dbus_message_iter_init(reply, &iter) ||
3454 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3455 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3456 log_error("Failed to parse reply.");
3460 dbus_message_iter_recurse(&iter, &sub);
3467 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3470 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3471 dbus_message_iter_recurse(&sub, &sub2);
3473 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3474 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3475 log_error("Failed to parse reply.");
3479 dbus_message_iter_recurse(&sub2, &sub3);
3481 if (show_properties)
3482 r = print_property(name, &sub3);
3484 r = status_property(name, &sub3, &info);
3486 log_error("Failed to parse reply.");
3490 dbus_message_iter_next(&sub);
3495 if (!show_properties) {
3496 if (streq(verb, "help"))
3497 show_unit_help(&info);
3499 print_status_info(&info);
3502 strv_free(info.documentation);
3503 strv_free(info.dropin_paths);
3504 strv_free(info.listen);
3506 if (!streq_ptr(info.active_state, "active") &&
3507 !streq_ptr(info.active_state, "reloading") &&
3508 streq(verb, "status"))
3509 /* According to LSB: "program not running" */
3512 while ((p = info.exec)) {
3513 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3514 exec_status_info_free(p);
3520 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3521 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3522 const char *path = NULL;
3523 _cleanup_dbus_error_free_ DBusError error;
3526 dbus_error_init(&error);
3528 r = bus_method_call_with_reply(
3530 "org.freedesktop.systemd1",
3531 "/org/freedesktop/systemd1",
3532 "org.freedesktop.systemd1.Manager",
3536 DBUS_TYPE_UINT32, &pid,
3541 if (!dbus_message_get_args(reply, &error,
3542 DBUS_TYPE_OBJECT_PATH, &path,
3543 DBUS_TYPE_INVALID)) {
3544 log_error("Failed to parse reply: %s", bus_error_message(&error));
3548 r = show_one(verb, bus, path, false, new_line);
3552 static int show_all(const char* verb, DBusConnection *bus, bool show_properties, bool *new_line) {
3553 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3554 _cleanup_free_ struct unit_info *unit_infos = NULL;
3556 const struct unit_info *u;
3559 r = get_unit_list(bus, &reply, &unit_infos, &c);
3563 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
3565 for (u = unit_infos; u < unit_infos + c; u++) {
3566 _cleanup_free_ char *p = NULL;
3568 if (!output_show_unit(u))
3571 p = unit_dbus_path_from_name(u->id);
3575 printf("%s -> '%s'\n", u->id, p);
3577 r = show_one(verb, bus, p, show_properties, new_line);
3585 static int show(DBusConnection *bus, char **args) {
3587 bool show_properties, show_status, new_line = false;
3593 show_properties = streq(args[0], "show");
3594 show_status = streq(args[0], "status");
3596 if (show_properties)
3597 pager_open_if_enabled();
3599 /* If no argument is specified inspect the manager itself */
3601 if (show_properties && strv_length(args) <= 1)
3602 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3604 if (show_status && strv_length(args) <= 1)
3605 return show_all(args[0], bus, false, &new_line);
3607 STRV_FOREACH(name, args+1) {
3610 if (safe_atou32(*name, &id) < 0) {
3611 _cleanup_free_ char *p = NULL, *n = NULL;
3612 /* Interpret as unit name */
3614 n = unit_name_mangle(*name);
3618 p = unit_dbus_path_from_name(n);
3622 r = show_one(args[0], bus, p, show_properties, &new_line);
3626 } else if (show_properties) {
3627 _cleanup_free_ char *p = NULL;
3629 /* Interpret as job id */
3630 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3633 r = show_one(args[0], bus, p, show_properties, &new_line);
3638 /* Interpret as PID */
3639 r = show_one_by_pid(args[0], bus, id, &new_line);
3648 static int dump(DBusConnection *bus, char **args) {
3649 _cleanup_free_ DBusMessage *reply = NULL;
3654 dbus_error_init(&error);
3656 pager_open_if_enabled();
3658 r = bus_method_call_with_reply(
3660 "org.freedesktop.systemd1",
3661 "/org/freedesktop/systemd1",
3662 "org.freedesktop.systemd1.Manager",
3670 if (!dbus_message_get_args(reply, &error,
3671 DBUS_TYPE_STRING, &text,
3672 DBUS_TYPE_INVALID)) {
3673 log_error("Failed to parse reply: %s", bus_error_message(&error));
3674 dbus_error_free(&error);
3678 fputs(text, stdout);
3682 static int snapshot(DBusConnection *bus, char **args) {
3683 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3686 dbus_bool_t cleanup = FALSE;
3687 DBusMessageIter iter, sub;
3690 *interface = "org.freedesktop.systemd1.Unit",
3692 _cleanup_free_ char *n = NULL;
3694 dbus_error_init(&error);
3696 if (strv_length(args) > 1)
3697 n = snapshot_name_mangle(args[1]);
3703 r = bus_method_call_with_reply (
3705 "org.freedesktop.systemd1",
3706 "/org/freedesktop/systemd1",
3707 "org.freedesktop.systemd1.Manager",
3711 DBUS_TYPE_STRING, &n,
3712 DBUS_TYPE_BOOLEAN, &cleanup,
3717 if (!dbus_message_get_args(reply, &error,
3718 DBUS_TYPE_OBJECT_PATH, &path,
3719 DBUS_TYPE_INVALID)) {
3720 log_error("Failed to parse reply: %s", bus_error_message(&error));
3721 dbus_error_free(&error);
3725 dbus_message_unref(reply);
3728 r = bus_method_call_with_reply (
3730 "org.freedesktop.systemd1",
3732 "org.freedesktop.DBus.Properties",
3736 DBUS_TYPE_STRING, &interface,
3737 DBUS_TYPE_STRING, &property,
3742 if (!dbus_message_iter_init(reply, &iter) ||
3743 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3744 log_error("Failed to parse reply.");
3748 dbus_message_iter_recurse(&iter, &sub);
3750 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3751 log_error("Failed to parse reply.");
3755 dbus_message_iter_get_basic(&sub, &id);
3763 static int delete_snapshot(DBusConnection *bus, char **args) {
3768 STRV_FOREACH(name, args+1) {
3769 _cleanup_free_ char *n = NULL;
3772 n = snapshot_name_mangle(*name);
3776 r = bus_method_call_with_reply(
3778 "org.freedesktop.systemd1",
3779 "/org/freedesktop/systemd1",
3780 "org.freedesktop.systemd1.Manager",
3784 DBUS_TYPE_STRING, &n,
3793 static int daemon_reload(DBusConnection *bus, char **args) {
3798 if (arg_action == ACTION_RELOAD)
3800 else if (arg_action == ACTION_REEXEC)
3801 method = "Reexecute";
3803 assert(arg_action == ACTION_SYSTEMCTL);
3806 streq(args[0], "clear-jobs") ||
3807 streq(args[0], "cancel") ? "ClearJobs" :
3808 streq(args[0], "daemon-reexec") ? "Reexecute" :
3809 streq(args[0], "reset-failed") ? "ResetFailed" :
3810 streq(args[0], "halt") ? "Halt" :
3811 streq(args[0], "poweroff") ? "PowerOff" :
3812 streq(args[0], "reboot") ? "Reboot" :
3813 streq(args[0], "kexec") ? "KExec" :
3814 streq(args[0], "exit") ? "Exit" :
3815 /* "daemon-reload" */ "Reload";
3818 r = bus_method_call_with_reply(
3820 "org.freedesktop.systemd1",
3821 "/org/freedesktop/systemd1",
3822 "org.freedesktop.systemd1.Manager",
3828 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3829 /* There's always a fallback possible for
3830 * legacy actions. */
3832 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3833 /* On reexecution, we expect a disconnect, not
3837 log_error("Failed to issue method call: %s", bus_error_message(&error));
3839 dbus_error_free(&error);
3843 static int reset_failed(DBusConnection *bus, char **args) {
3847 if (strv_length(args) <= 1)
3848 return daemon_reload(bus, args);
3850 STRV_FOREACH(name, args+1) {
3851 _cleanup_free_ char *n;
3853 n = unit_name_mangle(*name);
3857 r = bus_method_call_with_reply(
3859 "org.freedesktop.systemd1",
3860 "/org/freedesktop/systemd1",
3861 "org.freedesktop.systemd1.Manager",
3865 DBUS_TYPE_STRING, &n,
3874 static int show_enviroment(DBusConnection *bus, char **args) {
3875 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3876 DBusMessageIter iter, sub, sub2;
3879 *interface = "org.freedesktop.systemd1.Manager",
3880 *property = "Environment";
3882 pager_open_if_enabled();
3884 r = bus_method_call_with_reply(
3886 "org.freedesktop.systemd1",
3887 "/org/freedesktop/systemd1",
3888 "org.freedesktop.DBus.Properties",
3892 DBUS_TYPE_STRING, &interface,
3893 DBUS_TYPE_STRING, &property,
3898 if (!dbus_message_iter_init(reply, &iter) ||
3899 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3900 log_error("Failed to parse reply.");
3904 dbus_message_iter_recurse(&iter, &sub);
3906 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3907 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3908 log_error("Failed to parse reply.");
3912 dbus_message_iter_recurse(&sub, &sub2);
3914 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3917 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3918 log_error("Failed to parse reply.");
3922 dbus_message_iter_get_basic(&sub2, &text);
3925 dbus_message_iter_next(&sub2);
3931 static int switch_root(DBusConnection *bus, char **args) {
3934 _cleanup_free_ char *init = NULL;
3936 l = strv_length(args);
3937 if (l < 2 || l > 3) {
3938 log_error("Wrong number of arguments.");
3945 init = strdup(args[2]);
3947 parse_env_file("/proc/cmdline", WHITESPACE,
3957 log_debug("switching root - root: %s; init: %s", root, init);
3959 return bus_method_call_with_reply(
3961 "org.freedesktop.systemd1",
3962 "/org/freedesktop/systemd1",
3963 "org.freedesktop.systemd1.Manager",
3967 DBUS_TYPE_STRING, &root,
3968 DBUS_TYPE_STRING, &init,
3972 static int set_environment(DBusConnection *bus, char **args) {
3973 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3976 DBusMessageIter iter;
3982 dbus_error_init(&error);
3984 method = streq(args[0], "set-environment")
3986 : "UnsetEnvironment";
3988 m = dbus_message_new_method_call(
3989 "org.freedesktop.systemd1",
3990 "/org/freedesktop/systemd1",
3991 "org.freedesktop.systemd1.Manager",
3996 dbus_message_iter_init_append(m, &iter);
3998 r = bus_append_strv_iter(&iter, args + 1);
4002 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4004 log_error("Failed to issue method call: %s", bus_error_message(&error));
4005 dbus_error_free(&error);
4012 static int enable_sysv_units(char **args) {
4015 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4016 const char *verb = args[0];
4017 unsigned f = 1, t = 1;
4018 LookupPaths paths = {};
4020 if (arg_scope != UNIT_FILE_SYSTEM)
4023 if (!streq(verb, "enable") &&
4024 !streq(verb, "disable") &&
4025 !streq(verb, "is-enabled"))
4028 /* Processes all SysV units, and reshuffles the array so that
4029 * afterwards only the native units remain */
4031 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4036 for (f = 1; args[f]; f++) {
4038 _cleanup_free_ char *p = NULL, *q = NULL;
4039 bool found_native = false, found_sysv;
4041 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4049 if (!endswith(name, ".service"))
4052 if (path_is_absolute(name))
4055 STRV_FOREACH(k, paths.unit_path) {
4056 if (!isempty(arg_root))
4057 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4059 asprintf(&p, "%s/%s", *k, name);
4066 found_native = access(p, F_OK) >= 0;
4077 if (!isempty(arg_root))
4078 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4080 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4086 p[strlen(p) - sizeof(".service") + 1] = 0;
4087 found_sysv = access(p, F_OK) >= 0;
4092 /* Mark this entry, so that we don't try enabling it as native unit */
4093 args[f] = (char*) "";
4095 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4097 if (!isempty(arg_root))
4098 argv[c++] = q = strappend("--root=", arg_root);
4100 argv[c++] = path_get_file_name(p);
4102 streq(verb, "enable") ? "on" :
4103 streq(verb, "disable") ? "off" : "--level=5";
4106 l = strv_join((char**)argv, " ");
4112 log_info("Executing %s", l);
4117 log_error("Failed to fork: %m");
4120 } else if (pid == 0) {
4123 execv(argv[0], (char**) argv);
4124 _exit(EXIT_FAILURE);
4127 j = wait_for_terminate(pid, &status);
4129 log_error("Failed to wait for child: %s", strerror(-r));
4134 if (status.si_code == CLD_EXITED) {
4135 if (streq(verb, "is-enabled")) {
4136 if (status.si_status == 0) {
4145 } else if (status.si_status != 0) {
4156 lookup_paths_free(&paths);
4158 /* Drop all SysV units */
4159 for (f = 1, t = 1; args[f]; f++) {
4161 if (isempty(args[f]))
4164 args[t++] = args[f];
4173 static int mangle_names(char **original_names, char ***mangled_names) {
4174 char **i, **l, **name;
4176 l = new(char*, strv_length(original_names) + 1);
4181 STRV_FOREACH(name, original_names) {
4183 /* When enabling units qualified path names are OK,
4184 * too, hence allow them explicitly. */
4189 *i = unit_name_mangle(*name);
4205 static int enable_unit(DBusConnection *bus, char **args) {
4206 const char *verb = args[0];
4207 UnitFileChange *changes = NULL;
4208 unsigned n_changes = 0, i;
4209 int carries_install_info = -1;
4210 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4212 _cleanup_dbus_error_free_ DBusError error;
4213 _cleanup_strv_free_ char **mangled_names = NULL;
4215 dbus_error_init(&error);
4217 r = enable_sysv_units(args);
4224 if (!bus || avoid_bus()) {
4225 if (streq(verb, "enable")) {
4226 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4227 carries_install_info = r;
4228 } else if (streq(verb, "disable"))
4229 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
4230 else if (streq(verb, "reenable")) {
4231 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4232 carries_install_info = r;
4233 } else if (streq(verb, "link"))
4234 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4235 else if (streq(verb, "preset")) {
4236 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4237 carries_install_info = r;
4238 } else if (streq(verb, "mask"))
4239 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4240 else if (streq(verb, "unmask"))
4241 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
4243 assert_not_reached("Unknown verb");
4246 log_error("Operation failed: %s", strerror(-r));
4251 for (i = 0; i < n_changes; i++) {
4252 if (changes[i].type == UNIT_FILE_SYMLINK)
4253 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4255 log_info("rm '%s'", changes[i].path);
4262 bool send_force = true, expect_carries_install_info = false;
4264 DBusMessageIter iter, sub, sub2;
4266 if (streq(verb, "enable")) {
4267 method = "EnableUnitFiles";
4268 expect_carries_install_info = true;
4269 } else if (streq(verb, "disable")) {
4270 method = "DisableUnitFiles";
4272 } else if (streq(verb, "reenable")) {
4273 method = "ReenableUnitFiles";
4274 expect_carries_install_info = true;
4275 } else if (streq(verb, "link"))
4276 method = "LinkUnitFiles";
4277 else if (streq(verb, "preset")) {
4278 method = "PresetUnitFiles";
4279 expect_carries_install_info = true;
4280 } else if (streq(verb, "mask"))
4281 method = "MaskUnitFiles";
4282 else if (streq(verb, "unmask")) {
4283 method = "UnmaskUnitFiles";
4286 assert_not_reached("Unknown verb");
4288 m = dbus_message_new_method_call(
4289 "org.freedesktop.systemd1",
4290 "/org/freedesktop/systemd1",
4291 "org.freedesktop.systemd1.Manager",
4298 dbus_message_iter_init_append(m, &iter);
4300 r = mangle_names(args+1, &mangled_names);
4304 r = bus_append_strv_iter(&iter, mangled_names);
4306 log_error("Failed to append unit files.");
4311 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4312 log_error("Failed to append runtime boolean.");
4320 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4321 log_error("Failed to append force boolean.");
4327 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4329 log_error("Failed to issue method call: %s", bus_error_message(&error));
4334 if (!dbus_message_iter_init(reply, &iter)) {
4335 log_error("Failed to initialize iterator.");
4339 if (expect_carries_install_info) {
4340 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4342 log_error("Failed to parse reply.");
4346 carries_install_info = b;
4349 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4350 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4351 log_error("Failed to parse reply.");
4356 dbus_message_iter_recurse(&iter, &sub);
4357 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4358 const char *type, *path, *source;
4360 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4361 log_error("Failed to parse reply.");
4366 dbus_message_iter_recurse(&sub, &sub2);
4368 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4369 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4370 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4371 log_error("Failed to parse reply.");
4377 if (streq(type, "symlink"))
4378 log_info("ln -s '%s' '%s'", source, path);
4380 log_info("rm '%s'", path);
4383 dbus_message_iter_next(&sub);
4386 /* Try to reload if enabeld */
4388 r = daemon_reload(bus, args);
4391 if (carries_install_info == 0)
4392 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4393 "using systemctl.\n"
4394 "Possible reasons for having this kind of units are:\n"
4395 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4396 " .wants/ or .requires/ directory.\n"
4397 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4398 " a requirement dependency on it.\n"
4399 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4400 " D-Bus, udev, scripted systemctl call, ...).\n");
4403 unit_file_changes_free(changes, n_changes);
4408 static int unit_is_enabled(DBusConnection *bus, char **args) {
4409 _cleanup_dbus_error_free_ DBusError error;
4411 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4416 dbus_error_init(&error);
4418 r = enable_sysv_units(args);
4424 if (!bus || avoid_bus()) {
4426 STRV_FOREACH(name, args+1) {
4427 UnitFileState state;
4429 n = unit_name_mangle(*name);
4433 state = unit_file_get_state(arg_scope, arg_root, n);
4440 if (state == UNIT_FILE_ENABLED ||
4441 state == UNIT_FILE_ENABLED_RUNTIME ||
4442 state == UNIT_FILE_STATIC)
4446 puts(unit_file_state_to_string(state));
4450 STRV_FOREACH(name, args+1) {
4453 n = unit_name_mangle(*name);
4457 r = bus_method_call_with_reply (
4459 "org.freedesktop.systemd1",
4460 "/org/freedesktop/systemd1",
4461 "org.freedesktop.systemd1.Manager",
4465 DBUS_TYPE_STRING, &n,
4473 if (!dbus_message_get_args(reply, &error,
4474 DBUS_TYPE_STRING, &s,
4475 DBUS_TYPE_INVALID)) {
4476 log_error("Failed to parse reply: %s", bus_error_message(&error));
4480 dbus_message_unref(reply);
4483 if (streq(s, "enabled") ||
4484 streq(s, "enabled-runtime") ||
4493 return enabled ? 0 : 1;
4496 static int systemctl_help(void) {
4498 pager_open_if_enabled();
4500 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4501 "Query or send control commands to the systemd manager.\n\n"
4502 " -h --help Show this help\n"
4503 " --version Show package version\n"
4504 " -t --type=TYPE List only units of a particular type\n"
4505 " -p --property=NAME Show only properties by this name\n"
4506 " -a --all Show all loaded units/properties, including dead/empty\n"
4507 " ones. To list all units installed on the system, use\n"
4508 " the 'list-unit-files' command instead.\n"
4509 " --reverse Show reverse dependencies with 'list-dependencies'\n"
4510 " --failed Show only failed units\n"
4511 " --full Don't ellipsize unit names on output\n"
4512 " --fail When queueing a new job, fail if conflicting jobs are\n"
4514 " --irreversible Create jobs which cannot be implicitly cancelled\n"
4515 " --show-types When showing sockets, explicitly show their type\n"
4516 " --ignore-dependencies\n"
4517 " When queueing a new job, ignore all its dependencies\n"
4518 " -i --ignore-inhibitors\n"
4519 " When shutting down or sleeping, ignore inhibitors\n"
4520 " --kill-who=WHO Who to send signal to\n"
4521 " -s --signal=SIGNAL Which signal to send\n"
4522 " -H --host=[USER@]HOST\n"
4523 " Show information for remote host\n"
4524 " -P --privileged Acquire privileges before execution\n"
4525 " -q --quiet Suppress output\n"
4526 " --no-block Do not wait until operation finished\n"
4527 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4528 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4530 " --no-legend Do not print a legend (column headers and hints)\n"
4531 " --no-pager Do not pipe output into a pager\n"
4532 " --no-ask-password\n"
4533 " Do not ask for system passwords\n"
4534 " --system Connect to system manager\n"
4535 " --user Connect to user service manager\n"
4536 " --global Enable/disable unit files globally\n"
4537 " -f --force When enabling unit files, override existing symlinks\n"
4538 " When shutting down, execute action immediately\n"
4539 " --root=PATH Enable unit files in the specified root directory\n"
4540 " --runtime Enable unit files only temporarily until next reboot\n"
4541 " -n --lines=INTEGER Journal entries to show\n"
4542 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4543 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4545 " list-units List loaded units\n"
4546 " start [NAME...] Start (activate) one or more units\n"
4547 " stop [NAME...] Stop (deactivate) one or more units\n"
4548 " reload [NAME...] Reload one or more units\n"
4549 " restart [NAME...] Start or restart one or more units\n"
4550 " try-restart [NAME...] Restart one or more units if active\n"
4551 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4552 " otherwise start or restart\n"
4553 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4554 " otherwise restart if active\n"
4555 " isolate [NAME] Start one unit and stop all others\n"
4556 " kill [NAME...] Send signal to processes of a unit\n"
4557 " is-active [NAME...] Check whether units are active\n"
4558 " is-failed [NAME...] Check whether units are failed\n"
4559 " status [NAME...|PID...] Show runtime status of one or more units\n"
4560 " show [NAME...|JOB...] Show properties of one or more\n"
4561 " units/jobs or the manager\n"
4562 " help [NAME...|PID...] Show manual for one or more units\n"
4563 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4565 " get-cgroup-attr [NAME] [ATTR] ...\n"
4566 " Get control group attrubute\n"
4567 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4568 " Set control group attribute\n"
4569 " unset-cgroup-attr [NAME] [ATTR...]\n"
4570 " Unset control group attribute\n"
4571 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4572 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4573 " load [NAME...] Load one or more units\n"
4574 " list-dependencies [NAME] Recursively show units which are required\n"
4575 " or wanted by this unit or by which this\n"
4576 " unit is required or wanted\n\n"
4577 "Unit File Commands:\n"
4578 " list-unit-files List installed unit files\n"
4579 " enable [NAME...] Enable one or more unit files\n"
4580 " disable [NAME...] Disable one or more unit files\n"
4581 " reenable [NAME...] Reenable one or more unit files\n"
4582 " preset [NAME...] Enable/disable one or more unit files\n"
4583 " based on preset configuration\n"
4584 " mask [NAME...] Mask one or more units\n"
4585 " unmask [NAME...] Unmask one or more units\n"
4586 " link [PATH...] Link one or more units files into\n"
4587 " the search path\n"
4588 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4590 " list-jobs List jobs\n"
4591 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4592 "Status Commands:\n"
4593 " dump Dump server status\n"
4594 "Snapshot Commands:\n"
4595 " snapshot [NAME] Create a snapshot\n"
4596 " delete [NAME...] Remove one or more snapshots\n\n"
4597 "Environment Commands:\n"
4598 " show-environment Dump environment\n"
4599 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4600 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4601 "Manager Lifecycle Commands:\n"
4602 " daemon-reload Reload systemd manager configuration\n"
4603 " daemon-reexec Reexecute systemd manager\n\n"
4604 "System Commands:\n"
4605 " default Enter system default mode\n"
4606 " rescue Enter system rescue mode\n"
4607 " emergency Enter system emergency mode\n"
4608 " halt Shut down and halt the system\n"
4609 " poweroff Shut down and power-off the system\n"
4610 " reboot Shut down and reboot the system\n"
4611 " kexec Shut down and reboot the system with kexec\n"
4612 " exit Request user instance exit\n"
4613 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4614 " suspend Suspend the system\n"
4615 " hibernate Hibernate the system\n"
4616 " hybrid-sleep Hibernate and suspend the system\n",
4617 program_invocation_short_name);
4622 static int halt_help(void) {
4624 printf("%s [OPTIONS...]\n\n"
4625 "%s the system.\n\n"
4626 " --help Show this help\n"
4627 " --halt Halt the machine\n"
4628 " -p --poweroff Switch off the machine\n"
4629 " --reboot Reboot the machine\n"
4630 " -f --force Force immediate halt/power-off/reboot\n"
4631 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4632 " -d --no-wtmp Don't write wtmp record\n"
4633 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4634 program_invocation_short_name,
4635 arg_action == ACTION_REBOOT ? "Reboot" :
4636 arg_action == ACTION_POWEROFF ? "Power off" :
4642 static int shutdown_help(void) {
4644 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4645 "Shut down the system.\n\n"
4646 " --help Show this help\n"
4647 " -H --halt Halt the machine\n"
4648 " -P --poweroff Power-off the machine\n"
4649 " -r --reboot Reboot the machine\n"
4650 " -h Equivalent to --poweroff, overridden by --halt\n"
4651 " -k Don't halt/power-off/reboot, just send warnings\n"
4652 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4653 " -c Cancel a pending shutdown\n",
4654 program_invocation_short_name);
4659 static int telinit_help(void) {
4661 printf("%s [OPTIONS...] {COMMAND}\n\n"
4662 "Send control commands to the init daemon.\n\n"
4663 " --help Show this help\n"
4664 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4666 " 0 Power-off the machine\n"
4667 " 6 Reboot the machine\n"
4668 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4669 " 1, s, S Enter rescue mode\n"
4670 " q, Q Reload init daemon configuration\n"
4671 " u, U Reexecute init daemon\n",
4672 program_invocation_short_name);
4677 static int runlevel_help(void) {
4679 printf("%s [OPTIONS...]\n\n"
4680 "Prints the previous and current runlevel of the init system.\n\n"
4681 " --help Show this help\n",
4682 program_invocation_short_name);
4687 static int help_types(void) {
4691 puts("Available unit types:");
4692 for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4693 t = unit_type_to_string(i);
4698 puts("\nAvailable unit load states: ");
4699 for(i = 0; i < _UNIT_LOAD_STATE_MAX; i++) {
4700 t = unit_load_state_to_string(i);
4708 static int systemctl_parse_argv(int argc, char *argv[]) {
4717 ARG_IGNORE_DEPENDENCIES,
4730 ARG_NO_ASK_PASSWORD,
4737 static const struct option options[] = {
4738 { "help", no_argument, NULL, 'h' },
4739 { "version", no_argument, NULL, ARG_VERSION },
4740 { "type", required_argument, NULL, 't' },
4741 { "property", required_argument, NULL, 'p' },
4742 { "all", no_argument, NULL, 'a' },
4743 { "reverse", no_argument, NULL, ARG_REVERSE },
4744 { "after", no_argument, NULL, ARG_AFTER },
4745 { "before", no_argument, NULL, ARG_BEFORE },
4746 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
4747 { "failed", no_argument, NULL, ARG_FAILED },
4748 { "full", no_argument, NULL, ARG_FULL },
4749 { "fail", no_argument, NULL, ARG_FAIL },
4750 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4751 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4752 { "ignore-inhibitors", no_argument, NULL, 'i' },
4753 { "user", no_argument, NULL, ARG_USER },
4754 { "system", no_argument, NULL, ARG_SYSTEM },
4755 { "global", no_argument, NULL, ARG_GLOBAL },
4756 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4757 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4758 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4759 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4760 { "quiet", no_argument, NULL, 'q' },
4761 { "root", required_argument, NULL, ARG_ROOT },
4762 { "force", no_argument, NULL, ARG_FORCE },
4763 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4764 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4765 { "signal", required_argument, NULL, 's' },
4766 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4767 { "host", required_argument, NULL, 'H' },
4768 { "privileged",no_argument, NULL, 'P' },
4769 { "runtime", no_argument, NULL, ARG_RUNTIME },
4770 { "lines", required_argument, NULL, 'n' },
4771 { "output", required_argument, NULL, 'o' },
4772 { "plain", no_argument, NULL, ARG_PLAIN },
4773 { NULL, 0, NULL, 0 }
4781 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4790 puts(PACKAGE_STRING);
4791 puts(SYSTEMD_FEATURES);
4798 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4799 _cleanup_free_ char *type;
4801 type = strndup(word, size);
4805 if (streq(type, "help")) {
4810 if (unit_type_from_string(type) >= 0) {
4811 if (strv_push(&arg_types, type))
4817 if (unit_load_state_from_string(optarg) >= 0) {
4818 if (strv_push(&arg_load_states, type))
4824 log_error("Unknown unit type or load state '%s'.", type);
4825 log_info("Use -t help to see a list of allowed values.");
4833 /* Make sure that if the empty property list
4834 was specified, we won't show any properties. */
4835 if (isempty(optarg) && !arg_properties) {
4836 arg_properties = strv_new(NULL, NULL);
4837 if (!arg_properties)
4843 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4846 prop = strndup(word, size);
4850 if (strv_push(&arg_properties, prop)) {
4857 /* If the user asked for a particular
4858 * property, show it to him, even if it is
4870 arg_dependency = DEPENDENCY_REVERSE;
4874 arg_dependency = DEPENDENCY_AFTER;
4878 arg_dependency = DEPENDENCY_BEFORE;
4881 case ARG_SHOW_TYPES:
4882 arg_show_types = true;
4886 arg_job_mode = "fail";
4889 case ARG_IRREVERSIBLE:
4890 arg_job_mode = "replace-irreversibly";
4893 case ARG_IGNORE_DEPENDENCIES:
4894 arg_job_mode = "ignore-dependencies";
4898 arg_scope = UNIT_FILE_USER;
4902 arg_scope = UNIT_FILE_SYSTEM;
4906 arg_scope = UNIT_FILE_GLOBAL;
4910 arg_no_block = true;
4914 arg_no_legend = true;
4918 arg_no_pager = true;
4950 arg_no_reload = true;
4954 arg_kill_who = optarg;
4958 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4959 log_error("Failed to parse signal string %s.", optarg);
4964 case ARG_NO_ASK_PASSWORD:
4965 arg_ask_password = false;
4969 arg_transport = TRANSPORT_POLKIT;
4973 arg_transport = TRANSPORT_SSH;
4982 if (safe_atou(optarg, &arg_lines) < 0) {
4983 log_error("Failed to parse lines '%s'", optarg);
4989 arg_output = output_mode_from_string(optarg);
4990 if (arg_output < 0) {
4991 log_error("Unknown output '%s'.", optarg);
4997 arg_ignore_inhibitors = true;
5008 log_error("Unknown option code '%c'.", c);
5013 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
5014 log_error("Cannot access user instance remotely.");
5021 static int halt_parse_argv(int argc, char *argv[]) {
5030 static const struct option options[] = {
5031 { "help", no_argument, NULL, ARG_HELP },
5032 { "halt", no_argument, NULL, ARG_HALT },
5033 { "poweroff", no_argument, NULL, 'p' },
5034 { "reboot", no_argument, NULL, ARG_REBOOT },
5035 { "force", no_argument, NULL, 'f' },
5036 { "wtmp-only", no_argument, NULL, 'w' },
5037 { "no-wtmp", no_argument, NULL, 'd' },
5038 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5039 { NULL, 0, NULL, 0 }
5047 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5048 if (runlevel == '0' || runlevel == '6')
5051 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5059 arg_action = ACTION_HALT;
5063 if (arg_action != ACTION_REBOOT)
5064 arg_action = ACTION_POWEROFF;
5068 arg_action = ACTION_REBOOT;
5090 /* Compatibility nops */
5097 log_error("Unknown option code '%c'.", c);
5102 if (optind < argc) {
5103 log_error("Too many arguments.");
5110 static int parse_time_spec(const char *t, usec_t *_u) {
5114 if (streq(t, "now"))
5116 else if (!strchr(t, ':')) {
5119 if (safe_atou64(t, &u) < 0)
5122 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5131 hour = strtol(t, &e, 10);
5132 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5135 minute = strtol(e+1, &e, 10);
5136 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5139 n = now(CLOCK_REALTIME);
5140 s = (time_t) (n / USEC_PER_SEC);
5142 assert_se(localtime_r(&s, &tm));
5144 tm.tm_hour = (int) hour;
5145 tm.tm_min = (int) minute;
5148 assert_se(s = mktime(&tm));
5150 *_u = (usec_t) s * USEC_PER_SEC;
5153 *_u += USEC_PER_DAY;
5159 static int shutdown_parse_argv(int argc, char *argv[]) {
5166 static const struct option options[] = {
5167 { "help", no_argument, NULL, ARG_HELP },
5168 { "halt", no_argument, NULL, 'H' },
5169 { "poweroff", no_argument, NULL, 'P' },
5170 { "reboot", no_argument, NULL, 'r' },
5171 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5172 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5173 { NULL, 0, NULL, 0 }
5181 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5189 arg_action = ACTION_HALT;
5193 arg_action = ACTION_POWEROFF;
5198 arg_action = ACTION_KEXEC;
5200 arg_action = ACTION_REBOOT;
5204 arg_action = ACTION_KEXEC;
5208 if (arg_action != ACTION_HALT)
5209 arg_action = ACTION_POWEROFF;
5222 /* Compatibility nops */
5226 arg_action = ACTION_CANCEL_SHUTDOWN;
5233 log_error("Unknown option code '%c'.", c);
5238 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5239 r = parse_time_spec(argv[optind], &arg_when);
5241 log_error("Failed to parse time specification: %s", argv[optind]);
5245 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5247 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5248 /* No time argument for shutdown cancel */
5249 arg_wall = argv + optind;
5250 else if (argc > optind + 1)
5251 /* We skip the time argument */
5252 arg_wall = argv + optind + 1;
5259 static int telinit_parse_argv(int argc, char *argv[]) {
5266 static const struct option options[] = {
5267 { "help", no_argument, NULL, ARG_HELP },
5268 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5269 { NULL, 0, NULL, 0 }
5272 static const struct {
5276 { '0', ACTION_POWEROFF },
5277 { '6', ACTION_REBOOT },
5278 { '1', ACTION_RESCUE },
5279 { '2', ACTION_RUNLEVEL2 },
5280 { '3', ACTION_RUNLEVEL3 },
5281 { '4', ACTION_RUNLEVEL4 },
5282 { '5', ACTION_RUNLEVEL5 },
5283 { 's', ACTION_RESCUE },
5284 { 'S', ACTION_RESCUE },
5285 { 'q', ACTION_RELOAD },
5286 { 'Q', ACTION_RELOAD },
5287 { 'u', ACTION_REEXEC },
5288 { 'U', ACTION_REEXEC }
5297 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5312 log_error("Unknown option code '%c'.", c);
5317 if (optind >= argc) {
5322 if (optind + 1 < argc) {
5323 log_error("Too many arguments.");
5327 if (strlen(argv[optind]) != 1) {
5328 log_error("Expected single character argument.");
5332 for (i = 0; i < ELEMENTSOF(table); i++)
5333 if (table[i].from == argv[optind][0])
5336 if (i >= ELEMENTSOF(table)) {
5337 log_error("Unknown command '%s'.", argv[optind]);
5341 arg_action = table[i].to;
5348 static int runlevel_parse_argv(int argc, char *argv[]) {
5354 static const struct option options[] = {
5355 { "help", no_argument, NULL, ARG_HELP },
5356 { NULL, 0, NULL, 0 }
5364 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5375 log_error("Unknown option code '%c'.", c);
5380 if (optind < argc) {
5381 log_error("Too many arguments.");
5388 static int parse_argv(int argc, char *argv[]) {
5392 if (program_invocation_short_name) {
5394 if (strstr(program_invocation_short_name, "halt")) {
5395 arg_action = ACTION_HALT;
5396 return halt_parse_argv(argc, argv);
5397 } else if (strstr(program_invocation_short_name, "poweroff")) {
5398 arg_action = ACTION_POWEROFF;
5399 return halt_parse_argv(argc, argv);
5400 } else if (strstr(program_invocation_short_name, "reboot")) {
5402 arg_action = ACTION_KEXEC;
5404 arg_action = ACTION_REBOOT;
5405 return halt_parse_argv(argc, argv);
5406 } else if (strstr(program_invocation_short_name, "shutdown")) {
5407 arg_action = ACTION_POWEROFF;
5408 return shutdown_parse_argv(argc, argv);
5409 } else if (strstr(program_invocation_short_name, "init")) {
5411 if (sd_booted() > 0) {
5412 arg_action = ACTION_INVALID;
5413 return telinit_parse_argv(argc, argv);
5415 /* Hmm, so some other init system is
5416 * running, we need to forward this
5417 * request to it. For now we simply
5418 * guess that it is Upstart. */
5420 execv(TELINIT, argv);
5422 log_error("Couldn't find an alternative telinit implementation to spawn.");
5426 } else if (strstr(program_invocation_short_name, "runlevel")) {
5427 arg_action = ACTION_RUNLEVEL;
5428 return runlevel_parse_argv(argc, argv);
5432 arg_action = ACTION_SYSTEMCTL;
5433 return systemctl_parse_argv(argc, argv);
5436 _pure_ static int action_to_runlevel(void) {
5438 static const char table[_ACTION_MAX] = {
5439 [ACTION_HALT] = '0',
5440 [ACTION_POWEROFF] = '0',
5441 [ACTION_REBOOT] = '6',
5442 [ACTION_RUNLEVEL2] = '2',
5443 [ACTION_RUNLEVEL3] = '3',
5444 [ACTION_RUNLEVEL4] = '4',
5445 [ACTION_RUNLEVEL5] = '5',
5446 [ACTION_RESCUE] = '1'
5449 assert(arg_action < _ACTION_MAX);
5451 return table[arg_action];
5454 static int talk_upstart(void) {
5455 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
5456 _cleanup_dbus_error_free_ DBusError error;
5457 int previous, rl, r;
5459 env1_buf[] = "RUNLEVEL=X",
5460 env2_buf[] = "PREVLEVEL=X";
5461 char *env1 = env1_buf, *env2 = env2_buf;
5462 const char *emit = "runlevel";
5463 dbus_bool_t b_false = FALSE;
5464 DBusMessageIter iter, sub;
5465 DBusConnection *bus;
5467 dbus_error_init(&error);
5469 if (!(rl = action_to_runlevel()))
5472 if (utmp_get_runlevel(&previous, NULL) < 0)
5475 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5476 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5481 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5486 if ((r = bus_check_peercred(bus)) < 0) {
5487 log_error("Failed to verify owner of bus.");
5491 if (!(m = dbus_message_new_method_call(
5492 "com.ubuntu.Upstart",
5493 "/com/ubuntu/Upstart",
5494 "com.ubuntu.Upstart0_6",
5497 log_error("Could not allocate message.");
5502 dbus_message_iter_init_append(m, &iter);
5504 env1_buf[sizeof(env1_buf)-2] = rl;
5505 env2_buf[sizeof(env2_buf)-2] = previous;
5507 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5508 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5509 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5510 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5511 !dbus_message_iter_close_container(&iter, &sub) ||
5512 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5513 log_error("Could not append arguments to message.");
5518 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5520 if (bus_error_is_no_service(&error)) {
5525 log_error("Failed to issue method call: %s", bus_error_message(&error));
5534 dbus_connection_flush(bus);
5535 dbus_connection_close(bus);
5536 dbus_connection_unref(bus);
5542 static int talk_initctl(void) {
5543 struct init_request request = {};
5545 _cleanup_close_ int fd = -1;
5548 rl = action_to_runlevel();
5552 request.magic = INIT_MAGIC;
5553 request.sleeptime = 0;
5554 request.cmd = INIT_CMD_RUNLVL;
5555 request.runlevel = rl;
5557 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5559 if (errno == ENOENT)
5562 log_error("Failed to open "INIT_FIFO": %m");
5567 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5569 log_error("Failed to write to "INIT_FIFO": %m");
5570 return errno > 0 ? -errno : -EIO;
5576 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5578 static const struct {
5586 int (* const dispatch)(DBusConnection *bus, char **args);
5588 { "list-units", LESS, 1, list_units },
5589 { "list-unit-files", EQUAL, 1, list_unit_files },
5590 { "list-sockets", LESS, 1, list_sockets },
5591 { "list-jobs", EQUAL, 1, list_jobs },
5592 { "clear-jobs", EQUAL, 1, daemon_reload },
5593 { "load", MORE, 2, load_unit },
5594 { "cancel", MORE, 2, cancel_job },
5595 { "start", MORE, 2, start_unit },
5596 { "stop", MORE, 2, start_unit },
5597 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5598 { "reload", MORE, 2, start_unit },
5599 { "restart", MORE, 2, start_unit },
5600 { "try-restart", MORE, 2, start_unit },
5601 { "reload-or-restart", MORE, 2, start_unit },
5602 { "reload-or-try-restart", MORE, 2, start_unit },
5603 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5604 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5605 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5606 { "isolate", EQUAL, 2, start_unit },
5607 { "set-cgroup", MORE, 3, set_cgroup },
5608 { "unset-cgroup", MORE, 3, set_cgroup },
5609 { "get-cgroup-attr", MORE, 3, get_cgroup_attr },
5610 { "set-cgroup-attr", MORE, 4, set_cgroup_attr },
5611 { "unset-cgroup-attr", MORE, 3, set_cgroup },
5612 { "kill", MORE, 2, kill_unit },
5613 { "is-active", MORE, 2, check_unit_active },
5614 { "check", MORE, 2, check_unit_active },
5615 { "is-failed", MORE, 2, check_unit_failed },
5616 { "show", MORE, 1, show },
5617 { "status", MORE, 1, show },
5618 { "help", MORE, 2, show },
5619 { "dump", EQUAL, 1, dump },
5620 { "snapshot", LESS, 2, snapshot },
5621 { "delete", MORE, 2, delete_snapshot },
5622 { "daemon-reload", EQUAL, 1, daemon_reload },
5623 { "daemon-reexec", EQUAL, 1, daemon_reload },
5624 { "show-environment", EQUAL, 1, show_enviroment },
5625 { "set-environment", MORE, 2, set_environment },
5626 { "unset-environment", MORE, 2, set_environment },
5627 { "halt", EQUAL, 1, start_special },
5628 { "poweroff", EQUAL, 1, start_special },
5629 { "reboot", EQUAL, 1, start_special },
5630 { "kexec", EQUAL, 1, start_special },
5631 { "suspend", EQUAL, 1, start_special },
5632 { "hibernate", EQUAL, 1, start_special },
5633 { "hybrid-sleep", EQUAL, 1, start_special },
5634 { "default", EQUAL, 1, start_special },
5635 { "rescue", EQUAL, 1, start_special },
5636 { "emergency", EQUAL, 1, start_special },
5637 { "exit", EQUAL, 1, start_special },
5638 { "reset-failed", MORE, 1, reset_failed },
5639 { "enable", MORE, 2, enable_unit },
5640 { "disable", MORE, 2, enable_unit },
5641 { "is-enabled", MORE, 2, unit_is_enabled },
5642 { "reenable", MORE, 2, enable_unit },
5643 { "preset", MORE, 2, enable_unit },
5644 { "mask", MORE, 2, enable_unit },
5645 { "unmask", MORE, 2, enable_unit },
5646 { "link", MORE, 2, enable_unit },
5647 { "switch-root", MORE, 2, switch_root },
5648 { "list-dependencies", LESS, 2, list_dependencies },
5658 left = argc - optind;
5661 /* Special rule: no arguments means "list-units" */
5664 if (streq(argv[optind], "help") && !argv[optind+1]) {
5665 log_error("This command expects one or more "
5666 "unit names. Did you mean --help?");
5670 for (i = 0; i < ELEMENTSOF(verbs); i++)
5671 if (streq(argv[optind], verbs[i].verb))
5674 if (i >= ELEMENTSOF(verbs)) {
5675 log_error("Unknown operation '%s'.", argv[optind]);
5680 switch (verbs[i].argc_cmp) {
5683 if (left != verbs[i].argc) {
5684 log_error("Invalid number of arguments.");
5691 if (left < verbs[i].argc) {
5692 log_error("Too few arguments.");
5699 if (left > verbs[i].argc) {
5700 log_error("Too many arguments.");
5707 assert_not_reached("Unknown comparison operator.");
5710 /* Require a bus connection for all operations but
5712 if (!streq(verbs[i].verb, "enable") &&
5713 !streq(verbs[i].verb, "disable") &&
5714 !streq(verbs[i].verb, "is-enabled") &&
5715 !streq(verbs[i].verb, "list-unit-files") &&
5716 !streq(verbs[i].verb, "reenable") &&
5717 !streq(verbs[i].verb, "preset") &&
5718 !streq(verbs[i].verb, "mask") &&
5719 !streq(verbs[i].verb, "unmask") &&
5720 !streq(verbs[i].verb, "link")) {
5722 if (running_in_chroot() > 0) {
5723 log_info("Running in chroot, ignoring request.");
5727 if (((!streq(verbs[i].verb, "reboot") &&
5728 !streq(verbs[i].verb, "halt") &&
5729 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5730 log_error("Failed to get D-Bus connection: %s",
5731 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5737 if (!bus && !avoid_bus()) {
5738 log_error("Failed to get D-Bus connection: %s",
5739 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5744 return verbs[i].dispatch(bus, argv + optind);
5747 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5748 _cleanup_close_ int fd;
5749 struct sd_shutdown_command c = {
5755 union sockaddr_union sockaddr = {
5756 .un.sun_family = AF_UNIX,
5757 .un.sun_path = "/run/systemd/shutdownd",
5759 struct iovec iovec[2] = {
5760 {.iov_base = (char*) &c,
5761 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
5764 struct msghdr msghdr = {
5765 .msg_name = &sockaddr,
5766 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
5767 + sizeof("/run/systemd/shutdownd") - 1,
5772 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5776 if (!isempty(message)) {
5777 iovec[1].iov_base = (char*) message;
5778 iovec[1].iov_len = strlen(message);
5779 msghdr.msg_iovlen++;
5782 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5788 static int reload_with_fallback(DBusConnection *bus) {
5791 /* First, try systemd via D-Bus. */
5792 if (daemon_reload(bus, NULL) >= 0)
5796 /* Nothing else worked, so let's try signals */
5797 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5799 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5800 log_error("kill() failed: %m");
5807 static int start_with_fallback(DBusConnection *bus) {
5810 /* First, try systemd via D-Bus. */
5811 if (start_unit(bus, NULL) >= 0)
5815 /* Hmm, talking to systemd via D-Bus didn't work. Then
5816 * let's try to talk to Upstart via D-Bus. */
5817 if (talk_upstart() > 0)
5820 /* Nothing else worked, so let's try
5822 if (talk_initctl() > 0)
5825 log_error("Failed to talk to init daemon.");
5829 warn_wall(arg_action);
5833 static _noreturn_ void halt_now(enum action a) {
5835 /* Make sure C-A-D is handled by the kernel from this
5837 reboot(RB_ENABLE_CAD);
5842 log_info("Halting.");
5843 reboot(RB_HALT_SYSTEM);
5846 case ACTION_POWEROFF:
5847 log_info("Powering off.");
5848 reboot(RB_POWER_OFF);
5852 log_info("Rebooting.");
5853 reboot(RB_AUTOBOOT);
5857 assert_not_reached("Unknown halt action.");
5860 assert_not_reached("Uh? This shouldn't happen.");
5863 static int halt_main(DBusConnection *bus) {
5866 r = check_inhibitors(bus, arg_action);
5870 if (geteuid() != 0) {
5871 /* Try logind if we are a normal user and no special
5872 * mode applies. Maybe PolicyKit allows us to shutdown
5875 if (arg_when <= 0 &&
5878 (arg_action == ACTION_POWEROFF ||
5879 arg_action == ACTION_REBOOT)) {
5880 r = reboot_with_logind(bus, arg_action);
5885 log_error("Must be root.");
5890 _cleanup_free_ char *m;
5892 m = strv_join(arg_wall, " ");
5893 r = send_shutdownd(arg_when,
5894 arg_action == ACTION_HALT ? 'H' :
5895 arg_action == ACTION_POWEROFF ? 'P' :
5896 arg_action == ACTION_KEXEC ? 'K' :
5903 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5905 char date[FORMAT_TIMESTAMP_MAX];
5907 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5908 format_timestamp(date, sizeof(date), arg_when));
5913 if (!arg_dry && !arg_force)
5914 return start_with_fallback(bus);
5917 if (sd_booted() > 0)
5918 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5920 r = utmp_put_shutdown();
5922 log_warning("Failed to write utmp record: %s", strerror(-r));
5929 halt_now(arg_action);
5930 /* We should never reach this. */
5934 static int runlevel_main(void) {
5935 int r, runlevel, previous;
5937 r = utmp_get_runlevel(&runlevel, &previous);
5944 previous <= 0 ? 'N' : previous,
5945 runlevel <= 0 ? 'N' : runlevel);
5950 int main(int argc, char*argv[]) {
5951 int r, retval = EXIT_FAILURE;
5952 DBusConnection *bus = NULL;
5953 _cleanup_dbus_error_free_ DBusError error;
5955 dbus_error_init(&error);
5957 setlocale(LC_ALL, "");
5958 log_parse_environment();
5961 r = parse_argv(argc, argv);
5965 retval = EXIT_SUCCESS;
5969 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5970 * let's shortcut this */
5971 if (arg_action == ACTION_RUNLEVEL) {
5972 r = runlevel_main();
5973 retval = r < 0 ? EXIT_FAILURE : r;
5977 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5978 log_info("Running in chroot, ignoring request.");
5984 if (arg_transport == TRANSPORT_NORMAL)
5985 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5986 else if (arg_transport == TRANSPORT_POLKIT) {
5987 bus_connect_system_polkit(&bus, &error);
5988 private_bus = false;
5989 } else if (arg_transport == TRANSPORT_SSH) {
5990 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5991 private_bus = false;
5993 assert_not_reached("Uh, invalid transport...");
5996 switch (arg_action) {
5998 case ACTION_SYSTEMCTL:
5999 r = systemctl_main(bus, argc, argv, &error);
6003 case ACTION_POWEROFF:
6009 case ACTION_RUNLEVEL2:
6010 case ACTION_RUNLEVEL3:
6011 case ACTION_RUNLEVEL4:
6012 case ACTION_RUNLEVEL5:
6014 case ACTION_EMERGENCY:
6015 case ACTION_DEFAULT:
6016 r = start_with_fallback(bus);
6021 r = reload_with_fallback(bus);
6024 case ACTION_CANCEL_SHUTDOWN: {
6028 m = strv_join(arg_wall, " ");
6030 retval = EXIT_FAILURE;
6034 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6036 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6041 case ACTION_INVALID:
6042 case ACTION_RUNLEVEL:
6044 assert_not_reached("Unknown action");
6047 retval = r < 0 ? EXIT_FAILURE : r;
6051 dbus_connection_flush(bus);
6052 dbus_connection_close(bus);
6053 dbus_connection_unref(bus);
6058 strv_free(arg_types);
6059 strv_free(arg_load_states);
6060 strv_free(arg_properties);
6063 ask_password_agent_close();
6064 polkit_agent_close();