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 %s daemon-reload' recommended.",
1917 n, arg_scope == UNIT_FILE_SYSTEM ? "--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;
2703 int maxlen = 8; /* a value that'll suffice most of the time */
2708 STRV_FOREACH_PAIR(t, t2, i->listen)
2709 maxlen = MAX(maxlen, (int)(sizeof("Listen") - 1 + strlen(*t)));
2711 maxlen = MAX(maxlen, (int)sizeof("Accept") - 1);
2712 if (i->main_pid > 0)
2713 maxlen = MAX(maxlen, (int)sizeof("Main PID") - 1);
2714 else if (i->control_pid > 0)
2715 maxlen = MAX(maxlen, (int)sizeof("Control") - 1);
2717 /* This shows pretty information about a unit. See
2718 * print_property() for a low-level property printer */
2720 printf("%s", strna(i->id));
2722 if (i->description && !streq_ptr(i->id, i->description))
2723 printf(" - %s", i->description);
2728 printf(" %*s: unit currently follows state of %s\n", maxlen, "Follow", i->following);
2730 if (streq_ptr(i->load_state, "error")) {
2731 on = ansi_highlight_red(true);
2732 off = ansi_highlight_red(false);
2736 path = i->source_path ? i->source_path : i->fragment_path;
2739 printf(" %*s: %s%s%s (Reason: %s)\n",
2740 maxlen, "Loaded", on, strna(i->load_state), off, i->load_error);
2741 else if (path && i->unit_file_state)
2742 printf(" %*s: %s%s%s (%s; %s)\n",
2743 maxlen, "Loaded", on, strna(i->load_state), off, path, i->unit_file_state);
2745 printf(" %*s: %s%s%s (%s)\n",
2746 maxlen, "Loaded", on, strna(i->load_state), off, path);
2748 printf(" %*s: %s%s%s\n",
2749 maxlen, "Loaded", on, strna(i->load_state), off);
2751 if (!strv_isempty(i->dropin_paths)) {
2756 STRV_FOREACH(dropin, i->dropin_paths) {
2757 if (! dir || last) {
2758 printf(" %*s ", maxlen, dir ? "" : "Drop-In:");
2762 if (path_get_parent(*dropin, &dir) < 0) {
2767 printf("%s\n %*s %s", dir, maxlen, "",
2768 draw_special_char(DRAW_TREE_RIGHT));
2771 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
2773 printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", ");
2779 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2781 if (streq_ptr(i->active_state, "failed")) {
2782 on = ansi_highlight_red(true);
2783 off = ansi_highlight_red(false);
2784 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2785 on = ansi_highlight_green(true);
2786 off = ansi_highlight_green(false);
2791 printf(" %*s: %s%s (%s)%s",
2792 maxlen, "Active", on, strna(i->active_state), ss, off);
2794 printf(" %*s: %s%s%s",
2795 maxlen, "Active", on, strna(i->active_state), off);
2797 if (!isempty(i->result) && !streq(i->result, "success"))
2798 printf(" (Result: %s)", i->result);
2800 timestamp = (streq_ptr(i->active_state, "active") ||
2801 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2802 (streq_ptr(i->active_state, "inactive") ||
2803 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2804 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2805 i->active_exit_timestamp;
2807 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2808 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2811 printf(" since %s; %s\n", s2, s1);
2813 printf(" since %s\n", s2);
2817 if (!i->condition_result && i->condition_timestamp > 0) {
2818 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2819 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2822 printf(" %*s start condition failed at %s; %s\n", maxlen, "", s2, s1);
2824 printf(" %*s start condition failed at %s\n", maxlen, "", s2);
2828 printf(" %*s: %s\n", maxlen, "Device", i->sysfs_path);
2830 printf(" %*s: %s\n", maxlen, "Where", i->where);
2832 printf(" %*s: %s\n", maxlen, "What", i->what);
2834 STRV_FOREACH(t, i->documentation)
2835 printf(" %*s %s\n", maxlen+1, t == i->documentation ? "Docs:" : "", *t);
2837 STRV_FOREACH_PAIR(t, t2, i->listen)
2838 printf(" %*s %s (%s)\n", maxlen+1, t == i->listen ? "Listen:" : "", *t2, *t);
2841 printf(" %*s: %u; Connected: %u\n", maxlen, "Accepted", i->n_accepted, i->n_connections);
2843 LIST_FOREACH(exec, p, i->exec) {
2844 _cleanup_free_ char *argv = NULL;
2847 /* Only show exited processes here */
2851 argv = strv_join(p->argv, " ");
2852 printf(" %*s: %u %s=%s ", maxlen, "Process", p->pid, p->name, strna(argv));
2854 good = is_clean_exit_lsb(p->code, p->status, NULL);
2856 on = ansi_highlight_red(true);
2857 off = ansi_highlight_red(false);
2861 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2863 if (p->code == CLD_EXITED) {
2866 printf("status=%i", p->status);
2868 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2873 printf("signal=%s", signal_to_string(p->status));
2875 printf(")%s\n", off);
2877 if (i->main_pid == p->pid &&
2878 i->start_timestamp == p->start_timestamp &&
2879 i->exit_timestamp == p->start_timestamp)
2880 /* Let's not show this twice */
2883 if (p->pid == i->control_pid)
2887 if (i->main_pid > 0 || i->control_pid > 0) {
2888 if (i->main_pid > 0) {
2889 printf(" %*s: %u", maxlen, "Main PID", (unsigned) i->main_pid);
2892 _cleanup_free_ char *comm = NULL;
2893 get_process_comm(i->main_pid, &comm);
2895 printf(" (%s)", comm);
2896 } else if (i->exit_code > 0) {
2897 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2899 if (i->exit_code == CLD_EXITED) {
2902 printf("status=%i", i->exit_status);
2904 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2909 printf("signal=%s", signal_to_string(i->exit_status));
2913 if (i->control_pid > 0)
2917 if (i->control_pid > 0) {
2918 _cleanup_free_ char *c = NULL;
2920 printf(" %*s: %u", i->main_pid ? 0 : maxlen, "Control", (unsigned) i->control_pid);
2922 get_process_comm(i->control_pid, &c);
2931 printf(" %*s: \"%s\"\n", maxlen, "Status", i->status_text);
2933 if (i->default_control_group &&
2934 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2937 printf(" %*s: %s\n", maxlen, "CGroup", i->default_control_group);
2939 if (arg_transport != TRANSPORT_SSH) {
2942 char prefix[maxlen + 4];
2943 memset(prefix, ' ', sizeof(prefix) - 1);
2944 prefix[sizeof(prefix) - 1] = '\0';
2947 if (c > sizeof(prefix) - 1)
2948 c -= sizeof(prefix) - 1;
2952 if (i->main_pid > 0)
2953 extra[k++] = i->main_pid;
2955 if (i->control_pid > 0)
2956 extra[k++] = i->control_pid;
2958 show_cgroup_and_extra_by_spec(i->default_control_group, prefix,
2959 c, false, extra, k, flags);
2963 if (i->id && arg_transport != TRANSPORT_SSH) {
2965 show_journal_by_unit(stdout,
2969 i->inactive_exit_timestamp_monotonic,
2973 arg_scope == UNIT_FILE_SYSTEM);
2976 if (i->need_daemon_reload)
2977 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2978 ansi_highlight_red(true),
2979 ansi_highlight_red(false),
2980 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2983 static void show_unit_help(UnitStatusInfo *i) {
2988 if (!i->documentation) {
2989 log_info("Documentation for %s not known.", i->id);
2993 STRV_FOREACH(p, i->documentation) {
2995 if (startswith(*p, "man:")) {
2998 _cleanup_free_ char *page = NULL, *section = NULL;
2999 const char *args[4] = { "man", NULL, NULL, NULL };
3004 if ((*p)[k-1] == ')')
3005 e = strrchr(*p, '(');
3008 page = strndup((*p) + 4, e - *p - 4);
3009 section = strndup(e + 1, *p + k - e - 2);
3010 if (!page || !section) {
3022 log_error("Failed to fork: %m");
3028 execvp(args[0], (char**) args);
3029 log_error("Failed to execute man: %m");
3030 _exit(EXIT_FAILURE);
3033 wait_for_terminate(pid, NULL);
3035 log_info("Can't show: %s", *p);
3039 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
3045 switch (dbus_message_iter_get_arg_type(iter)) {
3047 case DBUS_TYPE_STRING: {
3050 dbus_message_iter_get_basic(iter, &s);
3053 if (streq(name, "Id"))
3055 else if (streq(name, "LoadState"))
3057 else if (streq(name, "ActiveState"))
3058 i->active_state = s;
3059 else if (streq(name, "SubState"))
3061 else if (streq(name, "Description"))
3063 else if (streq(name, "FragmentPath"))
3064 i->fragment_path = s;
3065 else if (streq(name, "SourcePath"))
3067 else if (streq(name, "DefaultControlGroup"))
3068 i->default_control_group = s;
3069 else if (streq(name, "StatusText"))
3071 else if (streq(name, "SysFSPath"))
3073 else if (streq(name, "Where"))
3075 else if (streq(name, "What"))
3077 else if (streq(name, "Following"))
3079 else if (streq(name, "UnitFileState"))
3080 i->unit_file_state = s;
3081 else if (streq(name, "Result"))
3088 case DBUS_TYPE_BOOLEAN: {
3091 dbus_message_iter_get_basic(iter, &b);
3093 if (streq(name, "Accept"))
3095 else if (streq(name, "NeedDaemonReload"))
3096 i->need_daemon_reload = b;
3097 else if (streq(name, "ConditionResult"))
3098 i->condition_result = b;
3103 case DBUS_TYPE_UINT32: {
3106 dbus_message_iter_get_basic(iter, &u);
3108 if (streq(name, "MainPID")) {
3110 i->main_pid = (pid_t) u;
3113 } else if (streq(name, "ControlPID"))
3114 i->control_pid = (pid_t) u;
3115 else if (streq(name, "ExecMainPID")) {
3117 i->main_pid = (pid_t) u;
3118 } else if (streq(name, "NAccepted"))
3120 else if (streq(name, "NConnections"))
3121 i->n_connections = u;
3126 case DBUS_TYPE_INT32: {
3129 dbus_message_iter_get_basic(iter, &j);
3131 if (streq(name, "ExecMainCode"))
3132 i->exit_code = (int) j;
3133 else if (streq(name, "ExecMainStatus"))
3134 i->exit_status = (int) j;
3139 case DBUS_TYPE_UINT64: {
3142 dbus_message_iter_get_basic(iter, &u);
3144 if (streq(name, "ExecMainStartTimestamp"))
3145 i->start_timestamp = (usec_t) u;
3146 else if (streq(name, "ExecMainExitTimestamp"))
3147 i->exit_timestamp = (usec_t) u;
3148 else if (streq(name, "ActiveEnterTimestamp"))
3149 i->active_enter_timestamp = (usec_t) u;
3150 else if (streq(name, "InactiveEnterTimestamp"))
3151 i->inactive_enter_timestamp = (usec_t) u;
3152 else if (streq(name, "InactiveExitTimestamp"))
3153 i->inactive_exit_timestamp = (usec_t) u;
3154 else if (streq(name, "InactiveExitTimestampMonotonic"))
3155 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3156 else if (streq(name, "ActiveExitTimestamp"))
3157 i->active_exit_timestamp = (usec_t) u;
3158 else if (streq(name, "ConditionTimestamp"))
3159 i->condition_timestamp = (usec_t) u;
3164 case DBUS_TYPE_ARRAY: {
3166 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3167 startswith(name, "Exec")) {
3168 DBusMessageIter sub;
3170 dbus_message_iter_recurse(iter, &sub);
3171 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3172 ExecStatusInfo *info;
3175 if (!(info = new0(ExecStatusInfo, 1)))
3178 if (!(info->name = strdup(name))) {
3183 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
3188 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
3190 dbus_message_iter_next(&sub);
3193 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3194 DBusMessageIter sub, sub2;
3196 dbus_message_iter_recurse(iter, &sub);
3197 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3198 const char *type, *path;
3200 dbus_message_iter_recurse(&sub, &sub2);
3202 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3203 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
3206 r = strv_extend(&i->listen, type);
3209 r = strv_extend(&i->listen, path);
3214 dbus_message_iter_next(&sub);
3219 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING && streq(name, "DropInPaths")) {
3220 int r = bus_parse_strv_iter(iter, &i->dropin_paths);
3224 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3225 streq(name, "Documentation")) {
3227 DBusMessageIter sub;
3229 dbus_message_iter_recurse(iter, &sub);
3230 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
3234 dbus_message_iter_get_basic(&sub, &s);
3236 r = strv_extend(&i->documentation, s);
3240 dbus_message_iter_next(&sub);
3247 case DBUS_TYPE_STRUCT: {
3249 if (streq(name, "LoadError")) {
3250 DBusMessageIter sub;
3251 const char *n, *message;
3254 dbus_message_iter_recurse(iter, &sub);
3256 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
3260 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
3264 if (!isempty(message))
3265 i->load_error = message;
3275 static int print_property(const char *name, DBusMessageIter *iter) {
3279 /* This is a low-level property printer, see
3280 * print_status_info() for the nicer output */
3282 if (arg_properties && !strv_find(arg_properties, name))
3285 switch (dbus_message_iter_get_arg_type(iter)) {
3287 case DBUS_TYPE_STRUCT: {
3288 DBusMessageIter sub;
3289 dbus_message_iter_recurse(iter, &sub);
3291 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
3294 dbus_message_iter_get_basic(&sub, &u);
3297 printf("%s=%u\n", name, (unsigned) u);
3299 printf("%s=\n", name);
3302 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
3305 dbus_message_iter_get_basic(&sub, &s);
3307 if (arg_all || s[0])
3308 printf("%s=%s\n", name, s);
3311 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
3312 const char *a = NULL, *b = NULL;
3314 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
3315 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
3317 if (arg_all || !isempty(a) || !isempty(b))
3318 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3326 case DBUS_TYPE_ARRAY:
3328 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
3329 DBusMessageIter sub, sub2;
3331 dbus_message_iter_recurse(iter, &sub);
3332 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3336 dbus_message_iter_recurse(&sub, &sub2);
3338 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3339 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3340 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3342 dbus_message_iter_next(&sub);
3347 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3348 DBusMessageIter sub, sub2;
3350 dbus_message_iter_recurse(iter, &sub);
3352 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3353 const char *type, *path;
3355 dbus_message_iter_recurse(&sub, &sub2);
3357 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3358 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3359 printf("%s=%s\n", type, path);
3361 dbus_message_iter_next(&sub);
3366 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3367 DBusMessageIter sub, sub2;
3369 dbus_message_iter_recurse(iter, &sub);
3370 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3371 const char *type, *path;
3373 dbus_message_iter_recurse(&sub, &sub2);
3375 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3376 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3377 printf("Listen%s=%s\n", type, path);
3379 dbus_message_iter_next(&sub);
3384 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3385 DBusMessageIter sub, sub2;
3387 dbus_message_iter_recurse(iter, &sub);
3388 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3390 uint64_t value, next_elapse;
3392 dbus_message_iter_recurse(&sub, &sub2);
3394 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3395 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3396 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3397 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3399 printf("%s={ value=%s ; next_elapse=%s }\n",
3401 format_timespan(timespan1, sizeof(timespan1), value, 0),
3402 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3405 dbus_message_iter_next(&sub);
3410 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
3411 DBusMessageIter sub, sub2;
3413 dbus_message_iter_recurse(iter, &sub);
3414 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3415 const char *controller, *attr, *value;
3417 dbus_message_iter_recurse(&sub, &sub2);
3419 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
3420 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
3421 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
3423 printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
3429 dbus_message_iter_next(&sub);
3434 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3435 DBusMessageIter sub;
3437 dbus_message_iter_recurse(iter, &sub);
3438 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3439 ExecStatusInfo info = {};
3441 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3442 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3443 _cleanup_free_ char *t;
3445 t = strv_join(info.argv, " ");
3447 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3451 yes_no(info.ignore),
3452 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3453 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3454 (unsigned) info. pid,
3455 sigchld_code_to_string(info.code),
3457 info.code == CLD_EXITED ? "" : "/",
3458 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3462 strv_free(info.argv);
3464 dbus_message_iter_next(&sub);
3473 if (generic_print_property(name, iter, arg_all) > 0)
3477 printf("%s=[unprintable]\n", name);
3482 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3483 _cleanup_free_ DBusMessage *reply = NULL;
3484 const char *interface = "";
3486 DBusMessageIter iter, sub, sub2, sub3;
3487 UnitStatusInfo info = {};
3493 r = bus_method_call_with_reply(
3495 "org.freedesktop.systemd1",
3497 "org.freedesktop.DBus.Properties",
3501 DBUS_TYPE_STRING, &interface,
3506 if (!dbus_message_iter_init(reply, &iter) ||
3507 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3508 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3509 log_error("Failed to parse reply.");
3513 dbus_message_iter_recurse(&iter, &sub);
3520 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3523 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3524 dbus_message_iter_recurse(&sub, &sub2);
3526 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3527 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3528 log_error("Failed to parse reply.");
3532 dbus_message_iter_recurse(&sub2, &sub3);
3534 if (show_properties)
3535 r = print_property(name, &sub3);
3537 r = status_property(name, &sub3, &info);
3539 log_error("Failed to parse reply.");
3543 dbus_message_iter_next(&sub);
3548 if (!show_properties) {
3549 if (streq(verb, "help"))
3550 show_unit_help(&info);
3552 print_status_info(&info);
3555 strv_free(info.documentation);
3556 strv_free(info.dropin_paths);
3557 strv_free(info.listen);
3559 if (!streq_ptr(info.active_state, "active") &&
3560 !streq_ptr(info.active_state, "reloading") &&
3561 streq(verb, "status"))
3562 /* According to LSB: "program not running" */
3565 while ((p = info.exec)) {
3566 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3567 exec_status_info_free(p);
3573 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3574 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3575 const char *path = NULL;
3576 _cleanup_dbus_error_free_ DBusError error;
3579 dbus_error_init(&error);
3581 r = bus_method_call_with_reply(
3583 "org.freedesktop.systemd1",
3584 "/org/freedesktop/systemd1",
3585 "org.freedesktop.systemd1.Manager",
3589 DBUS_TYPE_UINT32, &pid,
3594 if (!dbus_message_get_args(reply, &error,
3595 DBUS_TYPE_OBJECT_PATH, &path,
3596 DBUS_TYPE_INVALID)) {
3597 log_error("Failed to parse reply: %s", bus_error_message(&error));
3601 r = show_one(verb, bus, path, false, new_line);
3605 static int show_all(const char* verb, DBusConnection *bus, bool show_properties, bool *new_line) {
3606 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3607 _cleanup_free_ struct unit_info *unit_infos = NULL;
3609 const struct unit_info *u;
3612 r = get_unit_list(bus, &reply, &unit_infos, &c);
3616 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
3618 for (u = unit_infos; u < unit_infos + c; u++) {
3619 _cleanup_free_ char *p = NULL;
3621 if (!output_show_unit(u))
3624 p = unit_dbus_path_from_name(u->id);
3628 printf("%s -> '%s'\n", u->id, p);
3630 r = show_one(verb, bus, p, show_properties, new_line);
3638 static int show(DBusConnection *bus, char **args) {
3640 bool show_properties, show_status, new_line = false;
3646 show_properties = streq(args[0], "show");
3647 show_status = streq(args[0], "status");
3649 if (show_properties)
3650 pager_open_if_enabled();
3652 /* If no argument is specified inspect the manager itself */
3654 if (show_properties && strv_length(args) <= 1)
3655 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3657 if (show_status && strv_length(args) <= 1)
3658 return show_all(args[0], bus, false, &new_line);
3660 STRV_FOREACH(name, args+1) {
3663 if (safe_atou32(*name, &id) < 0) {
3664 _cleanup_free_ char *p = NULL, *n = NULL;
3665 /* Interpret as unit name */
3667 n = unit_name_mangle(*name);
3671 p = unit_dbus_path_from_name(n);
3675 r = show_one(args[0], bus, p, show_properties, &new_line);
3679 } else if (show_properties) {
3680 _cleanup_free_ char *p = NULL;
3682 /* Interpret as job id */
3683 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3686 r = show_one(args[0], bus, p, show_properties, &new_line);
3691 /* Interpret as PID */
3692 r = show_one_by_pid(args[0], bus, id, &new_line);
3701 static int dump(DBusConnection *bus, char **args) {
3702 _cleanup_free_ DBusMessage *reply = NULL;
3707 dbus_error_init(&error);
3709 pager_open_if_enabled();
3711 r = bus_method_call_with_reply(
3713 "org.freedesktop.systemd1",
3714 "/org/freedesktop/systemd1",
3715 "org.freedesktop.systemd1.Manager",
3723 if (!dbus_message_get_args(reply, &error,
3724 DBUS_TYPE_STRING, &text,
3725 DBUS_TYPE_INVALID)) {
3726 log_error("Failed to parse reply: %s", bus_error_message(&error));
3727 dbus_error_free(&error);
3731 fputs(text, stdout);
3735 static int snapshot(DBusConnection *bus, char **args) {
3736 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3739 dbus_bool_t cleanup = FALSE;
3740 DBusMessageIter iter, sub;
3743 *interface = "org.freedesktop.systemd1.Unit",
3745 _cleanup_free_ char *n = NULL;
3747 dbus_error_init(&error);
3749 if (strv_length(args) > 1)
3750 n = snapshot_name_mangle(args[1]);
3756 r = bus_method_call_with_reply (
3758 "org.freedesktop.systemd1",
3759 "/org/freedesktop/systemd1",
3760 "org.freedesktop.systemd1.Manager",
3764 DBUS_TYPE_STRING, &n,
3765 DBUS_TYPE_BOOLEAN, &cleanup,
3770 if (!dbus_message_get_args(reply, &error,
3771 DBUS_TYPE_OBJECT_PATH, &path,
3772 DBUS_TYPE_INVALID)) {
3773 log_error("Failed to parse reply: %s", bus_error_message(&error));
3774 dbus_error_free(&error);
3778 dbus_message_unref(reply);
3781 r = bus_method_call_with_reply (
3783 "org.freedesktop.systemd1",
3785 "org.freedesktop.DBus.Properties",
3789 DBUS_TYPE_STRING, &interface,
3790 DBUS_TYPE_STRING, &property,
3795 if (!dbus_message_iter_init(reply, &iter) ||
3796 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3797 log_error("Failed to parse reply.");
3801 dbus_message_iter_recurse(&iter, &sub);
3803 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3804 log_error("Failed to parse reply.");
3808 dbus_message_iter_get_basic(&sub, &id);
3816 static int delete_snapshot(DBusConnection *bus, char **args) {
3821 STRV_FOREACH(name, args+1) {
3822 _cleanup_free_ char *n = NULL;
3825 n = snapshot_name_mangle(*name);
3829 r = bus_method_call_with_reply(
3831 "org.freedesktop.systemd1",
3832 "/org/freedesktop/systemd1",
3833 "org.freedesktop.systemd1.Manager",
3837 DBUS_TYPE_STRING, &n,
3846 static int daemon_reload(DBusConnection *bus, char **args) {
3851 if (arg_action == ACTION_RELOAD)
3853 else if (arg_action == ACTION_REEXEC)
3854 method = "Reexecute";
3856 assert(arg_action == ACTION_SYSTEMCTL);
3859 streq(args[0], "clear-jobs") ||
3860 streq(args[0], "cancel") ? "ClearJobs" :
3861 streq(args[0], "daemon-reexec") ? "Reexecute" :
3862 streq(args[0], "reset-failed") ? "ResetFailed" :
3863 streq(args[0], "halt") ? "Halt" :
3864 streq(args[0], "poweroff") ? "PowerOff" :
3865 streq(args[0], "reboot") ? "Reboot" :
3866 streq(args[0], "kexec") ? "KExec" :
3867 streq(args[0], "exit") ? "Exit" :
3868 /* "daemon-reload" */ "Reload";
3871 r = bus_method_call_with_reply(
3873 "org.freedesktop.systemd1",
3874 "/org/freedesktop/systemd1",
3875 "org.freedesktop.systemd1.Manager",
3881 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3882 /* There's always a fallback possible for
3883 * legacy actions. */
3885 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3886 /* On reexecution, we expect a disconnect, not
3890 log_error("Failed to issue method call: %s", bus_error_message(&error));
3892 dbus_error_free(&error);
3896 static int reset_failed(DBusConnection *bus, char **args) {
3900 if (strv_length(args) <= 1)
3901 return daemon_reload(bus, args);
3903 STRV_FOREACH(name, args+1) {
3904 _cleanup_free_ char *n;
3906 n = unit_name_mangle(*name);
3910 r = bus_method_call_with_reply(
3912 "org.freedesktop.systemd1",
3913 "/org/freedesktop/systemd1",
3914 "org.freedesktop.systemd1.Manager",
3918 DBUS_TYPE_STRING, &n,
3927 static int show_enviroment(DBusConnection *bus, char **args) {
3928 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3929 DBusMessageIter iter, sub, sub2;
3932 *interface = "org.freedesktop.systemd1.Manager",
3933 *property = "Environment";
3935 pager_open_if_enabled();
3937 r = bus_method_call_with_reply(
3939 "org.freedesktop.systemd1",
3940 "/org/freedesktop/systemd1",
3941 "org.freedesktop.DBus.Properties",
3945 DBUS_TYPE_STRING, &interface,
3946 DBUS_TYPE_STRING, &property,
3951 if (!dbus_message_iter_init(reply, &iter) ||
3952 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3953 log_error("Failed to parse reply.");
3957 dbus_message_iter_recurse(&iter, &sub);
3959 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3960 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3961 log_error("Failed to parse reply.");
3965 dbus_message_iter_recurse(&sub, &sub2);
3967 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3970 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3971 log_error("Failed to parse reply.");
3975 dbus_message_iter_get_basic(&sub2, &text);
3978 dbus_message_iter_next(&sub2);
3984 static int switch_root(DBusConnection *bus, char **args) {
3987 _cleanup_free_ char *init = NULL;
3989 l = strv_length(args);
3990 if (l < 2 || l > 3) {
3991 log_error("Wrong number of arguments.");
3998 init = strdup(args[2]);
4000 parse_env_file("/proc/cmdline", WHITESPACE,
4010 log_debug("switching root - root: %s; init: %s", root, init);
4012 return bus_method_call_with_reply(
4014 "org.freedesktop.systemd1",
4015 "/org/freedesktop/systemd1",
4016 "org.freedesktop.systemd1.Manager",
4020 DBUS_TYPE_STRING, &root,
4021 DBUS_TYPE_STRING, &init,
4025 static int set_environment(DBusConnection *bus, char **args) {
4026 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4029 DBusMessageIter iter;
4035 dbus_error_init(&error);
4037 method = streq(args[0], "set-environment")
4039 : "UnsetEnvironment";
4041 m = dbus_message_new_method_call(
4042 "org.freedesktop.systemd1",
4043 "/org/freedesktop/systemd1",
4044 "org.freedesktop.systemd1.Manager",
4049 dbus_message_iter_init_append(m, &iter);
4051 r = bus_append_strv_iter(&iter, args + 1);
4055 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4057 log_error("Failed to issue method call: %s", bus_error_message(&error));
4058 dbus_error_free(&error);
4065 static int enable_sysv_units(char **args) {
4068 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4069 const char *verb = args[0];
4070 unsigned f = 1, t = 1;
4071 LookupPaths paths = {};
4073 if (arg_scope != UNIT_FILE_SYSTEM)
4076 if (!streq(verb, "enable") &&
4077 !streq(verb, "disable") &&
4078 !streq(verb, "is-enabled"))
4081 /* Processes all SysV units, and reshuffles the array so that
4082 * afterwards only the native units remain */
4084 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4089 for (f = 1; args[f]; f++) {
4091 _cleanup_free_ char *p = NULL, *q = NULL;
4092 bool found_native = false, found_sysv;
4094 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4102 if (!endswith(name, ".service"))
4105 if (path_is_absolute(name))
4108 STRV_FOREACH(k, paths.unit_path) {
4109 if (!isempty(arg_root))
4110 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4112 asprintf(&p, "%s/%s", *k, name);
4119 found_native = access(p, F_OK) >= 0;
4130 if (!isempty(arg_root))
4131 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4133 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4139 p[strlen(p) - sizeof(".service") + 1] = 0;
4140 found_sysv = access(p, F_OK) >= 0;
4145 /* Mark this entry, so that we don't try enabling it as native unit */
4146 args[f] = (char*) "";
4148 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4150 if (!isempty(arg_root))
4151 argv[c++] = q = strappend("--root=", arg_root);
4153 argv[c++] = path_get_file_name(p);
4155 streq(verb, "enable") ? "on" :
4156 streq(verb, "disable") ? "off" : "--level=5";
4159 l = strv_join((char**)argv, " ");
4165 log_info("Executing %s", l);
4170 log_error("Failed to fork: %m");
4173 } else if (pid == 0) {
4176 execv(argv[0], (char**) argv);
4177 _exit(EXIT_FAILURE);
4180 j = wait_for_terminate(pid, &status);
4182 log_error("Failed to wait for child: %s", strerror(-r));
4187 if (status.si_code == CLD_EXITED) {
4188 if (streq(verb, "is-enabled")) {
4189 if (status.si_status == 0) {
4198 } else if (status.si_status != 0) {
4209 lookup_paths_free(&paths);
4211 /* Drop all SysV units */
4212 for (f = 1, t = 1; args[f]; f++) {
4214 if (isempty(args[f]))
4217 args[t++] = args[f];
4226 static int mangle_names(char **original_names, char ***mangled_names) {
4227 char **i, **l, **name;
4229 l = new(char*, strv_length(original_names) + 1);
4234 STRV_FOREACH(name, original_names) {
4236 /* When enabling units qualified path names are OK,
4237 * too, hence allow them explicitly. */
4242 *i = unit_name_mangle(*name);
4258 static int enable_unit(DBusConnection *bus, char **args) {
4259 const char *verb = args[0];
4260 UnitFileChange *changes = NULL;
4261 unsigned n_changes = 0, i;
4262 int carries_install_info = -1;
4263 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4265 _cleanup_dbus_error_free_ DBusError error;
4266 _cleanup_strv_free_ char **mangled_names = NULL;
4268 dbus_error_init(&error);
4270 r = enable_sysv_units(args);
4277 r = mangle_names(args+1, &mangled_names);
4281 if (!bus || avoid_bus()) {
4282 if (streq(verb, "enable")) {
4283 r = unit_file_enable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4284 carries_install_info = r;
4285 } else if (streq(verb, "disable"))
4286 r = unit_file_disable(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4287 else if (streq(verb, "reenable")) {
4288 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4289 carries_install_info = r;
4290 } else if (streq(verb, "link"))
4291 r = unit_file_link(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4292 else if (streq(verb, "preset")) {
4293 r = unit_file_preset(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4294 carries_install_info = r;
4295 } else if (streq(verb, "mask"))
4296 r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
4297 else if (streq(verb, "unmask"))
4298 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
4299 else if (streq(verb, "set-default"))
4300 r = unit_file_set_default(arg_scope, arg_root, args[1], &changes, &n_changes);
4302 assert_not_reached("Unknown verb");
4305 log_error("Operation failed: %s", strerror(-r));
4310 for (i = 0; i < n_changes; i++) {
4311 if (changes[i].type == UNIT_FILE_SYMLINK)
4312 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4314 log_info("rm '%s'", changes[i].path);
4321 bool send_force = true, expect_carries_install_info = false;
4323 DBusMessageIter iter, sub, sub2;
4325 if (streq(verb, "enable")) {
4326 method = "EnableUnitFiles";
4327 expect_carries_install_info = true;
4328 } else if (streq(verb, "disable")) {
4329 method = "DisableUnitFiles";
4331 } else if (streq(verb, "reenable")) {
4332 method = "ReenableUnitFiles";
4333 expect_carries_install_info = true;
4334 } else if (streq(verb, "link"))
4335 method = "LinkUnitFiles";
4336 else if (streq(verb, "preset")) {
4337 method = "PresetUnitFiles";
4338 expect_carries_install_info = true;
4339 } else if (streq(verb, "mask"))
4340 method = "MaskUnitFiles";
4341 else if (streq(verb, "unmask")) {
4342 method = "UnmaskUnitFiles";
4344 } else if (streq(verb, "set-default")) {
4345 method = "SetDefaultTarget";
4347 assert_not_reached("Unknown verb");
4349 m = dbus_message_new_method_call(
4350 "org.freedesktop.systemd1",
4351 "/org/freedesktop/systemd1",
4352 "org.freedesktop.systemd1.Manager",
4359 dbus_message_iter_init_append(m, &iter);
4361 r = bus_append_strv_iter(&iter, mangled_names);
4363 log_error("Failed to append unit files.");
4368 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4369 log_error("Failed to append runtime boolean.");
4377 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4378 log_error("Failed to append force boolean.");
4384 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4386 log_error("Failed to issue method call: %s", bus_error_message(&error));
4391 if (!dbus_message_iter_init(reply, &iter)) {
4392 log_error("Failed to initialize iterator.");
4396 if (expect_carries_install_info) {
4397 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4399 log_error("Failed to parse reply.");
4403 carries_install_info = b;
4406 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4407 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4408 log_error("Failed to parse reply.");
4413 dbus_message_iter_recurse(&iter, &sub);
4414 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4415 const char *type, *path, *source;
4417 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4418 log_error("Failed to parse reply.");
4423 dbus_message_iter_recurse(&sub, &sub2);
4425 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4426 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4427 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4428 log_error("Failed to parse reply.");
4434 if (streq(type, "symlink"))
4435 log_info("ln -s '%s' '%s'", source, path);
4437 log_info("rm '%s'", path);
4440 dbus_message_iter_next(&sub);
4443 /* Try to reload if enabeld */
4445 r = daemon_reload(bus, args);
4448 if (carries_install_info == 0)
4449 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4450 "using systemctl.\n"
4451 "Possible reasons for having this kind of units are:\n"
4452 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4453 " .wants/ or .requires/ directory.\n"
4454 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4455 " a requirement dependency on it.\n"
4456 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4457 " D-Bus, udev, scripted systemctl call, ...).\n");
4460 unit_file_changes_free(changes, n_changes);
4465 static int unit_is_enabled(DBusConnection *bus, char **args) {
4466 _cleanup_dbus_error_free_ DBusError error;
4468 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4473 dbus_error_init(&error);
4475 r = enable_sysv_units(args);
4481 if (!bus || avoid_bus()) {
4483 STRV_FOREACH(name, args+1) {
4484 UnitFileState state;
4486 n = unit_name_mangle(*name);
4490 state = unit_file_get_state(arg_scope, arg_root, n);
4497 if (state == UNIT_FILE_ENABLED ||
4498 state == UNIT_FILE_ENABLED_RUNTIME ||
4499 state == UNIT_FILE_STATIC)
4503 puts(unit_file_state_to_string(state));
4507 STRV_FOREACH(name, args+1) {
4510 n = unit_name_mangle(*name);
4514 r = bus_method_call_with_reply (
4516 "org.freedesktop.systemd1",
4517 "/org/freedesktop/systemd1",
4518 "org.freedesktop.systemd1.Manager",
4522 DBUS_TYPE_STRING, &n,
4530 if (!dbus_message_get_args(reply, &error,
4531 DBUS_TYPE_STRING, &s,
4532 DBUS_TYPE_INVALID)) {
4533 log_error("Failed to parse reply: %s", bus_error_message(&error));
4537 dbus_message_unref(reply);
4540 if (streq(s, "enabled") ||
4541 streq(s, "enabled-runtime") ||
4550 return enabled ? 0 : 1;
4553 static int systemctl_help(void) {
4555 pager_open_if_enabled();
4557 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4558 "Query or send control commands to the systemd manager.\n\n"
4559 " -h --help Show this help\n"
4560 " --version Show package version\n"
4561 " -t --type=TYPE List only units of a particular type\n"
4562 " -p --property=NAME Show only properties by this name\n"
4563 " -a --all Show all loaded units/properties, including dead/empty\n"
4564 " ones. To list all units installed on the system, use\n"
4565 " the 'list-unit-files' command instead.\n"
4566 " --reverse Show reverse dependencies with 'list-dependencies'\n"
4567 " --failed Show only failed units\n"
4568 " --full Don't ellipsize unit names on output\n"
4569 " --fail When queueing a new job, fail if conflicting jobs are\n"
4571 " --irreversible Create jobs which cannot be implicitly cancelled\n"
4572 " --show-types When showing sockets, explicitly show their type\n"
4573 " --ignore-dependencies\n"
4574 " When queueing a new job, ignore all its dependencies\n"
4575 " -i --ignore-inhibitors\n"
4576 " When shutting down or sleeping, ignore inhibitors\n"
4577 " --kill-who=WHO Who to send signal to\n"
4578 " -s --signal=SIGNAL Which signal to send\n"
4579 " -H --host=[USER@]HOST\n"
4580 " Show information for remote host\n"
4581 " -P --privileged Acquire privileges before execution\n"
4582 " -q --quiet Suppress output\n"
4583 " --no-block Do not wait until operation finished\n"
4584 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4585 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4587 " --no-legend Do not print a legend (column headers and hints)\n"
4588 " --no-pager Do not pipe output into a pager\n"
4589 " --no-ask-password\n"
4590 " Do not ask for system passwords\n"
4591 " --system Connect to system manager\n"
4592 " --user Connect to user service manager\n"
4593 " --global Enable/disable unit files globally\n"
4594 " -f --force When enabling unit files, override existing symlinks\n"
4595 " When shutting down, execute action immediately\n"
4596 " --root=PATH Enable unit files in the specified root directory\n"
4597 " --runtime Enable unit files only temporarily until next reboot\n"
4598 " -n --lines=INTEGER Journal entries to show\n"
4599 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4600 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4602 " list-units List loaded units\n"
4603 " start [NAME...] Start (activate) one or more units\n"
4604 " stop [NAME...] Stop (deactivate) one or more units\n"
4605 " reload [NAME...] Reload one or more units\n"
4606 " restart [NAME...] Start or restart one or more units\n"
4607 " try-restart [NAME...] Restart one or more units if active\n"
4608 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4609 " otherwise start or restart\n"
4610 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4611 " otherwise restart if active\n"
4612 " isolate [NAME] Start one unit and stop all others\n"
4613 " kill [NAME...] Send signal to processes of a unit\n"
4614 " is-active [NAME...] Check whether units are active\n"
4615 " is-failed [NAME...] Check whether units are failed\n"
4616 " status [NAME...|PID...] Show runtime status of one or more units\n"
4617 " show [NAME...|JOB...] Show properties of one or more\n"
4618 " units/jobs or the manager\n"
4619 " help [NAME...|PID...] Show manual for one or more units\n"
4620 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4622 " get-cgroup-attr [NAME] [ATTR] ...\n"
4623 " Get control group attrubute\n"
4624 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4625 " Set control group attribute\n"
4626 " unset-cgroup-attr [NAME] [ATTR...]\n"
4627 " Unset control group attribute\n"
4628 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4629 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4630 " load [NAME...] Load one or more units\n"
4631 " list-dependencies [NAME] Recursively show units which are required\n"
4632 " or wanted by this unit or by which this\n"
4633 " unit is required or wanted\n\n"
4634 "Unit File Commands:\n"
4635 " list-unit-files List installed unit files\n"
4636 " enable [NAME...] Enable one or more unit files\n"
4637 " disable [NAME...] Disable one or more unit files\n"
4638 " reenable [NAME...] Reenable one or more unit files\n"
4639 " preset [NAME...] Enable/disable one or more unit files\n"
4640 " based on preset configuration\n"
4641 " mask [NAME...] Mask one or more units\n"
4642 " unmask [NAME...] Unmask one or more units\n"
4643 " link [PATH...] Link one or more units files into\n"
4644 " the search path\n"
4645 " get-default Get the name of the default target\n"
4646 " set-default NAME Set the default target\n"
4647 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4649 " list-jobs List jobs\n"
4650 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4651 "Status Commands:\n"
4652 " dump Dump server status\n"
4653 "Snapshot Commands:\n"
4654 " snapshot [NAME] Create a snapshot\n"
4655 " delete [NAME...] Remove one or more snapshots\n\n"
4656 "Environment Commands:\n"
4657 " show-environment Dump environment\n"
4658 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4659 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4660 "Manager Lifecycle Commands:\n"
4661 " daemon-reload Reload systemd manager configuration\n"
4662 " daemon-reexec Reexecute systemd manager\n\n"
4663 "System Commands:\n"
4664 " default Enter system default mode\n"
4665 " rescue Enter system rescue mode\n"
4666 " emergency Enter system emergency mode\n"
4667 " halt Shut down and halt the system\n"
4668 " poweroff Shut down and power-off the system\n"
4669 " reboot Shut down and reboot the system\n"
4670 " kexec Shut down and reboot the system with kexec\n"
4671 " exit Request user instance exit\n"
4672 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4673 " suspend Suspend the system\n"
4674 " hibernate Hibernate the system\n"
4675 " hybrid-sleep Hibernate and suspend the system\n",
4676 program_invocation_short_name);
4681 static int halt_help(void) {
4683 printf("%s [OPTIONS...]\n\n"
4684 "%s the system.\n\n"
4685 " --help Show this help\n"
4686 " --halt Halt the machine\n"
4687 " -p --poweroff Switch off the machine\n"
4688 " --reboot Reboot the machine\n"
4689 " -f --force Force immediate halt/power-off/reboot\n"
4690 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4691 " -d --no-wtmp Don't write wtmp record\n"
4692 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4693 program_invocation_short_name,
4694 arg_action == ACTION_REBOOT ? "Reboot" :
4695 arg_action == ACTION_POWEROFF ? "Power off" :
4701 static int shutdown_help(void) {
4703 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4704 "Shut down the system.\n\n"
4705 " --help Show this help\n"
4706 " -H --halt Halt the machine\n"
4707 " -P --poweroff Power-off the machine\n"
4708 " -r --reboot Reboot the machine\n"
4709 " -h Equivalent to --poweroff, overridden by --halt\n"
4710 " -k Don't halt/power-off/reboot, just send warnings\n"
4711 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4712 " -c Cancel a pending shutdown\n",
4713 program_invocation_short_name);
4718 static int telinit_help(void) {
4720 printf("%s [OPTIONS...] {COMMAND}\n\n"
4721 "Send control commands to the init daemon.\n\n"
4722 " --help Show this help\n"
4723 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4725 " 0 Power-off the machine\n"
4726 " 6 Reboot the machine\n"
4727 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4728 " 1, s, S Enter rescue mode\n"
4729 " q, Q Reload init daemon configuration\n"
4730 " u, U Reexecute init daemon\n",
4731 program_invocation_short_name);
4736 static int runlevel_help(void) {
4738 printf("%s [OPTIONS...]\n\n"
4739 "Prints the previous and current runlevel of the init system.\n\n"
4740 " --help Show this help\n",
4741 program_invocation_short_name);
4746 static int help_types(void) {
4750 puts("Available unit types:");
4751 for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4752 t = unit_type_to_string(i);
4757 puts("\nAvailable unit load states: ");
4758 for(i = 0; i < _UNIT_LOAD_STATE_MAX; i++) {
4759 t = unit_load_state_to_string(i);
4767 static int systemctl_parse_argv(int argc, char *argv[]) {
4776 ARG_IGNORE_DEPENDENCIES,
4789 ARG_NO_ASK_PASSWORD,
4796 static const struct option options[] = {
4797 { "help", no_argument, NULL, 'h' },
4798 { "version", no_argument, NULL, ARG_VERSION },
4799 { "type", required_argument, NULL, 't' },
4800 { "property", required_argument, NULL, 'p' },
4801 { "all", no_argument, NULL, 'a' },
4802 { "reverse", no_argument, NULL, ARG_REVERSE },
4803 { "after", no_argument, NULL, ARG_AFTER },
4804 { "before", no_argument, NULL, ARG_BEFORE },
4805 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
4806 { "failed", no_argument, NULL, ARG_FAILED },
4807 { "full", no_argument, NULL, ARG_FULL },
4808 { "fail", no_argument, NULL, ARG_FAIL },
4809 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4810 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4811 { "ignore-inhibitors", no_argument, NULL, 'i' },
4812 { "user", no_argument, NULL, ARG_USER },
4813 { "system", no_argument, NULL, ARG_SYSTEM },
4814 { "global", no_argument, NULL, ARG_GLOBAL },
4815 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4816 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4817 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4818 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4819 { "quiet", no_argument, NULL, 'q' },
4820 { "root", required_argument, NULL, ARG_ROOT },
4821 { "force", no_argument, NULL, ARG_FORCE },
4822 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4823 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4824 { "signal", required_argument, NULL, 's' },
4825 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4826 { "host", required_argument, NULL, 'H' },
4827 { "privileged",no_argument, NULL, 'P' },
4828 { "runtime", no_argument, NULL, ARG_RUNTIME },
4829 { "lines", required_argument, NULL, 'n' },
4830 { "output", required_argument, NULL, 'o' },
4831 { "plain", no_argument, NULL, ARG_PLAIN },
4832 { NULL, 0, NULL, 0 }
4840 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4849 puts(PACKAGE_STRING);
4850 puts(SYSTEMD_FEATURES);
4857 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4858 _cleanup_free_ char *type;
4860 type = strndup(word, size);
4864 if (streq(type, "help")) {
4869 if (unit_type_from_string(type) >= 0) {
4870 if (strv_push(&arg_types, type))
4876 if (unit_load_state_from_string(optarg) >= 0) {
4877 if (strv_push(&arg_load_states, type))
4883 log_error("Unknown unit type or load state '%s'.", type);
4884 log_info("Use -t help to see a list of allowed values.");
4892 /* Make sure that if the empty property list
4893 was specified, we won't show any properties. */
4894 if (isempty(optarg) && !arg_properties) {
4895 arg_properties = strv_new(NULL, NULL);
4896 if (!arg_properties)
4902 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4905 prop = strndup(word, size);
4909 if (strv_push(&arg_properties, prop)) {
4916 /* If the user asked for a particular
4917 * property, show it to him, even if it is
4929 arg_dependency = DEPENDENCY_REVERSE;
4933 arg_dependency = DEPENDENCY_AFTER;
4937 arg_dependency = DEPENDENCY_BEFORE;
4940 case ARG_SHOW_TYPES:
4941 arg_show_types = true;
4945 arg_job_mode = "fail";
4948 case ARG_IRREVERSIBLE:
4949 arg_job_mode = "replace-irreversibly";
4952 case ARG_IGNORE_DEPENDENCIES:
4953 arg_job_mode = "ignore-dependencies";
4957 arg_scope = UNIT_FILE_USER;
4961 arg_scope = UNIT_FILE_SYSTEM;
4965 arg_scope = UNIT_FILE_GLOBAL;
4969 arg_no_block = true;
4973 arg_no_legend = true;
4977 arg_no_pager = true;
5009 arg_no_reload = true;
5013 arg_kill_who = optarg;
5017 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
5018 log_error("Failed to parse signal string %s.", optarg);
5023 case ARG_NO_ASK_PASSWORD:
5024 arg_ask_password = false;
5028 arg_transport = TRANSPORT_POLKIT;
5032 arg_transport = TRANSPORT_SSH;
5041 if (safe_atou(optarg, &arg_lines) < 0) {
5042 log_error("Failed to parse lines '%s'", optarg);
5048 arg_output = output_mode_from_string(optarg);
5049 if (arg_output < 0) {
5050 log_error("Unknown output '%s'.", optarg);
5056 arg_ignore_inhibitors = true;
5067 log_error("Unknown option code '%c'.", c);
5072 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
5073 log_error("Cannot access user instance remotely.");
5080 static int halt_parse_argv(int argc, char *argv[]) {
5089 static const struct option options[] = {
5090 { "help", no_argument, NULL, ARG_HELP },
5091 { "halt", no_argument, NULL, ARG_HALT },
5092 { "poweroff", no_argument, NULL, 'p' },
5093 { "reboot", no_argument, NULL, ARG_REBOOT },
5094 { "force", no_argument, NULL, 'f' },
5095 { "wtmp-only", no_argument, NULL, 'w' },
5096 { "no-wtmp", no_argument, NULL, 'd' },
5097 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5098 { NULL, 0, NULL, 0 }
5106 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5107 if (runlevel == '0' || runlevel == '6')
5110 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5118 arg_action = ACTION_HALT;
5122 if (arg_action != ACTION_REBOOT)
5123 arg_action = ACTION_POWEROFF;
5127 arg_action = ACTION_REBOOT;
5149 /* Compatibility nops */
5156 log_error("Unknown option code '%c'.", c);
5161 if (optind < argc) {
5162 log_error("Too many arguments.");
5169 static int parse_time_spec(const char *t, usec_t *_u) {
5173 if (streq(t, "now"))
5175 else if (!strchr(t, ':')) {
5178 if (safe_atou64(t, &u) < 0)
5181 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5190 hour = strtol(t, &e, 10);
5191 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5194 minute = strtol(e+1, &e, 10);
5195 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5198 n = now(CLOCK_REALTIME);
5199 s = (time_t) (n / USEC_PER_SEC);
5201 assert_se(localtime_r(&s, &tm));
5203 tm.tm_hour = (int) hour;
5204 tm.tm_min = (int) minute;
5207 assert_se(s = mktime(&tm));
5209 *_u = (usec_t) s * USEC_PER_SEC;
5212 *_u += USEC_PER_DAY;
5218 static int shutdown_parse_argv(int argc, char *argv[]) {
5225 static const struct option options[] = {
5226 { "help", no_argument, NULL, ARG_HELP },
5227 { "halt", no_argument, NULL, 'H' },
5228 { "poweroff", no_argument, NULL, 'P' },
5229 { "reboot", no_argument, NULL, 'r' },
5230 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5231 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5232 { NULL, 0, NULL, 0 }
5240 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5248 arg_action = ACTION_HALT;
5252 arg_action = ACTION_POWEROFF;
5257 arg_action = ACTION_KEXEC;
5259 arg_action = ACTION_REBOOT;
5263 arg_action = ACTION_KEXEC;
5267 if (arg_action != ACTION_HALT)
5268 arg_action = ACTION_POWEROFF;
5281 /* Compatibility nops */
5285 arg_action = ACTION_CANCEL_SHUTDOWN;
5292 log_error("Unknown option code '%c'.", c);
5297 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5298 r = parse_time_spec(argv[optind], &arg_when);
5300 log_error("Failed to parse time specification: %s", argv[optind]);
5304 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5306 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5307 /* No time argument for shutdown cancel */
5308 arg_wall = argv + optind;
5309 else if (argc > optind + 1)
5310 /* We skip the time argument */
5311 arg_wall = argv + optind + 1;
5318 static int telinit_parse_argv(int argc, char *argv[]) {
5325 static const struct option options[] = {
5326 { "help", no_argument, NULL, ARG_HELP },
5327 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5328 { NULL, 0, NULL, 0 }
5331 static const struct {
5335 { '0', ACTION_POWEROFF },
5336 { '6', ACTION_REBOOT },
5337 { '1', ACTION_RESCUE },
5338 { '2', ACTION_RUNLEVEL2 },
5339 { '3', ACTION_RUNLEVEL3 },
5340 { '4', ACTION_RUNLEVEL4 },
5341 { '5', ACTION_RUNLEVEL5 },
5342 { 's', ACTION_RESCUE },
5343 { 'S', ACTION_RESCUE },
5344 { 'q', ACTION_RELOAD },
5345 { 'Q', ACTION_RELOAD },
5346 { 'u', ACTION_REEXEC },
5347 { 'U', ACTION_REEXEC }
5356 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5371 log_error("Unknown option code '%c'.", c);
5376 if (optind >= argc) {
5381 if (optind + 1 < argc) {
5382 log_error("Too many arguments.");
5386 if (strlen(argv[optind]) != 1) {
5387 log_error("Expected single character argument.");
5391 for (i = 0; i < ELEMENTSOF(table); i++)
5392 if (table[i].from == argv[optind][0])
5395 if (i >= ELEMENTSOF(table)) {
5396 log_error("Unknown command '%s'.", argv[optind]);
5400 arg_action = table[i].to;
5407 static int runlevel_parse_argv(int argc, char *argv[]) {
5413 static const struct option options[] = {
5414 { "help", no_argument, NULL, ARG_HELP },
5415 { NULL, 0, NULL, 0 }
5423 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5434 log_error("Unknown option code '%c'.", c);
5439 if (optind < argc) {
5440 log_error("Too many arguments.");
5447 static int parse_argv(int argc, char *argv[]) {
5451 if (program_invocation_short_name) {
5453 if (strstr(program_invocation_short_name, "halt")) {
5454 arg_action = ACTION_HALT;
5455 return halt_parse_argv(argc, argv);
5456 } else if (strstr(program_invocation_short_name, "poweroff")) {
5457 arg_action = ACTION_POWEROFF;
5458 return halt_parse_argv(argc, argv);
5459 } else if (strstr(program_invocation_short_name, "reboot")) {
5461 arg_action = ACTION_KEXEC;
5463 arg_action = ACTION_REBOOT;
5464 return halt_parse_argv(argc, argv);
5465 } else if (strstr(program_invocation_short_name, "shutdown")) {
5466 arg_action = ACTION_POWEROFF;
5467 return shutdown_parse_argv(argc, argv);
5468 } else if (strstr(program_invocation_short_name, "init")) {
5470 if (sd_booted() > 0) {
5471 arg_action = ACTION_INVALID;
5472 return telinit_parse_argv(argc, argv);
5474 /* Hmm, so some other init system is
5475 * running, we need to forward this
5476 * request to it. For now we simply
5477 * guess that it is Upstart. */
5479 execv(TELINIT, argv);
5481 log_error("Couldn't find an alternative telinit implementation to spawn.");
5485 } else if (strstr(program_invocation_short_name, "runlevel")) {
5486 arg_action = ACTION_RUNLEVEL;
5487 return runlevel_parse_argv(argc, argv);
5491 arg_action = ACTION_SYSTEMCTL;
5492 return systemctl_parse_argv(argc, argv);
5495 _pure_ static int action_to_runlevel(void) {
5497 static const char table[_ACTION_MAX] = {
5498 [ACTION_HALT] = '0',
5499 [ACTION_POWEROFF] = '0',
5500 [ACTION_REBOOT] = '6',
5501 [ACTION_RUNLEVEL2] = '2',
5502 [ACTION_RUNLEVEL3] = '3',
5503 [ACTION_RUNLEVEL4] = '4',
5504 [ACTION_RUNLEVEL5] = '5',
5505 [ACTION_RESCUE] = '1'
5508 assert(arg_action < _ACTION_MAX);
5510 return table[arg_action];
5513 static int talk_upstart(void) {
5514 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
5515 _cleanup_dbus_error_free_ DBusError error;
5516 int previous, rl, r;
5518 env1_buf[] = "RUNLEVEL=X",
5519 env2_buf[] = "PREVLEVEL=X";
5520 char *env1 = env1_buf, *env2 = env2_buf;
5521 const char *emit = "runlevel";
5522 dbus_bool_t b_false = FALSE;
5523 DBusMessageIter iter, sub;
5524 DBusConnection *bus;
5526 dbus_error_init(&error);
5528 if (!(rl = action_to_runlevel()))
5531 if (utmp_get_runlevel(&previous, NULL) < 0)
5534 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5535 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5540 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5545 if ((r = bus_check_peercred(bus)) < 0) {
5546 log_error("Failed to verify owner of bus.");
5550 if (!(m = dbus_message_new_method_call(
5551 "com.ubuntu.Upstart",
5552 "/com/ubuntu/Upstart",
5553 "com.ubuntu.Upstart0_6",
5556 log_error("Could not allocate message.");
5561 dbus_message_iter_init_append(m, &iter);
5563 env1_buf[sizeof(env1_buf)-2] = rl;
5564 env2_buf[sizeof(env2_buf)-2] = previous;
5566 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5567 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5568 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5569 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5570 !dbus_message_iter_close_container(&iter, &sub) ||
5571 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5572 log_error("Could not append arguments to message.");
5577 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5579 if (bus_error_is_no_service(&error)) {
5584 log_error("Failed to issue method call: %s", bus_error_message(&error));
5593 dbus_connection_flush(bus);
5594 dbus_connection_close(bus);
5595 dbus_connection_unref(bus);
5601 static int talk_initctl(void) {
5602 struct init_request request = {};
5604 _cleanup_close_ int fd = -1;
5607 rl = action_to_runlevel();
5611 request.magic = INIT_MAGIC;
5612 request.sleeptime = 0;
5613 request.cmd = INIT_CMD_RUNLVL;
5614 request.runlevel = rl;
5616 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5618 if (errno == ENOENT)
5621 log_error("Failed to open "INIT_FIFO": %m");
5626 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5628 log_error("Failed to write to "INIT_FIFO": %m");
5629 return errno > 0 ? -errno : -EIO;
5635 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5637 static const struct {
5645 int (* const dispatch)(DBusConnection *bus, char **args);
5647 { "list-units", LESS, 1, list_units },
5648 { "list-unit-files", EQUAL, 1, list_unit_files },
5649 { "list-sockets", LESS, 1, list_sockets },
5650 { "list-jobs", EQUAL, 1, list_jobs },
5651 { "clear-jobs", EQUAL, 1, daemon_reload },
5652 { "load", MORE, 2, load_unit },
5653 { "cancel", MORE, 2, cancel_job },
5654 { "start", MORE, 2, start_unit },
5655 { "stop", MORE, 2, start_unit },
5656 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5657 { "reload", MORE, 2, start_unit },
5658 { "restart", MORE, 2, start_unit },
5659 { "try-restart", MORE, 2, start_unit },
5660 { "reload-or-restart", MORE, 2, start_unit },
5661 { "reload-or-try-restart", MORE, 2, start_unit },
5662 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5663 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5664 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5665 { "isolate", EQUAL, 2, start_unit },
5666 { "set-cgroup", MORE, 3, set_cgroup },
5667 { "unset-cgroup", MORE, 3, set_cgroup },
5668 { "get-cgroup-attr", MORE, 3, get_cgroup_attr },
5669 { "set-cgroup-attr", MORE, 4, set_cgroup_attr },
5670 { "unset-cgroup-attr", MORE, 3, set_cgroup },
5671 { "kill", MORE, 2, kill_unit },
5672 { "is-active", MORE, 2, check_unit_active },
5673 { "check", MORE, 2, check_unit_active },
5674 { "is-failed", MORE, 2, check_unit_failed },
5675 { "show", MORE, 1, show },
5676 { "status", MORE, 1, show },
5677 { "help", MORE, 2, show },
5678 { "dump", EQUAL, 1, dump },
5679 { "snapshot", LESS, 2, snapshot },
5680 { "delete", MORE, 2, delete_snapshot },
5681 { "daemon-reload", EQUAL, 1, daemon_reload },
5682 { "daemon-reexec", EQUAL, 1, daemon_reload },
5683 { "show-environment", EQUAL, 1, show_enviroment },
5684 { "set-environment", MORE, 2, set_environment },
5685 { "unset-environment", MORE, 2, set_environment },
5686 { "halt", EQUAL, 1, start_special },
5687 { "poweroff", EQUAL, 1, start_special },
5688 { "reboot", EQUAL, 1, start_special },
5689 { "kexec", EQUAL, 1, start_special },
5690 { "suspend", EQUAL, 1, start_special },
5691 { "hibernate", EQUAL, 1, start_special },
5692 { "hybrid-sleep", EQUAL, 1, start_special },
5693 { "default", EQUAL, 1, start_special },
5694 { "rescue", EQUAL, 1, start_special },
5695 { "emergency", EQUAL, 1, start_special },
5696 { "exit", EQUAL, 1, start_special },
5697 { "reset-failed", MORE, 1, reset_failed },
5698 { "enable", MORE, 2, enable_unit },
5699 { "disable", MORE, 2, enable_unit },
5700 { "is-enabled", MORE, 2, unit_is_enabled },
5701 { "reenable", MORE, 2, enable_unit },
5702 { "preset", MORE, 2, enable_unit },
5703 { "mask", MORE, 2, enable_unit },
5704 { "unmask", MORE, 2, enable_unit },
5705 { "link", MORE, 2, enable_unit },
5706 { "switch-root", MORE, 2, switch_root },
5707 { "list-dependencies", LESS, 2, list_dependencies },
5708 { "set-default", EQUAL, 2, enable_unit },
5709 { "get-default", LESS, 1, get_default },
5719 left = argc - optind;
5722 /* Special rule: no arguments means "list-units" */
5725 if (streq(argv[optind], "help") && !argv[optind+1]) {
5726 log_error("This command expects one or more "
5727 "unit names. Did you mean --help?");
5731 for (i = 0; i < ELEMENTSOF(verbs); i++)
5732 if (streq(argv[optind], verbs[i].verb))
5735 if (i >= ELEMENTSOF(verbs)) {
5736 log_error("Unknown operation '%s'.", argv[optind]);
5741 switch (verbs[i].argc_cmp) {
5744 if (left != verbs[i].argc) {
5745 log_error("Invalid number of arguments.");
5752 if (left < verbs[i].argc) {
5753 log_error("Too few arguments.");
5760 if (left > verbs[i].argc) {
5761 log_error("Too many arguments.");
5768 assert_not_reached("Unknown comparison operator.");
5771 /* Require a bus connection for all operations but
5773 if (!streq(verbs[i].verb, "enable") &&
5774 !streq(verbs[i].verb, "disable") &&
5775 !streq(verbs[i].verb, "is-enabled") &&
5776 !streq(verbs[i].verb, "list-unit-files") &&
5777 !streq(verbs[i].verb, "reenable") &&
5778 !streq(verbs[i].verb, "preset") &&
5779 !streq(verbs[i].verb, "mask") &&
5780 !streq(verbs[i].verb, "unmask") &&
5781 !streq(verbs[i].verb, "link") &&
5782 !streq(verbs[i].verb, "set-default") &&
5783 !streq(verbs[i].verb, "get-default")) {
5785 if (running_in_chroot() > 0) {
5786 log_info("Running in chroot, ignoring request.");
5790 if (((!streq(verbs[i].verb, "reboot") &&
5791 !streq(verbs[i].verb, "halt") &&
5792 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5793 log_error("Failed to get D-Bus connection: %s",
5794 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5800 if (!bus && !avoid_bus()) {
5801 log_error("Failed to get D-Bus connection: %s",
5802 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5807 return verbs[i].dispatch(bus, argv + optind);
5810 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5811 _cleanup_close_ int fd;
5812 struct sd_shutdown_command c = {
5818 union sockaddr_union sockaddr = {
5819 .un.sun_family = AF_UNIX,
5820 .un.sun_path = "/run/systemd/shutdownd",
5822 struct iovec iovec[2] = {
5823 {.iov_base = (char*) &c,
5824 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
5827 struct msghdr msghdr = {
5828 .msg_name = &sockaddr,
5829 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
5830 + sizeof("/run/systemd/shutdownd") - 1,
5835 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5839 if (!isempty(message)) {
5840 iovec[1].iov_base = (char*) message;
5841 iovec[1].iov_len = strlen(message);
5842 msghdr.msg_iovlen++;
5845 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5851 static int reload_with_fallback(DBusConnection *bus) {
5854 /* First, try systemd via D-Bus. */
5855 if (daemon_reload(bus, NULL) >= 0)
5859 /* Nothing else worked, so let's try signals */
5860 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5862 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5863 log_error("kill() failed: %m");
5870 static int start_with_fallback(DBusConnection *bus) {
5873 /* First, try systemd via D-Bus. */
5874 if (start_unit(bus, NULL) >= 0)
5878 /* Hmm, talking to systemd via D-Bus didn't work. Then
5879 * let's try to talk to Upstart via D-Bus. */
5880 if (talk_upstart() > 0)
5883 /* Nothing else worked, so let's try
5885 if (talk_initctl() > 0)
5888 log_error("Failed to talk to init daemon.");
5892 warn_wall(arg_action);
5896 static _noreturn_ void halt_now(enum action a) {
5898 /* Make sure C-A-D is handled by the kernel from this
5900 reboot(RB_ENABLE_CAD);
5905 log_info("Halting.");
5906 reboot(RB_HALT_SYSTEM);
5909 case ACTION_POWEROFF:
5910 log_info("Powering off.");
5911 reboot(RB_POWER_OFF);
5915 log_info("Rebooting.");
5916 reboot(RB_AUTOBOOT);
5920 assert_not_reached("Unknown halt action.");
5923 assert_not_reached("Uh? This shouldn't happen.");
5926 static int halt_main(DBusConnection *bus) {
5929 r = check_inhibitors(bus, arg_action);
5933 if (geteuid() != 0) {
5934 /* Try logind if we are a normal user and no special
5935 * mode applies. Maybe PolicyKit allows us to shutdown
5938 if (arg_when <= 0 &&
5941 (arg_action == ACTION_POWEROFF ||
5942 arg_action == ACTION_REBOOT)) {
5943 r = reboot_with_logind(bus, arg_action);
5948 log_error("Must be root.");
5953 _cleanup_free_ char *m;
5955 m = strv_join(arg_wall, " ");
5956 r = send_shutdownd(arg_when,
5957 arg_action == ACTION_HALT ? 'H' :
5958 arg_action == ACTION_POWEROFF ? 'P' :
5959 arg_action == ACTION_KEXEC ? 'K' :
5966 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5968 char date[FORMAT_TIMESTAMP_MAX];
5970 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5971 format_timestamp(date, sizeof(date), arg_when));
5976 if (!arg_dry && !arg_force)
5977 return start_with_fallback(bus);
5980 if (sd_booted() > 0)
5981 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5983 r = utmp_put_shutdown();
5985 log_warning("Failed to write utmp record: %s", strerror(-r));
5992 halt_now(arg_action);
5993 /* We should never reach this. */
5997 static int runlevel_main(void) {
5998 int r, runlevel, previous;
6000 r = utmp_get_runlevel(&runlevel, &previous);
6007 previous <= 0 ? 'N' : previous,
6008 runlevel <= 0 ? 'N' : runlevel);
6013 int main(int argc, char*argv[]) {
6014 int r, retval = EXIT_FAILURE;
6015 DBusConnection *bus = NULL;
6016 _cleanup_dbus_error_free_ DBusError error;
6018 dbus_error_init(&error);
6020 setlocale(LC_ALL, "");
6021 log_parse_environment();
6024 r = parse_argv(argc, argv);
6028 retval = EXIT_SUCCESS;
6032 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
6033 * let's shortcut this */
6034 if (arg_action == ACTION_RUNLEVEL) {
6035 r = runlevel_main();
6036 retval = r < 0 ? EXIT_FAILURE : r;
6040 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
6041 log_info("Running in chroot, ignoring request.");
6047 if (arg_transport == TRANSPORT_NORMAL)
6048 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
6049 else if (arg_transport == TRANSPORT_POLKIT) {
6050 bus_connect_system_polkit(&bus, &error);
6051 private_bus = false;
6052 } else if (arg_transport == TRANSPORT_SSH) {
6053 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
6054 private_bus = false;
6056 assert_not_reached("Uh, invalid transport...");
6059 switch (arg_action) {
6061 case ACTION_SYSTEMCTL:
6062 r = systemctl_main(bus, argc, argv, &error);
6066 case ACTION_POWEROFF:
6072 case ACTION_RUNLEVEL2:
6073 case ACTION_RUNLEVEL3:
6074 case ACTION_RUNLEVEL4:
6075 case ACTION_RUNLEVEL5:
6077 case ACTION_EMERGENCY:
6078 case ACTION_DEFAULT:
6079 r = start_with_fallback(bus);
6084 r = reload_with_fallback(bus);
6087 case ACTION_CANCEL_SHUTDOWN: {
6091 m = strv_join(arg_wall, " ");
6093 retval = EXIT_FAILURE;
6097 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6099 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6104 case ACTION_INVALID:
6105 case ACTION_RUNLEVEL:
6107 assert_not_reached("Unknown action");
6110 retval = r < 0 ? EXIT_FAILURE : r;
6114 dbus_connection_flush(bus);
6115 dbus_connection_close(bus);
6116 dbus_connection_unref(bus);
6121 strv_free(arg_types);
6122 strv_free(arg_load_states);
6123 strv_free(arg_properties);
6126 ask_password_agent_close();
6127 polkit_agent_close();