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);
1180 static int get_default(DBusConnection *bus, char **args) {
1182 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
1184 _cleanup_dbus_error_free_ DBusError error;
1186 dbus_error_init(&error);
1188 if (!bus || avoid_bus()) {
1189 r = unit_file_get_default(arg_scope, arg_root, &path);
1192 log_error("Operation failed: %s", strerror(-r));
1198 r = bus_method_call_with_reply(
1200 "org.freedesktop.systemd1",
1201 "/org/freedesktop/systemd1",
1202 "org.freedesktop.systemd1.Manager",
1209 log_error("Operation failed: %s", strerror(-r));
1213 if (!dbus_message_get_args(reply, &error,
1214 DBUS_TYPE_STRING, &path,
1215 DBUS_TYPE_INVALID)) {
1216 log_error("Failed to parse reply: %s", bus_error_message(&error));
1217 dbus_error_free(&error);
1223 printf("%s\n", path);
1226 if ((!bus || avoid_bus()) && path)
1235 char *name, *type, *state;
1238 static void list_jobs_print(struct job_info* jobs, size_t n) {
1241 const char *on, *off;
1242 bool shorten = false;
1244 assert(n == 0 || jobs);
1247 on = ansi_highlight_green(true);
1248 off = ansi_highlight_green(false);
1250 printf("%sNo jobs running.%s\n", on, off);
1254 pager_open_if_enabled();
1257 /* JOB UNIT TYPE STATE */
1258 unsigned l0 = 3, l1 = 4, l2 = 4, l3 = 5;
1260 for (i = 0, j = jobs; i < n; i++, j++) {
1261 assert(j->name && j->type && j->state);
1262 l0 = MAX(l0, DECIMAL_STR_WIDTH(j->id));
1263 l1 = MAX(l1, strlen(j->name));
1264 l2 = MAX(l2, strlen(j->type));
1265 l3 = MAX(l3, strlen(j->state));
1268 if (!arg_full && l0 + 1 + l1 + l2 + 1 + l3 > columns()) {
1269 l1 = MAX(33u, columns() - l0 - l2 - l3 - 3);
1274 printf("%*s %-*s %-*s %-*s\n",
1280 for (i = 0, j = jobs; i < n; i++, j++) {
1281 _cleanup_free_ char *e = NULL;
1283 if (streq(j->state, "running")) {
1284 on = ansi_highlight(true);
1285 off = ansi_highlight(false);
1289 e = shorten ? ellipsize(j->name, l1, 33) : NULL;
1290 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
1292 on, l1, e ? e : j->name, off,
1294 on, l3, j->state, off);
1298 on = ansi_highlight(true);
1299 off = ansi_highlight(false);
1302 printf("\n%s%zu jobs listed%s.\n", on, n, off);
1305 static int list_jobs(DBusConnection *bus, char **args) {
1306 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1307 DBusMessageIter iter, sub, sub2;
1309 struct job_info *jobs = NULL;
1310 size_t size = 0, used = 0;
1312 r = bus_method_call_with_reply(
1314 "org.freedesktop.systemd1",
1315 "/org/freedesktop/systemd1",
1316 "org.freedesktop.systemd1.Manager",
1324 if (!dbus_message_iter_init(reply, &iter) ||
1325 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1326 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1327 log_error("Failed to parse reply.");
1331 dbus_message_iter_recurse(&iter, &sub);
1333 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1334 const char *name, *type, *state, *job_path, *unit_path;
1337 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1338 log_error("Failed to parse reply.");
1342 dbus_message_iter_recurse(&sub, &sub2);
1344 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1345 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1346 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1347 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1348 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1349 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1350 log_error("Failed to parse reply.");
1355 if (!GREEDY_REALLOC(jobs, size, used + 1)) {
1360 jobs[used++] = (struct job_info) { id,
1364 if (!jobs[used-1].name || !jobs[used-1].type || !jobs[used-1].state) {
1369 dbus_message_iter_next(&sub);
1372 list_jobs_print(jobs, used);
1376 free(jobs[used].name);
1377 free(jobs[used].type);
1378 free(jobs[used].state);
1385 static int load_unit(DBusConnection *bus, char **args) {
1390 STRV_FOREACH(name, args+1) {
1391 _cleanup_free_ char *n = NULL;
1394 n = unit_name_mangle(*name);
1398 r = bus_method_call_with_reply(
1400 "org.freedesktop.systemd1",
1401 "/org/freedesktop/systemd1",
1402 "org.freedesktop.systemd1.Manager",
1406 DBUS_TYPE_STRING, &n,
1415 static int cancel_job(DBusConnection *bus, char **args) {
1420 if (strv_length(args) <= 1)
1421 return daemon_reload(bus, args);
1423 STRV_FOREACH(name, args+1) {
1427 r = safe_atou32(*name, &id);
1429 log_error("Failed to parse job id: %s", strerror(-r));
1433 r = bus_method_call_with_reply(
1435 "org.freedesktop.systemd1",
1436 "/org/freedesktop/systemd1",
1437 "org.freedesktop.systemd1.Manager",
1441 DBUS_TYPE_UINT32, &id,
1450 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1451 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1452 dbus_bool_t b = FALSE;
1453 DBusMessageIter iter, sub;
1455 *interface = "org.freedesktop.systemd1.Unit",
1456 *property = "NeedDaemonReload",
1458 _cleanup_free_ char *n = NULL;
1461 /* We ignore all errors here, since this is used to show a warning only */
1463 n = unit_name_mangle(unit);
1467 r = bus_method_call_with_reply(
1469 "org.freedesktop.systemd1",
1470 "/org/freedesktop/systemd1",
1471 "org.freedesktop.systemd1.Manager",
1475 DBUS_TYPE_STRING, &n,
1480 if (!dbus_message_get_args(reply, NULL,
1481 DBUS_TYPE_OBJECT_PATH, &path,
1485 dbus_message_unref(reply);
1488 r = bus_method_call_with_reply(
1490 "org.freedesktop.systemd1",
1492 "org.freedesktop.DBus.Properties",
1496 DBUS_TYPE_STRING, &interface,
1497 DBUS_TYPE_STRING, &property,
1502 if (!dbus_message_iter_init(reply, &iter) ||
1503 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1506 dbus_message_iter_recurse(&iter, &sub);
1507 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1510 dbus_message_iter_get_basic(&sub, &b);
1514 typedef struct WaitData {
1521 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1522 _cleanup_dbus_error_free_ DBusError error;
1525 dbus_error_init(&error);
1531 log_debug("Got D-Bus request: %s.%s() on %s",
1532 dbus_message_get_interface(message),
1533 dbus_message_get_member(message),
1534 dbus_message_get_path(message));
1536 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1537 log_error("Warning! D-Bus connection terminated.");
1538 dbus_connection_close(connection);
1540 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1542 const char *path, *result, *unit;
1544 if (dbus_message_get_args(message, &error,
1545 DBUS_TYPE_UINT32, &id,
1546 DBUS_TYPE_OBJECT_PATH, &path,
1547 DBUS_TYPE_STRING, &unit,
1548 DBUS_TYPE_STRING, &result,
1549 DBUS_TYPE_INVALID)) {
1551 free(set_remove(d->set, (char*) path));
1553 if (!isempty(result))
1554 d->result = strdup(result);
1557 d->name = strdup(unit);
1559 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1562 dbus_error_free(&error);
1563 if (dbus_message_get_args(message, &error,
1564 DBUS_TYPE_UINT32, &id,
1565 DBUS_TYPE_OBJECT_PATH, &path,
1566 DBUS_TYPE_STRING, &result,
1567 DBUS_TYPE_INVALID)) {
1568 /* Compatibility with older systemd versions <
1569 * 183 during upgrades. This should be dropped
1571 free(set_remove(d->set, (char*) path));
1574 d->result = strdup(result);
1576 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1580 log_error("Failed to parse message: %s", bus_error_message(&error));
1583 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1586 static int enable_wait_for_jobs(DBusConnection *bus) {
1594 dbus_error_init(&error);
1595 dbus_bus_add_match(bus,
1597 "sender='org.freedesktop.systemd1',"
1598 "interface='org.freedesktop.systemd1.Manager',"
1599 "member='JobRemoved',"
1600 "path='/org/freedesktop/systemd1'",
1603 if (dbus_error_is_set(&error)) {
1604 log_error("Failed to add match: %s", bus_error_message(&error));
1605 dbus_error_free(&error);
1609 /* This is slightly dirty, since we don't undo the match registrations. */
1613 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1615 WaitData d = { .set = s };
1620 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1623 while (!set_isempty(s)) {
1625 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1626 log_error("Disconnected from bus.");
1627 return -ECONNREFUSED;
1634 if (streq(d.result, "timeout"))
1635 log_error("Job for %s timed out.", strna(d.name));
1636 else if (streq(d.result, "canceled"))
1637 log_error("Job for %s canceled.", strna(d.name));
1638 else if (streq(d.result, "dependency"))
1639 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1640 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1641 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1644 if (streq_ptr(d.result, "timeout"))
1646 else if (streq_ptr(d.result, "canceled"))
1648 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1659 dbus_connection_remove_filter(bus, wait_filter, &d);
1663 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1664 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1665 _cleanup_free_ char *n = NULL;
1666 DBusMessageIter iter, sub;
1668 *interface = "org.freedesktop.systemd1.Unit",
1669 *property = "ActiveState";
1670 const char *state, *path;
1676 dbus_error_init(&error);
1678 n = unit_name_mangle(name);
1682 r = bus_method_call_with_reply (
1684 "org.freedesktop.systemd1",
1685 "/org/freedesktop/systemd1",
1686 "org.freedesktop.systemd1.Manager",
1690 DBUS_TYPE_STRING, &n,
1693 dbus_error_free(&error);
1700 if (!dbus_message_get_args(reply, NULL,
1701 DBUS_TYPE_OBJECT_PATH, &path,
1702 DBUS_TYPE_INVALID)) {
1703 log_error("Failed to parse reply.");
1707 dbus_message_unref(reply);
1710 r = bus_method_call_with_reply(
1712 "org.freedesktop.systemd1",
1714 "org.freedesktop.DBus.Properties",
1718 DBUS_TYPE_STRING, &interface,
1719 DBUS_TYPE_STRING, &property,
1727 if (!dbus_message_iter_init(reply, &iter) ||
1728 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1729 log_error("Failed to parse reply.");
1733 dbus_message_iter_recurse(&iter, &sub);
1735 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1736 log_error("Failed to parse reply.");
1740 dbus_message_iter_get_basic(&sub, &state);
1745 return strv_find(check_states, state) ? 1 : 0;
1748 static void check_triggering_units(
1749 DBusConnection *bus,
1750 const char *unit_name) {
1752 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1753 DBusMessageIter iter, sub;
1754 const char *interface = "org.freedesktop.systemd1.Unit",
1755 *load_state_property = "LoadState",
1756 *triggered_by_property = "TriggeredBy",
1758 _cleanup_free_ char *unit_path = NULL, *n = NULL;
1759 bool print_warning_label = true;
1762 n = unit_name_mangle(unit_name);
1768 unit_path = unit_dbus_path_from_name(n);
1774 r = bus_method_call_with_reply(
1776 "org.freedesktop.systemd1",
1778 "org.freedesktop.DBus.Properties",
1782 DBUS_TYPE_STRING, &interface,
1783 DBUS_TYPE_STRING, &load_state_property,
1788 if (!dbus_message_iter_init(reply, &iter) ||
1789 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1790 log_error("Failed to parse reply.");
1794 dbus_message_iter_recurse(&iter, &sub);
1796 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1797 log_error("Failed to parse reply.");
1801 dbus_message_iter_get_basic(&sub, &state);
1803 if (streq(state, "masked"))
1806 dbus_message_unref(reply);
1809 r = bus_method_call_with_reply(
1811 "org.freedesktop.systemd1",
1813 "org.freedesktop.DBus.Properties",
1817 DBUS_TYPE_STRING, &interface,
1818 DBUS_TYPE_STRING, &triggered_by_property,
1823 if (!dbus_message_iter_init(reply, &iter) ||
1824 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1825 log_error("Failed to parse reply.");
1829 dbus_message_iter_recurse(&iter, &sub);
1830 dbus_message_iter_recurse(&sub, &iter);
1833 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1834 const char * const check_states[] = {
1839 const char *service_trigger;
1841 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1842 log_error("Failed to parse reply.");
1846 dbus_message_iter_get_basic(&sub, &service_trigger);
1848 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1852 if (print_warning_label) {
1853 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1854 print_warning_label = false;
1857 log_warning(" %s", service_trigger);
1860 dbus_message_iter_next(&sub);
1864 static int start_unit_one(
1865 DBusConnection *bus,
1872 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1873 _cleanup_free_ char *n;
1882 n = unit_name_mangle(name);
1886 r = bus_method_call_with_reply(
1888 "org.freedesktop.systemd1",
1889 "/org/freedesktop/systemd1",
1890 "org.freedesktop.systemd1.Manager",
1894 DBUS_TYPE_STRING, &n,
1895 DBUS_TYPE_STRING, &mode,
1898 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1899 /* There's always a fallback possible for
1900 * legacy actions. */
1903 log_error("Failed to issue method call: %s", bus_error_message(error));
1908 if (!dbus_message_get_args(reply, error,
1909 DBUS_TYPE_OBJECT_PATH, &path,
1910 DBUS_TYPE_INVALID)) {
1911 log_error("Failed to parse reply: %s", bus_error_message(error));
1915 if (need_daemon_reload(bus, n))
1916 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %sdaemon-reload' recommended.",
1917 n, arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
1926 r = set_consume(s, p);
1928 log_error("Failed to add path to set.");
1936 static const struct {
1940 } action_table[_ACTION_MAX] = {
1941 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
1942 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
1943 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
1944 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
1945 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
1946 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
1947 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
1948 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
1949 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
1950 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
1951 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
1952 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
1953 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
1954 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
1955 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1958 static enum action verb_to_action(const char *verb) {
1961 for (i = ACTION_INVALID; i < _ACTION_MAX; i++)
1962 if (action_table[i].verb && streq(verb, action_table[i].verb))
1964 return ACTION_INVALID;
1967 static int start_unit(DBusConnection *bus, char **args) {
1970 const char *method, *mode, *one_name;
1971 _cleanup_set_free_free_ Set *s = NULL;
1972 _cleanup_dbus_error_free_ DBusError error;
1975 dbus_error_init(&error);
1979 ask_password_agent_open_if_enabled();
1981 if (arg_action == ACTION_SYSTEMCTL) {
1984 streq(args[0], "stop") ||
1985 streq(args[0], "condstop") ? "StopUnit" :
1986 streq(args[0], "reload") ? "ReloadUnit" :
1987 streq(args[0], "restart") ? "RestartUnit" :
1989 streq(args[0], "try-restart") ||
1990 streq(args[0], "condrestart") ? "TryRestartUnit" :
1992 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1994 streq(args[0], "reload-or-try-restart") ||
1995 streq(args[0], "condreload") ||
1997 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1999 action = verb_to_action(args[0]);
2001 mode = streq(args[0], "isolate") ? "isolate" :
2002 action_table[action].mode ?: arg_job_mode;
2004 one_name = action_table[action].target;
2007 assert(arg_action < ELEMENTSOF(action_table));
2008 assert(action_table[arg_action].target);
2010 method = "StartUnit";
2012 mode = action_table[arg_action].mode;
2013 one_name = action_table[arg_action].target;
2016 if (!arg_no_block) {
2017 ret = enable_wait_for_jobs(bus);
2019 log_error("Could not watch jobs: %s", strerror(-ret));
2023 s = set_new(string_hash_func, string_compare_func);
2029 ret = start_unit_one(bus, method, one_name, mode, &error, s);
2031 ret = translate_bus_error_to_exit_status(ret, &error);
2033 STRV_FOREACH(name, args+1) {
2034 r = start_unit_one(bus, method, *name, mode, &error, s);
2036 ret = translate_bus_error_to_exit_status(r, &error);
2037 dbus_error_free(&error);
2042 if (!arg_no_block) {
2043 r = wait_for_jobs(bus, s);
2047 /* When stopping units, warn if they can still be triggered by
2048 * another active unit (socket, path, timer) */
2049 if (!arg_quiet && streq(method, "StopUnit")) {
2051 check_triggering_units(bus, one_name);
2053 STRV_FOREACH(name, args+1)
2054 check_triggering_units(bus, *name);
2061 /* Ask systemd-logind, which might grant access to unprivileged users
2062 * through PolicyKit */
2063 static int reboot_with_logind(DBusConnection *bus, enum action a) {
2066 dbus_bool_t interactive = true;
2071 polkit_agent_open_if_enabled();
2079 case ACTION_POWEROFF:
2080 method = "PowerOff";
2083 case ACTION_SUSPEND:
2087 case ACTION_HIBERNATE:
2088 method = "Hibernate";
2091 case ACTION_HYBRID_SLEEP:
2092 method = "HybridSleep";
2099 return bus_method_call_with_reply(
2101 "org.freedesktop.login1",
2102 "/org/freedesktop/login1",
2103 "org.freedesktop.login1.Manager",
2107 DBUS_TYPE_BOOLEAN, &interactive,
2114 static int check_inhibitors(DBusConnection *bus, enum action a) {
2116 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2117 DBusMessageIter iter, sub, sub2;
2120 _cleanup_strv_free_ char **sessions = NULL;
2126 if (arg_ignore_inhibitors || arg_force > 0)
2138 r = bus_method_call_with_reply(
2140 "org.freedesktop.login1",
2141 "/org/freedesktop/login1",
2142 "org.freedesktop.login1.Manager",
2148 /* If logind is not around, then there are no inhibitors... */
2151 if (!dbus_message_iter_init(reply, &iter) ||
2152 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2153 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
2154 log_error("Failed to parse reply.");
2158 dbus_message_iter_recurse(&iter, &sub);
2159 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2160 const char *what, *who, *why, *mode;
2162 _cleanup_strv_free_ char **sv = NULL;
2163 _cleanup_free_ char *comm = NULL, *user = NULL;
2165 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
2166 log_error("Failed to parse reply.");
2170 dbus_message_iter_recurse(&sub, &sub2);
2172 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
2173 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
2174 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
2175 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
2176 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
2177 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
2178 log_error("Failed to parse reply.");
2182 if (!streq(mode, "block"))
2185 sv = strv_split(what, ":");
2189 if (!strv_contains(sv,
2191 a == ACTION_POWEROFF ||
2192 a == ACTION_REBOOT ||
2193 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2196 get_process_comm(pid, &comm);
2197 user = uid_to_name(uid);
2198 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2199 who, (unsigned long) pid, strna(comm), strna(user), why);
2203 dbus_message_iter_next(&sub);
2206 dbus_message_iter_recurse(&iter, &sub);
2208 /* Check for current sessions */
2209 sd_get_sessions(&sessions);
2210 STRV_FOREACH(s, sessions) {
2212 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2214 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2217 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2220 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2223 sd_session_get_tty(*s, &tty);
2224 sd_session_get_seat(*s, &seat);
2225 sd_session_get_service(*s, &service);
2226 user = uid_to_name(uid);
2228 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2235 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2236 action_table[a].verb);
2244 static int start_special(DBusConnection *bus, char **args) {
2250 a = verb_to_action(args[0]);
2252 r = check_inhibitors(bus, a);
2256 if (arg_force >= 2 && geteuid() != 0) {
2257 log_error("Must be root.");
2261 if (arg_force >= 2 &&
2262 (a == ACTION_HALT ||
2263 a == ACTION_POWEROFF ||
2264 a == ACTION_REBOOT))
2267 if (arg_force >= 1 &&
2268 (a == ACTION_HALT ||
2269 a == ACTION_POWEROFF ||
2270 a == ACTION_REBOOT ||
2271 a == ACTION_KEXEC ||
2273 return daemon_reload(bus, args);
2275 /* first try logind, to allow authentication with polkit */
2276 if (geteuid() != 0 &&
2277 (a == ACTION_POWEROFF ||
2278 a == ACTION_REBOOT ||
2279 a == ACTION_SUSPEND ||
2280 a == ACTION_HIBERNATE ||
2281 a == ACTION_HYBRID_SLEEP)) {
2282 r = reboot_with_logind(bus, a);
2287 r = start_unit(bus, args);
2288 if (r == EXIT_SUCCESS)
2294 static int check_unit_active(DBusConnection *bus, char **args) {
2295 const char * const check_states[] = {
2302 int r = 3; /* According to LSB: "program is not running" */
2307 STRV_FOREACH(name, args+1) {
2310 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2320 static int check_unit_failed(DBusConnection *bus, char **args) {
2321 const char * const check_states[] = {
2332 STRV_FOREACH(name, args+1) {
2335 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2345 static int kill_unit(DBusConnection *bus, char **args) {
2353 arg_kill_who = "all";
2355 STRV_FOREACH(name, args+1) {
2356 _cleanup_free_ char *n = NULL;
2358 n = unit_name_mangle(*name);
2362 r = bus_method_call_with_reply(
2364 "org.freedesktop.systemd1",
2365 "/org/freedesktop/systemd1",
2366 "org.freedesktop.systemd1.Manager",
2370 DBUS_TYPE_STRING, &n,
2371 DBUS_TYPE_STRING, &arg_kill_who,
2372 DBUS_TYPE_INT32, &arg_signal,
2380 static int set_cgroup(DBusConnection *bus, char **args) {
2381 _cleanup_free_ char *n = NULL;
2382 const char *method, *runtime;
2390 streq(args[0], "set-cgroup") ? "SetUnitControlGroup" :
2391 streq(args[0], "unset-cgroup") ? "UnsetUnitControlGroup"
2392 : "UnsetUnitControlGroupAttribute";
2394 runtime = arg_runtime ? "runtime" : "persistent";
2396 n = unit_name_mangle(args[1]);
2400 STRV_FOREACH(argument, args + 2) {
2402 r = bus_method_call_with_reply(
2404 "org.freedesktop.systemd1",
2405 "/org/freedesktop/systemd1",
2406 "org.freedesktop.systemd1.Manager",
2410 DBUS_TYPE_STRING, &n,
2411 DBUS_TYPE_STRING, argument,
2412 DBUS_TYPE_STRING, &runtime,
2421 static int set_cgroup_attr(DBusConnection *bus, char **args) {
2422 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2424 DBusMessageIter iter;
2425 _cleanup_free_ char *n = NULL;
2426 const char *runtime;
2432 dbus_error_init(&error);
2434 runtime = arg_runtime ? "runtime" : "persistent";
2436 n = unit_name_mangle(args[1]);
2440 m = dbus_message_new_method_call(
2441 "org.freedesktop.systemd1",
2442 "/org/freedesktop/systemd1",
2443 "org.freedesktop.systemd1.Manager",
2444 "SetUnitControlGroupAttribute");
2448 dbus_message_iter_init_append(m, &iter);
2449 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2450 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[2]))
2453 r = bus_append_strv_iter(&iter, args + 3);
2457 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2460 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2462 log_error("Failed to issue method call: %s", bus_error_message(&error));
2463 dbus_error_free(&error);
2470 static int get_cgroup_attr(DBusConnection *bus, char **args) {
2471 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2472 _cleanup_free_ char *n = NULL;
2479 n = unit_name_mangle(args[1]);
2483 STRV_FOREACH(argument, args + 2) {
2484 _cleanup_strv_free_ char **list = NULL;
2485 DBusMessageIter iter;
2488 r = bus_method_call_with_reply(
2490 "org.freedesktop.systemd1",
2491 "/org/freedesktop/systemd1",
2492 "org.freedesktop.systemd1.Manager",
2493 "GetUnitControlGroupAttribute",
2496 DBUS_TYPE_STRING, &n,
2497 DBUS_TYPE_STRING, argument,
2502 if (!dbus_message_iter_init(reply, &iter)) {
2503 log_error("Failed to initialize iterator.");
2507 r = bus_parse_strv_iter(&iter, &list);
2509 log_error("Failed to parse value list.");
2513 STRV_FOREACH(a, list) {
2514 if (endswith(*a, "\n"))
2524 typedef struct ExecStatusInfo {
2532 usec_t start_timestamp;
2533 usec_t exit_timestamp;
2538 LIST_FIELDS(struct ExecStatusInfo, exec);
2541 static void exec_status_info_free(ExecStatusInfo *i) {
2550 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2551 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2552 DBusMessageIter sub2, sub3;
2556 int32_t code, status;
2562 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2565 dbus_message_iter_recurse(sub, &sub2);
2567 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2570 i->path = strdup(path);
2574 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2575 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2579 dbus_message_iter_recurse(&sub2, &sub3);
2580 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2581 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2582 dbus_message_iter_next(&sub3);
2586 i->argv = new0(char*, n+1);
2591 dbus_message_iter_recurse(&sub2, &sub3);
2592 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2595 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2596 dbus_message_iter_get_basic(&sub3, &s);
2597 dbus_message_iter_next(&sub3);
2599 i->argv[n] = strdup(s);
2606 if (!dbus_message_iter_next(&sub2) ||
2607 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2608 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2609 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2610 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2611 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2612 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2613 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2614 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2618 i->start_timestamp = (usec_t) start_timestamp;
2619 i->exit_timestamp = (usec_t) exit_timestamp;
2620 i->pid = (pid_t) pid;
2627 typedef struct UnitStatusInfo {
2629 const char *load_state;
2630 const char *active_state;
2631 const char *sub_state;
2632 const char *unit_file_state;
2634 const char *description;
2635 const char *following;
2637 char **documentation;
2639 const char *fragment_path;
2640 const char *source_path;
2641 const char *default_control_group;
2643 char **dropin_paths;
2645 const char *load_error;
2648 usec_t inactive_exit_timestamp;
2649 usec_t inactive_exit_timestamp_monotonic;
2650 usec_t active_enter_timestamp;
2651 usec_t active_exit_timestamp;
2652 usec_t inactive_enter_timestamp;
2654 bool need_daemon_reload;
2659 const char *status_text;
2662 usec_t start_timestamp;
2663 usec_t exit_timestamp;
2665 int exit_code, exit_status;
2667 usec_t condition_timestamp;
2668 bool condition_result;
2671 unsigned n_accepted;
2672 unsigned n_connections;
2675 /* Pairs of type, path */
2679 const char *sysfs_path;
2681 /* Mount, Automount */
2687 LIST_HEAD(ExecStatusInfo, exec);
2690 static void print_status_info(UnitStatusInfo *i) {
2692 const char *on, *off, *ss;
2694 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2695 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2698 arg_all * OUTPUT_SHOW_ALL |
2699 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2700 on_tty() * OUTPUT_COLOR |
2701 !arg_quiet * OUTPUT_WARN_CUTOFF |
2702 arg_full * OUTPUT_FULL_WIDTH;
2707 /* This shows pretty information about a unit. See
2708 * print_property() for a low-level property printer */
2710 printf("%s", strna(i->id));
2712 if (i->description && !streq_ptr(i->id, i->description))
2713 printf(" - %s", i->description);
2718 printf(" Follow: unit currently follows state of %s\n", i->following);
2720 if (streq_ptr(i->load_state, "error")) {
2721 on = ansi_highlight_red(true);
2722 off = ansi_highlight_red(false);
2726 path = i->source_path ? i->source_path : i->fragment_path;
2729 printf(" Loaded: %s%s%s (Reason: %s)\n",
2730 on, strna(i->load_state), off, i->load_error);
2731 else if (path && i->unit_file_state)
2732 printf(" Loaded: %s%s%s (%s; %s)\n",
2733 on, strna(i->load_state), off, path, i->unit_file_state);
2735 printf(" Loaded: %s%s%s (%s)\n",
2736 on, strna(i->load_state), off, path);
2738 printf(" Loaded: %s%s%s\n",
2739 on, strna(i->load_state), off);
2741 if (!strv_isempty(i->dropin_paths)) {
2746 STRV_FOREACH(dropin, i->dropin_paths) {
2747 if (! dir || last) {
2748 printf(dir ? " " : " Drop-In: ");
2752 if (path_get_parent(*dropin, &dir) < 0) {
2757 printf("%s\n %s", dir,
2758 draw_special_char(DRAW_TREE_RIGHT));
2761 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
2763 printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", ");
2769 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2771 if (streq_ptr(i->active_state, "failed")) {
2772 on = ansi_highlight_red(true);
2773 off = ansi_highlight_red(false);
2774 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2775 on = ansi_highlight_green(true);
2776 off = ansi_highlight_green(false);
2781 printf(" Active: %s%s (%s)%s",
2782 on, strna(i->active_state), ss, off);
2784 printf(" Active: %s%s%s",
2785 on, strna(i->active_state), off);
2787 if (!isempty(i->result) && !streq(i->result, "success"))
2788 printf(" (Result: %s)", i->result);
2790 timestamp = (streq_ptr(i->active_state, "active") ||
2791 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2792 (streq_ptr(i->active_state, "inactive") ||
2793 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2794 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2795 i->active_exit_timestamp;
2797 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2798 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2801 printf(" since %s; %s\n", s2, s1);
2803 printf(" since %s\n", s2);
2807 if (!i->condition_result && i->condition_timestamp > 0) {
2808 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2809 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2812 printf(" start condition failed at %s; %s\n", s2, s1);
2814 printf(" start condition failed at %s\n", s2);
2818 printf(" Device: %s\n", i->sysfs_path);
2820 printf(" Where: %s\n", i->where);
2822 printf(" What: %s\n", i->what);
2824 STRV_FOREACH(t, i->documentation)
2825 printf(" %*s %s\n", 9, t == i->documentation ? "Docs:" : "", *t);
2827 STRV_FOREACH_PAIR(t, t2, i->listen)
2828 printf(" %*s %s (%s)\n", 9, t == i->listen ? "Listen:" : "", *t2, *t);
2831 printf(" Accepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2833 LIST_FOREACH(exec, p, i->exec) {
2834 _cleanup_free_ char *argv = NULL;
2837 /* Only show exited processes here */
2841 argv = strv_join(p->argv, " ");
2842 printf(" Process: %u %s=%s ", p->pid, p->name, strna(argv));
2844 good = is_clean_exit_lsb(p->code, p->status, NULL);
2846 on = ansi_highlight_red(true);
2847 off = ansi_highlight_red(false);
2851 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2853 if (p->code == CLD_EXITED) {
2856 printf("status=%i", p->status);
2858 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2863 printf("signal=%s", signal_to_string(p->status));
2865 printf(")%s\n", off);
2867 if (i->main_pid == p->pid &&
2868 i->start_timestamp == p->start_timestamp &&
2869 i->exit_timestamp == p->start_timestamp)
2870 /* Let's not show this twice */
2873 if (p->pid == i->control_pid)
2877 if (i->main_pid > 0 || i->control_pid > 0) {
2878 if (i->main_pid > 0) {
2879 printf(" Main PID: %u", (unsigned) i->main_pid);
2882 _cleanup_free_ char *comm = NULL;
2883 get_process_comm(i->main_pid, &comm);
2885 printf(" (%s)", comm);
2886 } else if (i->exit_code > 0) {
2887 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2889 if (i->exit_code == CLD_EXITED) {
2892 printf("status=%i", i->exit_status);
2894 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2899 printf("signal=%s", signal_to_string(i->exit_status));
2903 if (i->control_pid > 0)
2907 if (i->control_pid > 0) {
2908 _cleanup_free_ char *c = NULL;
2910 printf(" %8s: %u", i->main_pid ? "" : " Control", (unsigned) i->control_pid);
2912 get_process_comm(i->control_pid, &c);
2921 printf(" Status: \"%s\"\n", i->status_text);
2923 if (i->default_control_group &&
2924 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2927 printf(" CGroup: %s\n", i->default_control_group);
2929 if (arg_transport != TRANSPORT_SSH) {
2932 char prefix[] = " ";
2935 if (c > sizeof(prefix) - 1)
2936 c -= sizeof(prefix) - 1;
2940 if (i->main_pid > 0)
2941 extra[k++] = i->main_pid;
2943 if (i->control_pid > 0)
2944 extra[k++] = i->control_pid;
2946 show_cgroup_and_extra_by_spec(i->default_control_group, prefix,
2947 c, false, extra, k, flags);
2951 if (i->id && arg_transport != TRANSPORT_SSH) {
2953 show_journal_by_unit(stdout,
2957 i->inactive_exit_timestamp_monotonic,
2961 arg_scope == UNIT_FILE_SYSTEM);
2964 if (i->need_daemon_reload)
2965 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %sdaemon-reload' recommended.\n",
2966 ansi_highlight_red(true),
2967 ansi_highlight_red(false),
2968 arg_scope == UNIT_FILE_SYSTEM ? "" : "--user ");
2971 static void show_unit_help(UnitStatusInfo *i) {
2976 if (!i->documentation) {
2977 log_info("Documentation for %s not known.", i->id);
2981 STRV_FOREACH(p, i->documentation) {
2983 if (startswith(*p, "man:")) {
2986 _cleanup_free_ char *page = NULL, *section = NULL;
2987 const char *args[4] = { "man", NULL, NULL, NULL };
2992 if ((*p)[k-1] == ')')
2993 e = strrchr(*p, '(');
2996 page = strndup((*p) + 4, e - *p - 4);
2997 section = strndup(e + 1, *p + k - e - 2);
2998 if (!page || !section) {
3010 log_error("Failed to fork: %m");
3016 execvp(args[0], (char**) args);
3017 log_error("Failed to execute man: %m");
3018 _exit(EXIT_FAILURE);
3021 wait_for_terminate(pid, NULL);
3023 log_info("Can't show: %s", *p);
3027 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
3033 switch (dbus_message_iter_get_arg_type(iter)) {
3035 case DBUS_TYPE_STRING: {
3038 dbus_message_iter_get_basic(iter, &s);
3041 if (streq(name, "Id"))
3043 else if (streq(name, "LoadState"))
3045 else if (streq(name, "ActiveState"))
3046 i->active_state = s;
3047 else if (streq(name, "SubState"))
3049 else if (streq(name, "Description"))
3051 else if (streq(name, "FragmentPath"))
3052 i->fragment_path = s;
3053 else if (streq(name, "SourcePath"))
3055 else if (streq(name, "DefaultControlGroup"))
3056 i->default_control_group = s;
3057 else if (streq(name, "StatusText"))
3059 else if (streq(name, "SysFSPath"))
3061 else if (streq(name, "Where"))
3063 else if (streq(name, "What"))
3065 else if (streq(name, "Following"))
3067 else if (streq(name, "UnitFileState"))
3068 i->unit_file_state = s;
3069 else if (streq(name, "Result"))
3076 case DBUS_TYPE_BOOLEAN: {
3079 dbus_message_iter_get_basic(iter, &b);
3081 if (streq(name, "Accept"))
3083 else if (streq(name, "NeedDaemonReload"))
3084 i->need_daemon_reload = b;
3085 else if (streq(name, "ConditionResult"))
3086 i->condition_result = b;
3091 case DBUS_TYPE_UINT32: {
3094 dbus_message_iter_get_basic(iter, &u);
3096 if (streq(name, "MainPID")) {
3098 i->main_pid = (pid_t) u;
3101 } else if (streq(name, "ControlPID"))
3102 i->control_pid = (pid_t) u;
3103 else if (streq(name, "ExecMainPID")) {
3105 i->main_pid = (pid_t) u;
3106 } else if (streq(name, "NAccepted"))
3108 else if (streq(name, "NConnections"))
3109 i->n_connections = u;
3114 case DBUS_TYPE_INT32: {
3117 dbus_message_iter_get_basic(iter, &j);
3119 if (streq(name, "ExecMainCode"))
3120 i->exit_code = (int) j;
3121 else if (streq(name, "ExecMainStatus"))
3122 i->exit_status = (int) j;
3127 case DBUS_TYPE_UINT64: {
3130 dbus_message_iter_get_basic(iter, &u);
3132 if (streq(name, "ExecMainStartTimestamp"))
3133 i->start_timestamp = (usec_t) u;
3134 else if (streq(name, "ExecMainExitTimestamp"))
3135 i->exit_timestamp = (usec_t) u;
3136 else if (streq(name, "ActiveEnterTimestamp"))
3137 i->active_enter_timestamp = (usec_t) u;
3138 else if (streq(name, "InactiveEnterTimestamp"))
3139 i->inactive_enter_timestamp = (usec_t) u;
3140 else if (streq(name, "InactiveExitTimestamp"))
3141 i->inactive_exit_timestamp = (usec_t) u;
3142 else if (streq(name, "InactiveExitTimestampMonotonic"))
3143 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3144 else if (streq(name, "ActiveExitTimestamp"))
3145 i->active_exit_timestamp = (usec_t) u;
3146 else if (streq(name, "ConditionTimestamp"))
3147 i->condition_timestamp = (usec_t) u;
3152 case DBUS_TYPE_ARRAY: {
3154 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3155 startswith(name, "Exec")) {
3156 DBusMessageIter sub;
3158 dbus_message_iter_recurse(iter, &sub);
3159 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3160 ExecStatusInfo *info;
3163 if (!(info = new0(ExecStatusInfo, 1)))
3166 if (!(info->name = strdup(name))) {
3171 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
3176 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
3178 dbus_message_iter_next(&sub);
3181 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3182 DBusMessageIter sub, sub2;
3184 dbus_message_iter_recurse(iter, &sub);
3185 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3186 const char *type, *path;
3188 dbus_message_iter_recurse(&sub, &sub2);
3190 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3191 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
3194 r = strv_extend(&i->listen, type);
3197 r = strv_extend(&i->listen, path);
3202 dbus_message_iter_next(&sub);
3207 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING && streq(name, "DropInPaths")) {
3208 int r = bus_parse_strv_iter(iter, &i->dropin_paths);
3212 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3213 streq(name, "Documentation")) {
3215 DBusMessageIter sub;
3217 dbus_message_iter_recurse(iter, &sub);
3218 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
3222 dbus_message_iter_get_basic(&sub, &s);
3224 r = strv_extend(&i->documentation, s);
3228 dbus_message_iter_next(&sub);
3235 case DBUS_TYPE_STRUCT: {
3237 if (streq(name, "LoadError")) {
3238 DBusMessageIter sub;
3239 const char *n, *message;
3242 dbus_message_iter_recurse(iter, &sub);
3244 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
3248 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
3252 if (!isempty(message))
3253 i->load_error = message;
3263 static int print_property(const char *name, DBusMessageIter *iter) {
3267 /* This is a low-level property printer, see
3268 * print_status_info() for the nicer output */
3270 if (arg_properties && !strv_find(arg_properties, name))
3273 switch (dbus_message_iter_get_arg_type(iter)) {
3275 case DBUS_TYPE_STRUCT: {
3276 DBusMessageIter sub;
3277 dbus_message_iter_recurse(iter, &sub);
3279 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
3282 dbus_message_iter_get_basic(&sub, &u);
3285 printf("%s=%u\n", name, (unsigned) u);
3287 printf("%s=\n", name);
3290 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
3293 dbus_message_iter_get_basic(&sub, &s);
3295 if (arg_all || s[0])
3296 printf("%s=%s\n", name, s);
3299 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
3300 const char *a = NULL, *b = NULL;
3302 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
3303 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
3305 if (arg_all || !isempty(a) || !isempty(b))
3306 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3314 case DBUS_TYPE_ARRAY:
3316 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
3317 DBusMessageIter sub, sub2;
3319 dbus_message_iter_recurse(iter, &sub);
3320 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3324 dbus_message_iter_recurse(&sub, &sub2);
3326 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3327 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3328 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3330 dbus_message_iter_next(&sub);
3335 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3336 DBusMessageIter sub, sub2;
3338 dbus_message_iter_recurse(iter, &sub);
3340 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3341 const char *type, *path;
3343 dbus_message_iter_recurse(&sub, &sub2);
3345 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3346 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3347 printf("%s=%s\n", type, path);
3349 dbus_message_iter_next(&sub);
3354 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3355 DBusMessageIter sub, sub2;
3357 dbus_message_iter_recurse(iter, &sub);
3358 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3359 const char *type, *path;
3361 dbus_message_iter_recurse(&sub, &sub2);
3363 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3364 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3365 printf("Listen%s=%s\n", type, path);
3367 dbus_message_iter_next(&sub);
3372 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3373 DBusMessageIter sub, sub2;
3375 dbus_message_iter_recurse(iter, &sub);
3376 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3378 uint64_t value, next_elapse;
3380 dbus_message_iter_recurse(&sub, &sub2);
3382 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3383 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3384 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3385 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3387 printf("%s={ value=%s ; next_elapse=%s }\n",
3389 format_timespan(timespan1, sizeof(timespan1), value, 0),
3390 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3393 dbus_message_iter_next(&sub);
3398 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
3399 DBusMessageIter sub, sub2;
3401 dbus_message_iter_recurse(iter, &sub);
3402 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3403 const char *controller, *attr, *value;
3405 dbus_message_iter_recurse(&sub, &sub2);
3407 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
3408 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
3409 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
3411 printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
3417 dbus_message_iter_next(&sub);
3422 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3423 DBusMessageIter sub;
3425 dbus_message_iter_recurse(iter, &sub);
3426 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3427 ExecStatusInfo info = {};
3429 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3430 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3431 _cleanup_free_ char *t;
3433 t = strv_join(info.argv, " ");
3435 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3439 yes_no(info.ignore),
3440 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3441 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3442 (unsigned) info. pid,
3443 sigchld_code_to_string(info.code),
3445 info.code == CLD_EXITED ? "" : "/",
3446 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3450 strv_free(info.argv);
3452 dbus_message_iter_next(&sub);
3461 if (generic_print_property(name, iter, arg_all) > 0)
3465 printf("%s=[unprintable]\n", name);
3470 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3471 _cleanup_free_ DBusMessage *reply = NULL;
3472 const char *interface = "";
3474 DBusMessageIter iter, sub, sub2, sub3;
3475 UnitStatusInfo info = {};
3481 r = bus_method_call_with_reply(
3483 "org.freedesktop.systemd1",
3485 "org.freedesktop.DBus.Properties",
3489 DBUS_TYPE_STRING, &interface,
3494 if (!dbus_message_iter_init(reply, &iter) ||
3495 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3496 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3497 log_error("Failed to parse reply.");
3501 dbus_message_iter_recurse(&iter, &sub);
3508 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3511 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3512 dbus_message_iter_recurse(&sub, &sub2);
3514 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3515 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3516 log_error("Failed to parse reply.");
3520 dbus_message_iter_recurse(&sub2, &sub3);
3522 if (show_properties)
3523 r = print_property(name, &sub3);
3525 r = status_property(name, &sub3, &info);
3527 log_error("Failed to parse reply.");
3531 dbus_message_iter_next(&sub);
3536 if (!show_properties) {
3537 if (streq(verb, "help"))
3538 show_unit_help(&info);
3540 print_status_info(&info);
3543 strv_free(info.documentation);
3544 strv_free(info.dropin_paths);
3545 strv_free(info.listen);
3547 if (!streq_ptr(info.active_state, "active") &&
3548 !streq_ptr(info.active_state, "reloading") &&
3549 streq(verb, "status"))
3550 /* According to LSB: "program not running" */
3553 while ((p = info.exec)) {
3554 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3555 exec_status_info_free(p);
3561 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3562 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3563 const char *path = NULL;
3564 _cleanup_dbus_error_free_ DBusError error;
3567 dbus_error_init(&error);
3569 r = bus_method_call_with_reply(
3571 "org.freedesktop.systemd1",
3572 "/org/freedesktop/systemd1",
3573 "org.freedesktop.systemd1.Manager",
3577 DBUS_TYPE_UINT32, &pid,
3582 if (!dbus_message_get_args(reply, &error,
3583 DBUS_TYPE_OBJECT_PATH, &path,
3584 DBUS_TYPE_INVALID)) {
3585 log_error("Failed to parse reply: %s", bus_error_message(&error));
3589 r = show_one(verb, bus, path, false, new_line);
3593 static int show_all(const char* verb, DBusConnection *bus, bool show_properties, bool *new_line) {
3594 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3595 _cleanup_free_ struct unit_info *unit_infos = NULL;
3597 const struct unit_info *u;
3600 r = get_unit_list(bus, &reply, &unit_infos, &c);
3604 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
3606 for (u = unit_infos; u < unit_infos + c; u++) {
3607 _cleanup_free_ char *p = NULL;
3609 if (!output_show_unit(u))
3612 p = unit_dbus_path_from_name(u->id);
3616 printf("%s -> '%s'\n", u->id, p);
3618 r = show_one(verb, bus, p, show_properties, new_line);
3626 static int show(DBusConnection *bus, char **args) {
3628 bool show_properties, show_status, new_line = false;
3634 show_properties = streq(args[0], "show");
3635 show_status = streq(args[0], "status");
3637 if (show_properties)
3638 pager_open_if_enabled();
3640 /* If no argument is specified inspect the manager itself */
3642 if (show_properties && strv_length(args) <= 1)
3643 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3645 if (show_status && strv_length(args) <= 1)
3646 return show_all(args[0], bus, false, &new_line);
3648 STRV_FOREACH(name, args+1) {
3651 if (safe_atou32(*name, &id) < 0) {
3652 _cleanup_free_ char *p = NULL, *n = NULL;
3653 /* Interpret as unit name */
3655 n = unit_name_mangle(*name);
3659 p = unit_dbus_path_from_name(n);
3663 r = show_one(args[0], bus, p, show_properties, &new_line);
3667 } else if (show_properties) {
3668 _cleanup_free_ char *p = NULL;
3670 /* Interpret as job id */
3671 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3674 r = show_one(args[0], bus, p, show_properties, &new_line);
3679 /* Interpret as PID */
3680 r = show_one_by_pid(args[0], bus, id, &new_line);
3689 static int dump(DBusConnection *bus, char **args) {
3690 _cleanup_free_ DBusMessage *reply = NULL;
3695 dbus_error_init(&error);
3697 pager_open_if_enabled();
3699 r = bus_method_call_with_reply(
3701 "org.freedesktop.systemd1",
3702 "/org/freedesktop/systemd1",
3703 "org.freedesktop.systemd1.Manager",
3711 if (!dbus_message_get_args(reply, &error,
3712 DBUS_TYPE_STRING, &text,
3713 DBUS_TYPE_INVALID)) {
3714 log_error("Failed to parse reply: %s", bus_error_message(&error));
3715 dbus_error_free(&error);
3719 fputs(text, stdout);
3723 static int snapshot(DBusConnection *bus, char **args) {
3724 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3727 dbus_bool_t cleanup = FALSE;
3728 DBusMessageIter iter, sub;
3731 *interface = "org.freedesktop.systemd1.Unit",
3733 _cleanup_free_ char *n = NULL;
3735 dbus_error_init(&error);
3737 if (strv_length(args) > 1)
3738 n = snapshot_name_mangle(args[1]);
3744 r = bus_method_call_with_reply (
3746 "org.freedesktop.systemd1",
3747 "/org/freedesktop/systemd1",
3748 "org.freedesktop.systemd1.Manager",
3752 DBUS_TYPE_STRING, &n,
3753 DBUS_TYPE_BOOLEAN, &cleanup,
3758 if (!dbus_message_get_args(reply, &error,
3759 DBUS_TYPE_OBJECT_PATH, &path,
3760 DBUS_TYPE_INVALID)) {
3761 log_error("Failed to parse reply: %s", bus_error_message(&error));
3762 dbus_error_free(&error);
3766 dbus_message_unref(reply);
3769 r = bus_method_call_with_reply (
3771 "org.freedesktop.systemd1",
3773 "org.freedesktop.DBus.Properties",
3777 DBUS_TYPE_STRING, &interface,
3778 DBUS_TYPE_STRING, &property,
3783 if (!dbus_message_iter_init(reply, &iter) ||
3784 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3785 log_error("Failed to parse reply.");
3789 dbus_message_iter_recurse(&iter, &sub);
3791 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3792 log_error("Failed to parse reply.");
3796 dbus_message_iter_get_basic(&sub, &id);
3804 static int delete_snapshot(DBusConnection *bus, char **args) {
3809 STRV_FOREACH(name, args+1) {
3810 _cleanup_free_ char *n = NULL;
3813 n = snapshot_name_mangle(*name);
3817 r = bus_method_call_with_reply(
3819 "org.freedesktop.systemd1",
3820 "/org/freedesktop/systemd1",
3821 "org.freedesktop.systemd1.Manager",
3825 DBUS_TYPE_STRING, &n,
3834 static int daemon_reload(DBusConnection *bus, char **args) {
3839 if (arg_action == ACTION_RELOAD)
3841 else if (arg_action == ACTION_REEXEC)
3842 method = "Reexecute";
3844 assert(arg_action == ACTION_SYSTEMCTL);
3847 streq(args[0], "clear-jobs") ||
3848 streq(args[0], "cancel") ? "ClearJobs" :
3849 streq(args[0], "daemon-reexec") ? "Reexecute" :
3850 streq(args[0], "reset-failed") ? "ResetFailed" :
3851 streq(args[0], "halt") ? "Halt" :
3852 streq(args[0], "poweroff") ? "PowerOff" :
3853 streq(args[0], "reboot") ? "Reboot" :
3854 streq(args[0], "kexec") ? "KExec" :
3855 streq(args[0], "exit") ? "Exit" :
3856 /* "daemon-reload" */ "Reload";
3859 r = bus_method_call_with_reply(
3861 "org.freedesktop.systemd1",
3862 "/org/freedesktop/systemd1",
3863 "org.freedesktop.systemd1.Manager",
3869 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3870 /* There's always a fallback possible for
3871 * legacy actions. */
3873 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3874 /* On reexecution, we expect a disconnect, not
3878 log_error("Failed to issue method call: %s", bus_error_message(&error));
3880 dbus_error_free(&error);
3884 static int reset_failed(DBusConnection *bus, char **args) {
3888 if (strv_length(args) <= 1)
3889 return daemon_reload(bus, args);
3891 STRV_FOREACH(name, args+1) {
3892 _cleanup_free_ char *n;
3894 n = unit_name_mangle(*name);
3898 r = bus_method_call_with_reply(
3900 "org.freedesktop.systemd1",
3901 "/org/freedesktop/systemd1",
3902 "org.freedesktop.systemd1.Manager",
3906 DBUS_TYPE_STRING, &n,
3915 static int show_enviroment(DBusConnection *bus, char **args) {
3916 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3917 DBusMessageIter iter, sub, sub2;
3920 *interface = "org.freedesktop.systemd1.Manager",
3921 *property = "Environment";
3923 pager_open_if_enabled();
3925 r = bus_method_call_with_reply(
3927 "org.freedesktop.systemd1",
3928 "/org/freedesktop/systemd1",
3929 "org.freedesktop.DBus.Properties",
3933 DBUS_TYPE_STRING, &interface,
3934 DBUS_TYPE_STRING, &property,
3939 if (!dbus_message_iter_init(reply, &iter) ||
3940 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3941 log_error("Failed to parse reply.");
3945 dbus_message_iter_recurse(&iter, &sub);
3947 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3948 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3949 log_error("Failed to parse reply.");
3953 dbus_message_iter_recurse(&sub, &sub2);
3955 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3958 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3959 log_error("Failed to parse reply.");
3963 dbus_message_iter_get_basic(&sub2, &text);
3966 dbus_message_iter_next(&sub2);
3972 static int switch_root(DBusConnection *bus, char **args) {
3975 _cleanup_free_ char *init = NULL;
3977 l = strv_length(args);
3978 if (l < 2 || l > 3) {
3979 log_error("Wrong number of arguments.");
3986 init = strdup(args[2]);
3988 parse_env_file("/proc/cmdline", WHITESPACE,
3998 log_debug("switching root - root: %s; init: %s", root, init);
4000 return bus_method_call_with_reply(
4002 "org.freedesktop.systemd1",
4003 "/org/freedesktop/systemd1",
4004 "org.freedesktop.systemd1.Manager",
4008 DBUS_TYPE_STRING, &root,
4009 DBUS_TYPE_STRING, &init,
4013 static int set_environment(DBusConnection *bus, char **args) {
4014 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4017 DBusMessageIter iter;
4023 dbus_error_init(&error);
4025 method = streq(args[0], "set-environment")
4027 : "UnsetEnvironment";
4029 m = dbus_message_new_method_call(
4030 "org.freedesktop.systemd1",
4031 "/org/freedesktop/systemd1",
4032 "org.freedesktop.systemd1.Manager",
4037 dbus_message_iter_init_append(m, &iter);
4039 r = bus_append_strv_iter(&iter, args + 1);
4043 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4045 log_error("Failed to issue method call: %s", bus_error_message(&error));
4046 dbus_error_free(&error);
4053 static int enable_sysv_units(char **args) {
4056 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4057 const char *verb = args[0];
4058 unsigned f = 1, t = 1;
4059 LookupPaths paths = {};
4061 if (arg_scope != UNIT_FILE_SYSTEM)
4064 if (!streq(verb, "enable") &&
4065 !streq(verb, "disable") &&
4066 !streq(verb, "is-enabled"))
4069 /* Processes all SysV units, and reshuffles the array so that
4070 * afterwards only the native units remain */
4072 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4077 for (f = 1; args[f]; f++) {
4079 _cleanup_free_ char *p = NULL, *q = NULL;
4080 bool found_native = false, found_sysv;
4082 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4090 if (!endswith(name, ".service"))
4093 if (path_is_absolute(name))
4096 STRV_FOREACH(k, paths.unit_path) {
4097 if (!isempty(arg_root))
4098 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4100 asprintf(&p, "%s/%s", *k, name);
4107 found_native = access(p, F_OK) >= 0;
4118 if (!isempty(arg_root))
4119 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4121 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4127 p[strlen(p) - sizeof(".service") + 1] = 0;
4128 found_sysv = access(p, F_OK) >= 0;
4133 /* Mark this entry, so that we don't try enabling it as native unit */
4134 args[f] = (char*) "";
4136 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4138 if (!isempty(arg_root))
4139 argv[c++] = q = strappend("--root=", arg_root);
4141 argv[c++] = path_get_file_name(p);
4143 streq(verb, "enable") ? "on" :
4144 streq(verb, "disable") ? "off" : "--level=5";
4147 l = strv_join((char**)argv, " ");
4153 log_info("Executing %s", l);
4158 log_error("Failed to fork: %m");
4161 } else if (pid == 0) {
4164 execv(argv[0], (char**) argv);
4165 _exit(EXIT_FAILURE);
4168 j = wait_for_terminate(pid, &status);
4170 log_error("Failed to wait for child: %s", strerror(-r));
4175 if (status.si_code == CLD_EXITED) {
4176 if (streq(verb, "is-enabled")) {
4177 if (status.si_status == 0) {
4186 } else if (status.si_status != 0) {
4197 lookup_paths_free(&paths);
4199 /* Drop all SysV units */
4200 for (f = 1, t = 1; args[f]; f++) {
4202 if (isempty(args[f]))
4205 args[t++] = args[f];
4214 static int mangle_names(char **original_names, char ***mangled_names) {
4215 char **i, **l, **name;
4217 l = new(char*, strv_length(original_names) + 1);
4222 STRV_FOREACH(name, original_names) {
4224 /* When enabling units qualified path names are OK,
4225 * too, hence allow them explicitly. */
4230 *i = unit_name_mangle(*name);
4246 static int enable_unit(DBusConnection *bus, char **args) {
4247 const char *verb = args[0];
4248 UnitFileChange *changes = NULL;
4249 unsigned n_changes = 0, i;
4250 int carries_install_info = -1;
4251 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4253 _cleanup_dbus_error_free_ DBusError error;
4254 _cleanup_strv_free_ char **mangled_names = NULL;
4256 dbus_error_init(&error);
4258 r = enable_sysv_units(args);
4265 r = mangle_names(args+1, &mangled_names);
4269 if (!bus || avoid_bus()) {
4270 if (streq(verb, "enable")) {
4271 r = unit_file_enable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4272 carries_install_info = r;
4273 } else if (streq(verb, "disable"))
4274 r = unit_file_disable(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4275 else if (streq(verb, "reenable")) {
4276 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4277 carries_install_info = r;
4278 } else if (streq(verb, "link"))
4279 r = unit_file_link(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4280 else if (streq(verb, "preset")) {
4281 r = unit_file_preset(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4282 carries_install_info = r;
4283 } else if (streq(verb, "mask"))
4284 r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4285 else if (streq(verb, "unmask"))
4286 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4287 else if (streq(verb, "set-default"))
4288 r = unit_file_set_default(arg_scope, arg_root, args[1], &changes, &n_changes);
4290 assert_not_reached("Unknown verb");
4293 log_error("Operation failed: %s", strerror(-r));
4298 for (i = 0; i < n_changes; i++) {
4299 if (changes[i].type == UNIT_FILE_SYMLINK)
4300 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4302 log_info("rm '%s'", changes[i].path);
4309 bool send_force = true, expect_carries_install_info = false;
4311 DBusMessageIter iter, sub, sub2;
4313 if (streq(verb, "enable")) {
4314 method = "EnableUnitFiles";
4315 expect_carries_install_info = true;
4316 } else if (streq(verb, "disable")) {
4317 method = "DisableUnitFiles";
4319 } else if (streq(verb, "reenable")) {
4320 method = "ReenableUnitFiles";
4321 expect_carries_install_info = true;
4322 } else if (streq(verb, "link"))
4323 method = "LinkUnitFiles";
4324 else if (streq(verb, "preset")) {
4325 method = "PresetUnitFiles";
4326 expect_carries_install_info = true;
4327 } else if (streq(verb, "mask"))
4328 method = "MaskUnitFiles";
4329 else if (streq(verb, "unmask")) {
4330 method = "UnmaskUnitFiles";
4332 } else if (streq(verb, "set-default")) {
4333 method = "SetDefaultTarget";
4335 assert_not_reached("Unknown verb");
4337 m = dbus_message_new_method_call(
4338 "org.freedesktop.systemd1",
4339 "/org/freedesktop/systemd1",
4340 "org.freedesktop.systemd1.Manager",
4347 dbus_message_iter_init_append(m, &iter);
4349 r = bus_append_strv_iter(&iter, mangled_names);
4351 log_error("Failed to append unit files.");
4356 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4357 log_error("Failed to append runtime boolean.");
4365 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4366 log_error("Failed to append force boolean.");
4372 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4374 log_error("Failed to issue method call: %s", bus_error_message(&error));
4379 if (!dbus_message_iter_init(reply, &iter)) {
4380 log_error("Failed to initialize iterator.");
4384 if (expect_carries_install_info) {
4385 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4387 log_error("Failed to parse reply.");
4391 carries_install_info = b;
4394 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4395 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4396 log_error("Failed to parse reply.");
4401 dbus_message_iter_recurse(&iter, &sub);
4402 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4403 const char *type, *path, *source;
4405 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4406 log_error("Failed to parse reply.");
4411 dbus_message_iter_recurse(&sub, &sub2);
4413 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4414 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4415 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4416 log_error("Failed to parse reply.");
4422 if (streq(type, "symlink"))
4423 log_info("ln -s '%s' '%s'", source, path);
4425 log_info("rm '%s'", path);
4428 dbus_message_iter_next(&sub);
4431 /* Try to reload if enabeld */
4433 r = daemon_reload(bus, args);
4436 if (carries_install_info == 0)
4437 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4438 "using systemctl.\n"
4439 "Possible reasons for having this kind of units are:\n"
4440 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4441 " .wants/ or .requires/ directory.\n"
4442 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4443 " a requirement dependency on it.\n"
4444 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4445 " D-Bus, udev, scripted systemctl call, ...).\n");
4448 unit_file_changes_free(changes, n_changes);
4453 static int set_log_level(DBusConnection *bus, char **args) {
4454 _cleanup_dbus_error_free_ DBusError error;
4455 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4456 DBusMessageIter iter, sub;
4457 const char* property = "LogLevel";
4458 const char* interface = "org.freedesktop.systemd1.Manager";
4465 dbus_error_init(&error);
4467 m = dbus_message_new_method_call("org.freedesktop.systemd1",
4468 "/org/freedesktop/systemd1",
4469 "org.freedesktop.DBus.Properties",
4474 dbus_message_iter_init_append(m, &iter);
4476 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface) ||
4477 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property) ||
4478 !dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, "s", &sub))
4481 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &value)) {
4482 dbus_message_iter_abandon_container(&iter, &sub);
4486 if (!dbus_message_iter_close_container(&iter, &sub))
4489 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4491 log_error("Failed to issue method call: %s", bus_error_message(&error));
4498 static int unit_is_enabled(DBusConnection *bus, char **args) {
4499 _cleanup_dbus_error_free_ DBusError error;
4501 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4506 dbus_error_init(&error);
4508 r = enable_sysv_units(args);
4514 if (!bus || avoid_bus()) {
4516 STRV_FOREACH(name, args+1) {
4517 UnitFileState state;
4519 n = unit_name_mangle(*name);
4523 state = unit_file_get_state(arg_scope, arg_root, n);
4530 if (state == UNIT_FILE_ENABLED ||
4531 state == UNIT_FILE_ENABLED_RUNTIME ||
4532 state == UNIT_FILE_STATIC)
4536 puts(unit_file_state_to_string(state));
4540 STRV_FOREACH(name, args+1) {
4543 n = unit_name_mangle(*name);
4547 r = bus_method_call_with_reply (
4549 "org.freedesktop.systemd1",
4550 "/org/freedesktop/systemd1",
4551 "org.freedesktop.systemd1.Manager",
4555 DBUS_TYPE_STRING, &n,
4563 if (!dbus_message_get_args(reply, &error,
4564 DBUS_TYPE_STRING, &s,
4565 DBUS_TYPE_INVALID)) {
4566 log_error("Failed to parse reply: %s", bus_error_message(&error));
4570 dbus_message_unref(reply);
4573 if (streq(s, "enabled") ||
4574 streq(s, "enabled-runtime") ||
4583 return enabled ? 0 : 1;
4586 static int systemctl_help(void) {
4588 pager_open_if_enabled();
4590 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4591 "Query or send control commands to the systemd manager.\n\n"
4592 " -h --help Show this help\n"
4593 " --version Show package version\n"
4594 " -t --type=TYPE List only units of a particular type\n"
4595 " -p --property=NAME Show only properties by this name\n"
4596 " -a --all Show all loaded units/properties, including dead/empty\n"
4597 " ones. To list all units installed on the system, use\n"
4598 " the 'list-unit-files' command instead.\n"
4599 " --reverse Show reverse dependencies with 'list-dependencies'\n"
4600 " --failed Show only failed units\n"
4601 " --full Don't ellipsize unit names on output\n"
4602 " --fail When queueing a new job, fail if conflicting jobs are\n"
4604 " --irreversible Create jobs which cannot be implicitly cancelled\n"
4605 " --show-types When showing sockets, explicitly show their type\n"
4606 " --ignore-dependencies\n"
4607 " When queueing a new job, ignore all its dependencies\n"
4608 " -i --ignore-inhibitors\n"
4609 " When shutting down or sleeping, ignore inhibitors\n"
4610 " --kill-who=WHO Who to send signal to\n"
4611 " -s --signal=SIGNAL Which signal to send\n"
4612 " -H --host=[USER@]HOST\n"
4613 " Show information for remote host\n"
4614 " -P --privileged Acquire privileges before execution\n"
4615 " -q --quiet Suppress output\n"
4616 " --no-block Do not wait until operation finished\n"
4617 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4618 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4620 " --no-legend Do not print a legend (column headers and hints)\n"
4621 " --no-pager Do not pipe output into a pager\n"
4622 " --no-ask-password\n"
4623 " Do not ask for system passwords\n"
4624 " --system Connect to system manager\n"
4625 " --user Connect to user service manager\n"
4626 " --global Enable/disable unit files globally\n"
4627 " -f --force When enabling unit files, override existing symlinks\n"
4628 " When shutting down, execute action immediately\n"
4629 " --root=PATH Enable unit files in the specified root directory\n"
4630 " --runtime Enable unit files only temporarily until next reboot\n"
4631 " -n --lines=INTEGER Journal entries to show\n"
4632 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4633 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4635 " list-units List loaded units\n"
4636 " list-sockets List loaded sockets ordered by address\n"
4637 " start [NAME...] Start (activate) one or more units\n"
4638 " stop [NAME...] Stop (deactivate) one or more units\n"
4639 " reload [NAME...] Reload one or more units\n"
4640 " restart [NAME...] Start or restart one or more units\n"
4641 " try-restart [NAME...] Restart one or more units if active\n"
4642 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4643 " otherwise start or restart\n"
4644 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4645 " otherwise restart if active\n"
4646 " isolate [NAME] Start one unit and stop all others\n"
4647 " kill [NAME...] Send signal to processes of a unit\n"
4648 " is-active [NAME...] Check whether units are active\n"
4649 " is-failed [NAME...] Check whether units are failed\n"
4650 " status [NAME...|PID...] Show runtime status of one or more units\n"
4651 " show [NAME...|JOB...] Show properties of one or more\n"
4652 " units/jobs or the manager\n"
4653 " help [NAME...|PID...] Show manual for one or more units\n"
4654 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4656 " get-cgroup-attr [NAME] [ATTR] ...\n"
4657 " Get control group attrubute\n"
4658 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4659 " Set control group attribute\n"
4660 " unset-cgroup-attr [NAME] [ATTR...]\n"
4661 " Unset control group attribute\n"
4662 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4663 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4664 " load [NAME...] Load one or more units\n"
4665 " list-dependencies [NAME] Recursively show units which are required\n"
4666 " or wanted by this unit or by which this\n"
4667 " unit is required or wanted\n\n"
4668 "Unit File Commands:\n"
4669 " list-unit-files List installed unit files\n"
4670 " enable [NAME...] Enable one or more unit files\n"
4671 " disable [NAME...] Disable one or more unit files\n"
4672 " reenable [NAME...] Reenable one or more unit files\n"
4673 " preset [NAME...] Enable/disable one or more unit files\n"
4674 " based on preset configuration\n"
4675 " mask [NAME...] Mask one or more units\n"
4676 " unmask [NAME...] Unmask one or more units\n"
4677 " link [PATH...] Link one or more units files into\n"
4678 " the search path\n"
4679 " get-default Get the name of the default target\n"
4680 " set-default NAME Set the default target\n"
4681 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4683 " list-jobs List jobs\n"
4684 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4685 "Status Commands:\n"
4686 " dump Dump server status\n"
4687 "Snapshot Commands:\n"
4688 " snapshot [NAME] Create a snapshot\n"
4689 " delete [NAME...] Remove one or more snapshots\n\n"
4690 "Environment Commands:\n"
4691 " show-environment Dump environment\n"
4692 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4693 " unset-environment [NAME...] Unset one or more environment variables\n"
4694 " set-log-level LEVEL Set logging threshold for systemd\n\n"
4695 "Manager Lifecycle Commands:\n"
4696 " daemon-reload Reload systemd manager configuration\n"
4697 " daemon-reexec Reexecute systemd manager\n\n"
4698 "System Commands:\n"
4699 " default Enter system default mode\n"
4700 " rescue Enter system rescue mode\n"
4701 " emergency Enter system emergency mode\n"
4702 " halt Shut down and halt the system\n"
4703 " poweroff Shut down and power-off the system\n"
4704 " reboot Shut down and reboot the system\n"
4705 " kexec Shut down and reboot the system with kexec\n"
4706 " exit Request user instance exit\n"
4707 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4708 " suspend Suspend the system\n"
4709 " hibernate Hibernate the system\n"
4710 " hybrid-sleep Hibernate and suspend the system\n",
4711 program_invocation_short_name);
4716 static int halt_help(void) {
4718 printf("%s [OPTIONS...]\n\n"
4719 "%s the system.\n\n"
4720 " --help Show this help\n"
4721 " --halt Halt the machine\n"
4722 " -p --poweroff Switch off the machine\n"
4723 " --reboot Reboot the machine\n"
4724 " -f --force Force immediate halt/power-off/reboot\n"
4725 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4726 " -d --no-wtmp Don't write wtmp record\n"
4727 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4728 program_invocation_short_name,
4729 arg_action == ACTION_REBOOT ? "Reboot" :
4730 arg_action == ACTION_POWEROFF ? "Power off" :
4736 static int shutdown_help(void) {
4738 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4739 "Shut down the system.\n\n"
4740 " --help Show this help\n"
4741 " -H --halt Halt the machine\n"
4742 " -P --poweroff Power-off the machine\n"
4743 " -r --reboot Reboot the machine\n"
4744 " -h Equivalent to --poweroff, overridden by --halt\n"
4745 " -k Don't halt/power-off/reboot, just send warnings\n"
4746 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4747 " -c Cancel a pending shutdown\n",
4748 program_invocation_short_name);
4753 static int telinit_help(void) {
4755 printf("%s [OPTIONS...] {COMMAND}\n\n"
4756 "Send control commands to the init daemon.\n\n"
4757 " --help Show this help\n"
4758 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4760 " 0 Power-off the machine\n"
4761 " 6 Reboot the machine\n"
4762 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4763 " 1, s, S Enter rescue mode\n"
4764 " q, Q Reload init daemon configuration\n"
4765 " u, U Reexecute init daemon\n",
4766 program_invocation_short_name);
4771 static int runlevel_help(void) {
4773 printf("%s [OPTIONS...]\n\n"
4774 "Prints the previous and current runlevel of the init system.\n\n"
4775 " --help Show this help\n",
4776 program_invocation_short_name);
4781 static int help_types(void) {
4785 puts("Available unit types:");
4786 for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4787 t = unit_type_to_string(i);
4792 puts("\nAvailable unit load states: ");
4793 for(i = 0; i < _UNIT_LOAD_STATE_MAX; i++) {
4794 t = unit_load_state_to_string(i);
4802 static int systemctl_parse_argv(int argc, char *argv[]) {
4811 ARG_IGNORE_DEPENDENCIES,
4824 ARG_NO_ASK_PASSWORD,
4831 static const struct option options[] = {
4832 { "help", no_argument, NULL, 'h' },
4833 { "version", no_argument, NULL, ARG_VERSION },
4834 { "type", required_argument, NULL, 't' },
4835 { "property", required_argument, NULL, 'p' },
4836 { "all", no_argument, NULL, 'a' },
4837 { "reverse", no_argument, NULL, ARG_REVERSE },
4838 { "after", no_argument, NULL, ARG_AFTER },
4839 { "before", no_argument, NULL, ARG_BEFORE },
4840 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
4841 { "failed", no_argument, NULL, ARG_FAILED },
4842 { "full", no_argument, NULL, ARG_FULL },
4843 { "fail", no_argument, NULL, ARG_FAIL },
4844 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4845 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4846 { "ignore-inhibitors", no_argument, NULL, 'i' },
4847 { "user", no_argument, NULL, ARG_USER },
4848 { "system", no_argument, NULL, ARG_SYSTEM },
4849 { "global", no_argument, NULL, ARG_GLOBAL },
4850 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4851 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4852 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4853 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4854 { "quiet", no_argument, NULL, 'q' },
4855 { "root", required_argument, NULL, ARG_ROOT },
4856 { "force", no_argument, NULL, ARG_FORCE },
4857 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4858 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4859 { "signal", required_argument, NULL, 's' },
4860 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4861 { "host", required_argument, NULL, 'H' },
4862 { "privileged",no_argument, NULL, 'P' },
4863 { "runtime", no_argument, NULL, ARG_RUNTIME },
4864 { "lines", required_argument, NULL, 'n' },
4865 { "output", required_argument, NULL, 'o' },
4866 { "plain", no_argument, NULL, ARG_PLAIN },
4867 { NULL, 0, NULL, 0 }
4875 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4884 puts(PACKAGE_STRING);
4885 puts(SYSTEMD_FEATURES);
4892 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4893 _cleanup_free_ char *type;
4895 type = strndup(word, size);
4899 if (streq(type, "help")) {
4904 if (unit_type_from_string(type) >= 0) {
4905 if (strv_push(&arg_types, type))
4911 if (unit_load_state_from_string(optarg) >= 0) {
4912 if (strv_push(&arg_load_states, type))
4918 log_error("Unknown unit type or load state '%s'.", type);
4919 log_info("Use -t help to see a list of allowed values.");
4927 /* Make sure that if the empty property list
4928 was specified, we won't show any properties. */
4929 if (isempty(optarg) && !arg_properties) {
4930 arg_properties = strv_new(NULL, NULL);
4931 if (!arg_properties)
4937 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4940 prop = strndup(word, size);
4944 if (strv_push(&arg_properties, prop)) {
4951 /* If the user asked for a particular
4952 * property, show it to him, even if it is
4964 arg_dependency = DEPENDENCY_REVERSE;
4968 arg_dependency = DEPENDENCY_AFTER;
4972 arg_dependency = DEPENDENCY_BEFORE;
4975 case ARG_SHOW_TYPES:
4976 arg_show_types = true;
4980 arg_job_mode = "fail";
4983 case ARG_IRREVERSIBLE:
4984 arg_job_mode = "replace-irreversibly";
4987 case ARG_IGNORE_DEPENDENCIES:
4988 arg_job_mode = "ignore-dependencies";
4992 arg_scope = UNIT_FILE_USER;
4996 arg_scope = UNIT_FILE_SYSTEM;
5000 arg_scope = UNIT_FILE_GLOBAL;
5004 arg_no_block = true;
5008 arg_no_legend = true;
5012 arg_no_pager = true;
5044 arg_no_reload = true;
5048 arg_kill_who = optarg;
5052 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5053 log_error("Failed to parse signal string %s.", optarg);
5058 case ARG_NO_ASK_PASSWORD:
5059 arg_ask_password = false;
5063 arg_transport = TRANSPORT_POLKIT;
5067 arg_transport = TRANSPORT_SSH;
5076 if (safe_atou(optarg, &arg_lines) < 0) {
5077 log_error("Failed to parse lines '%s'", optarg);
5083 arg_output = output_mode_from_string(optarg);
5084 if (arg_output < 0) {
5085 log_error("Unknown output '%s'.", optarg);
5091 arg_ignore_inhibitors = true;
5102 log_error("Unknown option code '%c'.", c);
5107 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
5108 log_error("Cannot access user instance remotely.");
5115 static int halt_parse_argv(int argc, char *argv[]) {
5124 static const struct option options[] = {
5125 { "help", no_argument, NULL, ARG_HELP },
5126 { "halt", no_argument, NULL, ARG_HALT },
5127 { "poweroff", no_argument, NULL, 'p' },
5128 { "reboot", no_argument, NULL, ARG_REBOOT },
5129 { "force", no_argument, NULL, 'f' },
5130 { "wtmp-only", no_argument, NULL, 'w' },
5131 { "no-wtmp", no_argument, NULL, 'd' },
5132 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5133 { NULL, 0, NULL, 0 }
5141 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5142 if (runlevel == '0' || runlevel == '6')
5145 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5153 arg_action = ACTION_HALT;
5157 if (arg_action != ACTION_REBOOT)
5158 arg_action = ACTION_POWEROFF;
5162 arg_action = ACTION_REBOOT;
5184 /* Compatibility nops */
5191 log_error("Unknown option code '%c'.", c);
5196 if (optind < argc) {
5197 log_error("Too many arguments.");
5204 static int parse_time_spec(const char *t, usec_t *_u) {
5208 if (streq(t, "now"))
5210 else if (!strchr(t, ':')) {
5213 if (safe_atou64(t, &u) < 0)
5216 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5225 hour = strtol(t, &e, 10);
5226 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5229 minute = strtol(e+1, &e, 10);
5230 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5233 n = now(CLOCK_REALTIME);
5234 s = (time_t) (n / USEC_PER_SEC);
5236 assert_se(localtime_r(&s, &tm));
5238 tm.tm_hour = (int) hour;
5239 tm.tm_min = (int) minute;
5242 assert_se(s = mktime(&tm));
5244 *_u = (usec_t) s * USEC_PER_SEC;
5247 *_u += USEC_PER_DAY;
5253 static int shutdown_parse_argv(int argc, char *argv[]) {
5260 static const struct option options[] = {
5261 { "help", no_argument, NULL, ARG_HELP },
5262 { "halt", no_argument, NULL, 'H' },
5263 { "poweroff", no_argument, NULL, 'P' },
5264 { "reboot", no_argument, NULL, 'r' },
5265 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5266 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5267 { NULL, 0, NULL, 0 }
5275 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5283 arg_action = ACTION_HALT;
5287 arg_action = ACTION_POWEROFF;
5292 arg_action = ACTION_KEXEC;
5294 arg_action = ACTION_REBOOT;
5298 arg_action = ACTION_KEXEC;
5302 if (arg_action != ACTION_HALT)
5303 arg_action = ACTION_POWEROFF;
5316 /* Compatibility nops */
5320 arg_action = ACTION_CANCEL_SHUTDOWN;
5327 log_error("Unknown option code '%c'.", c);
5332 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5333 r = parse_time_spec(argv[optind], &arg_when);
5335 log_error("Failed to parse time specification: %s", argv[optind]);
5339 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5341 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5342 /* No time argument for shutdown cancel */
5343 arg_wall = argv + optind;
5344 else if (argc > optind + 1)
5345 /* We skip the time argument */
5346 arg_wall = argv + optind + 1;
5353 static int telinit_parse_argv(int argc, char *argv[]) {
5360 static const struct option options[] = {
5361 { "help", no_argument, NULL, ARG_HELP },
5362 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5363 { NULL, 0, NULL, 0 }
5366 static const struct {
5370 { '0', ACTION_POWEROFF },
5371 { '6', ACTION_REBOOT },
5372 { '1', ACTION_RESCUE },
5373 { '2', ACTION_RUNLEVEL2 },
5374 { '3', ACTION_RUNLEVEL3 },
5375 { '4', ACTION_RUNLEVEL4 },
5376 { '5', ACTION_RUNLEVEL5 },
5377 { 's', ACTION_RESCUE },
5378 { 'S', ACTION_RESCUE },
5379 { 'q', ACTION_RELOAD },
5380 { 'Q', ACTION_RELOAD },
5381 { 'u', ACTION_REEXEC },
5382 { 'U', ACTION_REEXEC }
5391 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5406 log_error("Unknown option code '%c'.", c);
5411 if (optind >= argc) {
5416 if (optind + 1 < argc) {
5417 log_error("Too many arguments.");
5421 if (strlen(argv[optind]) != 1) {
5422 log_error("Expected single character argument.");
5426 for (i = 0; i < ELEMENTSOF(table); i++)
5427 if (table[i].from == argv[optind][0])
5430 if (i >= ELEMENTSOF(table)) {
5431 log_error("Unknown command '%s'.", argv[optind]);
5435 arg_action = table[i].to;
5442 static int runlevel_parse_argv(int argc, char *argv[]) {
5448 static const struct option options[] = {
5449 { "help", no_argument, NULL, ARG_HELP },
5450 { NULL, 0, NULL, 0 }
5458 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5469 log_error("Unknown option code '%c'.", c);
5474 if (optind < argc) {
5475 log_error("Too many arguments.");
5482 static int parse_argv(int argc, char *argv[]) {
5486 if (program_invocation_short_name) {
5488 if (strstr(program_invocation_short_name, "halt")) {
5489 arg_action = ACTION_HALT;
5490 return halt_parse_argv(argc, argv);
5491 } else if (strstr(program_invocation_short_name, "poweroff")) {
5492 arg_action = ACTION_POWEROFF;
5493 return halt_parse_argv(argc, argv);
5494 } else if (strstr(program_invocation_short_name, "reboot")) {
5496 arg_action = ACTION_KEXEC;
5498 arg_action = ACTION_REBOOT;
5499 return halt_parse_argv(argc, argv);
5500 } else if (strstr(program_invocation_short_name, "shutdown")) {
5501 arg_action = ACTION_POWEROFF;
5502 return shutdown_parse_argv(argc, argv);
5503 } else if (strstr(program_invocation_short_name, "init")) {
5505 if (sd_booted() > 0) {
5506 arg_action = ACTION_INVALID;
5507 return telinit_parse_argv(argc, argv);
5509 /* Hmm, so some other init system is
5510 * running, we need to forward this
5511 * request to it. For now we simply
5512 * guess that it is Upstart. */
5514 execv(TELINIT, argv);
5516 log_error("Couldn't find an alternative telinit implementation to spawn.");
5520 } else if (strstr(program_invocation_short_name, "runlevel")) {
5521 arg_action = ACTION_RUNLEVEL;
5522 return runlevel_parse_argv(argc, argv);
5526 arg_action = ACTION_SYSTEMCTL;
5527 return systemctl_parse_argv(argc, argv);
5530 _pure_ static int action_to_runlevel(void) {
5532 static const char table[_ACTION_MAX] = {
5533 [ACTION_HALT] = '0',
5534 [ACTION_POWEROFF] = '0',
5535 [ACTION_REBOOT] = '6',
5536 [ACTION_RUNLEVEL2] = '2',
5537 [ACTION_RUNLEVEL3] = '3',
5538 [ACTION_RUNLEVEL4] = '4',
5539 [ACTION_RUNLEVEL5] = '5',
5540 [ACTION_RESCUE] = '1'
5543 assert(arg_action < _ACTION_MAX);
5545 return table[arg_action];
5548 static int talk_upstart(void) {
5549 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
5550 _cleanup_dbus_error_free_ DBusError error;
5551 int previous, rl, r;
5553 env1_buf[] = "RUNLEVEL=X",
5554 env2_buf[] = "PREVLEVEL=X";
5555 char *env1 = env1_buf, *env2 = env2_buf;
5556 const char *emit = "runlevel";
5557 dbus_bool_t b_false = FALSE;
5558 DBusMessageIter iter, sub;
5559 DBusConnection *bus;
5561 dbus_error_init(&error);
5563 if (!(rl = action_to_runlevel()))
5566 if (utmp_get_runlevel(&previous, NULL) < 0)
5569 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5570 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5575 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5580 if ((r = bus_check_peercred(bus)) < 0) {
5581 log_error("Failed to verify owner of bus.");
5585 if (!(m = dbus_message_new_method_call(
5586 "com.ubuntu.Upstart",
5587 "/com/ubuntu/Upstart",
5588 "com.ubuntu.Upstart0_6",
5591 log_error("Could not allocate message.");
5596 dbus_message_iter_init_append(m, &iter);
5598 env1_buf[sizeof(env1_buf)-2] = rl;
5599 env2_buf[sizeof(env2_buf)-2] = previous;
5601 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5602 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5603 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5604 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5605 !dbus_message_iter_close_container(&iter, &sub) ||
5606 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5607 log_error("Could not append arguments to message.");
5612 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5614 if (bus_error_is_no_service(&error)) {
5619 log_error("Failed to issue method call: %s", bus_error_message(&error));
5628 dbus_connection_flush(bus);
5629 dbus_connection_close(bus);
5630 dbus_connection_unref(bus);
5636 static int talk_initctl(void) {
5637 struct init_request request = {};
5639 _cleanup_close_ int fd = -1;
5642 rl = action_to_runlevel();
5646 request.magic = INIT_MAGIC;
5647 request.sleeptime = 0;
5648 request.cmd = INIT_CMD_RUNLVL;
5649 request.runlevel = rl;
5651 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5653 if (errno == ENOENT)
5656 log_error("Failed to open "INIT_FIFO": %m");
5661 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5663 log_error("Failed to write to "INIT_FIFO": %m");
5664 return errno > 0 ? -errno : -EIO;
5670 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5672 static const struct {
5680 int (* const dispatch)(DBusConnection *bus, char **args);
5682 { "list-units", LESS, 1, list_units },
5683 { "list-unit-files", EQUAL, 1, list_unit_files },
5684 { "list-sockets", LESS, 1, list_sockets },
5685 { "list-jobs", EQUAL, 1, list_jobs },
5686 { "clear-jobs", EQUAL, 1, daemon_reload },
5687 { "load", MORE, 2, load_unit },
5688 { "cancel", MORE, 2, cancel_job },
5689 { "start", MORE, 2, start_unit },
5690 { "stop", MORE, 2, start_unit },
5691 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5692 { "reload", MORE, 2, start_unit },
5693 { "restart", MORE, 2, start_unit },
5694 { "try-restart", MORE, 2, start_unit },
5695 { "reload-or-restart", MORE, 2, start_unit },
5696 { "reload-or-try-restart", MORE, 2, start_unit },
5697 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5698 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5699 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5700 { "isolate", EQUAL, 2, start_unit },
5701 { "set-cgroup", MORE, 3, set_cgroup },
5702 { "unset-cgroup", MORE, 3, set_cgroup },
5703 { "get-cgroup-attr", MORE, 3, get_cgroup_attr },
5704 { "set-cgroup-attr", MORE, 4, set_cgroup_attr },
5705 { "unset-cgroup-attr", MORE, 3, set_cgroup },
5706 { "kill", MORE, 2, kill_unit },
5707 { "is-active", MORE, 2, check_unit_active },
5708 { "check", MORE, 2, check_unit_active },
5709 { "is-failed", MORE, 2, check_unit_failed },
5710 { "show", MORE, 1, show },
5711 { "status", MORE, 1, show },
5712 { "help", MORE, 2, show },
5713 { "dump", EQUAL, 1, dump },
5714 { "snapshot", LESS, 2, snapshot },
5715 { "delete", MORE, 2, delete_snapshot },
5716 { "daemon-reload", EQUAL, 1, daemon_reload },
5717 { "daemon-reexec", EQUAL, 1, daemon_reload },
5718 { "show-environment", EQUAL, 1, show_enviroment },
5719 { "set-environment", MORE, 2, set_environment },
5720 { "unset-environment", MORE, 2, set_environment },
5721 { "halt", EQUAL, 1, start_special },
5722 { "poweroff", EQUAL, 1, start_special },
5723 { "reboot", EQUAL, 1, start_special },
5724 { "kexec", EQUAL, 1, start_special },
5725 { "suspend", EQUAL, 1, start_special },
5726 { "hibernate", EQUAL, 1, start_special },
5727 { "hybrid-sleep", EQUAL, 1, start_special },
5728 { "default", EQUAL, 1, start_special },
5729 { "rescue", EQUAL, 1, start_special },
5730 { "emergency", EQUAL, 1, start_special },
5731 { "exit", EQUAL, 1, start_special },
5732 { "reset-failed", MORE, 1, reset_failed },
5733 { "enable", MORE, 2, enable_unit },
5734 { "disable", MORE, 2, enable_unit },
5735 { "is-enabled", MORE, 2, unit_is_enabled },
5736 { "reenable", MORE, 2, enable_unit },
5737 { "preset", MORE, 2, enable_unit },
5738 { "mask", MORE, 2, enable_unit },
5739 { "unmask", MORE, 2, enable_unit },
5740 { "link", MORE, 2, enable_unit },
5741 { "switch-root", MORE, 2, switch_root },
5742 { "list-dependencies", LESS, 2, list_dependencies },
5743 { "set-default", EQUAL, 2, enable_unit },
5744 { "get-default", LESS, 1, get_default },
5745 { "set-log-level", EQUAL, 2, set_log_level },
5755 left = argc - optind;
5758 /* Special rule: no arguments means "list-units" */
5761 if (streq(argv[optind], "help") && !argv[optind+1]) {
5762 log_error("This command expects one or more "
5763 "unit names. Did you mean --help?");
5767 for (i = 0; i < ELEMENTSOF(verbs); i++)
5768 if (streq(argv[optind], verbs[i].verb))
5771 if (i >= ELEMENTSOF(verbs)) {
5772 log_error("Unknown operation '%s'.", argv[optind]);
5777 switch (verbs[i].argc_cmp) {
5780 if (left != verbs[i].argc) {
5781 log_error("Invalid number of arguments.");
5788 if (left < verbs[i].argc) {
5789 log_error("Too few arguments.");
5796 if (left > verbs[i].argc) {
5797 log_error("Too many arguments.");
5804 assert_not_reached("Unknown comparison operator.");
5807 /* Require a bus connection for all operations but
5809 if (!streq(verbs[i].verb, "enable") &&
5810 !streq(verbs[i].verb, "disable") &&
5811 !streq(verbs[i].verb, "is-enabled") &&
5812 !streq(verbs[i].verb, "list-unit-files") &&
5813 !streq(verbs[i].verb, "reenable") &&
5814 !streq(verbs[i].verb, "preset") &&
5815 !streq(verbs[i].verb, "mask") &&
5816 !streq(verbs[i].verb, "unmask") &&
5817 !streq(verbs[i].verb, "link") &&
5818 !streq(verbs[i].verb, "set-default") &&
5819 !streq(verbs[i].verb, "get-default")) {
5821 if (running_in_chroot() > 0) {
5822 log_info("Running in chroot, ignoring request.");
5826 if (((!streq(verbs[i].verb, "reboot") &&
5827 !streq(verbs[i].verb, "halt") &&
5828 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5829 log_error("Failed to get D-Bus connection: %s",
5830 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5836 if (!bus && !avoid_bus()) {
5837 log_error("Failed to get D-Bus connection: %s",
5838 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5843 return verbs[i].dispatch(bus, argv + optind);
5846 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5847 _cleanup_close_ int fd;
5848 struct sd_shutdown_command c = {
5854 union sockaddr_union sockaddr = {
5855 .un.sun_family = AF_UNIX,
5856 .un.sun_path = "/run/systemd/shutdownd",
5858 struct iovec iovec[2] = {
5859 {.iov_base = (char*) &c,
5860 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
5863 struct msghdr msghdr = {
5864 .msg_name = &sockaddr,
5865 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
5866 + sizeof("/run/systemd/shutdownd") - 1,
5871 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5875 if (!isempty(message)) {
5876 iovec[1].iov_base = (char*) message;
5877 iovec[1].iov_len = strlen(message);
5878 msghdr.msg_iovlen++;
5881 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5887 static int reload_with_fallback(DBusConnection *bus) {
5890 /* First, try systemd via D-Bus. */
5891 if (daemon_reload(bus, NULL) >= 0)
5895 /* Nothing else worked, so let's try signals */
5896 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5898 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5899 log_error("kill() failed: %m");
5906 static int start_with_fallback(DBusConnection *bus) {
5909 /* First, try systemd via D-Bus. */
5910 if (start_unit(bus, NULL) >= 0)
5914 /* Hmm, talking to systemd via D-Bus didn't work. Then
5915 * let's try to talk to Upstart via D-Bus. */
5916 if (talk_upstart() > 0)
5919 /* Nothing else worked, so let's try
5921 if (talk_initctl() > 0)
5924 log_error("Failed to talk to init daemon.");
5928 warn_wall(arg_action);
5932 static _noreturn_ void halt_now(enum action a) {
5934 /* Make sure C-A-D is handled by the kernel from this
5936 reboot(RB_ENABLE_CAD);
5941 log_info("Halting.");
5942 reboot(RB_HALT_SYSTEM);
5945 case ACTION_POWEROFF:
5946 log_info("Powering off.");
5947 reboot(RB_POWER_OFF);
5951 log_info("Rebooting.");
5952 reboot(RB_AUTOBOOT);
5956 assert_not_reached("Unknown halt action.");
5959 assert_not_reached("Uh? This shouldn't happen.");
5962 static int halt_main(DBusConnection *bus) {
5965 r = check_inhibitors(bus, arg_action);
5969 if (geteuid() != 0) {
5970 /* Try logind if we are a normal user and no special
5971 * mode applies. Maybe PolicyKit allows us to shutdown
5974 if (arg_when <= 0 &&
5977 (arg_action == ACTION_POWEROFF ||
5978 arg_action == ACTION_REBOOT)) {
5979 r = reboot_with_logind(bus, arg_action);
5984 log_error("Must be root.");
5989 _cleanup_free_ char *m;
5991 m = strv_join(arg_wall, " ");
5992 r = send_shutdownd(arg_when,
5993 arg_action == ACTION_HALT ? 'H' :
5994 arg_action == ACTION_POWEROFF ? 'P' :
5995 arg_action == ACTION_KEXEC ? 'K' :
6002 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
6004 char date[FORMAT_TIMESTAMP_MAX];
6006 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
6007 format_timestamp(date, sizeof(date), arg_when));
6012 if (!arg_dry && !arg_force)
6013 return start_with_fallback(bus);
6016 if (sd_booted() > 0)
6017 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
6019 r = utmp_put_shutdown();
6021 log_warning("Failed to write utmp record: %s", strerror(-r));
6028 halt_now(arg_action);
6029 /* We should never reach this. */
6033 static int runlevel_main(void) {
6034 int r, runlevel, previous;
6036 r = utmp_get_runlevel(&runlevel, &previous);
6043 previous <= 0 ? 'N' : previous,
6044 runlevel <= 0 ? 'N' : runlevel);
6049 int main(int argc, char*argv[]) {
6050 int r, retval = EXIT_FAILURE;
6051 DBusConnection *bus = NULL;
6052 _cleanup_dbus_error_free_ DBusError error;
6054 dbus_error_init(&error);
6056 setlocale(LC_ALL, "");
6057 log_parse_environment();
6060 r = parse_argv(argc, argv);
6064 retval = EXIT_SUCCESS;
6068 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6069 * let's shortcut this */
6070 if (arg_action == ACTION_RUNLEVEL) {
6071 r = runlevel_main();
6072 retval = r < 0 ? EXIT_FAILURE : r;
6076 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6077 log_info("Running in chroot, ignoring request.");
6083 if (arg_transport == TRANSPORT_NORMAL)
6084 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
6085 else if (arg_transport == TRANSPORT_POLKIT) {
6086 bus_connect_system_polkit(&bus, &error);
6087 private_bus = false;
6088 } else if (arg_transport == TRANSPORT_SSH) {
6089 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
6090 private_bus = false;
6092 assert_not_reached("Uh, invalid transport...");
6095 switch (arg_action) {
6097 case ACTION_SYSTEMCTL:
6098 r = systemctl_main(bus, argc, argv, &error);
6102 case ACTION_POWEROFF:
6108 case ACTION_RUNLEVEL2:
6109 case ACTION_RUNLEVEL3:
6110 case ACTION_RUNLEVEL4:
6111 case ACTION_RUNLEVEL5:
6113 case ACTION_EMERGENCY:
6114 case ACTION_DEFAULT:
6115 r = start_with_fallback(bus);
6120 r = reload_with_fallback(bus);
6123 case ACTION_CANCEL_SHUTDOWN: {
6127 m = strv_join(arg_wall, " ");
6129 retval = EXIT_FAILURE;
6133 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6135 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6140 case ACTION_INVALID:
6141 case ACTION_RUNLEVEL:
6143 assert_not_reached("Unknown action");
6146 retval = r < 0 ? EXIT_FAILURE : r;
6150 dbus_connection_flush(bus);
6151 dbus_connection_close(bus);
6152 dbus_connection_unref(bus);
6157 strv_free(arg_types);
6158 strv_free(arg_load_states);
6159 strv_free(arg_properties);
6162 ask_password_agent_close();
6163 polkit_agent_close();