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);
658 printf("%-*s %-*.*s%-*s %s\n",
660 typelen + arg_show_types, typelen + arg_show_types, "TYPE ",
664 for (s = socket_infos; s < socket_infos + cs; s++) {
668 printf("%-*s %-*s %-*s",
669 pathlen, s->path, typelen, s->type, socklen, s->id);
672 pathlen, s->path, socklen, s->id);
673 STRV_FOREACH(a, s->triggered)
675 a == s->triggered ? "" : ",", *a);
679 on = ansi_highlight(true);
680 off = ansi_highlight(false);
683 on = ansi_highlight_red(true);
684 off = ansi_highlight_red(false);
687 printf("%s%u sockets listed.%s\n", on, cs, off);
689 printf("Pass --all to see loaded but inactive sockets, too.\n");
694 static int list_sockets(DBusConnection *bus, char **args) {
695 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
696 _cleanup_free_ struct unit_info *unit_infos = NULL;
697 struct socket_info *socket_infos = NULL;
698 const struct unit_info *u;
699 struct socket_info *s;
700 unsigned cu = 0, cs = 0;
704 pager_open_if_enabled();
706 r = get_unit_list(bus, &reply, &unit_infos, &cu);
710 for (u = unit_infos; u < unit_infos + cu; u++) {
712 _cleanup_strv_free_ char **listen = NULL, **triggered = NULL;
715 if (!output_show_unit(u))
718 if ((dot = strrchr(u->id, '.')) && !streq(dot+1, "socket"))
721 r = get_triggered_units(bus, u->unit_path, &triggered);
725 r = get_listening(bus, u->unit_path, &listen, &c);
729 if (!GREEDY_REALLOC(socket_infos, size, cs + c)) {
734 for (i = 0; i < c; i++)
735 socket_infos[cs + i] = (struct socket_info) {
738 .path = listen[i*2 + 1],
739 .triggered = triggered,
740 .own_triggered = i==0,
743 /* from this point on we will cleanup those socket_infos */
746 listen = triggered = NULL; /* avoid cleanup */
749 qsort(socket_infos, cs, sizeof(struct socket_info),
750 (__compar_fn_t) socket_info_compare);
752 output_sockets_list(socket_infos, cs);
755 assert(cs == 0 || socket_infos);
756 for (s = socket_infos; s < socket_infos + cs; s++) {
759 if (s->own_triggered)
760 strv_free(s->triggered);
767 static int compare_unit_file_list(const void *a, const void *b) {
769 const UnitFileList *u = a, *v = b;
771 d1 = strrchr(u->path, '.');
772 d2 = strrchr(v->path, '.');
777 r = strcasecmp(d1, d2);
782 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
785 static bool output_show_unit_file(const UnitFileList *u) {
788 return !arg_types || ((dot = strrchr(u->path, '.')) && strv_find(arg_types, dot+1));
791 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
792 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
793 const UnitFileList *u;
795 max_id_len = sizeof("UNIT FILE")-1;
796 state_cols = sizeof("STATE")-1;
797 for (u = units; u < units + c; u++) {
798 if (!output_show_unit_file(u))
801 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
802 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
807 id_cols = MIN(max_id_len, 25u);
808 basic_cols = 1 + id_cols + state_cols;
809 if (basic_cols < (unsigned) columns())
810 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
812 id_cols = max_id_len;
815 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
817 for (u = units; u < units + c; u++) {
818 _cleanup_free_ char *e = NULL;
819 const char *on, *off;
822 if (!output_show_unit_file(u))
827 if (u->state == UNIT_FILE_MASKED ||
828 u->state == UNIT_FILE_MASKED_RUNTIME ||
829 u->state == UNIT_FILE_DISABLED ||
830 u->state == UNIT_FILE_INVALID) {
831 on = ansi_highlight_red(true);
832 off = ansi_highlight_red(false);
833 } else if (u->state == UNIT_FILE_ENABLED) {
834 on = ansi_highlight_green(true);
835 off = ansi_highlight_green(false);
839 id = path_get_file_name(u->path);
841 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
843 printf("%-*s %s%-*s%s\n",
845 on, state_cols, unit_file_state_to_string(u->state), off);
849 printf("\n%u unit files listed.\n", n_shown);
852 static int list_unit_files(DBusConnection *bus, char **args) {
853 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
854 _cleanup_free_ UnitFileList *units = NULL;
855 DBusMessageIter iter, sub, sub2;
856 unsigned c = 0, n_units = 0;
859 pager_open_if_enabled();
866 h = hashmap_new(string_hash_func, string_compare_func);
870 r = unit_file_get_list(arg_scope, arg_root, h);
872 unit_file_list_free(h);
873 log_error("Failed to get unit file list: %s", strerror(-r));
877 n_units = hashmap_size(h);
878 units = new(UnitFileList, n_units);
880 unit_file_list_free(h);
884 HASHMAP_FOREACH(u, h, i) {
885 memcpy(units + c++, u, sizeof(UnitFileList));
891 r = bus_method_call_with_reply(
893 "org.freedesktop.systemd1",
894 "/org/freedesktop/systemd1",
895 "org.freedesktop.systemd1.Manager",
903 if (!dbus_message_iter_init(reply, &iter) ||
904 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
905 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
906 log_error("Failed to parse reply.");
910 dbus_message_iter_recurse(&iter, &sub);
912 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
916 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
921 n_units = MAX(2*c, 16u);
922 w = realloc(units, sizeof(struct UnitFileList) * n_units);
931 dbus_message_iter_recurse(&sub, &sub2);
933 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
934 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
935 log_error("Failed to parse reply.");
939 u->state = unit_file_state_from_string(state);
941 dbus_message_iter_next(&sub);
947 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
948 output_unit_file_list(units, c);
954 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
956 _cleanup_free_ char *n = NULL;
958 size_t max_len = MAX(columns(),20u);
961 for (i = level - 1; i >= 0; i--) {
963 if(len > max_len - 3 && !arg_full) {
964 printf("%s...\n",max_len % 2 ? "" : " ");
967 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
970 if(len > max_len - 3 && !arg_full) {
971 printf("%s...\n",max_len % 2 ? "" : " ");
974 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
978 printf("%s\n", name);
982 n = ellipsize(name, max_len-len, 100);
990 static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
991 static const char *dependencies[] = {
992 [DEPENDENCY_FORWARD] = "Requires\0"
993 "RequiresOverridable\0"
995 "RequisiteOverridable\0"
997 [DEPENDENCY_REVERSE] = "RequiredBy\0"
998 "RequiredByOverridable\0"
1001 [DEPENDENCY_AFTER] = "After\0",
1002 [DEPENDENCY_BEFORE] = "Before\0",
1005 _cleanup_free_ char *path;
1006 const char *interface = "org.freedesktop.systemd1.Unit";
1008 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1009 DBusMessageIter iter, sub, sub2, sub3;
1018 path = unit_dbus_path_from_name(name);
1024 r = bus_method_call_with_reply(
1026 "org.freedesktop.systemd1",
1028 "org.freedesktop.DBus.Properties",
1032 DBUS_TYPE_STRING, &interface,
1037 if (!dbus_message_iter_init(reply, &iter) ||
1038 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1039 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
1040 log_error("Failed to parse reply.");
1045 dbus_message_iter_recurse(&iter, &sub);
1047 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1050 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
1051 dbus_message_iter_recurse(&sub, &sub2);
1053 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
1054 log_error("Failed to parse reply.");
1059 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
1060 log_error("Failed to parse reply.");
1065 dbus_message_iter_recurse(&sub2, &sub3);
1066 dbus_message_iter_next(&sub);
1068 assert(arg_dependency < ELEMENTSOF(dependencies));
1069 if (!nulstr_contains(dependencies[arg_dependency], prop))
1072 if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
1073 if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
1074 DBusMessageIter sub4;
1075 dbus_message_iter_recurse(&sub3, &sub4);
1077 while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
1080 assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
1081 dbus_message_iter_get_basic(&sub4, &s);
1083 r = strv_extend(&ret, s);
1089 dbus_message_iter_next(&sub4);
1102 static int list_dependencies_compare(const void *_a, const void *_b) {
1103 const char **a = (const char**) _a, **b = (const char**) _b;
1104 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
1106 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
1108 return strcasecmp(*a, *b);
1111 static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char ***units, unsigned int branches) {
1112 _cleanup_strv_free_ char **deps = NULL, **u;
1116 u = strv_append(*units, name);
1120 r = list_dependencies_get_dependencies(bus, name, &deps);
1124 qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
1126 STRV_FOREACH(c, deps) {
1127 if (strv_contains(u, *c)) {
1129 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
1136 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
1140 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
1141 r = list_dependencies_one(bus, *c, level + 1, &u, (branches << 1) | (c[1] == NULL ? 0 : 1));
1154 static int list_dependencies(DBusConnection *bus, char **args) {
1155 _cleanup_free_ char *unit = NULL;
1156 _cleanup_strv_free_ char **units = NULL;
1162 unit = unit_name_mangle(args[1]);
1167 u = SPECIAL_DEFAULT_TARGET;
1169 pager_open_if_enabled();
1173 return list_dependencies_one(bus, u, 0, &units, 0);
1178 char *name, *type, *state;
1181 static void list_jobs_print(struct job_info* jobs, size_t n) {
1184 const char *on, *off;
1185 bool shorten = false;
1187 assert(n == 0 || jobs);
1190 on = ansi_highlight_green(true);
1191 off = ansi_highlight_green(false);
1193 printf("%sNo jobs running.%s\n", on, off);
1197 pager_open_if_enabled();
1200 /* JOB UNIT TYPE STATE */
1201 unsigned l0 = 3, l1 = 4, l2 = 4, l3 = 5;
1203 for (i = 0, j = jobs; i < n; i++, j++) {
1204 assert(j->name && j->type && j->state);
1205 l0 = MAX(l0, DECIMAL_STR_WIDTH(j->id));
1206 l1 = MAX(l1, strlen(j->name));
1207 l2 = MAX(l2, strlen(j->type));
1208 l3 = MAX(l3, strlen(j->state));
1211 if (!arg_full && l0 + 1 + l1 + l2 + 1 + l3 > columns()) {
1212 l1 = MAX(33u, columns() - l0 - l2 - l3 - 3);
1217 printf("%*s %-*s %-*s %-*s\n",
1223 for (i = 0, j = jobs; i < n; i++, j++) {
1224 _cleanup_free_ char *e = NULL;
1226 if (streq(j->state, "running")) {
1227 on = ansi_highlight(true);
1228 off = ansi_highlight(false);
1232 e = shorten ? ellipsize(j->name, l1, 33) : NULL;
1233 printf("%*u %s%-*s%s %-*s %s%-*s%s\n",
1235 on, l1, e ? e : j->name, off,
1237 on, l3, j->state, off);
1241 on = ansi_highlight(true);
1242 off = ansi_highlight(false);
1245 printf("\n%s%zu jobs listed%s.\n", on, n, off);
1248 static int list_jobs(DBusConnection *bus, char **args) {
1249 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1250 DBusMessageIter iter, sub, sub2;
1252 struct job_info *jobs = NULL;
1253 size_t size = 0, used = 0;
1255 r = bus_method_call_with_reply(
1257 "org.freedesktop.systemd1",
1258 "/org/freedesktop/systemd1",
1259 "org.freedesktop.systemd1.Manager",
1267 if (!dbus_message_iter_init(reply, &iter) ||
1268 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1269 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1270 log_error("Failed to parse reply.");
1274 dbus_message_iter_recurse(&iter, &sub);
1276 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1277 const char *name, *type, *state, *job_path, *unit_path;
1280 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1281 log_error("Failed to parse reply.");
1285 dbus_message_iter_recurse(&sub, &sub2);
1287 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1288 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1289 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1290 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1291 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1292 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1293 log_error("Failed to parse reply.");
1298 if (!GREEDY_REALLOC(jobs, size, used + 1)) {
1303 jobs[used++] = (struct job_info) { id,
1307 if (!jobs[used-1].name || !jobs[used-1].type || !jobs[used-1].state) {
1312 dbus_message_iter_next(&sub);
1315 list_jobs_print(jobs, used);
1319 free(jobs[used].name);
1320 free(jobs[used].type);
1321 free(jobs[used].state);
1328 static int load_unit(DBusConnection *bus, char **args) {
1333 STRV_FOREACH(name, args+1) {
1334 _cleanup_free_ char *n = NULL;
1337 n = unit_name_mangle(*name);
1341 r = bus_method_call_with_reply(
1343 "org.freedesktop.systemd1",
1344 "/org/freedesktop/systemd1",
1345 "org.freedesktop.systemd1.Manager",
1349 DBUS_TYPE_STRING, &n,
1358 static int cancel_job(DBusConnection *bus, char **args) {
1363 if (strv_length(args) <= 1)
1364 return daemon_reload(bus, args);
1366 STRV_FOREACH(name, args+1) {
1370 r = safe_atou32(*name, &id);
1372 log_error("Failed to parse job id: %s", strerror(-r));
1376 r = bus_method_call_with_reply(
1378 "org.freedesktop.systemd1",
1379 "/org/freedesktop/systemd1",
1380 "org.freedesktop.systemd1.Manager",
1384 DBUS_TYPE_UINT32, &id,
1393 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1394 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1395 dbus_bool_t b = FALSE;
1396 DBusMessageIter iter, sub;
1398 *interface = "org.freedesktop.systemd1.Unit",
1399 *property = "NeedDaemonReload",
1401 _cleanup_free_ char *n = NULL;
1404 /* We ignore all errors here, since this is used to show a warning only */
1406 n = unit_name_mangle(unit);
1410 r = bus_method_call_with_reply(
1412 "org.freedesktop.systemd1",
1413 "/org/freedesktop/systemd1",
1414 "org.freedesktop.systemd1.Manager",
1418 DBUS_TYPE_STRING, &n,
1423 if (!dbus_message_get_args(reply, NULL,
1424 DBUS_TYPE_OBJECT_PATH, &path,
1428 dbus_message_unref(reply);
1431 r = bus_method_call_with_reply(
1433 "org.freedesktop.systemd1",
1435 "org.freedesktop.DBus.Properties",
1439 DBUS_TYPE_STRING, &interface,
1440 DBUS_TYPE_STRING, &property,
1445 if (!dbus_message_iter_init(reply, &iter) ||
1446 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1449 dbus_message_iter_recurse(&iter, &sub);
1450 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1453 dbus_message_iter_get_basic(&sub, &b);
1457 typedef struct WaitData {
1464 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1465 _cleanup_dbus_error_free_ DBusError error;
1468 dbus_error_init(&error);
1474 log_debug("Got D-Bus request: %s.%s() on %s",
1475 dbus_message_get_interface(message),
1476 dbus_message_get_member(message),
1477 dbus_message_get_path(message));
1479 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1480 log_error("Warning! D-Bus connection terminated.");
1481 dbus_connection_close(connection);
1483 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1485 const char *path, *result, *unit;
1487 if (dbus_message_get_args(message, &error,
1488 DBUS_TYPE_UINT32, &id,
1489 DBUS_TYPE_OBJECT_PATH, &path,
1490 DBUS_TYPE_STRING, &unit,
1491 DBUS_TYPE_STRING, &result,
1492 DBUS_TYPE_INVALID)) {
1494 free(set_remove(d->set, (char*) path));
1496 if (!isempty(result))
1497 d->result = strdup(result);
1500 d->name = strdup(unit);
1502 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1505 dbus_error_free(&error);
1506 if (dbus_message_get_args(message, &error,
1507 DBUS_TYPE_UINT32, &id,
1508 DBUS_TYPE_OBJECT_PATH, &path,
1509 DBUS_TYPE_STRING, &result,
1510 DBUS_TYPE_INVALID)) {
1511 /* Compatibility with older systemd versions <
1512 * 183 during upgrades. This should be dropped
1514 free(set_remove(d->set, (char*) path));
1517 d->result = strdup(result);
1519 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1523 log_error("Failed to parse message: %s", bus_error_message(&error));
1526 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1529 static int enable_wait_for_jobs(DBusConnection *bus) {
1537 dbus_error_init(&error);
1538 dbus_bus_add_match(bus,
1540 "sender='org.freedesktop.systemd1',"
1541 "interface='org.freedesktop.systemd1.Manager',"
1542 "member='JobRemoved',"
1543 "path='/org/freedesktop/systemd1'",
1546 if (dbus_error_is_set(&error)) {
1547 log_error("Failed to add match: %s", bus_error_message(&error));
1548 dbus_error_free(&error);
1552 /* This is slightly dirty, since we don't undo the match registrations. */
1556 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1558 WaitData d = { .set = s };
1563 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1566 while (!set_isempty(s)) {
1568 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1569 log_error("Disconnected from bus.");
1570 return -ECONNREFUSED;
1577 if (streq(d.result, "timeout"))
1578 log_error("Job for %s timed out.", strna(d.name));
1579 else if (streq(d.result, "canceled"))
1580 log_error("Job for %s canceled.", strna(d.name));
1581 else if (streq(d.result, "dependency"))
1582 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1583 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1584 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1587 if (streq_ptr(d.result, "timeout"))
1589 else if (streq_ptr(d.result, "canceled"))
1591 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1602 dbus_connection_remove_filter(bus, wait_filter, &d);
1606 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1607 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1608 _cleanup_free_ char *n = NULL;
1609 DBusMessageIter iter, sub;
1611 *interface = "org.freedesktop.systemd1.Unit",
1612 *property = "ActiveState";
1613 const char *state, *path;
1619 dbus_error_init(&error);
1621 n = unit_name_mangle(name);
1625 r = bus_method_call_with_reply (
1627 "org.freedesktop.systemd1",
1628 "/org/freedesktop/systemd1",
1629 "org.freedesktop.systemd1.Manager",
1633 DBUS_TYPE_STRING, &n,
1636 dbus_error_free(&error);
1643 if (!dbus_message_get_args(reply, NULL,
1644 DBUS_TYPE_OBJECT_PATH, &path,
1645 DBUS_TYPE_INVALID)) {
1646 log_error("Failed to parse reply.");
1650 dbus_message_unref(reply);
1653 r = bus_method_call_with_reply(
1655 "org.freedesktop.systemd1",
1657 "org.freedesktop.DBus.Properties",
1661 DBUS_TYPE_STRING, &interface,
1662 DBUS_TYPE_STRING, &property,
1670 if (!dbus_message_iter_init(reply, &iter) ||
1671 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1672 log_error("Failed to parse reply.");
1676 dbus_message_iter_recurse(&iter, &sub);
1678 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1679 log_error("Failed to parse reply.");
1683 dbus_message_iter_get_basic(&sub, &state);
1688 return strv_find(check_states, state) ? 1 : 0;
1691 static void check_triggering_units(
1692 DBusConnection *bus,
1693 const char *unit_name) {
1695 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1696 DBusMessageIter iter, sub;
1697 const char *interface = "org.freedesktop.systemd1.Unit",
1698 *load_state_property = "LoadState",
1699 *triggered_by_property = "TriggeredBy",
1701 _cleanup_free_ char *unit_path = NULL, *n = NULL;
1702 bool print_warning_label = true;
1705 n = unit_name_mangle(unit_name);
1711 unit_path = unit_dbus_path_from_name(n);
1717 r = bus_method_call_with_reply(
1719 "org.freedesktop.systemd1",
1721 "org.freedesktop.DBus.Properties",
1725 DBUS_TYPE_STRING, &interface,
1726 DBUS_TYPE_STRING, &load_state_property,
1731 if (!dbus_message_iter_init(reply, &iter) ||
1732 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1733 log_error("Failed to parse reply.");
1737 dbus_message_iter_recurse(&iter, &sub);
1739 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1740 log_error("Failed to parse reply.");
1744 dbus_message_iter_get_basic(&sub, &state);
1746 if (streq(state, "masked"))
1749 dbus_message_unref(reply);
1752 r = bus_method_call_with_reply(
1754 "org.freedesktop.systemd1",
1756 "org.freedesktop.DBus.Properties",
1760 DBUS_TYPE_STRING, &interface,
1761 DBUS_TYPE_STRING, &triggered_by_property,
1766 if (!dbus_message_iter_init(reply, &iter) ||
1767 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1768 log_error("Failed to parse reply.");
1772 dbus_message_iter_recurse(&iter, &sub);
1773 dbus_message_iter_recurse(&sub, &iter);
1776 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1777 const char * const check_states[] = {
1782 const char *service_trigger;
1784 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1785 log_error("Failed to parse reply.");
1789 dbus_message_iter_get_basic(&sub, &service_trigger);
1791 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1795 if (print_warning_label) {
1796 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1797 print_warning_label = false;
1800 log_warning(" %s", service_trigger);
1803 dbus_message_iter_next(&sub);
1807 static int start_unit_one(
1808 DBusConnection *bus,
1815 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1816 _cleanup_free_ char *n;
1825 n = unit_name_mangle(name);
1829 r = bus_method_call_with_reply(
1831 "org.freedesktop.systemd1",
1832 "/org/freedesktop/systemd1",
1833 "org.freedesktop.systemd1.Manager",
1837 DBUS_TYPE_STRING, &n,
1838 DBUS_TYPE_STRING, &mode,
1841 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1842 /* There's always a fallback possible for
1843 * legacy actions. */
1846 log_error("Failed to issue method call: %s", bus_error_message(error));
1851 if (!dbus_message_get_args(reply, error,
1852 DBUS_TYPE_OBJECT_PATH, &path,
1853 DBUS_TYPE_INVALID)) {
1854 log_error("Failed to parse reply: %s", bus_error_message(error));
1858 if (need_daemon_reload(bus, n))
1859 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1860 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1869 r = set_consume(s, p);
1871 log_error("Failed to add path to set.");
1879 static const struct {
1883 } action_table[_ACTION_MAX] = {
1884 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
1885 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
1886 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
1887 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
1888 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
1889 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
1890 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
1891 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
1892 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
1893 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
1894 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
1895 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
1896 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
1897 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
1898 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1901 static enum action verb_to_action(const char *verb) {
1904 for (i = ACTION_INVALID; i < _ACTION_MAX; i++)
1905 if (action_table[i].verb && streq(verb, action_table[i].verb))
1907 return ACTION_INVALID;
1910 static int start_unit(DBusConnection *bus, char **args) {
1913 const char *method, *mode, *one_name;
1914 _cleanup_set_free_free_ Set *s = NULL;
1915 _cleanup_dbus_error_free_ DBusError error;
1918 dbus_error_init(&error);
1922 ask_password_agent_open_if_enabled();
1924 if (arg_action == ACTION_SYSTEMCTL) {
1927 streq(args[0], "stop") ||
1928 streq(args[0], "condstop") ? "StopUnit" :
1929 streq(args[0], "reload") ? "ReloadUnit" :
1930 streq(args[0], "restart") ? "RestartUnit" :
1932 streq(args[0], "try-restart") ||
1933 streq(args[0], "condrestart") ? "TryRestartUnit" :
1935 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1937 streq(args[0], "reload-or-try-restart") ||
1938 streq(args[0], "condreload") ||
1940 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1942 action = verb_to_action(args[0]);
1944 mode = streq(args[0], "isolate") ? "isolate" :
1945 action_table[action].mode ?: arg_job_mode;
1947 one_name = action_table[action].target;
1950 assert(arg_action < ELEMENTSOF(action_table));
1951 assert(action_table[arg_action].target);
1953 method = "StartUnit";
1955 mode = action_table[arg_action].mode;
1956 one_name = action_table[arg_action].target;
1959 if (!arg_no_block) {
1960 ret = enable_wait_for_jobs(bus);
1962 log_error("Could not watch jobs: %s", strerror(-ret));
1966 s = set_new(string_hash_func, string_compare_func);
1972 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1974 ret = translate_bus_error_to_exit_status(ret, &error);
1976 STRV_FOREACH(name, args+1) {
1977 r = start_unit_one(bus, method, *name, mode, &error, s);
1979 ret = translate_bus_error_to_exit_status(r, &error);
1980 dbus_error_free(&error);
1985 if (!arg_no_block) {
1986 r = wait_for_jobs(bus, s);
1990 /* When stopping units, warn if they can still be triggered by
1991 * another active unit (socket, path, timer) */
1992 if (!arg_quiet && streq(method, "StopUnit")) {
1994 check_triggering_units(bus, one_name);
1996 STRV_FOREACH(name, args+1)
1997 check_triggering_units(bus, *name);
2004 /* Ask systemd-logind, which might grant access to unprivileged users
2005 * through PolicyKit */
2006 static int reboot_with_logind(DBusConnection *bus, enum action a) {
2009 dbus_bool_t interactive = true;
2014 polkit_agent_open_if_enabled();
2022 case ACTION_POWEROFF:
2023 method = "PowerOff";
2026 case ACTION_SUSPEND:
2030 case ACTION_HIBERNATE:
2031 method = "Hibernate";
2034 case ACTION_HYBRID_SLEEP:
2035 method = "HybridSleep";
2042 return bus_method_call_with_reply(
2044 "org.freedesktop.login1",
2045 "/org/freedesktop/login1",
2046 "org.freedesktop.login1.Manager",
2050 DBUS_TYPE_BOOLEAN, &interactive,
2057 static int check_inhibitors(DBusConnection *bus, enum action a) {
2059 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2060 DBusMessageIter iter, sub, sub2;
2063 _cleanup_strv_free_ char **sessions = NULL;
2069 if (arg_ignore_inhibitors || arg_force > 0)
2081 r = bus_method_call_with_reply(
2083 "org.freedesktop.login1",
2084 "/org/freedesktop/login1",
2085 "org.freedesktop.login1.Manager",
2091 /* If logind is not around, then there are no inhibitors... */
2094 if (!dbus_message_iter_init(reply, &iter) ||
2095 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2096 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
2097 log_error("Failed to parse reply.");
2101 dbus_message_iter_recurse(&iter, &sub);
2102 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2103 const char *what, *who, *why, *mode;
2105 _cleanup_strv_free_ char **sv = NULL;
2106 _cleanup_free_ char *comm = NULL, *user = NULL;
2108 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
2109 log_error("Failed to parse reply.");
2113 dbus_message_iter_recurse(&sub, &sub2);
2115 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
2116 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
2117 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
2118 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
2119 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
2120 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
2121 log_error("Failed to parse reply.");
2125 if (!streq(mode, "block"))
2128 sv = strv_split(what, ":");
2132 if (!strv_contains(sv,
2134 a == ACTION_POWEROFF ||
2135 a == ACTION_REBOOT ||
2136 a == ACTION_KEXEC ? "shutdown" : "sleep"))
2139 get_process_comm(pid, &comm);
2140 user = uid_to_name(uid);
2141 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
2142 who, (unsigned long) pid, strna(comm), strna(user), why);
2146 dbus_message_iter_next(&sub);
2149 dbus_message_iter_recurse(&iter, &sub);
2151 /* Check for current sessions */
2152 sd_get_sessions(&sessions);
2153 STRV_FOREACH(s, sessions) {
2155 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2157 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2160 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2163 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2166 sd_session_get_tty(*s, &tty);
2167 sd_session_get_seat(*s, &seat);
2168 sd_session_get_service(*s, &service);
2169 user = uid_to_name(uid);
2171 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2178 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2179 action_table[a].verb);
2187 static int start_special(DBusConnection *bus, char **args) {
2193 a = verb_to_action(args[0]);
2195 r = check_inhibitors(bus, a);
2199 if (arg_force >= 2 && geteuid() != 0) {
2200 log_error("Must be root.");
2204 if (arg_force >= 2 &&
2205 (a == ACTION_HALT ||
2206 a == ACTION_POWEROFF ||
2207 a == ACTION_REBOOT))
2210 if (arg_force >= 1 &&
2211 (a == ACTION_HALT ||
2212 a == ACTION_POWEROFF ||
2213 a == ACTION_REBOOT ||
2214 a == ACTION_KEXEC ||
2216 return daemon_reload(bus, args);
2218 /* first try logind, to allow authentication with polkit */
2219 if (geteuid() != 0 &&
2220 (a == ACTION_POWEROFF ||
2221 a == ACTION_REBOOT ||
2222 a == ACTION_SUSPEND ||
2223 a == ACTION_HIBERNATE ||
2224 a == ACTION_HYBRID_SLEEP)) {
2225 r = reboot_with_logind(bus, a);
2230 r = start_unit(bus, args);
2231 if (r == EXIT_SUCCESS)
2237 static int check_unit_active(DBusConnection *bus, char **args) {
2238 const char * const check_states[] = {
2245 int r = 3; /* According to LSB: "program is not running" */
2250 STRV_FOREACH(name, args+1) {
2253 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2263 static int check_unit_failed(DBusConnection *bus, char **args) {
2264 const char * const check_states[] = {
2275 STRV_FOREACH(name, args+1) {
2278 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2288 static int kill_unit(DBusConnection *bus, char **args) {
2296 arg_kill_who = "all";
2298 STRV_FOREACH(name, args+1) {
2299 _cleanup_free_ char *n = NULL;
2301 n = unit_name_mangle(*name);
2305 r = bus_method_call_with_reply(
2307 "org.freedesktop.systemd1",
2308 "/org/freedesktop/systemd1",
2309 "org.freedesktop.systemd1.Manager",
2313 DBUS_TYPE_STRING, &n,
2314 DBUS_TYPE_STRING, &arg_kill_who,
2315 DBUS_TYPE_INT32, &arg_signal,
2323 static int set_cgroup(DBusConnection *bus, char **args) {
2324 _cleanup_free_ char *n = NULL;
2325 const char *method, *runtime;
2333 streq(args[0], "set-cgroup") ? "SetUnitControlGroup" :
2334 streq(args[0], "unset-cgroup") ? "UnsetUnitControlGroup"
2335 : "UnsetUnitControlGroupAttribute";
2337 runtime = arg_runtime ? "runtime" : "persistent";
2339 n = unit_name_mangle(args[1]);
2343 STRV_FOREACH(argument, args + 2) {
2345 r = bus_method_call_with_reply(
2347 "org.freedesktop.systemd1",
2348 "/org/freedesktop/systemd1",
2349 "org.freedesktop.systemd1.Manager",
2353 DBUS_TYPE_STRING, &n,
2354 DBUS_TYPE_STRING, argument,
2355 DBUS_TYPE_STRING, &runtime,
2364 static int set_cgroup_attr(DBusConnection *bus, char **args) {
2365 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2367 DBusMessageIter iter;
2368 _cleanup_free_ char *n = NULL;
2369 const char *runtime;
2375 dbus_error_init(&error);
2377 runtime = arg_runtime ? "runtime" : "persistent";
2379 n = unit_name_mangle(args[1]);
2383 m = dbus_message_new_method_call(
2384 "org.freedesktop.systemd1",
2385 "/org/freedesktop/systemd1",
2386 "org.freedesktop.systemd1.Manager",
2387 "SetUnitControlGroupAttribute");
2391 dbus_message_iter_init_append(m, &iter);
2392 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2393 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[2]))
2396 r = bus_append_strv_iter(&iter, args + 3);
2400 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2403 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2405 log_error("Failed to issue method call: %s", bus_error_message(&error));
2406 dbus_error_free(&error);
2413 static int get_cgroup_attr(DBusConnection *bus, char **args) {
2414 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2415 _cleanup_free_ char *n = NULL;
2422 n = unit_name_mangle(args[1]);
2426 STRV_FOREACH(argument, args + 2) {
2427 _cleanup_strv_free_ char **list = NULL;
2428 DBusMessageIter iter;
2431 r = bus_method_call_with_reply(
2433 "org.freedesktop.systemd1",
2434 "/org/freedesktop/systemd1",
2435 "org.freedesktop.systemd1.Manager",
2436 "GetUnitControlGroupAttribute",
2439 DBUS_TYPE_STRING, &n,
2440 DBUS_TYPE_STRING, argument,
2445 if (!dbus_message_iter_init(reply, &iter)) {
2446 log_error("Failed to initialize iterator.");
2450 r = bus_parse_strv_iter(&iter, &list);
2452 log_error("Failed to parse value list.");
2456 STRV_FOREACH(a, list) {
2457 if (endswith(*a, "\n"))
2467 typedef struct ExecStatusInfo {
2475 usec_t start_timestamp;
2476 usec_t exit_timestamp;
2481 LIST_FIELDS(struct ExecStatusInfo, exec);
2484 static void exec_status_info_free(ExecStatusInfo *i) {
2493 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2494 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2495 DBusMessageIter sub2, sub3;
2499 int32_t code, status;
2505 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2508 dbus_message_iter_recurse(sub, &sub2);
2510 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2513 i->path = strdup(path);
2517 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2518 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2522 dbus_message_iter_recurse(&sub2, &sub3);
2523 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2524 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2525 dbus_message_iter_next(&sub3);
2529 i->argv = new0(char*, n+1);
2534 dbus_message_iter_recurse(&sub2, &sub3);
2535 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2538 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2539 dbus_message_iter_get_basic(&sub3, &s);
2540 dbus_message_iter_next(&sub3);
2542 i->argv[n] = strdup(s);
2549 if (!dbus_message_iter_next(&sub2) ||
2550 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2551 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2552 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2553 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2554 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2555 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2556 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2557 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2561 i->start_timestamp = (usec_t) start_timestamp;
2562 i->exit_timestamp = (usec_t) exit_timestamp;
2563 i->pid = (pid_t) pid;
2570 typedef struct UnitStatusInfo {
2572 const char *load_state;
2573 const char *active_state;
2574 const char *sub_state;
2575 const char *unit_file_state;
2577 const char *description;
2578 const char *following;
2580 char **documentation;
2582 const char *fragment_path;
2583 const char *source_path;
2584 const char *default_control_group;
2586 char **dropin_paths;
2588 const char *load_error;
2591 usec_t inactive_exit_timestamp;
2592 usec_t inactive_exit_timestamp_monotonic;
2593 usec_t active_enter_timestamp;
2594 usec_t active_exit_timestamp;
2595 usec_t inactive_enter_timestamp;
2597 bool need_daemon_reload;
2602 const char *status_text;
2605 usec_t start_timestamp;
2606 usec_t exit_timestamp;
2608 int exit_code, exit_status;
2610 usec_t condition_timestamp;
2611 bool condition_result;
2614 unsigned n_accepted;
2615 unsigned n_connections;
2618 /* Pairs of type, path */
2622 const char *sysfs_path;
2624 /* Mount, Automount */
2630 LIST_HEAD(ExecStatusInfo, exec);
2633 static void print_status_info(UnitStatusInfo *i) {
2635 const char *on, *off, *ss;
2637 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2638 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2641 arg_all * OUTPUT_SHOW_ALL |
2642 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2643 on_tty() * OUTPUT_COLOR |
2644 !arg_quiet * OUTPUT_WARN_CUTOFF |
2645 arg_full * OUTPUT_FULL_WIDTH;
2646 int maxlen = 8; /* a value that'll suffice most of the time */
2651 STRV_FOREACH_PAIR(t, t2, i->listen)
2652 maxlen = MAX(maxlen, (int)(sizeof("Listen") - 1 + strlen(*t)));
2654 maxlen = MAX(maxlen, (int)sizeof("Accept") - 1);
2655 if (i->main_pid > 0)
2656 maxlen = MAX(maxlen, (int)sizeof("Main PID") - 1);
2657 else if (i->control_pid > 0)
2658 maxlen = MAX(maxlen, (int)sizeof("Control") - 1);
2660 /* This shows pretty information about a unit. See
2661 * print_property() for a low-level property printer */
2663 printf("%s", strna(i->id));
2665 if (i->description && !streq_ptr(i->id, i->description))
2666 printf(" - %s", i->description);
2671 printf(" %*s: unit currently follows state of %s\n", maxlen, "Follow", i->following);
2673 if (streq_ptr(i->load_state, "error")) {
2674 on = ansi_highlight_red(true);
2675 off = ansi_highlight_red(false);
2679 path = i->source_path ? i->source_path : i->fragment_path;
2682 printf(" %*s: %s%s%s (Reason: %s)\n",
2683 maxlen, "Loaded", on, strna(i->load_state), off, i->load_error);
2684 else if (path && i->unit_file_state)
2685 printf(" %*s: %s%s%s (%s; %s)\n",
2686 maxlen, "Loaded", on, strna(i->load_state), off, path, i->unit_file_state);
2688 printf(" %*s: %s%s%s (%s)\n",
2689 maxlen, "Loaded", on, strna(i->load_state), off, path);
2691 printf(" %*s: %s%s%s\n",
2692 maxlen, "Loaded", on, strna(i->load_state), off);
2694 if (!strv_isempty(i->dropin_paths)) {
2699 STRV_FOREACH(dropin, i->dropin_paths) {
2700 if (! dir || last) {
2701 printf(" %*s ", maxlen, dir ? "" : "Drop-In:");
2705 if (path_get_parent(*dropin, &dir) < 0) {
2710 printf("%s\n %*s %s", dir, maxlen, "",
2711 draw_special_char(DRAW_TREE_RIGHT));
2714 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
2716 printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", ");
2722 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2724 if (streq_ptr(i->active_state, "failed")) {
2725 on = ansi_highlight_red(true);
2726 off = ansi_highlight_red(false);
2727 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2728 on = ansi_highlight_green(true);
2729 off = ansi_highlight_green(false);
2734 printf(" %*s: %s%s (%s)%s",
2735 maxlen, "Active", on, strna(i->active_state), ss, off);
2737 printf(" %*s: %s%s%s",
2738 maxlen, "Active", on, strna(i->active_state), off);
2740 if (!isempty(i->result) && !streq(i->result, "success"))
2741 printf(" (Result: %s)", i->result);
2743 timestamp = (streq_ptr(i->active_state, "active") ||
2744 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2745 (streq_ptr(i->active_state, "inactive") ||
2746 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2747 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2748 i->active_exit_timestamp;
2750 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2751 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2754 printf(" since %s; %s\n", s2, s1);
2756 printf(" since %s\n", s2);
2760 if (!i->condition_result && i->condition_timestamp > 0) {
2761 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2762 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2765 printf(" %*s start condition failed at %s; %s\n", maxlen, "", s2, s1);
2767 printf(" %*s start condition failed at %s\n", maxlen, "", s2);
2771 printf(" %*s: %s\n", maxlen, "Device", i->sysfs_path);
2773 printf(" %*s: %s\n", maxlen, "Where", i->where);
2775 printf(" %*s: %s\n", maxlen, "What", i->what);
2777 STRV_FOREACH(t, i->documentation)
2778 printf(" %*s %s\n", maxlen+1, t == i->documentation ? "Docs:" : "", *t);
2780 STRV_FOREACH_PAIR(t, t2, i->listen)
2781 printf(" %*s %s (%s)\n", maxlen+1, t == i->listen ? "Listen:" : "", *t2, *t);
2784 printf(" %*s: %u; Connected: %u\n", maxlen, "Accepted", i->n_accepted, i->n_connections);
2786 LIST_FOREACH(exec, p, i->exec) {
2787 _cleanup_free_ char *argv = NULL;
2790 /* Only show exited processes here */
2794 argv = strv_join(p->argv, " ");
2795 printf(" %*s: %u %s=%s ", maxlen, "Process", p->pid, p->name, strna(argv));
2797 good = is_clean_exit_lsb(p->code, p->status, NULL);
2799 on = ansi_highlight_red(true);
2800 off = ansi_highlight_red(false);
2804 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2806 if (p->code == CLD_EXITED) {
2809 printf("status=%i", p->status);
2811 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2816 printf("signal=%s", signal_to_string(p->status));
2818 printf(")%s\n", off);
2820 if (i->main_pid == p->pid &&
2821 i->start_timestamp == p->start_timestamp &&
2822 i->exit_timestamp == p->start_timestamp)
2823 /* Let's not show this twice */
2826 if (p->pid == i->control_pid)
2830 if (i->main_pid > 0 || i->control_pid > 0) {
2831 if (i->main_pid > 0) {
2832 printf(" %*s: %u", maxlen, "Main PID", (unsigned) i->main_pid);
2835 _cleanup_free_ char *comm = NULL;
2836 get_process_comm(i->main_pid, &comm);
2838 printf(" (%s)", comm);
2839 } else if (i->exit_code > 0) {
2840 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2842 if (i->exit_code == CLD_EXITED) {
2845 printf("status=%i", i->exit_status);
2847 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2852 printf("signal=%s", signal_to_string(i->exit_status));
2856 if (i->control_pid > 0)
2860 if (i->control_pid > 0) {
2861 _cleanup_free_ char *c = NULL;
2863 printf(" %*s: %u", i->main_pid ? 0 : maxlen, "Control", (unsigned) i->control_pid);
2865 get_process_comm(i->control_pid, &c);
2874 printf(" %*s: \"%s\"\n", maxlen, "Status", i->status_text);
2876 if (i->default_control_group &&
2877 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2880 printf(" %*s: %s\n", maxlen, "CGroup", i->default_control_group);
2882 if (arg_transport != TRANSPORT_SSH) {
2885 char prefix[maxlen + 4];
2886 memset(prefix, ' ', sizeof(prefix) - 1);
2887 prefix[sizeof(prefix) - 1] = '\0';
2890 if (c > sizeof(prefix) - 1)
2891 c -= sizeof(prefix) - 1;
2895 if (i->main_pid > 0)
2896 extra[k++] = i->main_pid;
2898 if (i->control_pid > 0)
2899 extra[k++] = i->control_pid;
2901 show_cgroup_and_extra_by_spec(i->default_control_group, prefix,
2902 c, false, extra, k, flags);
2906 if (i->id && arg_transport != TRANSPORT_SSH) {
2908 show_journal_by_unit(stdout,
2912 i->inactive_exit_timestamp_monotonic,
2916 arg_scope == UNIT_FILE_SYSTEM);
2919 if (i->need_daemon_reload)
2920 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2921 ansi_highlight_red(true),
2922 ansi_highlight_red(false),
2923 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2926 static void show_unit_help(UnitStatusInfo *i) {
2931 if (!i->documentation) {
2932 log_info("Documentation for %s not known.", i->id);
2936 STRV_FOREACH(p, i->documentation) {
2938 if (startswith(*p, "man:")) {
2941 _cleanup_free_ char *page = NULL, *section = NULL;
2942 const char *args[4] = { "man", NULL, NULL, NULL };
2947 if ((*p)[k-1] == ')')
2948 e = strrchr(*p, '(');
2951 page = strndup((*p) + 4, e - *p - 4);
2952 section = strndup(e + 1, *p + k - e - 2);
2953 if (!page || !section) {
2965 log_error("Failed to fork: %m");
2971 execvp(args[0], (char**) args);
2972 log_error("Failed to execute man: %m");
2973 _exit(EXIT_FAILURE);
2976 wait_for_terminate(pid, NULL);
2978 log_info("Can't show: %s", *p);
2982 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2988 switch (dbus_message_iter_get_arg_type(iter)) {
2990 case DBUS_TYPE_STRING: {
2993 dbus_message_iter_get_basic(iter, &s);
2996 if (streq(name, "Id"))
2998 else if (streq(name, "LoadState"))
3000 else if (streq(name, "ActiveState"))
3001 i->active_state = s;
3002 else if (streq(name, "SubState"))
3004 else if (streq(name, "Description"))
3006 else if (streq(name, "FragmentPath"))
3007 i->fragment_path = s;
3008 else if (streq(name, "SourcePath"))
3010 else if (streq(name, "DefaultControlGroup"))
3011 i->default_control_group = s;
3012 else if (streq(name, "StatusText"))
3014 else if (streq(name, "SysFSPath"))
3016 else if (streq(name, "Where"))
3018 else if (streq(name, "What"))
3020 else if (streq(name, "Following"))
3022 else if (streq(name, "UnitFileState"))
3023 i->unit_file_state = s;
3024 else if (streq(name, "Result"))
3031 case DBUS_TYPE_BOOLEAN: {
3034 dbus_message_iter_get_basic(iter, &b);
3036 if (streq(name, "Accept"))
3038 else if (streq(name, "NeedDaemonReload"))
3039 i->need_daemon_reload = b;
3040 else if (streq(name, "ConditionResult"))
3041 i->condition_result = b;
3046 case DBUS_TYPE_UINT32: {
3049 dbus_message_iter_get_basic(iter, &u);
3051 if (streq(name, "MainPID")) {
3053 i->main_pid = (pid_t) u;
3056 } else if (streq(name, "ControlPID"))
3057 i->control_pid = (pid_t) u;
3058 else if (streq(name, "ExecMainPID")) {
3060 i->main_pid = (pid_t) u;
3061 } else if (streq(name, "NAccepted"))
3063 else if (streq(name, "NConnections"))
3064 i->n_connections = u;
3069 case DBUS_TYPE_INT32: {
3072 dbus_message_iter_get_basic(iter, &j);
3074 if (streq(name, "ExecMainCode"))
3075 i->exit_code = (int) j;
3076 else if (streq(name, "ExecMainStatus"))
3077 i->exit_status = (int) j;
3082 case DBUS_TYPE_UINT64: {
3085 dbus_message_iter_get_basic(iter, &u);
3087 if (streq(name, "ExecMainStartTimestamp"))
3088 i->start_timestamp = (usec_t) u;
3089 else if (streq(name, "ExecMainExitTimestamp"))
3090 i->exit_timestamp = (usec_t) u;
3091 else if (streq(name, "ActiveEnterTimestamp"))
3092 i->active_enter_timestamp = (usec_t) u;
3093 else if (streq(name, "InactiveEnterTimestamp"))
3094 i->inactive_enter_timestamp = (usec_t) u;
3095 else if (streq(name, "InactiveExitTimestamp"))
3096 i->inactive_exit_timestamp = (usec_t) u;
3097 else if (streq(name, "InactiveExitTimestampMonotonic"))
3098 i->inactive_exit_timestamp_monotonic = (usec_t) u;
3099 else if (streq(name, "ActiveExitTimestamp"))
3100 i->active_exit_timestamp = (usec_t) u;
3101 else if (streq(name, "ConditionTimestamp"))
3102 i->condition_timestamp = (usec_t) u;
3107 case DBUS_TYPE_ARRAY: {
3109 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
3110 startswith(name, "Exec")) {
3111 DBusMessageIter sub;
3113 dbus_message_iter_recurse(iter, &sub);
3114 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3115 ExecStatusInfo *info;
3118 if (!(info = new0(ExecStatusInfo, 1)))
3121 if (!(info->name = strdup(name))) {
3126 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
3131 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
3133 dbus_message_iter_next(&sub);
3136 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3137 DBusMessageIter sub, sub2;
3139 dbus_message_iter_recurse(iter, &sub);
3140 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3141 const char *type, *path;
3143 dbus_message_iter_recurse(&sub, &sub2);
3145 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3146 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
3149 r = strv_extend(&i->listen, type);
3152 r = strv_extend(&i->listen, path);
3157 dbus_message_iter_next(&sub);
3162 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING && streq(name, "DropInPaths")) {
3163 int r = bus_parse_strv_iter(iter, &i->dropin_paths);
3167 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
3168 streq(name, "Documentation")) {
3170 DBusMessageIter sub;
3172 dbus_message_iter_recurse(iter, &sub);
3173 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
3177 dbus_message_iter_get_basic(&sub, &s);
3179 r = strv_extend(&i->documentation, s);
3183 dbus_message_iter_next(&sub);
3190 case DBUS_TYPE_STRUCT: {
3192 if (streq(name, "LoadError")) {
3193 DBusMessageIter sub;
3194 const char *n, *message;
3197 dbus_message_iter_recurse(iter, &sub);
3199 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
3203 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
3207 if (!isempty(message))
3208 i->load_error = message;
3218 static int print_property(const char *name, DBusMessageIter *iter) {
3222 /* This is a low-level property printer, see
3223 * print_status_info() for the nicer output */
3225 if (arg_properties && !strv_find(arg_properties, name))
3228 switch (dbus_message_iter_get_arg_type(iter)) {
3230 case DBUS_TYPE_STRUCT: {
3231 DBusMessageIter sub;
3232 dbus_message_iter_recurse(iter, &sub);
3234 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
3237 dbus_message_iter_get_basic(&sub, &u);
3240 printf("%s=%u\n", name, (unsigned) u);
3242 printf("%s=\n", name);
3245 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
3248 dbus_message_iter_get_basic(&sub, &s);
3250 if (arg_all || s[0])
3251 printf("%s=%s\n", name, s);
3254 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
3255 const char *a = NULL, *b = NULL;
3257 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
3258 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
3260 if (arg_all || !isempty(a) || !isempty(b))
3261 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3269 case DBUS_TYPE_ARRAY:
3271 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
3272 DBusMessageIter sub, sub2;
3274 dbus_message_iter_recurse(iter, &sub);
3275 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3279 dbus_message_iter_recurse(&sub, &sub2);
3281 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3282 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3283 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3285 dbus_message_iter_next(&sub);
3290 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3291 DBusMessageIter sub, sub2;
3293 dbus_message_iter_recurse(iter, &sub);
3295 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3296 const char *type, *path;
3298 dbus_message_iter_recurse(&sub, &sub2);
3300 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3301 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3302 printf("%s=%s\n", type, path);
3304 dbus_message_iter_next(&sub);
3309 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
3310 DBusMessageIter sub, sub2;
3312 dbus_message_iter_recurse(iter, &sub);
3313 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3314 const char *type, *path;
3316 dbus_message_iter_recurse(&sub, &sub2);
3318 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3319 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3320 printf("Listen%s=%s\n", type, path);
3322 dbus_message_iter_next(&sub);
3327 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3328 DBusMessageIter sub, sub2;
3330 dbus_message_iter_recurse(iter, &sub);
3331 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3333 uint64_t value, next_elapse;
3335 dbus_message_iter_recurse(&sub, &sub2);
3337 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3338 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3339 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3340 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3342 printf("%s={ value=%s ; next_elapse=%s }\n",
3344 format_timespan(timespan1, sizeof(timespan1), value, 0),
3345 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
3348 dbus_message_iter_next(&sub);
3353 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
3354 DBusMessageIter sub, sub2;
3356 dbus_message_iter_recurse(iter, &sub);
3357 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3358 const char *controller, *attr, *value;
3360 dbus_message_iter_recurse(&sub, &sub2);
3362 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
3363 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
3364 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
3366 printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
3372 dbus_message_iter_next(&sub);
3377 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3378 DBusMessageIter sub;
3380 dbus_message_iter_recurse(iter, &sub);
3381 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3382 ExecStatusInfo info = {};
3384 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3385 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3386 _cleanup_free_ char *t;
3388 t = strv_join(info.argv, " ");
3390 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3394 yes_no(info.ignore),
3395 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3396 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3397 (unsigned) info. pid,
3398 sigchld_code_to_string(info.code),
3400 info.code == CLD_EXITED ? "" : "/",
3401 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3405 strv_free(info.argv);
3407 dbus_message_iter_next(&sub);
3416 if (generic_print_property(name, iter, arg_all) > 0)
3420 printf("%s=[unprintable]\n", name);
3425 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3426 _cleanup_free_ DBusMessage *reply = NULL;
3427 const char *interface = "";
3429 DBusMessageIter iter, sub, sub2, sub3;
3430 UnitStatusInfo info = {};
3436 r = bus_method_call_with_reply(
3438 "org.freedesktop.systemd1",
3440 "org.freedesktop.DBus.Properties",
3444 DBUS_TYPE_STRING, &interface,
3449 if (!dbus_message_iter_init(reply, &iter) ||
3450 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3451 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3452 log_error("Failed to parse reply.");
3456 dbus_message_iter_recurse(&iter, &sub);
3463 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3466 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3467 dbus_message_iter_recurse(&sub, &sub2);
3469 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3470 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3471 log_error("Failed to parse reply.");
3475 dbus_message_iter_recurse(&sub2, &sub3);
3477 if (show_properties)
3478 r = print_property(name, &sub3);
3480 r = status_property(name, &sub3, &info);
3482 log_error("Failed to parse reply.");
3486 dbus_message_iter_next(&sub);
3491 if (!show_properties) {
3492 if (streq(verb, "help"))
3493 show_unit_help(&info);
3495 print_status_info(&info);
3498 strv_free(info.documentation);
3499 strv_free(info.dropin_paths);
3500 strv_free(info.listen);
3502 if (!streq_ptr(info.active_state, "active") &&
3503 !streq_ptr(info.active_state, "reloading") &&
3504 streq(verb, "status"))
3505 /* According to LSB: "program not running" */
3508 while ((p = info.exec)) {
3509 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3510 exec_status_info_free(p);
3516 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3517 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3518 const char *path = NULL;
3519 _cleanup_dbus_error_free_ DBusError error;
3522 dbus_error_init(&error);
3524 r = bus_method_call_with_reply(
3526 "org.freedesktop.systemd1",
3527 "/org/freedesktop/systemd1",
3528 "org.freedesktop.systemd1.Manager",
3532 DBUS_TYPE_UINT32, &pid,
3537 if (!dbus_message_get_args(reply, &error,
3538 DBUS_TYPE_OBJECT_PATH, &path,
3539 DBUS_TYPE_INVALID)) {
3540 log_error("Failed to parse reply: %s", bus_error_message(&error));
3544 r = show_one(verb, bus, path, false, new_line);
3548 static int show_all(const char* verb, DBusConnection *bus, bool show_properties, bool *new_line) {
3549 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3550 _cleanup_free_ struct unit_info *unit_infos = NULL;
3552 const struct unit_info *u;
3555 r = get_unit_list(bus, &reply, &unit_infos, &c);
3559 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
3561 for (u = unit_infos; u < unit_infos + c; u++) {
3562 _cleanup_free_ char *p = NULL;
3564 if (!output_show_unit(u))
3567 p = unit_dbus_path_from_name(u->id);
3571 printf("%s -> '%s'\n", u->id, p);
3573 r = show_one(verb, bus, p, show_properties, new_line);
3581 static int show(DBusConnection *bus, char **args) {
3583 bool show_properties, show_status, new_line = false;
3589 show_properties = streq(args[0], "show");
3590 show_status = streq(args[0], "status");
3592 if (show_properties)
3593 pager_open_if_enabled();
3595 /* If no argument is specified inspect the manager itself */
3597 if (show_properties && strv_length(args) <= 1)
3598 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3600 if (show_status && strv_length(args) <= 1)
3601 return show_all(args[0], bus, false, &new_line);
3603 STRV_FOREACH(name, args+1) {
3606 if (safe_atou32(*name, &id) < 0) {
3607 _cleanup_free_ char *p = NULL, *n = NULL;
3608 /* Interpret as unit name */
3610 n = unit_name_mangle(*name);
3614 p = unit_dbus_path_from_name(n);
3618 r = show_one(args[0], bus, p, show_properties, &new_line);
3622 } else if (show_properties) {
3623 _cleanup_free_ char *p = NULL;
3625 /* Interpret as job id */
3626 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3629 r = show_one(args[0], bus, p, show_properties, &new_line);
3634 /* Interpret as PID */
3635 r = show_one_by_pid(args[0], bus, id, &new_line);
3644 static int dump(DBusConnection *bus, char **args) {
3645 _cleanup_free_ DBusMessage *reply = NULL;
3650 dbus_error_init(&error);
3652 pager_open_if_enabled();
3654 r = bus_method_call_with_reply(
3656 "org.freedesktop.systemd1",
3657 "/org/freedesktop/systemd1",
3658 "org.freedesktop.systemd1.Manager",
3666 if (!dbus_message_get_args(reply, &error,
3667 DBUS_TYPE_STRING, &text,
3668 DBUS_TYPE_INVALID)) {
3669 log_error("Failed to parse reply: %s", bus_error_message(&error));
3670 dbus_error_free(&error);
3674 fputs(text, stdout);
3678 static int snapshot(DBusConnection *bus, char **args) {
3679 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3682 dbus_bool_t cleanup = FALSE;
3683 DBusMessageIter iter, sub;
3686 *interface = "org.freedesktop.systemd1.Unit",
3688 _cleanup_free_ char *n = NULL;
3690 dbus_error_init(&error);
3692 if (strv_length(args) > 1)
3693 n = snapshot_name_mangle(args[1]);
3699 r = bus_method_call_with_reply (
3701 "org.freedesktop.systemd1",
3702 "/org/freedesktop/systemd1",
3703 "org.freedesktop.systemd1.Manager",
3707 DBUS_TYPE_STRING, &n,
3708 DBUS_TYPE_BOOLEAN, &cleanup,
3713 if (!dbus_message_get_args(reply, &error,
3714 DBUS_TYPE_OBJECT_PATH, &path,
3715 DBUS_TYPE_INVALID)) {
3716 log_error("Failed to parse reply: %s", bus_error_message(&error));
3717 dbus_error_free(&error);
3721 dbus_message_unref(reply);
3724 r = bus_method_call_with_reply (
3726 "org.freedesktop.systemd1",
3728 "org.freedesktop.DBus.Properties",
3732 DBUS_TYPE_STRING, &interface,
3733 DBUS_TYPE_STRING, &property,
3738 if (!dbus_message_iter_init(reply, &iter) ||
3739 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3740 log_error("Failed to parse reply.");
3744 dbus_message_iter_recurse(&iter, &sub);
3746 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3747 log_error("Failed to parse reply.");
3751 dbus_message_iter_get_basic(&sub, &id);
3759 static int delete_snapshot(DBusConnection *bus, char **args) {
3764 STRV_FOREACH(name, args+1) {
3765 _cleanup_free_ char *n = NULL;
3768 n = snapshot_name_mangle(*name);
3772 r = bus_method_call_with_reply(
3774 "org.freedesktop.systemd1",
3775 "/org/freedesktop/systemd1",
3776 "org.freedesktop.systemd1.Manager",
3780 DBUS_TYPE_STRING, &n,
3789 static int daemon_reload(DBusConnection *bus, char **args) {
3794 if (arg_action == ACTION_RELOAD)
3796 else if (arg_action == ACTION_REEXEC)
3797 method = "Reexecute";
3799 assert(arg_action == ACTION_SYSTEMCTL);
3802 streq(args[0], "clear-jobs") ||
3803 streq(args[0], "cancel") ? "ClearJobs" :
3804 streq(args[0], "daemon-reexec") ? "Reexecute" :
3805 streq(args[0], "reset-failed") ? "ResetFailed" :
3806 streq(args[0], "halt") ? "Halt" :
3807 streq(args[0], "poweroff") ? "PowerOff" :
3808 streq(args[0], "reboot") ? "Reboot" :
3809 streq(args[0], "kexec") ? "KExec" :
3810 streq(args[0], "exit") ? "Exit" :
3811 /* "daemon-reload" */ "Reload";
3814 r = bus_method_call_with_reply(
3816 "org.freedesktop.systemd1",
3817 "/org/freedesktop/systemd1",
3818 "org.freedesktop.systemd1.Manager",
3824 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3825 /* There's always a fallback possible for
3826 * legacy actions. */
3828 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3829 /* On reexecution, we expect a disconnect, not
3833 log_error("Failed to issue method call: %s", bus_error_message(&error));
3835 dbus_error_free(&error);
3839 static int reset_failed(DBusConnection *bus, char **args) {
3843 if (strv_length(args) <= 1)
3844 return daemon_reload(bus, args);
3846 STRV_FOREACH(name, args+1) {
3847 _cleanup_free_ char *n;
3849 n = unit_name_mangle(*name);
3853 r = bus_method_call_with_reply(
3855 "org.freedesktop.systemd1",
3856 "/org/freedesktop/systemd1",
3857 "org.freedesktop.systemd1.Manager",
3861 DBUS_TYPE_STRING, &n,
3870 static int show_enviroment(DBusConnection *bus, char **args) {
3871 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3872 DBusMessageIter iter, sub, sub2;
3875 *interface = "org.freedesktop.systemd1.Manager",
3876 *property = "Environment";
3878 pager_open_if_enabled();
3880 r = bus_method_call_with_reply(
3882 "org.freedesktop.systemd1",
3883 "/org/freedesktop/systemd1",
3884 "org.freedesktop.DBus.Properties",
3888 DBUS_TYPE_STRING, &interface,
3889 DBUS_TYPE_STRING, &property,
3894 if (!dbus_message_iter_init(reply, &iter) ||
3895 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3896 log_error("Failed to parse reply.");
3900 dbus_message_iter_recurse(&iter, &sub);
3902 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3903 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3904 log_error("Failed to parse reply.");
3908 dbus_message_iter_recurse(&sub, &sub2);
3910 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3913 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3914 log_error("Failed to parse reply.");
3918 dbus_message_iter_get_basic(&sub2, &text);
3921 dbus_message_iter_next(&sub2);
3927 static int switch_root(DBusConnection *bus, char **args) {
3930 _cleanup_free_ char *init = NULL;
3932 l = strv_length(args);
3933 if (l < 2 || l > 3) {
3934 log_error("Wrong number of arguments.");
3941 init = strdup(args[2]);
3943 parse_env_file("/proc/cmdline", WHITESPACE,
3953 log_debug("switching root - root: %s; init: %s", root, init);
3955 return bus_method_call_with_reply(
3957 "org.freedesktop.systemd1",
3958 "/org/freedesktop/systemd1",
3959 "org.freedesktop.systemd1.Manager",
3963 DBUS_TYPE_STRING, &root,
3964 DBUS_TYPE_STRING, &init,
3968 static int set_environment(DBusConnection *bus, char **args) {
3969 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3972 DBusMessageIter iter;
3978 dbus_error_init(&error);
3980 method = streq(args[0], "set-environment")
3982 : "UnsetEnvironment";
3984 m = dbus_message_new_method_call(
3985 "org.freedesktop.systemd1",
3986 "/org/freedesktop/systemd1",
3987 "org.freedesktop.systemd1.Manager",
3992 dbus_message_iter_init_append(m, &iter);
3994 r = bus_append_strv_iter(&iter, args + 1);
3998 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4000 log_error("Failed to issue method call: %s", bus_error_message(&error));
4001 dbus_error_free(&error);
4008 static int enable_sysv_units(char **args) {
4011 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
4012 const char *verb = args[0];
4013 unsigned f = 1, t = 1;
4014 LookupPaths paths = {};
4016 if (arg_scope != UNIT_FILE_SYSTEM)
4019 if (!streq(verb, "enable") &&
4020 !streq(verb, "disable") &&
4021 !streq(verb, "is-enabled"))
4024 /* Processes all SysV units, and reshuffles the array so that
4025 * afterwards only the native units remain */
4027 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
4032 for (f = 1; args[f]; f++) {
4034 _cleanup_free_ char *p = NULL, *q = NULL;
4035 bool found_native = false, found_sysv;
4037 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
4045 if (!endswith(name, ".service"))
4048 if (path_is_absolute(name))
4051 STRV_FOREACH(k, paths.unit_path) {
4052 if (!isempty(arg_root))
4053 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
4055 asprintf(&p, "%s/%s", *k, name);
4062 found_native = access(p, F_OK) >= 0;
4073 if (!isempty(arg_root))
4074 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
4076 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
4082 p[strlen(p) - sizeof(".service") + 1] = 0;
4083 found_sysv = access(p, F_OK) >= 0;
4088 /* Mark this entry, so that we don't try enabling it as native unit */
4089 args[f] = (char*) "";
4091 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
4093 if (!isempty(arg_root))
4094 argv[c++] = q = strappend("--root=", arg_root);
4096 argv[c++] = path_get_file_name(p);
4098 streq(verb, "enable") ? "on" :
4099 streq(verb, "disable") ? "off" : "--level=5";
4102 l = strv_join((char**)argv, " ");
4108 log_info("Executing %s", l);
4113 log_error("Failed to fork: %m");
4116 } else if (pid == 0) {
4119 execv(argv[0], (char**) argv);
4120 _exit(EXIT_FAILURE);
4123 j = wait_for_terminate(pid, &status);
4125 log_error("Failed to wait for child: %s", strerror(-r));
4130 if (status.si_code == CLD_EXITED) {
4131 if (streq(verb, "is-enabled")) {
4132 if (status.si_status == 0) {
4141 } else if (status.si_status != 0) {
4152 lookup_paths_free(&paths);
4154 /* Drop all SysV units */
4155 for (f = 1, t = 1; args[f]; f++) {
4157 if (isempty(args[f]))
4160 args[t++] = args[f];
4169 static int mangle_names(char **original_names, char ***mangled_names) {
4170 char **i, **l, **name;
4172 l = new(char*, strv_length(original_names) + 1);
4177 STRV_FOREACH(name, original_names) {
4179 /* When enabling units qualified path names are OK,
4180 * too, hence allow them explicitly. */
4185 *i = unit_name_mangle(*name);
4201 static int enable_unit(DBusConnection *bus, char **args) {
4202 const char *verb = args[0];
4203 UnitFileChange *changes = NULL;
4204 unsigned n_changes = 0, i;
4205 int carries_install_info = -1;
4206 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
4208 _cleanup_dbus_error_free_ DBusError error;
4209 _cleanup_strv_free_ char **mangled_names = NULL;
4211 dbus_error_init(&error);
4213 r = enable_sysv_units(args);
4220 if (!bus || avoid_bus()) {
4221 if (streq(verb, "enable")) {
4222 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4223 carries_install_info = r;
4224 } else if (streq(verb, "disable"))
4225 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
4226 else if (streq(verb, "reenable")) {
4227 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4228 carries_install_info = r;
4229 } else if (streq(verb, "link"))
4230 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4231 else if (streq(verb, "preset")) {
4232 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4233 carries_install_info = r;
4234 } else if (streq(verb, "mask"))
4235 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4236 else if (streq(verb, "unmask"))
4237 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
4239 assert_not_reached("Unknown verb");
4242 log_error("Operation failed: %s", strerror(-r));
4247 for (i = 0; i < n_changes; i++) {
4248 if (changes[i].type == UNIT_FILE_SYMLINK)
4249 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4251 log_info("rm '%s'", changes[i].path);
4258 bool send_force = true, expect_carries_install_info = false;
4260 DBusMessageIter iter, sub, sub2;
4262 if (streq(verb, "enable")) {
4263 method = "EnableUnitFiles";
4264 expect_carries_install_info = true;
4265 } else if (streq(verb, "disable")) {
4266 method = "DisableUnitFiles";
4268 } else if (streq(verb, "reenable")) {
4269 method = "ReenableUnitFiles";
4270 expect_carries_install_info = true;
4271 } else if (streq(verb, "link"))
4272 method = "LinkUnitFiles";
4273 else if (streq(verb, "preset")) {
4274 method = "PresetUnitFiles";
4275 expect_carries_install_info = true;
4276 } else if (streq(verb, "mask"))
4277 method = "MaskUnitFiles";
4278 else if (streq(verb, "unmask")) {
4279 method = "UnmaskUnitFiles";
4282 assert_not_reached("Unknown verb");
4284 m = dbus_message_new_method_call(
4285 "org.freedesktop.systemd1",
4286 "/org/freedesktop/systemd1",
4287 "org.freedesktop.systemd1.Manager",
4294 dbus_message_iter_init_append(m, &iter);
4296 r = mangle_names(args+1, &mangled_names);
4300 r = bus_append_strv_iter(&iter, mangled_names);
4302 log_error("Failed to append unit files.");
4307 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4308 log_error("Failed to append runtime boolean.");
4316 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4317 log_error("Failed to append force boolean.");
4323 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4325 log_error("Failed to issue method call: %s", bus_error_message(&error));
4330 if (!dbus_message_iter_init(reply, &iter)) {
4331 log_error("Failed to initialize iterator.");
4335 if (expect_carries_install_info) {
4336 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4338 log_error("Failed to parse reply.");
4342 carries_install_info = b;
4345 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4346 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4347 log_error("Failed to parse reply.");
4352 dbus_message_iter_recurse(&iter, &sub);
4353 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4354 const char *type, *path, *source;
4356 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4357 log_error("Failed to parse reply.");
4362 dbus_message_iter_recurse(&sub, &sub2);
4364 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4365 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4366 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4367 log_error("Failed to parse reply.");
4373 if (streq(type, "symlink"))
4374 log_info("ln -s '%s' '%s'", source, path);
4376 log_info("rm '%s'", path);
4379 dbus_message_iter_next(&sub);
4382 /* Try to reload if enabeld */
4384 r = daemon_reload(bus, args);
4387 if (carries_install_info == 0)
4388 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4389 "using systemctl.\n"
4390 "Possible reasons for having this kind of units are:\n"
4391 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4392 " .wants/ or .requires/ directory.\n"
4393 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4394 " a requirement dependency on it.\n"
4395 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4396 " D-Bus, udev, scripted systemctl call, ...).\n");
4399 unit_file_changes_free(changes, n_changes);
4404 static int unit_is_enabled(DBusConnection *bus, char **args) {
4405 _cleanup_dbus_error_free_ DBusError error;
4407 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
4412 dbus_error_init(&error);
4414 r = enable_sysv_units(args);
4420 if (!bus || avoid_bus()) {
4422 STRV_FOREACH(name, args+1) {
4423 UnitFileState state;
4425 n = unit_name_mangle(*name);
4429 state = unit_file_get_state(arg_scope, arg_root, n);
4436 if (state == UNIT_FILE_ENABLED ||
4437 state == UNIT_FILE_ENABLED_RUNTIME ||
4438 state == UNIT_FILE_STATIC)
4442 puts(unit_file_state_to_string(state));
4446 STRV_FOREACH(name, args+1) {
4449 n = unit_name_mangle(*name);
4453 r = bus_method_call_with_reply (
4455 "org.freedesktop.systemd1",
4456 "/org/freedesktop/systemd1",
4457 "org.freedesktop.systemd1.Manager",
4461 DBUS_TYPE_STRING, &n,
4469 if (!dbus_message_get_args(reply, &error,
4470 DBUS_TYPE_STRING, &s,
4471 DBUS_TYPE_INVALID)) {
4472 log_error("Failed to parse reply: %s", bus_error_message(&error));
4476 dbus_message_unref(reply);
4479 if (streq(s, "enabled") ||
4480 streq(s, "enabled-runtime") ||
4489 return enabled ? 0 : 1;
4492 static int systemctl_help(void) {
4494 pager_open_if_enabled();
4496 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4497 "Query or send control commands to the systemd manager.\n\n"
4498 " -h --help Show this help\n"
4499 " --version Show package version\n"
4500 " -t --type=TYPE List only units of a particular type\n"
4501 " -p --property=NAME Show only properties by this name\n"
4502 " -a --all Show all loaded units/properties, including dead/empty\n"
4503 " ones. To list all units installed on the system, use\n"
4504 " the 'list-unit-files' command instead.\n"
4505 " --reverse Show reverse dependencies with 'list-dependencies'\n"
4506 " --failed Show only failed units\n"
4507 " --full Don't ellipsize unit names on output\n"
4508 " --fail When queueing a new job, fail if conflicting jobs are\n"
4510 " --irreversible Create jobs which cannot be implicitly cancelled\n"
4511 " --show-types When showing sockets, explicitly show their type\n"
4512 " --ignore-dependencies\n"
4513 " When queueing a new job, ignore all its dependencies\n"
4514 " -i --ignore-inhibitors\n"
4515 " When shutting down or sleeping, ignore inhibitors\n"
4516 " --kill-who=WHO Who to send signal to\n"
4517 " -s --signal=SIGNAL Which signal to send\n"
4518 " -H --host=[USER@]HOST\n"
4519 " Show information for remote host\n"
4520 " -P --privileged Acquire privileges before execution\n"
4521 " -q --quiet Suppress output\n"
4522 " --no-block Do not wait until operation finished\n"
4523 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4524 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4526 " --no-legend Do not print a legend (column headers and hints)\n"
4527 " --no-pager Do not pipe output into a pager\n"
4528 " --no-ask-password\n"
4529 " Do not ask for system passwords\n"
4530 " --system Connect to system manager\n"
4531 " --user Connect to user service manager\n"
4532 " --global Enable/disable unit files globally\n"
4533 " -f --force When enabling unit files, override existing symlinks\n"
4534 " When shutting down, execute action immediately\n"
4535 " --root=PATH Enable unit files in the specified root directory\n"
4536 " --runtime Enable unit files only temporarily until next reboot\n"
4537 " -n --lines=INTEGER Journal entries to show\n"
4538 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4539 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4541 " list-units List loaded units\n"
4542 " start [NAME...] Start (activate) one or more units\n"
4543 " stop [NAME...] Stop (deactivate) one or more units\n"
4544 " reload [NAME...] Reload one or more units\n"
4545 " restart [NAME...] Start or restart one or more units\n"
4546 " try-restart [NAME...] Restart one or more units if active\n"
4547 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4548 " otherwise start or restart\n"
4549 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4550 " otherwise restart if active\n"
4551 " isolate [NAME] Start one unit and stop all others\n"
4552 " kill [NAME...] Send signal to processes of a unit\n"
4553 " is-active [NAME...] Check whether units are active\n"
4554 " is-failed [NAME...] Check whether units are failed\n"
4555 " status [NAME...|PID...] Show runtime status of one or more units\n"
4556 " show [NAME...|JOB...] Show properties of one or more\n"
4557 " units/jobs or the manager\n"
4558 " help [NAME...|PID...] Show manual for one or more units\n"
4559 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4561 " get-cgroup-attr [NAME] [ATTR] ...\n"
4562 " Get control group attrubute\n"
4563 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4564 " Set control group attribute\n"
4565 " unset-cgroup-attr [NAME] [ATTR...]\n"
4566 " Unset control group attribute\n"
4567 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4568 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4569 " load [NAME...] Load one or more units\n"
4570 " list-dependencies [NAME] Recursively show units which are required\n"
4571 " or wanted by this unit or by which this\n"
4572 " unit is required or wanted\n\n"
4573 "Unit File Commands:\n"
4574 " list-unit-files List installed unit files\n"
4575 " enable [NAME...] Enable one or more unit files\n"
4576 " disable [NAME...] Disable one or more unit files\n"
4577 " reenable [NAME...] Reenable one or more unit files\n"
4578 " preset [NAME...] Enable/disable one or more unit files\n"
4579 " based on preset configuration\n"
4580 " mask [NAME...] Mask one or more units\n"
4581 " unmask [NAME...] Unmask one or more units\n"
4582 " link [PATH...] Link one or more units files into\n"
4583 " the search path\n"
4584 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4586 " list-jobs List jobs\n"
4587 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4588 "Status Commands:\n"
4589 " dump Dump server status\n"
4590 "Snapshot Commands:\n"
4591 " snapshot [NAME] Create a snapshot\n"
4592 " delete [NAME...] Remove one or more snapshots\n\n"
4593 "Environment Commands:\n"
4594 " show-environment Dump environment\n"
4595 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4596 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4597 "Manager Lifecycle Commands:\n"
4598 " daemon-reload Reload systemd manager configuration\n"
4599 " daemon-reexec Reexecute systemd manager\n\n"
4600 "System Commands:\n"
4601 " default Enter system default mode\n"
4602 " rescue Enter system rescue mode\n"
4603 " emergency Enter system emergency mode\n"
4604 " halt Shut down and halt the system\n"
4605 " poweroff Shut down and power-off the system\n"
4606 " reboot Shut down and reboot the system\n"
4607 " kexec Shut down and reboot the system with kexec\n"
4608 " exit Request user instance exit\n"
4609 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4610 " suspend Suspend the system\n"
4611 " hibernate Hibernate the system\n"
4612 " hybrid-sleep Hibernate and suspend the system\n",
4613 program_invocation_short_name);
4618 static int halt_help(void) {
4620 printf("%s [OPTIONS...]\n\n"
4621 "%s the system.\n\n"
4622 " --help Show this help\n"
4623 " --halt Halt the machine\n"
4624 " -p --poweroff Switch off the machine\n"
4625 " --reboot Reboot the machine\n"
4626 " -f --force Force immediate halt/power-off/reboot\n"
4627 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4628 " -d --no-wtmp Don't write wtmp record\n"
4629 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4630 program_invocation_short_name,
4631 arg_action == ACTION_REBOOT ? "Reboot" :
4632 arg_action == ACTION_POWEROFF ? "Power off" :
4638 static int shutdown_help(void) {
4640 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4641 "Shut down the system.\n\n"
4642 " --help Show this help\n"
4643 " -H --halt Halt the machine\n"
4644 " -P --poweroff Power-off the machine\n"
4645 " -r --reboot Reboot the machine\n"
4646 " -h Equivalent to --poweroff, overridden by --halt\n"
4647 " -k Don't halt/power-off/reboot, just send warnings\n"
4648 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4649 " -c Cancel a pending shutdown\n",
4650 program_invocation_short_name);
4655 static int telinit_help(void) {
4657 printf("%s [OPTIONS...] {COMMAND}\n\n"
4658 "Send control commands to the init daemon.\n\n"
4659 " --help Show this help\n"
4660 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4662 " 0 Power-off the machine\n"
4663 " 6 Reboot the machine\n"
4664 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4665 " 1, s, S Enter rescue mode\n"
4666 " q, Q Reload init daemon configuration\n"
4667 " u, U Reexecute init daemon\n",
4668 program_invocation_short_name);
4673 static int runlevel_help(void) {
4675 printf("%s [OPTIONS...]\n\n"
4676 "Prints the previous and current runlevel of the init system.\n\n"
4677 " --help Show this help\n",
4678 program_invocation_short_name);
4683 static int help_types(void) {
4687 puts("Available unit types:");
4688 for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4689 t = unit_type_to_string(i);
4694 puts("\nAvailable unit load states: ");
4695 for(i = 0; i < _UNIT_LOAD_STATE_MAX; i++) {
4696 t = unit_load_state_to_string(i);
4704 static int systemctl_parse_argv(int argc, char *argv[]) {
4713 ARG_IGNORE_DEPENDENCIES,
4726 ARG_NO_ASK_PASSWORD,
4733 static const struct option options[] = {
4734 { "help", no_argument, NULL, 'h' },
4735 { "version", no_argument, NULL, ARG_VERSION },
4736 { "type", required_argument, NULL, 't' },
4737 { "property", required_argument, NULL, 'p' },
4738 { "all", no_argument, NULL, 'a' },
4739 { "reverse", no_argument, NULL, ARG_REVERSE },
4740 { "after", no_argument, NULL, ARG_AFTER },
4741 { "before", no_argument, NULL, ARG_BEFORE },
4742 { "show-types", no_argument, NULL, ARG_SHOW_TYPES },
4743 { "failed", no_argument, NULL, ARG_FAILED },
4744 { "full", no_argument, NULL, ARG_FULL },
4745 { "fail", no_argument, NULL, ARG_FAIL },
4746 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4747 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4748 { "ignore-inhibitors", no_argument, NULL, 'i' },
4749 { "user", no_argument, NULL, ARG_USER },
4750 { "system", no_argument, NULL, ARG_SYSTEM },
4751 { "global", no_argument, NULL, ARG_GLOBAL },
4752 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4753 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4754 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4755 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4756 { "quiet", no_argument, NULL, 'q' },
4757 { "root", required_argument, NULL, ARG_ROOT },
4758 { "force", no_argument, NULL, ARG_FORCE },
4759 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4760 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4761 { "signal", required_argument, NULL, 's' },
4762 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4763 { "host", required_argument, NULL, 'H' },
4764 { "privileged",no_argument, NULL, 'P' },
4765 { "runtime", no_argument, NULL, ARG_RUNTIME },
4766 { "lines", required_argument, NULL, 'n' },
4767 { "output", required_argument, NULL, 'o' },
4768 { "plain", no_argument, NULL, ARG_PLAIN },
4769 { NULL, 0, NULL, 0 }
4777 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4786 puts(PACKAGE_STRING);
4787 puts(SYSTEMD_FEATURES);
4794 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4795 _cleanup_free_ char *type;
4797 type = strndup(word, size);
4801 if (streq(type, "help")) {
4806 if (unit_type_from_string(type) >= 0) {
4807 if (strv_push(&arg_types, type))
4813 if (unit_load_state_from_string(optarg) >= 0) {
4814 if (strv_push(&arg_load_states, type))
4820 log_error("Unknown unit type or load state '%s'.", type);
4821 log_info("Use -t help to see a list of allowed values.");
4829 /* Make sure that if the empty property list
4830 was specified, we won't show any properties. */
4831 if (isempty(optarg) && !arg_properties) {
4832 arg_properties = strv_new(NULL, NULL);
4833 if (!arg_properties)
4839 FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
4842 prop = strndup(word, size);
4846 if (strv_push(&arg_properties, prop)) {
4853 /* If the user asked for a particular
4854 * property, show it to him, even if it is
4866 arg_dependency = DEPENDENCY_REVERSE;
4870 arg_dependency = DEPENDENCY_AFTER;
4874 arg_dependency = DEPENDENCY_BEFORE;
4877 case ARG_SHOW_TYPES:
4878 arg_show_types = true;
4882 arg_job_mode = "fail";
4885 case ARG_IRREVERSIBLE:
4886 arg_job_mode = "replace-irreversibly";
4889 case ARG_IGNORE_DEPENDENCIES:
4890 arg_job_mode = "ignore-dependencies";
4894 arg_scope = UNIT_FILE_USER;
4898 arg_scope = UNIT_FILE_SYSTEM;
4902 arg_scope = UNIT_FILE_GLOBAL;
4906 arg_no_block = true;
4910 arg_no_legend = true;
4914 arg_no_pager = true;
4946 arg_no_reload = true;
4950 arg_kill_who = optarg;
4954 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4955 log_error("Failed to parse signal string %s.", optarg);
4960 case ARG_NO_ASK_PASSWORD:
4961 arg_ask_password = false;
4965 arg_transport = TRANSPORT_POLKIT;
4969 arg_transport = TRANSPORT_SSH;
4978 if (safe_atou(optarg, &arg_lines) < 0) {
4979 log_error("Failed to parse lines '%s'", optarg);
4985 arg_output = output_mode_from_string(optarg);
4986 if (arg_output < 0) {
4987 log_error("Unknown output '%s'.", optarg);
4993 arg_ignore_inhibitors = true;
5004 log_error("Unknown option code '%c'.", c);
5009 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
5010 log_error("Cannot access user instance remotely.");
5017 static int halt_parse_argv(int argc, char *argv[]) {
5026 static const struct option options[] = {
5027 { "help", no_argument, NULL, ARG_HELP },
5028 { "halt", no_argument, NULL, ARG_HALT },
5029 { "poweroff", no_argument, NULL, 'p' },
5030 { "reboot", no_argument, NULL, ARG_REBOOT },
5031 { "force", no_argument, NULL, 'f' },
5032 { "wtmp-only", no_argument, NULL, 'w' },
5033 { "no-wtmp", no_argument, NULL, 'd' },
5034 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5035 { NULL, 0, NULL, 0 }
5043 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
5044 if (runlevel == '0' || runlevel == '6')
5047 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
5055 arg_action = ACTION_HALT;
5059 if (arg_action != ACTION_REBOOT)
5060 arg_action = ACTION_POWEROFF;
5064 arg_action = ACTION_REBOOT;
5086 /* Compatibility nops */
5093 log_error("Unknown option code '%c'.", c);
5098 if (optind < argc) {
5099 log_error("Too many arguments.");
5106 static int parse_time_spec(const char *t, usec_t *_u) {
5110 if (streq(t, "now"))
5112 else if (!strchr(t, ':')) {
5115 if (safe_atou64(t, &u) < 0)
5118 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
5127 hour = strtol(t, &e, 10);
5128 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
5131 minute = strtol(e+1, &e, 10);
5132 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
5135 n = now(CLOCK_REALTIME);
5136 s = (time_t) (n / USEC_PER_SEC);
5138 assert_se(localtime_r(&s, &tm));
5140 tm.tm_hour = (int) hour;
5141 tm.tm_min = (int) minute;
5144 assert_se(s = mktime(&tm));
5146 *_u = (usec_t) s * USEC_PER_SEC;
5149 *_u += USEC_PER_DAY;
5155 static int shutdown_parse_argv(int argc, char *argv[]) {
5162 static const struct option options[] = {
5163 { "help", no_argument, NULL, ARG_HELP },
5164 { "halt", no_argument, NULL, 'H' },
5165 { "poweroff", no_argument, NULL, 'P' },
5166 { "reboot", no_argument, NULL, 'r' },
5167 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
5168 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5169 { NULL, 0, NULL, 0 }
5177 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
5185 arg_action = ACTION_HALT;
5189 arg_action = ACTION_POWEROFF;
5194 arg_action = ACTION_KEXEC;
5196 arg_action = ACTION_REBOOT;
5200 arg_action = ACTION_KEXEC;
5204 if (arg_action != ACTION_HALT)
5205 arg_action = ACTION_POWEROFF;
5218 /* Compatibility nops */
5222 arg_action = ACTION_CANCEL_SHUTDOWN;
5229 log_error("Unknown option code '%c'.", c);
5234 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
5235 r = parse_time_spec(argv[optind], &arg_when);
5237 log_error("Failed to parse time specification: %s", argv[optind]);
5241 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
5243 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
5244 /* No time argument for shutdown cancel */
5245 arg_wall = argv + optind;
5246 else if (argc > optind + 1)
5247 /* We skip the time argument */
5248 arg_wall = argv + optind + 1;
5255 static int telinit_parse_argv(int argc, char *argv[]) {
5262 static const struct option options[] = {
5263 { "help", no_argument, NULL, ARG_HELP },
5264 { "no-wall", no_argument, NULL, ARG_NO_WALL },
5265 { NULL, 0, NULL, 0 }
5268 static const struct {
5272 { '0', ACTION_POWEROFF },
5273 { '6', ACTION_REBOOT },
5274 { '1', ACTION_RESCUE },
5275 { '2', ACTION_RUNLEVEL2 },
5276 { '3', ACTION_RUNLEVEL3 },
5277 { '4', ACTION_RUNLEVEL4 },
5278 { '5', ACTION_RUNLEVEL5 },
5279 { 's', ACTION_RESCUE },
5280 { 'S', ACTION_RESCUE },
5281 { 'q', ACTION_RELOAD },
5282 { 'Q', ACTION_RELOAD },
5283 { 'u', ACTION_REEXEC },
5284 { 'U', ACTION_REEXEC }
5293 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5308 log_error("Unknown option code '%c'.", c);
5313 if (optind >= argc) {
5318 if (optind + 1 < argc) {
5319 log_error("Too many arguments.");
5323 if (strlen(argv[optind]) != 1) {
5324 log_error("Expected single character argument.");
5328 for (i = 0; i < ELEMENTSOF(table); i++)
5329 if (table[i].from == argv[optind][0])
5332 if (i >= ELEMENTSOF(table)) {
5333 log_error("Unknown command '%s'.", argv[optind]);
5337 arg_action = table[i].to;
5344 static int runlevel_parse_argv(int argc, char *argv[]) {
5350 static const struct option options[] = {
5351 { "help", no_argument, NULL, ARG_HELP },
5352 { NULL, 0, NULL, 0 }
5360 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5371 log_error("Unknown option code '%c'.", c);
5376 if (optind < argc) {
5377 log_error("Too many arguments.");
5384 static int parse_argv(int argc, char *argv[]) {
5388 if (program_invocation_short_name) {
5390 if (strstr(program_invocation_short_name, "halt")) {
5391 arg_action = ACTION_HALT;
5392 return halt_parse_argv(argc, argv);
5393 } else if (strstr(program_invocation_short_name, "poweroff")) {
5394 arg_action = ACTION_POWEROFF;
5395 return halt_parse_argv(argc, argv);
5396 } else if (strstr(program_invocation_short_name, "reboot")) {
5398 arg_action = ACTION_KEXEC;
5400 arg_action = ACTION_REBOOT;
5401 return halt_parse_argv(argc, argv);
5402 } else if (strstr(program_invocation_short_name, "shutdown")) {
5403 arg_action = ACTION_POWEROFF;
5404 return shutdown_parse_argv(argc, argv);
5405 } else if (strstr(program_invocation_short_name, "init")) {
5407 if (sd_booted() > 0) {
5408 arg_action = ACTION_INVALID;
5409 return telinit_parse_argv(argc, argv);
5411 /* Hmm, so some other init system is
5412 * running, we need to forward this
5413 * request to it. For now we simply
5414 * guess that it is Upstart. */
5416 execv(TELINIT, argv);
5418 log_error("Couldn't find an alternative telinit implementation to spawn.");
5422 } else if (strstr(program_invocation_short_name, "runlevel")) {
5423 arg_action = ACTION_RUNLEVEL;
5424 return runlevel_parse_argv(argc, argv);
5428 arg_action = ACTION_SYSTEMCTL;
5429 return systemctl_parse_argv(argc, argv);
5432 _pure_ static int action_to_runlevel(void) {
5434 static const char table[_ACTION_MAX] = {
5435 [ACTION_HALT] = '0',
5436 [ACTION_POWEROFF] = '0',
5437 [ACTION_REBOOT] = '6',
5438 [ACTION_RUNLEVEL2] = '2',
5439 [ACTION_RUNLEVEL3] = '3',
5440 [ACTION_RUNLEVEL4] = '4',
5441 [ACTION_RUNLEVEL5] = '5',
5442 [ACTION_RESCUE] = '1'
5445 assert(arg_action < _ACTION_MAX);
5447 return table[arg_action];
5450 static int talk_upstart(void) {
5451 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
5452 _cleanup_dbus_error_free_ DBusError error;
5453 int previous, rl, r;
5455 env1_buf[] = "RUNLEVEL=X",
5456 env2_buf[] = "PREVLEVEL=X";
5457 char *env1 = env1_buf, *env2 = env2_buf;
5458 const char *emit = "runlevel";
5459 dbus_bool_t b_false = FALSE;
5460 DBusMessageIter iter, sub;
5461 DBusConnection *bus;
5463 dbus_error_init(&error);
5465 if (!(rl = action_to_runlevel()))
5468 if (utmp_get_runlevel(&previous, NULL) < 0)
5471 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5472 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5477 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5482 if ((r = bus_check_peercred(bus)) < 0) {
5483 log_error("Failed to verify owner of bus.");
5487 if (!(m = dbus_message_new_method_call(
5488 "com.ubuntu.Upstart",
5489 "/com/ubuntu/Upstart",
5490 "com.ubuntu.Upstart0_6",
5493 log_error("Could not allocate message.");
5498 dbus_message_iter_init_append(m, &iter);
5500 env1_buf[sizeof(env1_buf)-2] = rl;
5501 env2_buf[sizeof(env2_buf)-2] = previous;
5503 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5504 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5505 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5506 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5507 !dbus_message_iter_close_container(&iter, &sub) ||
5508 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5509 log_error("Could not append arguments to message.");
5514 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5516 if (bus_error_is_no_service(&error)) {
5521 log_error("Failed to issue method call: %s", bus_error_message(&error));
5530 dbus_connection_flush(bus);
5531 dbus_connection_close(bus);
5532 dbus_connection_unref(bus);
5538 static int talk_initctl(void) {
5539 struct init_request request = {};
5541 _cleanup_close_ int fd = -1;
5544 rl = action_to_runlevel();
5548 request.magic = INIT_MAGIC;
5549 request.sleeptime = 0;
5550 request.cmd = INIT_CMD_RUNLVL;
5551 request.runlevel = rl;
5553 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5555 if (errno == ENOENT)
5558 log_error("Failed to open "INIT_FIFO": %m");
5563 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5565 log_error("Failed to write to "INIT_FIFO": %m");
5566 return errno > 0 ? -errno : -EIO;
5572 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5574 static const struct {
5582 int (* const dispatch)(DBusConnection *bus, char **args);
5584 { "list-units", LESS, 1, list_units },
5585 { "list-unit-files", EQUAL, 1, list_unit_files },
5586 { "list-sockets", LESS, 1, list_sockets },
5587 { "list-jobs", EQUAL, 1, list_jobs },
5588 { "clear-jobs", EQUAL, 1, daemon_reload },
5589 { "load", MORE, 2, load_unit },
5590 { "cancel", MORE, 2, cancel_job },
5591 { "start", MORE, 2, start_unit },
5592 { "stop", MORE, 2, start_unit },
5593 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5594 { "reload", MORE, 2, start_unit },
5595 { "restart", MORE, 2, start_unit },
5596 { "try-restart", MORE, 2, start_unit },
5597 { "reload-or-restart", MORE, 2, start_unit },
5598 { "reload-or-try-restart", MORE, 2, start_unit },
5599 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5600 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5601 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5602 { "isolate", EQUAL, 2, start_unit },
5603 { "set-cgroup", MORE, 3, set_cgroup },
5604 { "unset-cgroup", MORE, 3, set_cgroup },
5605 { "get-cgroup-attr", MORE, 3, get_cgroup_attr },
5606 { "set-cgroup-attr", MORE, 4, set_cgroup_attr },
5607 { "unset-cgroup-attr", MORE, 3, set_cgroup },
5608 { "kill", MORE, 2, kill_unit },
5609 { "is-active", MORE, 2, check_unit_active },
5610 { "check", MORE, 2, check_unit_active },
5611 { "is-failed", MORE, 2, check_unit_failed },
5612 { "show", MORE, 1, show },
5613 { "status", MORE, 1, show },
5614 { "help", MORE, 2, show },
5615 { "dump", EQUAL, 1, dump },
5616 { "snapshot", LESS, 2, snapshot },
5617 { "delete", MORE, 2, delete_snapshot },
5618 { "daemon-reload", EQUAL, 1, daemon_reload },
5619 { "daemon-reexec", EQUAL, 1, daemon_reload },
5620 { "show-environment", EQUAL, 1, show_enviroment },
5621 { "set-environment", MORE, 2, set_environment },
5622 { "unset-environment", MORE, 2, set_environment },
5623 { "halt", EQUAL, 1, start_special },
5624 { "poweroff", EQUAL, 1, start_special },
5625 { "reboot", EQUAL, 1, start_special },
5626 { "kexec", EQUAL, 1, start_special },
5627 { "suspend", EQUAL, 1, start_special },
5628 { "hibernate", EQUAL, 1, start_special },
5629 { "hybrid-sleep", EQUAL, 1, start_special },
5630 { "default", EQUAL, 1, start_special },
5631 { "rescue", EQUAL, 1, start_special },
5632 { "emergency", EQUAL, 1, start_special },
5633 { "exit", EQUAL, 1, start_special },
5634 { "reset-failed", MORE, 1, reset_failed },
5635 { "enable", MORE, 2, enable_unit },
5636 { "disable", MORE, 2, enable_unit },
5637 { "is-enabled", MORE, 2, unit_is_enabled },
5638 { "reenable", MORE, 2, enable_unit },
5639 { "preset", MORE, 2, enable_unit },
5640 { "mask", MORE, 2, enable_unit },
5641 { "unmask", MORE, 2, enable_unit },
5642 { "link", MORE, 2, enable_unit },
5643 { "switch-root", MORE, 2, switch_root },
5644 { "list-dependencies", LESS, 2, list_dependencies },
5654 left = argc - optind;
5657 /* Special rule: no arguments means "list-units" */
5660 if (streq(argv[optind], "help") && !argv[optind+1]) {
5661 log_error("This command expects one or more "
5662 "unit names. Did you mean --help?");
5666 for (i = 0; i < ELEMENTSOF(verbs); i++)
5667 if (streq(argv[optind], verbs[i].verb))
5670 if (i >= ELEMENTSOF(verbs)) {
5671 log_error("Unknown operation '%s'.", argv[optind]);
5676 switch (verbs[i].argc_cmp) {
5679 if (left != verbs[i].argc) {
5680 log_error("Invalid number of arguments.");
5687 if (left < verbs[i].argc) {
5688 log_error("Too few arguments.");
5695 if (left > verbs[i].argc) {
5696 log_error("Too many arguments.");
5703 assert_not_reached("Unknown comparison operator.");
5706 /* Require a bus connection for all operations but
5708 if (!streq(verbs[i].verb, "enable") &&
5709 !streq(verbs[i].verb, "disable") &&
5710 !streq(verbs[i].verb, "is-enabled") &&
5711 !streq(verbs[i].verb, "list-unit-files") &&
5712 !streq(verbs[i].verb, "reenable") &&
5713 !streq(verbs[i].verb, "preset") &&
5714 !streq(verbs[i].verb, "mask") &&
5715 !streq(verbs[i].verb, "unmask") &&
5716 !streq(verbs[i].verb, "link")) {
5718 if (running_in_chroot() > 0) {
5719 log_info("Running in chroot, ignoring request.");
5723 if (((!streq(verbs[i].verb, "reboot") &&
5724 !streq(verbs[i].verb, "halt") &&
5725 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5726 log_error("Failed to get D-Bus connection: %s",
5727 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5733 if (!bus && !avoid_bus()) {
5734 log_error("Failed to get D-Bus connection: %s",
5735 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5740 return verbs[i].dispatch(bus, argv + optind);
5743 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5744 _cleanup_close_ int fd;
5745 struct sd_shutdown_command c = {
5751 union sockaddr_union sockaddr = {
5752 .un.sun_family = AF_UNIX,
5753 .un.sun_path = "/run/systemd/shutdownd",
5755 struct iovec iovec[2] = {
5756 {.iov_base = (char*) &c,
5757 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
5760 struct msghdr msghdr = {
5761 .msg_name = &sockaddr,
5762 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
5763 + sizeof("/run/systemd/shutdownd") - 1,
5768 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5772 if (!isempty(message)) {
5773 iovec[1].iov_base = (char*) message;
5774 iovec[1].iov_len = strlen(message);
5775 msghdr.msg_iovlen++;
5778 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5784 static int reload_with_fallback(DBusConnection *bus) {
5787 /* First, try systemd via D-Bus. */
5788 if (daemon_reload(bus, NULL) >= 0)
5792 /* Nothing else worked, so let's try signals */
5793 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5795 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5796 log_error("kill() failed: %m");
5803 static int start_with_fallback(DBusConnection *bus) {
5806 /* First, try systemd via D-Bus. */
5807 if (start_unit(bus, NULL) >= 0)
5811 /* Hmm, talking to systemd via D-Bus didn't work. Then
5812 * let's try to talk to Upstart via D-Bus. */
5813 if (talk_upstart() > 0)
5816 /* Nothing else worked, so let's try
5818 if (talk_initctl() > 0)
5821 log_error("Failed to talk to init daemon.");
5825 warn_wall(arg_action);
5829 static _noreturn_ void halt_now(enum action a) {
5831 /* Make sure C-A-D is handled by the kernel from this
5833 reboot(RB_ENABLE_CAD);
5838 log_info("Halting.");
5839 reboot(RB_HALT_SYSTEM);
5842 case ACTION_POWEROFF:
5843 log_info("Powering off.");
5844 reboot(RB_POWER_OFF);
5848 log_info("Rebooting.");
5849 reboot(RB_AUTOBOOT);
5853 assert_not_reached("Unknown halt action.");
5856 assert_not_reached("Uh? This shouldn't happen.");
5859 static int halt_main(DBusConnection *bus) {
5862 r = check_inhibitors(bus, arg_action);
5866 if (geteuid() != 0) {
5867 /* Try logind if we are a normal user and no special
5868 * mode applies. Maybe PolicyKit allows us to shutdown
5871 if (arg_when <= 0 &&
5874 (arg_action == ACTION_POWEROFF ||
5875 arg_action == ACTION_REBOOT)) {
5876 r = reboot_with_logind(bus, arg_action);
5881 log_error("Must be root.");
5886 _cleanup_free_ char *m;
5888 m = strv_join(arg_wall, " ");
5889 r = send_shutdownd(arg_when,
5890 arg_action == ACTION_HALT ? 'H' :
5891 arg_action == ACTION_POWEROFF ? 'P' :
5892 arg_action == ACTION_KEXEC ? 'K' :
5899 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5901 char date[FORMAT_TIMESTAMP_MAX];
5903 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5904 format_timestamp(date, sizeof(date), arg_when));
5909 if (!arg_dry && !arg_force)
5910 return start_with_fallback(bus);
5913 if (sd_booted() > 0)
5914 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5916 r = utmp_put_shutdown();
5918 log_warning("Failed to write utmp record: %s", strerror(-r));
5925 halt_now(arg_action);
5926 /* We should never reach this. */
5930 static int runlevel_main(void) {
5931 int r, runlevel, previous;
5933 r = utmp_get_runlevel(&runlevel, &previous);
5940 previous <= 0 ? 'N' : previous,
5941 runlevel <= 0 ? 'N' : runlevel);
5946 int main(int argc, char*argv[]) {
5947 int r, retval = EXIT_FAILURE;
5948 DBusConnection *bus = NULL;
5949 _cleanup_dbus_error_free_ DBusError error;
5951 dbus_error_init(&error);
5953 setlocale(LC_ALL, "");
5954 log_parse_environment();
5957 r = parse_argv(argc, argv);
5961 retval = EXIT_SUCCESS;
5965 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5966 * let's shortcut this */
5967 if (arg_action == ACTION_RUNLEVEL) {
5968 r = runlevel_main();
5969 retval = r < 0 ? EXIT_FAILURE : r;
5973 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5974 log_info("Running in chroot, ignoring request.");
5980 if (arg_transport == TRANSPORT_NORMAL)
5981 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5982 else if (arg_transport == TRANSPORT_POLKIT) {
5983 bus_connect_system_polkit(&bus, &error);
5984 private_bus = false;
5985 } else if (arg_transport == TRANSPORT_SSH) {
5986 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5987 private_bus = false;
5989 assert_not_reached("Uh, invalid transport...");
5992 switch (arg_action) {
5994 case ACTION_SYSTEMCTL:
5995 r = systemctl_main(bus, argc, argv, &error);
5999 case ACTION_POWEROFF:
6005 case ACTION_RUNLEVEL2:
6006 case ACTION_RUNLEVEL3:
6007 case ACTION_RUNLEVEL4:
6008 case ACTION_RUNLEVEL5:
6010 case ACTION_EMERGENCY:
6011 case ACTION_DEFAULT:
6012 r = start_with_fallback(bus);
6017 r = reload_with_fallback(bus);
6020 case ACTION_CANCEL_SHUTDOWN: {
6024 m = strv_join(arg_wall, " ");
6026 retval = EXIT_FAILURE;
6030 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
6032 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
6037 case ACTION_INVALID:
6038 case ACTION_RUNLEVEL:
6040 assert_not_reached("Unknown action");
6043 retval = r < 0 ? EXIT_FAILURE : r;
6047 dbus_connection_flush(bus);
6048 dbus_connection_close(bus);
6049 dbus_connection_unref(bus);
6054 strv_free(arg_types);
6055 strv_free(arg_load_states);
6056 strv_free(arg_properties);
6059 ask_password_agent_close();
6060 polkit_agent_close();