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"
70 static const char *arg_type = NULL;
71 static const char *arg_load_state = NULL;
72 static char **arg_property = NULL;
73 static bool arg_all = false;
74 static const char *arg_job_mode = "replace";
75 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
76 static bool arg_no_block = false;
77 static bool arg_no_legend = false;
78 static bool arg_no_pager = false;
79 static bool arg_no_wtmp = false;
80 static bool arg_no_wall = false;
81 static bool arg_no_reload = false;
82 static bool arg_ignore_inhibitors = false;
83 static bool arg_dry = false;
84 static bool arg_quiet = false;
85 static bool arg_full = false;
86 static int arg_force = 0;
87 static bool arg_ask_password = true;
88 static bool arg_failed = false;
89 static bool arg_runtime = false;
90 static char **arg_wall = NULL;
91 static const char *arg_kill_who = NULL;
92 static int arg_signal = SIGTERM;
93 static const char *arg_root = NULL;
94 static usec_t arg_when = 0;
116 ACTION_CANCEL_SHUTDOWN,
118 } arg_action = ACTION_SYSTEMCTL;
119 static enum transport {
123 } arg_transport = TRANSPORT_NORMAL;
124 static const char *arg_host = NULL;
125 static unsigned arg_lines = 10;
126 static OutputMode arg_output = OUTPUT_SHORT;
128 static bool private_bus = false;
130 static int daemon_reload(DBusConnection *bus, char **args);
131 static void halt_now(enum action a);
133 static void pager_open_if_enabled(void) {
141 static void ask_password_agent_open_if_enabled(void) {
143 /* Open the password agent as a child process if necessary */
145 if (!arg_ask_password)
148 if (arg_scope != UNIT_FILE_SYSTEM)
151 ask_password_agent_open();
155 static void polkit_agent_open_if_enabled(void) {
157 /* Open the polkit agent as a child process if necessary */
159 if (!arg_ask_password)
162 if (arg_scope != UNIT_FILE_SYSTEM)
169 static const char *ansi_highlight(bool b) {
174 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
177 static const char *ansi_highlight_red(bool b) {
182 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
185 static const char *ansi_highlight_green(bool b) {
190 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
193 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
196 if (!dbus_error_is_set(error))
199 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
200 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
201 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
202 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
203 return EXIT_NOPERMISSION;
205 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
206 return EXIT_NOTINSTALLED;
208 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
209 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
210 return EXIT_NOTIMPLEMENTED;
212 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
213 return EXIT_NOTCONFIGURED;
221 static void warn_wall(enum action a) {
222 static const char *table[_ACTION_MAX] = {
223 [ACTION_HALT] = "The system is going down for system halt NOW!",
224 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
225 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
226 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
227 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
228 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
229 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
236 _cleanup_free_ char *p;
238 p = strv_join(arg_wall, " ");
253 utmp_wall(table[a], NULL);
256 static bool avoid_bus(void) {
258 if (running_in_chroot() > 0)
261 if (sd_booted() <= 0)
264 if (!isempty(arg_root))
267 if (arg_scope == UNIT_FILE_GLOBAL)
273 static int compare_unit_info(const void *a, const void *b) {
275 const struct unit_info *u = a, *v = b;
277 d1 = strrchr(u->id, '.');
278 d2 = strrchr(v->id, '.');
283 r = strcasecmp(d1, d2);
288 return strcasecmp(u->id, v->id);
291 static bool output_show_unit(const struct unit_info *u) {
295 return streq(u->active_state, "failed");
297 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
298 streq(dot+1, arg_type))) &&
299 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
300 (arg_all || !(streq(u->active_state, "inactive")
301 || u->following[0]) || u->job_id > 0);
304 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
305 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
306 const struct unit_info *u;
309 max_id_len = sizeof("UNIT")-1;
310 active_len = sizeof("ACTIVE")-1;
311 sub_len = sizeof("SUB")-1;
312 job_len = sizeof("JOB")-1;
315 for (u = unit_infos; u < unit_infos + c; u++) {
316 if (!output_show_unit(u))
319 max_id_len = MAX(max_id_len, strlen(u->id));
320 active_len = MAX(active_len, strlen(u->active_state));
321 sub_len = MAX(sub_len, strlen(u->sub_state));
322 if (u->job_id != 0) {
323 job_len = MAX(job_len, strlen(u->job_type));
330 id_len = MIN(max_id_len, 25);
331 basic_len = 5 + id_len + 5 + active_len + sub_len;
333 basic_len += job_len + 1;
334 if (basic_len < (unsigned) columns()) {
335 unsigned extra_len, incr;
336 extra_len = columns() - basic_len;
337 /* Either UNIT already got 25, or is fully satisfied.
338 * Grant up to 25 to DESC now. */
339 incr = MIN(extra_len, 25);
342 /* split the remaining space between UNIT and DESC,
343 * but do not give UNIT more than it needs. */
345 incr = MIN(extra_len / 2, max_id_len - id_len);
347 desc_len += extra_len - incr;
353 for (u = unit_infos; u < unit_infos + c; u++) {
355 const char *on_loaded, *off_loaded;
356 const char *on_active, *off_active;
358 if (!output_show_unit(u))
361 if (!n_shown && !arg_no_legend) {
362 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
363 active_len, "ACTIVE", sub_len, "SUB");
365 printf("%-*s ", job_len, "JOB");
366 if (!arg_full && arg_no_pager)
367 printf("%.*s\n", desc_len, "DESCRIPTION");
369 printf("%s\n", "DESCRIPTION");
374 if (streq(u->load_state, "error")) {
375 on_loaded = ansi_highlight_red(true);
376 off_loaded = ansi_highlight_red(false);
378 on_loaded = off_loaded = "";
380 if (streq(u->active_state, "failed")) {
381 on_active = ansi_highlight_red(true);
382 off_active = ansi_highlight_red(false);
384 on_active = off_active = "";
386 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
388 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s",
389 id_len, e ? e : u->id,
390 on_loaded, u->load_state, off_loaded,
391 on_active, active_len, u->active_state,
392 sub_len, u->sub_state, off_active,
393 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
394 if (!arg_full && arg_no_pager)
395 printf("%.*s\n", desc_len, u->description);
397 printf("%s\n", u->description);
402 if (!arg_no_legend) {
403 const char *on, *off;
406 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
407 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
408 "SUB = The low-level unit activation state, values depend on unit type.\n");
410 printf("JOB = Pending job for the unit.\n");
412 on = ansi_highlight(true);
413 off = ansi_highlight(false);
415 on = ansi_highlight_red(true);
416 off = ansi_highlight_red(false);
420 printf("%s%u loaded units listed.%s\n"
421 "To show all installed unit files use 'systemctl list-unit-files'.\n",
424 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
425 "To show all installed unit files use 'systemctl list-unit-files'.\n",
430 static int list_units(DBusConnection *bus, char **args) {
431 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
432 _cleanup_free_ struct unit_info *unit_infos = NULL;
433 DBusMessageIter iter, sub;
434 unsigned c = 0, n_units = 0;
437 pager_open_if_enabled();
439 r = bus_method_call_with_reply(
441 "org.freedesktop.systemd1",
442 "/org/freedesktop/systemd1",
443 "org.freedesktop.systemd1.Manager",
451 if (!dbus_message_iter_init(reply, &iter) ||
452 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
453 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
454 log_error("Failed to parse reply.");
458 dbus_message_iter_recurse(&iter, &sub);
460 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
466 n_units = MAX(2*c, 16);
467 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
476 bus_parse_unit_info(&sub, u);
478 dbus_message_iter_next(&sub);
483 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
484 output_units_list(unit_infos, c);
490 static int compare_unit_file_list(const void *a, const void *b) {
492 const UnitFileList *u = a, *v = b;
494 d1 = strrchr(u->path, '.');
495 d2 = strrchr(v->path, '.');
500 r = strcasecmp(d1, d2);
505 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
508 static bool output_show_unit_file(const UnitFileList *u) {
511 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
514 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
515 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
516 const UnitFileList *u;
518 max_id_len = sizeof("UNIT FILE")-1;
519 state_cols = sizeof("STATE")-1;
520 for (u = units; u < units + c; u++) {
521 if (!output_show_unit_file(u))
524 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
525 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
530 id_cols = MIN(max_id_len, 25);
531 basic_cols = 1 + id_cols + state_cols;
532 if (basic_cols < (unsigned) columns())
533 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
535 id_cols = max_id_len;
538 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
540 for (u = units; u < units + c; u++) {
542 const char *on, *off;
545 if (!output_show_unit_file(u))
550 if (u->state == UNIT_FILE_MASKED ||
551 u->state == UNIT_FILE_MASKED_RUNTIME ||
552 u->state == UNIT_FILE_DISABLED ||
553 u->state == UNIT_FILE_INVALID) {
554 on = ansi_highlight_red(true);
555 off = ansi_highlight_red(false);
556 } else if (u->state == UNIT_FILE_ENABLED) {
557 on = ansi_highlight_green(true);
558 off = ansi_highlight_green(false);
562 id = path_get_file_name(u->path);
564 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
566 printf("%-*s %s%-*s%s\n",
568 on, state_cols, unit_file_state_to_string(u->state), off);
574 printf("\n%u unit files listed.\n", n_shown);
577 static int list_unit_files(DBusConnection *bus, char **args) {
578 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
579 _cleanup_free_ UnitFileList *units = NULL;
580 DBusMessageIter iter, sub, sub2;
581 unsigned c = 0, n_units = 0;
584 pager_open_if_enabled();
591 h = hashmap_new(string_hash_func, string_compare_func);
595 r = unit_file_get_list(arg_scope, arg_root, h);
597 unit_file_list_free(h);
598 log_error("Failed to get unit file list: %s", strerror(-r));
602 n_units = hashmap_size(h);
603 units = new(UnitFileList, n_units);
605 unit_file_list_free(h);
609 HASHMAP_FOREACH(u, h, i) {
610 memcpy(units + c++, u, sizeof(UnitFileList));
616 r = bus_method_call_with_reply(
618 "org.freedesktop.systemd1",
619 "/org/freedesktop/systemd1",
620 "org.freedesktop.systemd1.Manager",
628 if (!dbus_message_iter_init(reply, &iter) ||
629 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
630 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
631 log_error("Failed to parse reply.");
635 dbus_message_iter_recurse(&iter, &sub);
637 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
641 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
646 n_units = MAX(2*c, 16);
647 w = realloc(units, sizeof(struct UnitFileList) * n_units);
656 dbus_message_iter_recurse(&sub, &sub2);
658 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
659 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
660 log_error("Failed to parse reply.");
664 u->state = unit_file_state_from_string(state);
666 dbus_message_iter_next(&sub);
672 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
673 output_unit_file_list(units, c);
679 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
681 _cleanup_free_ char *n = NULL;
683 size_t max_len = MAX(columns(),20);
685 for (i = level - 1; i >= 0; i--) {
687 if(len > max_len - 3 && !arg_full) {
688 printf("%s...\n",max_len % 2 ? "" : " ");
691 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
694 if(len > max_len - 3 && !arg_full) {
695 printf("%s...\n",max_len % 2 ? "" : " ");
698 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
701 printf("%s\n", name);
705 n = ellipsize(name, max_len-len, 100);
713 static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
714 static const char dependencies[] =
716 "RequiresOverridable\0"
718 "RequisiteOverridable\0"
721 _cleanup_free_ char *path;
722 const char *interface = "org.freedesktop.systemd1.Unit";
724 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
725 DBusMessageIter iter, sub, sub2, sub3;
734 path = unit_dbus_path_from_name(name);
740 r = bus_method_call_with_reply(
742 "org.freedesktop.systemd1",
744 "org.freedesktop.DBus.Properties",
748 DBUS_TYPE_STRING, &interface,
753 if (!dbus_message_iter_init(reply, &iter) ||
754 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
755 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
756 log_error("Failed to parse reply.");
761 dbus_message_iter_recurse(&iter, &sub);
763 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
766 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
767 dbus_message_iter_recurse(&sub, &sub2);
769 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
770 log_error("Failed to parse reply.");
775 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
776 log_error("Failed to parse reply.");
781 dbus_message_iter_recurse(&sub2, &sub3);
782 dbus_message_iter_next(&sub);
784 if (!nulstr_contains(dependencies, prop))
787 if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
788 if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
789 DBusMessageIter sub4;
790 dbus_message_iter_recurse(&sub3, &sub4);
792 while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
795 assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
796 dbus_message_iter_get_basic(&sub4, &s);
798 r = strv_extend(&ret, s);
804 dbus_message_iter_next(&sub4);
817 static int list_dependencies_compare(const void *_a, const void *_b) {
818 const char **a = (const char**) _a, **b = (const char**) _b;
819 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
821 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
823 return strcasecmp(*a, *b);
826 static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char **units, unsigned int branches) {
832 u = strv_append(units, name);
836 r = list_dependencies_get_dependencies(bus, name, &deps);
840 qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
842 STRV_FOREACH(c, deps) {
843 if (strv_contains(u, *c)) {
844 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
850 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
854 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
855 r = list_dependencies_one(bus, *c, level + 1, u, (branches << 1) | (c[1] == NULL ? 0 : 1));
868 static int list_dependencies(DBusConnection *bus, char **args) {
869 _cleanup_free_ char *unit = NULL;
875 unit = unit_name_mangle(args[1]);
880 u = SPECIAL_DEFAULT_TARGET;
882 pager_open_if_enabled();
886 return list_dependencies_one(bus, u, 0, NULL, 0);
889 static int list_jobs(DBusConnection *bus, char **args) {
890 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
891 DBusMessageIter iter, sub, sub2;
895 pager_open_if_enabled();
897 r = bus_method_call_with_reply(
899 "org.freedesktop.systemd1",
900 "/org/freedesktop/systemd1",
901 "org.freedesktop.systemd1.Manager",
909 if (!dbus_message_iter_init(reply, &iter) ||
910 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
911 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
912 log_error("Failed to parse reply.");
916 dbus_message_iter_recurse(&iter, &sub);
919 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
921 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
922 const char *name, *type, *state, *job_path, *unit_path;
926 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
927 log_error("Failed to parse reply.");
931 dbus_message_iter_recurse(&sub, &sub2);
933 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
934 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
935 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
936 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
937 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
938 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
939 log_error("Failed to parse reply.");
943 e = arg_full ? NULL : ellipsize(name, 25, 33);
944 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
949 dbus_message_iter_next(&sub);
953 printf("\n%u jobs listed.\n", k);
958 static int load_unit(DBusConnection *bus, char **args) {
963 STRV_FOREACH(name, args+1) {
964 _cleanup_free_ char *n = NULL;
967 n = unit_name_mangle(*name);
971 r = bus_method_call_with_reply(
973 "org.freedesktop.systemd1",
974 "/org/freedesktop/systemd1",
975 "org.freedesktop.systemd1.Manager",
979 DBUS_TYPE_STRING, &n,
988 static int cancel_job(DBusConnection *bus, char **args) {
993 if (strv_length(args) <= 1)
994 return daemon_reload(bus, args);
996 STRV_FOREACH(name, args+1) {
1000 r = safe_atou32(*name, &id);
1002 log_error("Failed to parse job id: %s", strerror(-r));
1006 r = bus_method_call_with_reply(
1008 "org.freedesktop.systemd1",
1009 "/org/freedesktop/systemd1",
1010 "org.freedesktop.systemd1.Manager",
1014 DBUS_TYPE_UINT32, &id,
1023 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1024 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1025 dbus_bool_t b = FALSE;
1026 DBusMessageIter iter, sub;
1028 *interface = "org.freedesktop.systemd1.Unit",
1029 *property = "NeedDaemonReload",
1031 _cleanup_free_ char *n = NULL;
1034 /* We ignore all errors here, since this is used to show a warning only */
1036 n = unit_name_mangle(unit);
1040 r = bus_method_call_with_reply (
1042 "org.freedesktop.systemd1",
1043 "/org/freedesktop/systemd1",
1044 "org.freedesktop.systemd1.Manager",
1048 DBUS_TYPE_STRING, &n,
1053 if (!dbus_message_get_args(reply, NULL,
1054 DBUS_TYPE_OBJECT_PATH, &path,
1058 dbus_message_unref(reply);
1061 r = bus_method_call_with_reply(
1063 "org.freedesktop.systemd1",
1065 "org.freedesktop.DBus.Properties",
1069 DBUS_TYPE_STRING, &interface,
1070 DBUS_TYPE_STRING, &property,
1075 if (!dbus_message_iter_init(reply, &iter) ||
1076 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1079 dbus_message_iter_recurse(&iter, &sub);
1080 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1083 dbus_message_iter_get_basic(&sub, &b);
1087 typedef struct WaitData {
1094 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1102 dbus_error_init(&error);
1104 log_debug("Got D-Bus request: %s.%s() on %s",
1105 dbus_message_get_interface(message),
1106 dbus_message_get_member(message),
1107 dbus_message_get_path(message));
1109 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1110 log_error("Warning! D-Bus connection terminated.");
1111 dbus_connection_close(connection);
1113 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1115 const char *path, *result, *unit;
1117 if (dbus_message_get_args(message, &error,
1118 DBUS_TYPE_UINT32, &id,
1119 DBUS_TYPE_OBJECT_PATH, &path,
1120 DBUS_TYPE_STRING, &unit,
1121 DBUS_TYPE_STRING, &result,
1122 DBUS_TYPE_INVALID)) {
1124 free(set_remove(d->set, (char*) path));
1126 if (!isempty(result))
1127 d->result = strdup(result);
1130 d->name = strdup(unit);
1135 dbus_error_free(&error);
1136 if (dbus_message_get_args(message, &error,
1137 DBUS_TYPE_UINT32, &id,
1138 DBUS_TYPE_OBJECT_PATH, &path,
1139 DBUS_TYPE_STRING, &result,
1140 DBUS_TYPE_INVALID)) {
1141 /* Compatibility with older systemd versions <
1142 * 183 during upgrades. This should be dropped
1144 free(set_remove(d->set, (char*) path));
1147 d->result = strdup(result);
1153 log_error("Failed to parse message: %s", bus_error_message(&error));
1157 dbus_error_free(&error);
1158 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1161 static int enable_wait_for_jobs(DBusConnection *bus) {
1169 dbus_error_init(&error);
1170 dbus_bus_add_match(bus,
1172 "sender='org.freedesktop.systemd1',"
1173 "interface='org.freedesktop.systemd1.Manager',"
1174 "member='JobRemoved',"
1175 "path='/org/freedesktop/systemd1'",
1178 if (dbus_error_is_set(&error)) {
1179 log_error("Failed to add match: %s", bus_error_message(&error));
1180 dbus_error_free(&error);
1184 /* This is slightly dirty, since we don't undo the match registrations. */
1188 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1198 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1201 while (!set_isempty(s)) {
1203 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1204 log_error("Disconnected from bus.");
1205 return -ECONNREFUSED;
1212 if (streq(d.result, "timeout"))
1213 log_error("Job for %s timed out.", strna(d.name));
1214 else if (streq(d.result, "canceled"))
1215 log_error("Job for %s canceled.", strna(d.name));
1216 else if (streq(d.result, "dependency"))
1217 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1218 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1219 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1222 if (streq_ptr(d.result, "timeout"))
1224 else if (streq_ptr(d.result, "canceled"))
1226 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1237 dbus_connection_remove_filter(bus, wait_filter, &d);
1241 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1242 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1243 _cleanup_free_ char *n = NULL;
1244 DBusMessageIter iter, sub;
1246 *interface = "org.freedesktop.systemd1.Unit",
1247 *property = "ActiveState";
1248 const char *state, *path;
1254 dbus_error_init(&error);
1256 n = unit_name_mangle(name);
1260 r = bus_method_call_with_reply (
1262 "org.freedesktop.systemd1",
1263 "/org/freedesktop/systemd1",
1264 "org.freedesktop.systemd1.Manager",
1268 DBUS_TYPE_STRING, &n,
1271 dbus_error_free(&error);
1278 if (!dbus_message_get_args(reply, NULL,
1279 DBUS_TYPE_OBJECT_PATH, &path,
1280 DBUS_TYPE_INVALID)) {
1281 log_error("Failed to parse reply.");
1285 dbus_message_unref(reply);
1288 r = bus_method_call_with_reply(
1290 "org.freedesktop.systemd1",
1292 "org.freedesktop.DBus.Properties",
1296 DBUS_TYPE_STRING, &interface,
1297 DBUS_TYPE_STRING, &property,
1305 if (!dbus_message_iter_init(reply, &iter) ||
1306 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1307 log_error("Failed to parse reply.");
1311 dbus_message_iter_recurse(&iter, &sub);
1313 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1314 log_error("Failed to parse reply.");
1318 dbus_message_iter_get_basic(&sub, &state);
1323 return strv_find(check_states, state) ? 1 : 0;
1326 static void check_triggering_units(
1327 DBusConnection *bus,
1328 const char *unit_name) {
1330 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1331 DBusMessageIter iter, sub;
1332 const char *interface = "org.freedesktop.systemd1.Unit",
1333 *triggered_by_property = "TriggeredBy";
1334 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1335 bool print_warning_label = true;
1338 n = unit_name_mangle(unit_name);
1344 unit_path = unit_dbus_path_from_name(n);
1350 r = bus_method_call_with_reply(
1352 "org.freedesktop.systemd1",
1354 "org.freedesktop.DBus.Properties",
1358 DBUS_TYPE_STRING, &interface,
1359 DBUS_TYPE_STRING, &triggered_by_property,
1364 if (!dbus_message_iter_init(reply, &iter) ||
1365 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1366 log_error("Failed to parse reply.");
1370 dbus_message_iter_recurse(&iter, &sub);
1371 dbus_message_iter_recurse(&sub, &iter);
1374 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1375 const char * const check_states[] = {
1380 const char *service_trigger;
1382 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1383 log_error("Failed to parse reply.");
1387 dbus_message_iter_get_basic(&sub, &service_trigger);
1389 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1393 if (print_warning_label) {
1394 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1395 print_warning_label = false;
1398 log_warning(" %s", service_trigger);
1401 dbus_message_iter_next(&sub);
1405 static int start_unit_one(
1406 DBusConnection *bus,
1413 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1414 _cleanup_free_ char *n;
1423 n = unit_name_mangle(name);
1427 r = bus_method_call_with_reply(
1429 "org.freedesktop.systemd1",
1430 "/org/freedesktop/systemd1",
1431 "org.freedesktop.systemd1.Manager",
1435 DBUS_TYPE_STRING, &n,
1436 DBUS_TYPE_STRING, &mode,
1439 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1440 /* There's always a fallback possible for
1441 * legacy actions. */
1444 log_error("Failed to issue method call: %s", bus_error_message(error));
1449 if (!dbus_message_get_args(reply, error,
1450 DBUS_TYPE_OBJECT_PATH, &path,
1451 DBUS_TYPE_INVALID)) {
1452 log_error("Failed to parse reply: %s", bus_error_message(error));
1456 if (need_daemon_reload(bus, n))
1457 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1458 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1470 log_error("Failed to add path to set.");
1478 static enum action verb_to_action(const char *verb) {
1479 if (streq(verb, "halt"))
1481 else if (streq(verb, "poweroff"))
1482 return ACTION_POWEROFF;
1483 else if (streq(verb, "reboot"))
1484 return ACTION_REBOOT;
1485 else if (streq(verb, "kexec"))
1486 return ACTION_KEXEC;
1487 else if (streq(verb, "rescue"))
1488 return ACTION_RESCUE;
1489 else if (streq(verb, "emergency"))
1490 return ACTION_EMERGENCY;
1491 else if (streq(verb, "default"))
1492 return ACTION_DEFAULT;
1493 else if (streq(verb, "exit"))
1495 else if (streq(verb, "suspend"))
1496 return ACTION_SUSPEND;
1497 else if (streq(verb, "hibernate"))
1498 return ACTION_HIBERNATE;
1499 else if (streq(verb, "hybrid-sleep"))
1500 return ACTION_HYBRID_SLEEP;
1502 return ACTION_INVALID;
1505 static int start_unit(DBusConnection *bus, char **args) {
1507 static const char * const table[_ACTION_MAX] = {
1508 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1509 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1510 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1511 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1512 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1513 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1514 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1515 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1516 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1517 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1518 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1519 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1520 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1521 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
1522 [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
1526 const char *method, *mode, *one_name;
1531 dbus_error_init(&error);
1535 ask_password_agent_open_if_enabled();
1537 if (arg_action == ACTION_SYSTEMCTL) {
1539 streq(args[0], "stop") ||
1540 streq(args[0], "condstop") ? "StopUnit" :
1541 streq(args[0], "reload") ? "ReloadUnit" :
1542 streq(args[0], "restart") ? "RestartUnit" :
1544 streq(args[0], "try-restart") ||
1545 streq(args[0], "condrestart") ? "TryRestartUnit" :
1547 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1549 streq(args[0], "reload-or-try-restart") ||
1550 streq(args[0], "condreload") ||
1552 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1556 (streq(args[0], "isolate") ||
1557 streq(args[0], "rescue") ||
1558 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1560 one_name = table[verb_to_action(args[0])];
1563 assert(arg_action < ELEMENTSOF(table));
1564 assert(table[arg_action]);
1566 method = "StartUnit";
1568 mode = (arg_action == ACTION_EMERGENCY ||
1569 arg_action == ACTION_RESCUE ||
1570 arg_action == ACTION_RUNLEVEL2 ||
1571 arg_action == ACTION_RUNLEVEL3 ||
1572 arg_action == ACTION_RUNLEVEL4 ||
1573 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1575 one_name = table[arg_action];
1578 if (!arg_no_block) {
1579 ret = enable_wait_for_jobs(bus);
1581 log_error("Could not watch jobs: %s", strerror(-ret));
1585 s = set_new(string_hash_func, string_compare_func);
1593 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1595 ret = translate_bus_error_to_exit_status(ret, &error);
1597 STRV_FOREACH(name, args+1) {
1598 r = start_unit_one(bus, method, *name, mode, &error, s);
1600 ret = translate_bus_error_to_exit_status(r, &error);
1601 dbus_error_free(&error);
1606 if (!arg_no_block) {
1607 r = wait_for_jobs(bus, s);
1613 /* When stopping units, warn if they can still be triggered by
1614 * another active unit (socket, path, timer) */
1615 if (!arg_quiet && streq(method, "StopUnit")) {
1617 check_triggering_units(bus, one_name);
1619 STRV_FOREACH(name, args+1)
1620 check_triggering_units(bus, *name);
1626 dbus_error_free(&error);
1631 /* Ask systemd-logind, which might grant access to unprivileged users
1632 * through PolicyKit */
1633 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1636 dbus_bool_t interactive = true;
1641 polkit_agent_open_if_enabled();
1649 case ACTION_POWEROFF:
1650 method = "PowerOff";
1653 case ACTION_SUSPEND:
1657 case ACTION_HIBERNATE:
1658 method = "Hibernate";
1661 case ACTION_HYBRID_SLEEP:
1662 method = "HybridSleep";
1669 return bus_method_call_with_reply(
1671 "org.freedesktop.login1",
1672 "/org/freedesktop/login1",
1673 "org.freedesktop.login1.Manager",
1677 DBUS_TYPE_BOOLEAN, &interactive,
1684 static int check_inhibitors(DBusConnection *bus, enum action a) {
1686 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1687 DBusMessageIter iter, sub, sub2;
1690 _cleanup_strv_free_ char **sessions = NULL;
1696 if (arg_ignore_inhibitors || arg_force > 0)
1708 r = bus_method_call_with_reply(
1710 "org.freedesktop.login1",
1711 "/org/freedesktop/login1",
1712 "org.freedesktop.login1.Manager",
1718 /* If logind is not around, then there are no inhibitors... */
1721 if (!dbus_message_iter_init(reply, &iter) ||
1722 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1723 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1724 log_error("Failed to parse reply.");
1728 dbus_message_iter_recurse(&iter, &sub);
1729 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1730 const char *what, *who, *why, *mode;
1732 _cleanup_strv_free_ char **sv = NULL;
1733 _cleanup_free_ char *comm = NULL, *user = NULL;
1735 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1736 log_error("Failed to parse reply.");
1740 dbus_message_iter_recurse(&sub, &sub2);
1742 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
1743 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
1744 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
1745 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
1746 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
1747 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
1748 log_error("Failed to parse reply.");
1752 if (!streq(mode, "block"))
1755 sv = strv_split(what, ":");
1759 if (!strv_contains(sv,
1761 a == ACTION_POWEROFF ||
1762 a == ACTION_REBOOT ||
1763 a == ACTION_KEXEC ? "shutdown" : "sleep"))
1766 get_process_comm(pid, &comm);
1767 user = uid_to_name(uid);
1768 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
1769 who, (unsigned long) pid, strna(comm), strna(user), why);
1773 dbus_message_iter_next(&sub);
1776 dbus_message_iter_recurse(&iter, &sub);
1778 /* Check for current sessions */
1779 sd_get_sessions(&sessions);
1780 STRV_FOREACH(s, sessions) {
1782 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
1784 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
1787 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
1790 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
1793 sd_session_get_tty(*s, &tty);
1794 sd_session_get_seat(*s, &seat);
1795 sd_session_get_service(*s, &service);
1796 user = uid_to_name(uid);
1798 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
1805 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
1806 a == ACTION_HALT ? "halt" :
1807 a == ACTION_POWEROFF ? "poweroff" :
1808 a == ACTION_REBOOT ? "reboot" :
1809 a == ACTION_KEXEC ? "kexec" :
1810 a == ACTION_SUSPEND ? "suspend" :
1811 a == ACTION_HIBERNATE ? "hibernate" : "hybrid-sleep");
1819 static int start_special(DBusConnection *bus, char **args) {
1825 a = verb_to_action(args[0]);
1827 r = check_inhibitors(bus, a);
1831 if (arg_force >= 2 && geteuid() != 0) {
1832 log_error("Must be root.");
1836 if (arg_force >= 2 &&
1837 (a == ACTION_HALT ||
1838 a == ACTION_POWEROFF ||
1839 a == ACTION_REBOOT))
1842 if (arg_force >= 1 &&
1843 (a == ACTION_HALT ||
1844 a == ACTION_POWEROFF ||
1845 a == ACTION_REBOOT ||
1846 a == ACTION_KEXEC ||
1848 return daemon_reload(bus, args);
1850 /* first try logind, to allow authentication with polkit */
1851 if (geteuid() != 0 &&
1852 (a == ACTION_POWEROFF ||
1853 a == ACTION_REBOOT ||
1854 a == ACTION_SUSPEND ||
1855 a == ACTION_HIBERNATE ||
1856 a == ACTION_HYBRID_SLEEP)) {
1857 r = reboot_with_logind(bus, a);
1862 r = start_unit(bus, args);
1869 static int check_unit_active(DBusConnection *bus, char **args) {
1870 const char * const check_states[] = {
1877 int r = 3; /* According to LSB: "program is not running" */
1882 STRV_FOREACH(name, args+1) {
1885 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1895 static int check_unit_failed(DBusConnection *bus, char **args) {
1896 const char * const check_states[] = {
1907 STRV_FOREACH(name, args+1) {
1910 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1920 static int kill_unit(DBusConnection *bus, char **args) {
1928 arg_kill_who = "all";
1930 STRV_FOREACH(name, args+1) {
1931 _cleanup_free_ char *n = NULL;
1933 n = unit_name_mangle(*name);
1937 r = bus_method_call_with_reply(
1939 "org.freedesktop.systemd1",
1940 "/org/freedesktop/systemd1",
1941 "org.freedesktop.systemd1.Manager",
1945 DBUS_TYPE_STRING, &n,
1946 DBUS_TYPE_STRING, &arg_kill_who,
1947 DBUS_TYPE_INT32, &arg_signal,
1955 static int set_cgroup(DBusConnection *bus, char **args) {
1956 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
1959 DBusMessageIter iter;
1961 _cleanup_free_ char *n = NULL;
1962 const char *runtime;
1967 dbus_error_init(&error);
1970 streq(args[0], "set-cgroup") ? "SetUnitControlGroups" :
1971 streq(args[0], "unset-group") ? "UnsetUnitControlGroups"
1972 : "UnsetUnitControlGroupAttributes";
1974 n = unit_name_mangle(args[1]);
1978 m = dbus_message_new_method_call(
1979 "org.freedesktop.systemd1",
1980 "/org/freedesktop/systemd1",
1981 "org.freedesktop.systemd1.Manager",
1986 dbus_message_iter_init_append(m, &iter);
1987 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
1990 r = bus_append_strv_iter(&iter, args + 2);
1994 runtime = arg_runtime ? "runtime" : "persistent";
1995 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
1998 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2000 log_error("Failed to issue method call: %s", bus_error_message(&error));
2001 dbus_error_free(&error);
2008 static int set_cgroup_attr(DBusConnection *bus, char **args) {
2009 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2011 DBusMessageIter iter, sub, sub2;
2013 _cleanup_free_ char *n = NULL;
2014 const char *runtime;
2019 dbus_error_init(&error);
2021 if (strv_length(args) % 2 != 0) {
2022 log_error("Expecting an uneven number of arguments!");
2026 n = unit_name_mangle(args[1]);
2030 m = dbus_message_new_method_call(
2031 "org.freedesktop.systemd1",
2032 "/org/freedesktop/systemd1",
2033 "org.freedesktop.systemd1.Manager",
2034 "SetUnitControlGroupAttributes");
2038 dbus_message_iter_init_append(m, &iter);
2039 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2040 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub))
2043 STRV_FOREACH_PAIR(x, y, args + 2) {
2044 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
2045 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, x) ||
2046 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, y) ||
2047 !dbus_message_iter_close_container(&sub, &sub2))
2051 runtime = arg_runtime ? "runtime" : "persistent";
2052 if (!dbus_message_iter_close_container(&iter, &sub) ||
2053 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2056 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2058 log_error("Failed to issue method call: %s", bus_error_message(&error));
2059 dbus_error_free(&error);
2066 static int get_cgroup_attr(DBusConnection *bus, char **args) {
2067 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2069 DBusMessageIter iter;
2071 _cleanup_free_ char *n = NULL;
2072 _cleanup_strv_free_ char **list = NULL;
2078 dbus_error_init(&error);
2080 n = unit_name_mangle(args[1]);
2084 m = dbus_message_new_method_call(
2085 "org.freedesktop.systemd1",
2086 "/org/freedesktop/systemd1",
2087 "org.freedesktop.systemd1.Manager",
2088 "GetUnitControlGroupAttributes");
2092 dbus_message_iter_init_append(m, &iter);
2093 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
2096 r = bus_append_strv_iter(&iter, args + 2);
2100 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2102 log_error("Failed to issue method call: %s", bus_error_message(&error));
2103 dbus_error_free(&error);
2107 dbus_message_iter_init(reply, &iter);
2108 r = bus_parse_strv_iter(&iter, &list);
2110 log_error("Failed to parse value list.");
2114 STRV_FOREACH(a, list) {
2115 if (endswith(*a, "\n"))
2124 typedef struct ExecStatusInfo {
2132 usec_t start_timestamp;
2133 usec_t exit_timestamp;
2138 LIST_FIELDS(struct ExecStatusInfo, exec);
2141 static void exec_status_info_free(ExecStatusInfo *i) {
2150 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2151 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2152 DBusMessageIter sub2, sub3;
2156 int32_t code, status;
2162 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2165 dbus_message_iter_recurse(sub, &sub2);
2167 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2170 i->path = strdup(path);
2174 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2175 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2179 dbus_message_iter_recurse(&sub2, &sub3);
2180 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2181 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2182 dbus_message_iter_next(&sub3);
2186 i->argv = new0(char*, n+1);
2191 dbus_message_iter_recurse(&sub2, &sub3);
2192 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2195 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2196 dbus_message_iter_get_basic(&sub3, &s);
2197 dbus_message_iter_next(&sub3);
2199 i->argv[n] = strdup(s);
2206 if (!dbus_message_iter_next(&sub2) ||
2207 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2208 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2209 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2210 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2211 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2212 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2213 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2214 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2218 i->start_timestamp = (usec_t) start_timestamp;
2219 i->exit_timestamp = (usec_t) exit_timestamp;
2220 i->pid = (pid_t) pid;
2227 typedef struct UnitStatusInfo {
2229 const char *load_state;
2230 const char *active_state;
2231 const char *sub_state;
2232 const char *unit_file_state;
2234 const char *description;
2235 const char *following;
2237 char **documentation;
2239 const char *fragment_path;
2240 const char *source_path;
2241 const char *default_control_group;
2243 const char *load_error;
2246 usec_t inactive_exit_timestamp;
2247 usec_t inactive_exit_timestamp_monotonic;
2248 usec_t active_enter_timestamp;
2249 usec_t active_exit_timestamp;
2250 usec_t inactive_enter_timestamp;
2252 bool need_daemon_reload;
2257 const char *status_text;
2260 usec_t start_timestamp;
2261 usec_t exit_timestamp;
2263 int exit_code, exit_status;
2265 usec_t condition_timestamp;
2266 bool condition_result;
2269 unsigned n_accepted;
2270 unsigned n_connections;
2274 const char *sysfs_path;
2276 /* Mount, Automount */
2282 LIST_HEAD(ExecStatusInfo, exec);
2285 static void print_status_info(UnitStatusInfo *i) {
2287 const char *on, *off, *ss;
2289 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2290 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2293 arg_all * OUTPUT_SHOW_ALL |
2294 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2295 on_tty() * OUTPUT_COLOR |
2296 !arg_quiet * OUTPUT_WARN_CUTOFF |
2297 arg_full * OUTPUT_FULL_WIDTH;
2301 /* This shows pretty information about a unit. See
2302 * print_property() for a low-level property printer */
2304 printf("%s", strna(i->id));
2306 if (i->description && !streq_ptr(i->id, i->description))
2307 printf(" - %s", i->description);
2312 printf("\t Follow: unit currently follows state of %s\n", i->following);
2314 if (streq_ptr(i->load_state, "error")) {
2315 on = ansi_highlight_red(true);
2316 off = ansi_highlight_red(false);
2320 path = i->source_path ? i->source_path : i->fragment_path;
2323 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2324 else if (path && i->unit_file_state)
2325 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2327 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2329 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2331 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2333 if (streq_ptr(i->active_state, "failed")) {
2334 on = ansi_highlight_red(true);
2335 off = ansi_highlight_red(false);
2336 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2337 on = ansi_highlight_green(true);
2338 off = ansi_highlight_green(false);
2343 printf("\t Active: %s%s (%s)%s",
2345 strna(i->active_state),
2349 printf("\t Active: %s%s%s",
2351 strna(i->active_state),
2354 if (!isempty(i->result) && !streq(i->result, "success"))
2355 printf(" (Result: %s)", i->result);
2357 timestamp = (streq_ptr(i->active_state, "active") ||
2358 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2359 (streq_ptr(i->active_state, "inactive") ||
2360 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2361 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2362 i->active_exit_timestamp;
2364 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2365 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2368 printf(" since %s; %s\n", s2, s1);
2370 printf(" since %s\n", s2);
2374 if (!i->condition_result && i->condition_timestamp > 0) {
2375 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2376 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2379 printf("\t start condition failed at %s; %s\n", s2, s1);
2381 printf("\t start condition failed at %s\n", s2);
2385 printf("\t Device: %s\n", i->sysfs_path);
2387 printf("\t Where: %s\n", i->where);
2389 printf("\t What: %s\n", i->what);
2391 if (!strv_isempty(i->documentation)) {
2395 STRV_FOREACH(t, i->documentation) {
2397 printf("\t Docs: %s\n", *t);
2400 printf("\t %s\n", *t);
2405 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2407 LIST_FOREACH(exec, p, i->exec) {
2408 _cleanup_free_ char *t = NULL;
2411 /* Only show exited processes here */
2415 t = strv_join(p->argv, " ");
2416 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2418 good = is_clean_exit_lsb(p->code, p->status, NULL);
2420 on = ansi_highlight_red(true);
2421 off = ansi_highlight_red(false);
2425 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2427 if (p->code == CLD_EXITED) {
2430 printf("status=%i", p->status);
2432 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2437 printf("signal=%s", signal_to_string(p->status));
2439 printf(")%s\n", off);
2441 if (i->main_pid == p->pid &&
2442 i->start_timestamp == p->start_timestamp &&
2443 i->exit_timestamp == p->start_timestamp)
2444 /* Let's not show this twice */
2447 if (p->pid == i->control_pid)
2451 if (i->main_pid > 0 || i->control_pid > 0) {
2454 if (i->main_pid > 0) {
2455 printf("Main PID: %u", (unsigned) i->main_pid);
2458 _cleanup_free_ char *t = NULL;
2459 get_process_comm(i->main_pid, &t);
2462 } else if (i->exit_code > 0) {
2463 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2465 if (i->exit_code == CLD_EXITED) {
2468 printf("status=%i", i->exit_status);
2470 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2475 printf("signal=%s", signal_to_string(i->exit_status));
2480 if (i->main_pid > 0 && i->control_pid > 0)
2483 if (i->control_pid > 0) {
2484 _cleanup_free_ char *t = NULL;
2486 printf(" Control: %u", (unsigned) i->control_pid);
2488 get_process_comm(i->control_pid, &t);
2497 printf("\t Status: \"%s\"\n", i->status_text);
2499 if (i->default_control_group &&
2500 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2503 printf("\t CGroup: %s\n", i->default_control_group);
2505 if (arg_transport != TRANSPORT_SSH) {
2515 if (i->main_pid > 0)
2516 extra[k++] = i->main_pid;
2518 if (i->control_pid > 0)
2519 extra[k++] = i->control_pid;
2521 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, extra, k, flags);
2525 if (i->id && arg_transport != TRANSPORT_SSH) {
2527 if(arg_scope == UNIT_FILE_SYSTEM)
2528 show_journal_by_unit(stdout,
2532 i->inactive_exit_timestamp_monotonic,
2536 show_journal_by_user_unit(stdout,
2540 i->inactive_exit_timestamp_monotonic,
2546 if (i->need_daemon_reload)
2547 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2548 ansi_highlight_red(true),
2549 ansi_highlight_red(false),
2550 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2553 static void show_unit_help(UnitStatusInfo *i) {
2558 if (!i->documentation) {
2559 log_info("Documentation for %s not known.", i->id);
2563 STRV_FOREACH(p, i->documentation) {
2565 if (startswith(*p, "man:")) {
2568 char *page = NULL, *section = NULL;
2569 const char *args[4] = { "man", NULL, NULL, NULL };
2574 if ((*p)[k-1] == ')')
2575 e = strrchr(*p, '(');
2578 page = strndup((*p) + 4, e - *p - 4);
2584 section = strndup(e + 1, *p + k - e - 2);
2598 log_error("Failed to fork: %m");
2606 execvp(args[0], (char**) args);
2607 log_error("Failed to execute man: %m");
2608 _exit(EXIT_FAILURE);
2614 wait_for_terminate(pid, NULL);
2616 log_info("Can't show: %s", *p);
2620 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2626 switch (dbus_message_iter_get_arg_type(iter)) {
2628 case DBUS_TYPE_STRING: {
2631 dbus_message_iter_get_basic(iter, &s);
2634 if (streq(name, "Id"))
2636 else if (streq(name, "LoadState"))
2638 else if (streq(name, "ActiveState"))
2639 i->active_state = s;
2640 else if (streq(name, "SubState"))
2642 else if (streq(name, "Description"))
2644 else if (streq(name, "FragmentPath"))
2645 i->fragment_path = s;
2646 else if (streq(name, "SourcePath"))
2648 else if (streq(name, "DefaultControlGroup"))
2649 i->default_control_group = s;
2650 else if (streq(name, "StatusText"))
2652 else if (streq(name, "SysFSPath"))
2654 else if (streq(name, "Where"))
2656 else if (streq(name, "What"))
2658 else if (streq(name, "Following"))
2660 else if (streq(name, "UnitFileState"))
2661 i->unit_file_state = s;
2662 else if (streq(name, "Result"))
2669 case DBUS_TYPE_BOOLEAN: {
2672 dbus_message_iter_get_basic(iter, &b);
2674 if (streq(name, "Accept"))
2676 else if (streq(name, "NeedDaemonReload"))
2677 i->need_daemon_reload = b;
2678 else if (streq(name, "ConditionResult"))
2679 i->condition_result = b;
2684 case DBUS_TYPE_UINT32: {
2687 dbus_message_iter_get_basic(iter, &u);
2689 if (streq(name, "MainPID")) {
2691 i->main_pid = (pid_t) u;
2694 } else if (streq(name, "ControlPID"))
2695 i->control_pid = (pid_t) u;
2696 else if (streq(name, "ExecMainPID")) {
2698 i->main_pid = (pid_t) u;
2699 } else if (streq(name, "NAccepted"))
2701 else if (streq(name, "NConnections"))
2702 i->n_connections = u;
2707 case DBUS_TYPE_INT32: {
2710 dbus_message_iter_get_basic(iter, &j);
2712 if (streq(name, "ExecMainCode"))
2713 i->exit_code = (int) j;
2714 else if (streq(name, "ExecMainStatus"))
2715 i->exit_status = (int) j;
2720 case DBUS_TYPE_UINT64: {
2723 dbus_message_iter_get_basic(iter, &u);
2725 if (streq(name, "ExecMainStartTimestamp"))
2726 i->start_timestamp = (usec_t) u;
2727 else if (streq(name, "ExecMainExitTimestamp"))
2728 i->exit_timestamp = (usec_t) u;
2729 else if (streq(name, "ActiveEnterTimestamp"))
2730 i->active_enter_timestamp = (usec_t) u;
2731 else if (streq(name, "InactiveEnterTimestamp"))
2732 i->inactive_enter_timestamp = (usec_t) u;
2733 else if (streq(name, "InactiveExitTimestamp"))
2734 i->inactive_exit_timestamp = (usec_t) u;
2735 else if (streq(name, "InactiveExitTimestampMonotonic"))
2736 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2737 else if (streq(name, "ActiveExitTimestamp"))
2738 i->active_exit_timestamp = (usec_t) u;
2739 else if (streq(name, "ConditionTimestamp"))
2740 i->condition_timestamp = (usec_t) u;
2745 case DBUS_TYPE_ARRAY: {
2747 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2748 startswith(name, "Exec")) {
2749 DBusMessageIter sub;
2751 dbus_message_iter_recurse(iter, &sub);
2752 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2753 ExecStatusInfo *info;
2756 if (!(info = new0(ExecStatusInfo, 1)))
2759 if (!(info->name = strdup(name))) {
2764 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2769 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2771 dbus_message_iter_next(&sub);
2773 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2774 streq(name, "Documentation")) {
2776 DBusMessageIter sub;
2778 dbus_message_iter_recurse(iter, &sub);
2779 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2783 dbus_message_iter_get_basic(&sub, &s);
2785 l = strv_append(i->documentation, s);
2789 strv_free(i->documentation);
2790 i->documentation = l;
2792 dbus_message_iter_next(&sub);
2799 case DBUS_TYPE_STRUCT: {
2801 if (streq(name, "LoadError")) {
2802 DBusMessageIter sub;
2803 const char *n, *message;
2806 dbus_message_iter_recurse(iter, &sub);
2808 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2812 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2816 if (!isempty(message))
2817 i->load_error = message;
2827 static int print_property(const char *name, DBusMessageIter *iter) {
2831 /* This is a low-level property printer, see
2832 * print_status_info() for the nicer output */
2834 if (arg_property && !strv_find(arg_property, name))
2837 switch (dbus_message_iter_get_arg_type(iter)) {
2839 case DBUS_TYPE_STRUCT: {
2840 DBusMessageIter sub;
2841 dbus_message_iter_recurse(iter, &sub);
2843 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2846 dbus_message_iter_get_basic(&sub, &u);
2849 printf("%s=%u\n", name, (unsigned) u);
2851 printf("%s=\n", name);
2854 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2857 dbus_message_iter_get_basic(&sub, &s);
2859 if (arg_all || s[0])
2860 printf("%s=%s\n", name, s);
2863 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2864 const char *a = NULL, *b = NULL;
2866 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2867 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2869 if (arg_all || !isempty(a) || !isempty(b))
2870 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2878 case DBUS_TYPE_ARRAY:
2880 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2881 DBusMessageIter sub, sub2;
2883 dbus_message_iter_recurse(iter, &sub);
2884 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2888 dbus_message_iter_recurse(&sub, &sub2);
2890 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2891 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2892 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2894 dbus_message_iter_next(&sub);
2899 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2900 DBusMessageIter sub, sub2;
2902 dbus_message_iter_recurse(iter, &sub);
2903 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2904 const char *type, *path;
2906 dbus_message_iter_recurse(&sub, &sub2);
2908 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2909 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2910 printf("%s=%s\n", type, path);
2912 dbus_message_iter_next(&sub);
2917 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2918 DBusMessageIter sub, sub2;
2920 dbus_message_iter_recurse(iter, &sub);
2921 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2923 uint64_t value, next_elapse;
2925 dbus_message_iter_recurse(&sub, &sub2);
2927 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2928 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2929 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2930 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2932 printf("%s={ value=%s ; next_elapse=%s }\n",
2934 format_timespan(timespan1, sizeof(timespan1), value),
2935 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2938 dbus_message_iter_next(&sub);
2943 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2944 DBusMessageIter sub, sub2;
2946 dbus_message_iter_recurse(iter, &sub);
2947 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2948 const char *controller, *attr, *value;
2950 dbus_message_iter_recurse(&sub, &sub2);
2952 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2953 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2954 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2956 printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2962 dbus_message_iter_next(&sub);
2967 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2968 DBusMessageIter sub;
2970 dbus_message_iter_recurse(iter, &sub);
2971 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2972 ExecStatusInfo info;
2975 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2976 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2979 t = strv_join(info.argv, " ");
2981 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2985 yes_no(info.ignore),
2986 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2987 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2988 (unsigned) info. pid,
2989 sigchld_code_to_string(info.code),
2991 info.code == CLD_EXITED ? "" : "/",
2992 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2998 strv_free(info.argv);
3000 dbus_message_iter_next(&sub);
3009 if (generic_print_property(name, iter, arg_all) > 0)
3013 printf("%s=[unprintable]\n", name);
3018 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3019 _cleanup_free_ DBusMessage *reply = NULL;
3020 const char *interface = "";
3022 DBusMessageIter iter, sub, sub2, sub3;
3023 UnitStatusInfo info;
3031 r = bus_method_call_with_reply(
3033 "org.freedesktop.systemd1",
3035 "org.freedesktop.DBus.Properties",
3039 DBUS_TYPE_STRING, &interface,
3044 if (!dbus_message_iter_init(reply, &iter) ||
3045 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3046 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3047 log_error("Failed to parse reply.");
3051 dbus_message_iter_recurse(&iter, &sub);
3058 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3061 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3062 dbus_message_iter_recurse(&sub, &sub2);
3064 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3065 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3066 log_error("Failed to parse reply.");
3070 dbus_message_iter_recurse(&sub2, &sub3);
3072 if (show_properties)
3073 r = print_property(name, &sub3);
3075 r = status_property(name, &sub3, &info);
3077 log_error("Failed to parse reply.");
3081 dbus_message_iter_next(&sub);
3086 if (!show_properties) {
3087 if (streq(verb, "help"))
3088 show_unit_help(&info);
3090 print_status_info(&info);
3093 strv_free(info.documentation);
3095 if (!streq_ptr(info.active_state, "active") &&
3096 !streq_ptr(info.active_state, "reloading") &&
3097 streq(verb, "status"))
3098 /* According to LSB: "program not running" */
3101 while ((p = info.exec)) {
3102 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3103 exec_status_info_free(p);
3109 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3110 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3111 const char *path = NULL;
3115 dbus_error_init(&error);
3117 r = bus_method_call_with_reply(
3119 "org.freedesktop.systemd1",
3120 "/org/freedesktop/systemd1",
3121 "org.freedesktop.systemd1.Manager",
3125 DBUS_TYPE_UINT32, &pid,
3130 if (!dbus_message_get_args(reply, &error,
3131 DBUS_TYPE_OBJECT_PATH, &path,
3132 DBUS_TYPE_INVALID)) {
3133 log_error("Failed to parse reply: %s", bus_error_message(&error));
3138 r = show_one(verb, bus, path, false, new_line);
3141 dbus_error_free(&error);
3146 static int show(DBusConnection *bus, char **args) {
3148 bool show_properties, new_line = false;
3154 show_properties = streq(args[0], "show");
3156 if (show_properties)
3157 pager_open_if_enabled();
3159 /* If no argument is specified inspect the manager itself */
3161 if (show_properties && strv_length(args) <= 1)
3162 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3164 STRV_FOREACH(name, args+1) {
3167 if (safe_atou32(*name, &id) < 0) {
3168 _cleanup_free_ char *p = NULL, *n = NULL;
3169 /* Interpret as unit name */
3171 n = unit_name_mangle(*name);
3175 p = unit_dbus_path_from_name(n);
3179 r = show_one(args[0], bus, p, show_properties, &new_line);
3183 } else if (show_properties) {
3184 _cleanup_free_ char *p = NULL;
3186 /* Interpret as job id */
3187 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3190 r = show_one(args[0], bus, p, show_properties, &new_line);
3195 /* Interpret as PID */
3196 r = show_one_by_pid(args[0], bus, id, &new_line);
3205 static int dump(DBusConnection *bus, char **args) {
3206 _cleanup_free_ DBusMessage *reply = NULL;
3211 dbus_error_init(&error);
3213 pager_open_if_enabled();
3215 r = bus_method_call_with_reply(
3217 "org.freedesktop.systemd1",
3218 "/org/freedesktop/systemd1",
3219 "org.freedesktop.systemd1.Manager",
3227 if (!dbus_message_get_args(reply, &error,
3228 DBUS_TYPE_STRING, &text,
3229 DBUS_TYPE_INVALID)) {
3230 log_error("Failed to parse reply: %s", bus_error_message(&error));
3231 dbus_error_free(&error);
3235 fputs(text, stdout);
3239 static int snapshot(DBusConnection *bus, char **args) {
3240 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3243 dbus_bool_t cleanup = FALSE;
3244 DBusMessageIter iter, sub;
3247 *interface = "org.freedesktop.systemd1.Unit",
3249 _cleanup_free_ char *n = NULL;
3251 dbus_error_init(&error);
3253 if (strv_length(args) > 1)
3254 n = snapshot_name_mangle(args[1]);
3260 r = bus_method_call_with_reply (
3262 "org.freedesktop.systemd1",
3263 "/org/freedesktop/systemd1",
3264 "org.freedesktop.systemd1.Manager",
3268 DBUS_TYPE_STRING, &n,
3269 DBUS_TYPE_BOOLEAN, &cleanup,
3274 if (!dbus_message_get_args(reply, &error,
3275 DBUS_TYPE_OBJECT_PATH, &path,
3276 DBUS_TYPE_INVALID)) {
3277 log_error("Failed to parse reply: %s", bus_error_message(&error));
3278 dbus_error_free(&error);
3282 dbus_message_unref(reply);
3285 r = bus_method_call_with_reply (
3287 "org.freedesktop.systemd1",
3289 "org.freedesktop.DBus.Properties",
3293 DBUS_TYPE_STRING, &interface,
3294 DBUS_TYPE_STRING, &property,
3299 if (!dbus_message_iter_init(reply, &iter) ||
3300 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3301 log_error("Failed to parse reply.");
3305 dbus_message_iter_recurse(&iter, &sub);
3307 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3308 log_error("Failed to parse reply.");
3312 dbus_message_iter_get_basic(&sub, &id);
3320 static int delete_snapshot(DBusConnection *bus, char **args) {
3325 STRV_FOREACH(name, args+1) {
3326 _cleanup_free_ char *n = NULL;
3329 n = snapshot_name_mangle(*name);
3333 r = bus_method_call_with_reply(
3335 "org.freedesktop.systemd1",
3336 "/org/freedesktop/systemd1",
3337 "org.freedesktop.systemd1.Manager",
3341 DBUS_TYPE_STRING, &n,
3350 static int daemon_reload(DBusConnection *bus, char **args) {
3355 if (arg_action == ACTION_RELOAD)
3357 else if (arg_action == ACTION_REEXEC)
3358 method = "Reexecute";
3360 assert(arg_action == ACTION_SYSTEMCTL);
3363 streq(args[0], "clear-jobs") ||
3364 streq(args[0], "cancel") ? "ClearJobs" :
3365 streq(args[0], "daemon-reexec") ? "Reexecute" :
3366 streq(args[0], "reset-failed") ? "ResetFailed" :
3367 streq(args[0], "halt") ? "Halt" :
3368 streq(args[0], "poweroff") ? "PowerOff" :
3369 streq(args[0], "reboot") ? "Reboot" :
3370 streq(args[0], "kexec") ? "KExec" :
3371 streq(args[0], "exit") ? "Exit" :
3372 /* "daemon-reload" */ "Reload";
3375 r = bus_method_call_with_reply(
3377 "org.freedesktop.systemd1",
3378 "/org/freedesktop/systemd1",
3379 "org.freedesktop.systemd1.Manager",
3385 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3386 /* There's always a fallback possible for
3387 * legacy actions. */
3389 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3390 /* On reexecution, we expect a disconnect, not
3394 log_error("Failed to issue method call: %s", bus_error_message(&error));
3396 dbus_error_free(&error);
3400 static int reset_failed(DBusConnection *bus, char **args) {
3404 if (strv_length(args) <= 1)
3405 return daemon_reload(bus, args);
3407 STRV_FOREACH(name, args+1) {
3408 _cleanup_free_ char *n;
3410 n = unit_name_mangle(*name);
3414 r = bus_method_call_with_reply(
3416 "org.freedesktop.systemd1",
3417 "/org/freedesktop/systemd1",
3418 "org.freedesktop.systemd1.Manager",
3422 DBUS_TYPE_STRING, &n,
3431 static int show_enviroment(DBusConnection *bus, char **args) {
3432 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3433 DBusMessageIter iter, sub, sub2;
3436 *interface = "org.freedesktop.systemd1.Manager",
3437 *property = "Environment";
3439 pager_open_if_enabled();
3441 r = bus_method_call_with_reply(
3443 "org.freedesktop.systemd1",
3444 "/org/freedesktop/systemd1",
3445 "org.freedesktop.DBus.Properties",
3449 DBUS_TYPE_STRING, &interface,
3450 DBUS_TYPE_STRING, &property,
3455 if (!dbus_message_iter_init(reply, &iter) ||
3456 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3457 log_error("Failed to parse reply.");
3461 dbus_message_iter_recurse(&iter, &sub);
3463 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3464 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3465 log_error("Failed to parse reply.");
3469 dbus_message_iter_recurse(&sub, &sub2);
3471 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3474 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3475 log_error("Failed to parse reply.");
3479 dbus_message_iter_get_basic(&sub2, &text);
3482 dbus_message_iter_next(&sub2);
3488 static int switch_root(DBusConnection *bus, char **args) {
3491 _cleanup_free_ char *init = NULL;
3493 l = strv_length(args);
3494 if (l < 2 || l > 3) {
3495 log_error("Wrong number of arguments.");
3502 init = strdup(args[2]);
3504 parse_env_file("/proc/cmdline", WHITESPACE,
3514 log_debug("switching root - root: %s; init: %s", root, init);
3516 return bus_method_call_with_reply(
3518 "org.freedesktop.systemd1",
3519 "/org/freedesktop/systemd1",
3520 "org.freedesktop.systemd1.Manager",
3524 DBUS_TYPE_STRING, &root,
3525 DBUS_TYPE_STRING, &init,
3529 static int set_environment(DBusConnection *bus, char **args) {
3530 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3533 DBusMessageIter iter;
3539 dbus_error_init(&error);
3541 method = streq(args[0], "set-environment")
3543 : "UnsetEnvironment";
3545 m = dbus_message_new_method_call(
3546 "org.freedesktop.systemd1",
3547 "/org/freedesktop/systemd1",
3548 "org.freedesktop.systemd1.Manager",
3553 dbus_message_iter_init_append(m, &iter);
3555 r = bus_append_strv_iter(&iter, args + 1);
3559 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3561 log_error("Failed to issue method call: %s", bus_error_message(&error));
3562 dbus_error_free(&error);
3569 static int enable_sysv_units(char **args) {
3572 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3573 const char *verb = args[0];
3574 unsigned f = 1, t = 1;
3577 if (arg_scope != UNIT_FILE_SYSTEM)
3580 if (!streq(verb, "enable") &&
3581 !streq(verb, "disable") &&
3582 !streq(verb, "is-enabled"))
3585 /* Processes all SysV units, and reshuffles the array so that
3586 * afterwards only the native units remain */
3589 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3594 for (f = 1; args[f]; f++) {
3597 bool found_native = false, found_sysv;
3599 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3600 char **k, *l, *q = NULL;
3607 if (!endswith(name, ".service"))
3610 if (path_is_absolute(name))
3613 STRV_FOREACH(k, paths.unit_path) {
3616 if (!isempty(arg_root))
3617 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3619 asprintf(&p, "%s/%s", *k, name);
3626 found_native = access(p, F_OK) >= 0;
3637 if (!isempty(arg_root))
3638 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3640 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3646 p[strlen(p) - sizeof(".service") + 1] = 0;
3647 found_sysv = access(p, F_OK) >= 0;
3654 /* Mark this entry, so that we don't try enabling it as native unit */
3655 args[f] = (char*) "";
3657 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3659 if (!isempty(arg_root))
3660 argv[c++] = q = strappend("--root=", arg_root);
3662 argv[c++] = path_get_file_name(p);
3664 streq(verb, "enable") ? "on" :
3665 streq(verb, "disable") ? "off" : "--level=5";
3668 l = strv_join((char**)argv, " ");
3676 log_info("Executing %s", l);
3681 log_error("Failed to fork: %m");
3686 } else if (pid == 0) {
3689 execv(argv[0], (char**) argv);
3690 _exit(EXIT_FAILURE);
3696 j = wait_for_terminate(pid, &status);
3698 log_error("Failed to wait for child: %s", strerror(-r));
3703 if (status.si_code == CLD_EXITED) {
3704 if (streq(verb, "is-enabled")) {
3705 if (status.si_status == 0) {
3714 } else if (status.si_status != 0) {
3725 lookup_paths_free(&paths);
3727 /* Drop all SysV units */
3728 for (f = 1, t = 1; args[f]; f++) {
3730 if (isempty(args[f]))
3733 args[t++] = args[f];
3742 static int mangle_names(char **original_names, char ***mangled_names) {
3743 char **i, **l, **name;
3745 l = new(char*, strv_length(original_names) + 1);
3750 STRV_FOREACH(name, original_names) {
3752 /* When enabling units qualified path names are OK,
3753 * too, hence allow them explicitly. */
3758 *i = unit_name_mangle(*name);
3774 static int enable_unit(DBusConnection *bus, char **args) {
3775 const char *verb = args[0];
3776 UnitFileChange *changes = NULL;
3777 unsigned n_changes = 0, i;
3778 int carries_install_info = -1;
3779 DBusMessage *m = NULL, *reply = NULL;
3782 char **mangled_names = NULL;
3784 r = enable_sysv_units(args);
3791 dbus_error_init(&error);
3793 if (!bus || avoid_bus()) {
3794 if (streq(verb, "enable")) {
3795 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3796 carries_install_info = r;
3797 } else if (streq(verb, "disable"))
3798 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3799 else if (streq(verb, "reenable")) {
3800 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3801 carries_install_info = r;
3802 } else if (streq(verb, "link"))
3803 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3804 else if (streq(verb, "preset")) {
3805 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3806 carries_install_info = r;
3807 } else if (streq(verb, "mask"))
3808 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3809 else if (streq(verb, "unmask"))
3810 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3812 assert_not_reached("Unknown verb");
3815 log_error("Operation failed: %s", strerror(-r));
3820 for (i = 0; i < n_changes; i++) {
3821 if (changes[i].type == UNIT_FILE_SYMLINK)
3822 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3824 log_info("rm '%s'", changes[i].path);
3831 bool send_force = true, expect_carries_install_info = false;
3833 DBusMessageIter iter, sub, sub2;
3835 if (streq(verb, "enable")) {
3836 method = "EnableUnitFiles";
3837 expect_carries_install_info = true;
3838 } else if (streq(verb, "disable")) {
3839 method = "DisableUnitFiles";
3841 } else if (streq(verb, "reenable")) {
3842 method = "ReenableUnitFiles";
3843 expect_carries_install_info = true;
3844 } else if (streq(verb, "link"))
3845 method = "LinkUnitFiles";
3846 else if (streq(verb, "preset")) {
3847 method = "PresetUnitFiles";
3848 expect_carries_install_info = true;
3849 } else if (streq(verb, "mask"))
3850 method = "MaskUnitFiles";
3851 else if (streq(verb, "unmask")) {
3852 method = "UnmaskUnitFiles";
3855 assert_not_reached("Unknown verb");
3857 m = dbus_message_new_method_call(
3858 "org.freedesktop.systemd1",
3859 "/org/freedesktop/systemd1",
3860 "org.freedesktop.systemd1.Manager",
3867 dbus_message_iter_init_append(m, &iter);
3869 r = mangle_names(args+1, &mangled_names);
3873 r = bus_append_strv_iter(&iter, mangled_names);
3875 log_error("Failed to append unit files.");
3880 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3881 log_error("Failed to append runtime boolean.");
3889 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3890 log_error("Failed to append force boolean.");
3896 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3898 log_error("Failed to issue method call: %s", bus_error_message(&error));
3903 if (!dbus_message_iter_init(reply, &iter)) {
3904 log_error("Failed to initialize iterator.");
3908 if (expect_carries_install_info) {
3909 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3911 log_error("Failed to parse reply.");
3915 carries_install_info = b;
3918 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3919 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3920 log_error("Failed to parse reply.");
3925 dbus_message_iter_recurse(&iter, &sub);
3926 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3927 const char *type, *path, *source;
3929 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3930 log_error("Failed to parse reply.");
3935 dbus_message_iter_recurse(&sub, &sub2);
3937 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3938 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3939 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3940 log_error("Failed to parse reply.");
3946 if (streq(type, "symlink"))
3947 log_info("ln -s '%s' '%s'", source, path);
3949 log_info("rm '%s'", path);
3952 dbus_message_iter_next(&sub);
3955 /* Try to reload if enabeld */
3957 r = daemon_reload(bus, args);
3960 if (carries_install_info == 0)
3962 "The unit files have no [Install] section. They are not meant to be enabled\n"
3963 "using systemctl.\n"
3964 "Possible reasons for having this kind of units are:\n"
3965 "1) A unit may be statically enabled by being symlinked from another unit's\n"
3966 " .wants/ or .requires/ directory.\n"
3967 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
3968 " a requirement dependency on it.\n"
3969 "3) A unit may be started when needed via activation (socket, path, timer,\n"
3970 " D-Bus, udev, scripted systemctl call, ...).\n");
3974 dbus_message_unref(m);
3977 dbus_message_unref(reply);
3979 unit_file_changes_free(changes, n_changes);
3981 dbus_error_free(&error);
3983 strv_free(mangled_names);
3988 static int unit_is_enabled(DBusConnection *bus, char **args) {
3991 DBusMessage *reply = NULL;
3995 dbus_error_init(&error);
3997 r = enable_sysv_units(args);
4003 if (!bus || avoid_bus()) {
4005 STRV_FOREACH(name, args+1) {
4006 UnitFileState state;
4008 state = unit_file_get_state(arg_scope, arg_root, *name);
4014 if (state == UNIT_FILE_ENABLED ||
4015 state == UNIT_FILE_ENABLED_RUNTIME ||
4016 state == UNIT_FILE_STATIC)
4020 puts(unit_file_state_to_string(state));
4024 STRV_FOREACH(name, args+1) {
4027 r = bus_method_call_with_reply (
4029 "org.freedesktop.systemd1",
4030 "/org/freedesktop/systemd1",
4031 "org.freedesktop.systemd1.Manager",
4035 DBUS_TYPE_STRING, name,
4040 if (!dbus_message_get_args(reply, &error,
4041 DBUS_TYPE_STRING, &s,
4042 DBUS_TYPE_INVALID)) {
4043 log_error("Failed to parse reply: %s", bus_error_message(&error));
4048 dbus_message_unref(reply);
4051 if (streq(s, "enabled") ||
4052 streq(s, "enabled-runtime") ||
4061 r = enabled ? 0 : 1;
4065 dbus_message_unref(reply);
4067 dbus_error_free(&error);
4071 static int systemctl_help(void) {
4073 pager_open_if_enabled();
4075 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4076 "Query or send control commands to the systemd manager.\n\n"
4077 " -h --help Show this help\n"
4078 " --version Show package version\n"
4079 " -t --type=TYPE List only units of a particular type\n"
4080 " -p --property=NAME Show only properties by this name\n"
4081 " -a --all Show all units/properties, including dead/empty ones\n"
4082 " --failed Show only failed units\n"
4083 " --full Don't ellipsize unit names on output\n"
4084 " --fail When queueing a new job, fail if conflicting jobs are\n"
4086 " --ignore-dependencies\n"
4087 " When queueing a new job, ignore all its dependencies\n"
4088 " -i --ignore-inhibitors\n"
4089 " When shutting down or sleeping, ignore inhibitors\n"
4090 " --kill-who=WHO Who to send signal to\n"
4091 " -s --signal=SIGNAL Which signal to send\n"
4092 " -H --host=[USER@]HOST\n"
4093 " Show information for remote host\n"
4094 " -P --privileged Acquire privileges before execution\n"
4095 " -q --quiet Suppress output\n"
4096 " --no-block Do not wait until operation finished\n"
4097 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4098 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4100 " --no-legend Do not print a legend (column headers and hints)\n"
4101 " --no-pager Do not pipe output into a pager\n"
4102 " --no-ask-password\n"
4103 " Do not ask for system passwords\n"
4104 " --system Connect to system manager\n"
4105 " --user Connect to user service manager\n"
4106 " --global Enable/disable unit files globally\n"
4107 " -f --force When enabling unit files, override existing symlinks\n"
4108 " When shutting down, execute action immediately\n"
4109 " --root=PATH Enable unit files in the specified root directory\n"
4110 " --runtime Enable unit files only temporarily until next reboot\n"
4111 " -n --lines=INTEGER Journal entries to show\n"
4112 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4113 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4115 " list-units List loaded units\n"
4116 " start [NAME...] Start (activate) one or more units\n"
4117 " stop [NAME...] Stop (deactivate) one or more units\n"
4118 " reload [NAME...] Reload one or more units\n"
4119 " restart [NAME...] Start or restart one or more units\n"
4120 " try-restart [NAME...] Restart one or more units if active\n"
4121 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4122 " otherwise start or restart\n"
4123 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4124 " otherwise restart if active\n"
4125 " isolate [NAME] Start one unit and stop all others\n"
4126 " kill [NAME...] Send signal to processes of a unit\n"
4127 " is-active [NAME...] Check whether units are active\n"
4128 " is-failed [NAME...] Check whether units are failed\n"
4129 " status [NAME...|PID...] Show runtime status of one or more units\n"
4130 " show [NAME...|JOB...] Show properties of one or more\n"
4131 " units/jobs or the manager\n"
4132 " help [NAME...|PID...] Show manual for one or more units\n"
4133 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4135 " get-cgroup-attr [NAME] [ATTR] ...\n"
4136 " Get control group attrubute\n"
4137 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4138 " Set control group attribute\n"
4139 " unset-cgroup-attr [NAME] [ATTR...]\n"
4140 " Unset control group attribute\n"
4141 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4142 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4143 " load [NAME...] Load one or more units\n"
4144 " list-dependencies [NAME] Recursively show units which are required\n"
4145 " or wanted by this unit\n\n"
4146 "Unit File Commands:\n"
4147 " list-unit-files List installed unit files\n"
4148 " enable [NAME...] Enable one or more unit files\n"
4149 " disable [NAME...] Disable one or more unit files\n"
4150 " reenable [NAME...] Reenable one or more unit files\n"
4151 " preset [NAME...] Enable/disable one or more unit files\n"
4152 " based on preset configuration\n"
4153 " mask [NAME...] Mask one or more units\n"
4154 " unmask [NAME...] Unmask one or more units\n"
4155 " link [PATH...] Link one or more units files into\n"
4156 " the search path\n"
4157 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4159 " list-jobs List jobs\n"
4160 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4161 "Status Commands:\n"
4162 " dump Dump server status\n"
4163 "Snapshot Commands:\n"
4164 " snapshot [NAME] Create a snapshot\n"
4165 " delete [NAME...] Remove one or more snapshots\n\n"
4166 "Environment Commands:\n"
4167 " show-environment Dump environment\n"
4168 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4169 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4170 "Manager Lifecycle Commands:\n"
4171 " daemon-reload Reload systemd manager configuration\n"
4172 " daemon-reexec Reexecute systemd manager\n\n"
4173 "System Commands:\n"
4174 " default Enter system default mode\n"
4175 " rescue Enter system rescue mode\n"
4176 " emergency Enter system emergency mode\n"
4177 " halt Shut down and halt the system\n"
4178 " poweroff Shut down and power-off the system\n"
4179 " reboot Shut down and reboot the system\n"
4180 " kexec Shut down and reboot the system with kexec\n"
4181 " exit Request user instance exit\n"
4182 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4183 " suspend Suspend the system\n"
4184 " hibernate Hibernate the system\n"
4185 " hybrid-sleep Hibernate and suspend the system\n",
4186 program_invocation_short_name);
4191 static int halt_help(void) {
4193 printf("%s [OPTIONS...]\n\n"
4194 "%s the system.\n\n"
4195 " --help Show this help\n"
4196 " --halt Halt the machine\n"
4197 " -p --poweroff Switch off the machine\n"
4198 " --reboot Reboot the machine\n"
4199 " -f --force Force immediate halt/power-off/reboot\n"
4200 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4201 " -d --no-wtmp Don't write wtmp record\n"
4202 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4203 program_invocation_short_name,
4204 arg_action == ACTION_REBOOT ? "Reboot" :
4205 arg_action == ACTION_POWEROFF ? "Power off" :
4211 static int shutdown_help(void) {
4213 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4214 "Shut down the system.\n\n"
4215 " --help Show this help\n"
4216 " -H --halt Halt the machine\n"
4217 " -P --poweroff Power-off the machine\n"
4218 " -r --reboot Reboot the machine\n"
4219 " -h Equivalent to --poweroff, overridden by --halt\n"
4220 " -k Don't halt/power-off/reboot, just send warnings\n"
4221 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4222 " -c Cancel a pending shutdown\n",
4223 program_invocation_short_name);
4228 static int telinit_help(void) {
4230 printf("%s [OPTIONS...] {COMMAND}\n\n"
4231 "Send control commands to the init daemon.\n\n"
4232 " --help Show this help\n"
4233 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4235 " 0 Power-off the machine\n"
4236 " 6 Reboot the machine\n"
4237 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4238 " 1, s, S Enter rescue mode\n"
4239 " q, Q Reload init daemon configuration\n"
4240 " u, U Reexecute init daemon\n",
4241 program_invocation_short_name);
4246 static int runlevel_help(void) {
4248 printf("%s [OPTIONS...]\n\n"
4249 "Prints the previous and current runlevel of the init system.\n\n"
4250 " --help Show this help\n",
4251 program_invocation_short_name);
4256 static int help_types(void) {
4259 puts("Available unit types:");
4260 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4261 if (unit_type_table[i])
4262 puts(unit_type_table[i]);
4264 puts("\nAvailable unit load states: ");
4265 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4266 if (unit_type_table[i])
4267 puts(unit_load_state_table[i]);
4272 static int systemctl_parse_argv(int argc, char *argv[]) {
4276 ARG_IGNORE_DEPENDENCIES,
4289 ARG_NO_ASK_PASSWORD,
4295 static const struct option options[] = {
4296 { "help", no_argument, NULL, 'h' },
4297 { "version", no_argument, NULL, ARG_VERSION },
4298 { "type", required_argument, NULL, 't' },
4299 { "property", required_argument, NULL, 'p' },
4300 { "all", no_argument, NULL, 'a' },
4301 { "failed", no_argument, NULL, ARG_FAILED },
4302 { "full", no_argument, NULL, ARG_FULL },
4303 { "fail", no_argument, NULL, ARG_FAIL },
4304 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4305 { "ignore-inhibitors", no_argument, NULL, 'i' },
4306 { "user", no_argument, NULL, ARG_USER },
4307 { "system", no_argument, NULL, ARG_SYSTEM },
4308 { "global", no_argument, NULL, ARG_GLOBAL },
4309 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4310 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4311 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4312 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4313 { "quiet", no_argument, NULL, 'q' },
4314 { "root", required_argument, NULL, ARG_ROOT },
4315 { "force", no_argument, NULL, ARG_FORCE },
4316 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4317 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4318 { "signal", required_argument, NULL, 's' },
4319 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4320 { "host", required_argument, NULL, 'H' },
4321 { "privileged",no_argument, NULL, 'P' },
4322 { "runtime", no_argument, NULL, ARG_RUNTIME },
4323 { "lines", required_argument, NULL, 'n' },
4324 { "output", required_argument, NULL, 'o' },
4325 { NULL, 0, NULL, 0 }
4333 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4342 puts(PACKAGE_STRING);
4343 puts(SYSTEMD_FEATURES);
4347 if (streq(optarg, "help")) {
4352 if (unit_type_from_string(optarg) >= 0) {
4356 if (unit_load_state_from_string(optarg) >= 0) {
4357 arg_load_state = optarg;
4360 log_error("Unkown unit type or load state '%s'.",
4362 log_info("Use -t help to see a list of allowed values.");
4367 if (!(l = strv_append(arg_property, optarg)))
4370 strv_free(arg_property);
4373 /* If the user asked for a particular
4374 * property, show it to him, even if it is
4385 arg_job_mode = "fail";
4388 case ARG_IGNORE_DEPENDENCIES:
4389 arg_job_mode = "ignore-dependencies";
4393 arg_scope = UNIT_FILE_USER;
4397 arg_scope = UNIT_FILE_SYSTEM;
4401 arg_scope = UNIT_FILE_GLOBAL;
4405 arg_no_block = true;
4409 arg_no_legend = true;
4413 arg_no_pager = true;
4445 arg_no_reload = true;
4449 arg_kill_who = optarg;
4453 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4454 log_error("Failed to parse signal string %s.", optarg);
4459 case ARG_NO_ASK_PASSWORD:
4460 arg_ask_password = false;
4464 arg_transport = TRANSPORT_POLKIT;
4468 arg_transport = TRANSPORT_SSH;
4477 if (safe_atou(optarg, &arg_lines) < 0) {
4478 log_error("Failed to parse lines '%s'", optarg);
4484 arg_output = output_mode_from_string(optarg);
4485 if (arg_output < 0) {
4486 log_error("Unknown output '%s'.", optarg);
4492 arg_ignore_inhibitors = true;
4499 log_error("Unknown option code '%c'.", c);
4504 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4505 log_error("Cannot access user instance remotely.");
4512 static int halt_parse_argv(int argc, char *argv[]) {
4521 static const struct option options[] = {
4522 { "help", no_argument, NULL, ARG_HELP },
4523 { "halt", no_argument, NULL, ARG_HALT },
4524 { "poweroff", no_argument, NULL, 'p' },
4525 { "reboot", no_argument, NULL, ARG_REBOOT },
4526 { "force", no_argument, NULL, 'f' },
4527 { "wtmp-only", no_argument, NULL, 'w' },
4528 { "no-wtmp", no_argument, NULL, 'd' },
4529 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4530 { NULL, 0, NULL, 0 }
4538 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4539 if (runlevel == '0' || runlevel == '6')
4542 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4550 arg_action = ACTION_HALT;
4554 if (arg_action != ACTION_REBOOT)
4555 arg_action = ACTION_POWEROFF;
4559 arg_action = ACTION_REBOOT;
4581 /* Compatibility nops */
4588 log_error("Unknown option code '%c'.", c);
4593 if (optind < argc) {
4594 log_error("Too many arguments.");
4601 static int parse_time_spec(const char *t, usec_t *_u) {
4605 if (streq(t, "now"))
4607 else if (!strchr(t, ':')) {
4610 if (safe_atou64(t, &u) < 0)
4613 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4622 hour = strtol(t, &e, 10);
4623 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4626 minute = strtol(e+1, &e, 10);
4627 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4630 n = now(CLOCK_REALTIME);
4631 s = (time_t) (n / USEC_PER_SEC);
4634 assert_se(localtime_r(&s, &tm));
4636 tm.tm_hour = (int) hour;
4637 tm.tm_min = (int) minute;
4640 assert_se(s = mktime(&tm));
4642 *_u = (usec_t) s * USEC_PER_SEC;
4645 *_u += USEC_PER_DAY;
4651 static int shutdown_parse_argv(int argc, char *argv[]) {
4658 static const struct option options[] = {
4659 { "help", no_argument, NULL, ARG_HELP },
4660 { "halt", no_argument, NULL, 'H' },
4661 { "poweroff", no_argument, NULL, 'P' },
4662 { "reboot", no_argument, NULL, 'r' },
4663 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4664 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4665 { NULL, 0, NULL, 0 }
4673 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4681 arg_action = ACTION_HALT;
4685 arg_action = ACTION_POWEROFF;
4690 arg_action = ACTION_KEXEC;
4692 arg_action = ACTION_REBOOT;
4696 arg_action = ACTION_KEXEC;
4700 if (arg_action != ACTION_HALT)
4701 arg_action = ACTION_POWEROFF;
4714 /* Compatibility nops */
4718 arg_action = ACTION_CANCEL_SHUTDOWN;
4725 log_error("Unknown option code '%c'.", c);
4730 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4731 r = parse_time_spec(argv[optind], &arg_when);
4733 log_error("Failed to parse time specification: %s", argv[optind]);
4737 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4739 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4740 /* No time argument for shutdown cancel */
4741 arg_wall = argv + optind;
4742 else if (argc > optind + 1)
4743 /* We skip the time argument */
4744 arg_wall = argv + optind + 1;
4751 static int telinit_parse_argv(int argc, char *argv[]) {
4758 static const struct option options[] = {
4759 { "help", no_argument, NULL, ARG_HELP },
4760 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4761 { NULL, 0, NULL, 0 }
4764 static const struct {
4768 { '0', ACTION_POWEROFF },
4769 { '6', ACTION_REBOOT },
4770 { '1', ACTION_RESCUE },
4771 { '2', ACTION_RUNLEVEL2 },
4772 { '3', ACTION_RUNLEVEL3 },
4773 { '4', ACTION_RUNLEVEL4 },
4774 { '5', ACTION_RUNLEVEL5 },
4775 { 's', ACTION_RESCUE },
4776 { 'S', ACTION_RESCUE },
4777 { 'q', ACTION_RELOAD },
4778 { 'Q', ACTION_RELOAD },
4779 { 'u', ACTION_REEXEC },
4780 { 'U', ACTION_REEXEC }
4789 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4804 log_error("Unknown option code '%c'.", c);
4809 if (optind >= argc) {
4814 if (optind + 1 < argc) {
4815 log_error("Too many arguments.");
4819 if (strlen(argv[optind]) != 1) {
4820 log_error("Expected single character argument.");
4824 for (i = 0; i < ELEMENTSOF(table); i++)
4825 if (table[i].from == argv[optind][0])
4828 if (i >= ELEMENTSOF(table)) {
4829 log_error("Unknown command '%s'.", argv[optind]);
4833 arg_action = table[i].to;
4840 static int runlevel_parse_argv(int argc, char *argv[]) {
4846 static const struct option options[] = {
4847 { "help", no_argument, NULL, ARG_HELP },
4848 { NULL, 0, NULL, 0 }
4856 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4867 log_error("Unknown option code '%c'.", c);
4872 if (optind < argc) {
4873 log_error("Too many arguments.");
4880 static int parse_argv(int argc, char *argv[]) {
4884 if (program_invocation_short_name) {
4886 if (strstr(program_invocation_short_name, "halt")) {
4887 arg_action = ACTION_HALT;
4888 return halt_parse_argv(argc, argv);
4889 } else if (strstr(program_invocation_short_name, "poweroff")) {
4890 arg_action = ACTION_POWEROFF;
4891 return halt_parse_argv(argc, argv);
4892 } else if (strstr(program_invocation_short_name, "reboot")) {
4894 arg_action = ACTION_KEXEC;
4896 arg_action = ACTION_REBOOT;
4897 return halt_parse_argv(argc, argv);
4898 } else if (strstr(program_invocation_short_name, "shutdown")) {
4899 arg_action = ACTION_POWEROFF;
4900 return shutdown_parse_argv(argc, argv);
4901 } else if (strstr(program_invocation_short_name, "init")) {
4903 if (sd_booted() > 0) {
4904 arg_action = ACTION_INVALID;
4905 return telinit_parse_argv(argc, argv);
4907 /* Hmm, so some other init system is
4908 * running, we need to forward this
4909 * request to it. For now we simply
4910 * guess that it is Upstart. */
4912 execv("/lib/upstart/telinit", argv);
4914 log_error("Couldn't find an alternative telinit implementation to spawn.");
4918 } else if (strstr(program_invocation_short_name, "runlevel")) {
4919 arg_action = ACTION_RUNLEVEL;
4920 return runlevel_parse_argv(argc, argv);
4924 arg_action = ACTION_SYSTEMCTL;
4925 return systemctl_parse_argv(argc, argv);
4928 static int action_to_runlevel(void) {
4930 static const char table[_ACTION_MAX] = {
4931 [ACTION_HALT] = '0',
4932 [ACTION_POWEROFF] = '0',
4933 [ACTION_REBOOT] = '6',
4934 [ACTION_RUNLEVEL2] = '2',
4935 [ACTION_RUNLEVEL3] = '3',
4936 [ACTION_RUNLEVEL4] = '4',
4937 [ACTION_RUNLEVEL5] = '5',
4938 [ACTION_RESCUE] = '1'
4941 assert(arg_action < _ACTION_MAX);
4943 return table[arg_action];
4946 static int talk_upstart(void) {
4947 DBusMessage *m = NULL, *reply = NULL;
4949 int previous, rl, r;
4951 env1_buf[] = "RUNLEVEL=X",
4952 env2_buf[] = "PREVLEVEL=X";
4953 char *env1 = env1_buf, *env2 = env2_buf;
4954 const char *emit = "runlevel";
4955 dbus_bool_t b_false = FALSE;
4956 DBusMessageIter iter, sub;
4957 DBusConnection *bus;
4959 dbus_error_init(&error);
4961 if (!(rl = action_to_runlevel()))
4964 if (utmp_get_runlevel(&previous, NULL) < 0)
4967 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4968 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4973 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4978 if ((r = bus_check_peercred(bus)) < 0) {
4979 log_error("Failed to verify owner of bus.");
4983 if (!(m = dbus_message_new_method_call(
4984 "com.ubuntu.Upstart",
4985 "/com/ubuntu/Upstart",
4986 "com.ubuntu.Upstart0_6",
4989 log_error("Could not allocate message.");
4994 dbus_message_iter_init_append(m, &iter);
4996 env1_buf[sizeof(env1_buf)-2] = rl;
4997 env2_buf[sizeof(env2_buf)-2] = previous;
4999 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5000 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5001 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5002 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5003 !dbus_message_iter_close_container(&iter, &sub) ||
5004 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5005 log_error("Could not append arguments to message.");
5010 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5012 if (bus_error_is_no_service(&error)) {
5017 log_error("Failed to issue method call: %s", bus_error_message(&error));
5026 dbus_message_unref(m);
5029 dbus_message_unref(reply);
5032 dbus_connection_flush(bus);
5033 dbus_connection_close(bus);
5034 dbus_connection_unref(bus);
5037 dbus_error_free(&error);
5042 static int talk_initctl(void) {
5043 struct init_request request;
5047 if (!(rl = action_to_runlevel()))
5051 request.magic = INIT_MAGIC;
5052 request.sleeptime = 0;
5053 request.cmd = INIT_CMD_RUNLVL;
5054 request.runlevel = rl;
5056 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5058 if (errno == ENOENT)
5061 log_error("Failed to open "INIT_FIFO": %m");
5066 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5067 close_nointr_nofail(fd);
5070 log_error("Failed to write to "INIT_FIFO": %m");
5071 return errno ? -errno : -EIO;
5077 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5079 static const struct {
5087 int (* const dispatch)(DBusConnection *bus, char **args);
5089 { "list-units", LESS, 1, list_units },
5090 { "list-unit-files", EQUAL, 1, list_unit_files },
5091 { "list-jobs", EQUAL, 1, list_jobs },
5092 { "clear-jobs", EQUAL, 1, daemon_reload },
5093 { "load", MORE, 2, load_unit },
5094 { "cancel", MORE, 2, cancel_job },
5095 { "start", MORE, 2, start_unit },
5096 { "stop", MORE, 2, start_unit },
5097 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5098 { "reload", MORE, 2, start_unit },
5099 { "restart", MORE, 2, start_unit },
5100 { "try-restart", MORE, 2, start_unit },
5101 { "reload-or-restart", MORE, 2, start_unit },
5102 { "reload-or-try-restart", MORE, 2, start_unit },
5103 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5104 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5105 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5106 { "isolate", EQUAL, 2, start_unit },
5107 { "set-cgroup", MORE, 2, set_cgroup },
5108 { "unset-cgroup", MORE, 2, set_cgroup },
5109 { "get-cgroup-attr", MORE, 2, get_cgroup_attr },
5110 { "set-cgroup-attr", MORE, 2, set_cgroup_attr },
5111 { "unset-cgroup-attr", MORE, 2, set_cgroup },
5112 { "kill", MORE, 2, kill_unit },
5113 { "is-active", MORE, 2, check_unit_active },
5114 { "check", MORE, 2, check_unit_active },
5115 { "is-failed", MORE, 2, check_unit_failed },
5116 { "show", MORE, 1, show },
5117 { "status", MORE, 2, show },
5118 { "help", MORE, 2, show },
5119 { "dump", EQUAL, 1, dump },
5120 { "snapshot", LESS, 2, snapshot },
5121 { "delete", MORE, 2, delete_snapshot },
5122 { "daemon-reload", EQUAL, 1, daemon_reload },
5123 { "daemon-reexec", EQUAL, 1, daemon_reload },
5124 { "show-environment", EQUAL, 1, show_enviroment },
5125 { "set-environment", MORE, 2, set_environment },
5126 { "unset-environment", MORE, 2, set_environment },
5127 { "halt", EQUAL, 1, start_special },
5128 { "poweroff", EQUAL, 1, start_special },
5129 { "reboot", EQUAL, 1, start_special },
5130 { "kexec", EQUAL, 1, start_special },
5131 { "suspend", EQUAL, 1, start_special },
5132 { "hibernate", EQUAL, 1, start_special },
5133 { "hybrid-sleep", EQUAL, 1, start_special },
5134 { "default", EQUAL, 1, start_special },
5135 { "rescue", EQUAL, 1, start_special },
5136 { "emergency", EQUAL, 1, start_special },
5137 { "exit", EQUAL, 1, start_special },
5138 { "reset-failed", MORE, 1, reset_failed },
5139 { "enable", MORE, 2, enable_unit },
5140 { "disable", MORE, 2, enable_unit },
5141 { "is-enabled", MORE, 2, unit_is_enabled },
5142 { "reenable", MORE, 2, enable_unit },
5143 { "preset", MORE, 2, enable_unit },
5144 { "mask", MORE, 2, enable_unit },
5145 { "unmask", MORE, 2, enable_unit },
5146 { "link", MORE, 2, enable_unit },
5147 { "switch-root", MORE, 2, switch_root },
5148 { "list-dependencies", LESS, 2, list_dependencies },
5158 left = argc - optind;
5161 /* Special rule: no arguments means "list-units" */
5164 if (streq(argv[optind], "help") && !argv[optind+1]) {
5165 log_error("This command expects one or more "
5166 "unit names. Did you mean --help?");
5170 for (i = 0; i < ELEMENTSOF(verbs); i++)
5171 if (streq(argv[optind], verbs[i].verb))
5174 if (i >= ELEMENTSOF(verbs)) {
5175 log_error("Unknown operation '%s'.", argv[optind]);
5180 switch (verbs[i].argc_cmp) {
5183 if (left != verbs[i].argc) {
5184 log_error("Invalid number of arguments.");
5191 if (left < verbs[i].argc) {
5192 log_error("Too few arguments.");
5199 if (left > verbs[i].argc) {
5200 log_error("Too many arguments.");
5207 assert_not_reached("Unknown comparison operator.");
5210 /* Require a bus connection for all operations but
5212 if (!streq(verbs[i].verb, "enable") &&
5213 !streq(verbs[i].verb, "disable") &&
5214 !streq(verbs[i].verb, "is-enabled") &&
5215 !streq(verbs[i].verb, "list-unit-files") &&
5216 !streq(verbs[i].verb, "reenable") &&
5217 !streq(verbs[i].verb, "preset") &&
5218 !streq(verbs[i].verb, "mask") &&
5219 !streq(verbs[i].verb, "unmask") &&
5220 !streq(verbs[i].verb, "link")) {
5222 if (running_in_chroot() > 0) {
5223 log_info("Running in chroot, ignoring request.");
5227 if (((!streq(verbs[i].verb, "reboot") &&
5228 !streq(verbs[i].verb, "halt") &&
5229 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5230 log_error("Failed to get D-Bus connection: %s",
5231 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5237 if (!bus && !avoid_bus()) {
5238 log_error("Failed to get D-Bus connection: %s",
5239 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5244 return verbs[i].dispatch(bus, argv + optind);
5247 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5249 struct msghdr msghdr;
5250 struct iovec iovec[2];
5251 union sockaddr_union sockaddr;
5252 struct sd_shutdown_command c;
5254 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5261 c.dry_run = dry_run;
5265 sockaddr.sa.sa_family = AF_UNIX;
5266 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5269 msghdr.msg_name = &sockaddr;
5270 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5273 iovec[0].iov_base = (char*) &c;
5274 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5276 if (isempty(message))
5277 msghdr.msg_iovlen = 1;
5279 iovec[1].iov_base = (char*) message;
5280 iovec[1].iov_len = strlen(message);
5281 msghdr.msg_iovlen = 2;
5283 msghdr.msg_iov = iovec;
5285 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5286 close_nointr_nofail(fd);
5290 close_nointr_nofail(fd);
5294 static int reload_with_fallback(DBusConnection *bus) {
5297 /* First, try systemd via D-Bus. */
5298 if (daemon_reload(bus, NULL) >= 0)
5302 /* Nothing else worked, so let's try signals */
5303 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5305 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5306 log_error("kill() failed: %m");
5313 static int start_with_fallback(DBusConnection *bus) {
5316 /* First, try systemd via D-Bus. */
5317 if (start_unit(bus, NULL) >= 0)
5321 /* Hmm, talking to systemd via D-Bus didn't work. Then
5322 * let's try to talk to Upstart via D-Bus. */
5323 if (talk_upstart() > 0)
5326 /* Nothing else worked, so let's try
5328 if (talk_initctl() > 0)
5331 log_error("Failed to talk to init daemon.");
5335 warn_wall(arg_action);
5339 static _noreturn_ void halt_now(enum action a) {
5341 /* Make sure C-A-D is handled by the kernel from this
5343 reboot(RB_ENABLE_CAD);
5348 log_info("Halting.");
5349 reboot(RB_HALT_SYSTEM);
5352 case ACTION_POWEROFF:
5353 log_info("Powering off.");
5354 reboot(RB_POWER_OFF);
5358 log_info("Rebooting.");
5359 reboot(RB_AUTOBOOT);
5363 assert_not_reached("Unknown halt action.");
5366 assert_not_reached("Uh? This shouldn't happen.");
5369 static int halt_main(DBusConnection *bus) {
5372 r = check_inhibitors(bus, arg_action);
5376 if (geteuid() != 0) {
5377 /* Try logind if we are a normal user and no special
5378 * mode applies. Maybe PolicyKit allows us to shutdown
5381 if (arg_when <= 0 &&
5384 (arg_action == ACTION_POWEROFF ||
5385 arg_action == ACTION_REBOOT)) {
5386 r = reboot_with_logind(bus, arg_action);
5391 log_error("Must be root.");
5398 m = strv_join(arg_wall, " ");
5399 r = send_shutdownd(arg_when,
5400 arg_action == ACTION_HALT ? 'H' :
5401 arg_action == ACTION_POWEROFF ? 'P' :
5402 arg_action == ACTION_KEXEC ? 'K' :
5410 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5412 char date[FORMAT_TIMESTAMP_MAX];
5414 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5415 format_timestamp(date, sizeof(date), arg_when));
5420 if (!arg_dry && !arg_force)
5421 return start_with_fallback(bus);
5424 if (sd_booted() > 0)
5425 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5427 r = utmp_put_shutdown();
5429 log_warning("Failed to write utmp record: %s", strerror(-r));
5436 halt_now(arg_action);
5437 /* We should never reach this. */
5441 static int runlevel_main(void) {
5442 int r, runlevel, previous;
5444 r = utmp_get_runlevel(&runlevel, &previous);
5451 previous <= 0 ? 'N' : previous,
5452 runlevel <= 0 ? 'N' : runlevel);
5457 int main(int argc, char*argv[]) {
5458 int r, retval = EXIT_FAILURE;
5459 DBusConnection *bus = NULL;
5462 dbus_error_init(&error);
5464 setlocale(LC_ALL, "");
5465 log_parse_environment();
5468 r = parse_argv(argc, argv);
5472 retval = EXIT_SUCCESS;
5476 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5477 * let's shortcut this */
5478 if (arg_action == ACTION_RUNLEVEL) {
5479 r = runlevel_main();
5480 retval = r < 0 ? EXIT_FAILURE : r;
5484 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5485 log_info("Running in chroot, ignoring request.");
5491 if (arg_transport == TRANSPORT_NORMAL)
5492 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5493 else if (arg_transport == TRANSPORT_POLKIT) {
5494 bus_connect_system_polkit(&bus, &error);
5495 private_bus = false;
5496 } else if (arg_transport == TRANSPORT_SSH) {
5497 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5498 private_bus = false;
5500 assert_not_reached("Uh, invalid transport...");
5503 switch (arg_action) {
5505 case ACTION_SYSTEMCTL:
5506 r = systemctl_main(bus, argc, argv, &error);
5510 case ACTION_POWEROFF:
5516 case ACTION_RUNLEVEL2:
5517 case ACTION_RUNLEVEL3:
5518 case ACTION_RUNLEVEL4:
5519 case ACTION_RUNLEVEL5:
5521 case ACTION_EMERGENCY:
5522 case ACTION_DEFAULT:
5523 r = start_with_fallback(bus);
5528 r = reload_with_fallback(bus);
5531 case ACTION_CANCEL_SHUTDOWN: {
5535 m = strv_join(arg_wall, " ");
5537 retval = EXIT_FAILURE;
5541 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5543 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5548 case ACTION_INVALID:
5549 case ACTION_RUNLEVEL:
5551 assert_not_reached("Unknown action");
5554 retval = r < 0 ? EXIT_FAILURE : r;
5558 dbus_connection_flush(bus);
5559 dbus_connection_close(bus);
5560 dbus_connection_unref(bus);
5563 dbus_error_free(&error);
5567 strv_free(arg_property);
5570 ask_password_agent_close();
5571 polkit_agent_close();