1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/reboot.h>
29 #include <sys/ioctl.h>
33 #include <sys/socket.h>
36 #include <sys/prctl.h>
37 #include <dbus/dbus.h>
39 #include <systemd/sd-daemon.h>
40 #include <systemd/sd-shutdown.h>
41 #include <systemd/sd-login.h>
47 #include "utmp-wtmp.h"
50 #include "path-util.h"
52 #include "dbus-common.h"
53 #include "cgroup-show.h"
54 #include "cgroup-util.h"
56 #include "path-lookup.h"
57 #include "conf-parser.h"
58 #include "exit-status.h"
59 #include "bus-errors.h"
61 #include "unit-name.h"
63 #include "spawn-ask-password-agent.h"
64 #include "spawn-polkit-agent.h"
66 #include "logs-show.h"
67 #include "path-util.h"
68 #include "socket-util.h"
71 static const char *arg_type = NULL;
72 static const char *arg_load_state = NULL;
73 static char **arg_property = NULL;
74 static bool arg_all = false;
75 static const char *arg_job_mode = "replace";
76 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
77 static bool arg_no_block = false;
78 static bool arg_no_legend = false;
79 static bool arg_no_pager = false;
80 static bool arg_no_wtmp = false;
81 static bool arg_no_wall = false;
82 static bool arg_no_reload = false;
83 static bool arg_ignore_inhibitors = false;
84 static bool arg_dry = false;
85 static bool arg_quiet = false;
86 static bool arg_full = false;
87 static int arg_force = 0;
88 static bool arg_ask_password = true;
89 static bool arg_failed = false;
90 static bool arg_runtime = false;
91 static char **arg_wall = NULL;
92 static const char *arg_kill_who = NULL;
93 static int arg_signal = SIGTERM;
94 static const char *arg_root = NULL;
95 static usec_t arg_when = 0;
117 ACTION_CANCEL_SHUTDOWN,
119 } arg_action = ACTION_SYSTEMCTL;
120 static enum transport {
124 } arg_transport = TRANSPORT_NORMAL;
125 static const char *arg_host = NULL;
126 static unsigned arg_lines = 10;
127 static OutputMode arg_output = OUTPUT_SHORT;
129 static bool private_bus = false;
131 static int daemon_reload(DBusConnection *bus, char **args);
132 static void halt_now(enum action a);
134 static void pager_open_if_enabled(void) {
142 static void ask_password_agent_open_if_enabled(void) {
144 /* Open the password agent as a child process if necessary */
146 if (!arg_ask_password)
149 if (arg_scope != UNIT_FILE_SYSTEM)
152 ask_password_agent_open();
156 static void polkit_agent_open_if_enabled(void) {
158 /* Open the polkit agent as a child process if necessary */
160 if (!arg_ask_password)
163 if (arg_scope != UNIT_FILE_SYSTEM)
170 static const char *ansi_highlight(bool b) {
175 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
178 static const char *ansi_highlight_red(bool b) {
183 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
186 static const char *ansi_highlight_green(bool b) {
191 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
194 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
197 if (!dbus_error_is_set(error))
200 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
201 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
202 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
203 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
204 return EXIT_NOPERMISSION;
206 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
207 return EXIT_NOTINSTALLED;
209 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
210 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
211 return EXIT_NOTIMPLEMENTED;
213 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
214 return EXIT_NOTCONFIGURED;
222 static void warn_wall(enum action a) {
223 static const char *table[_ACTION_MAX] = {
224 [ACTION_HALT] = "The system is going down for system halt NOW!",
225 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
226 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
227 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
228 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
229 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
230 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
237 _cleanup_free_ char *p;
239 p = strv_join(arg_wall, " ");
254 utmp_wall(table[a], NULL);
257 static bool avoid_bus(void) {
259 if (running_in_chroot() > 0)
262 if (sd_booted() <= 0)
265 if (!isempty(arg_root))
268 if (arg_scope == UNIT_FILE_GLOBAL)
274 static int compare_unit_info(const void *a, const void *b) {
276 const struct unit_info *u = a, *v = b;
278 d1 = strrchr(u->id, '.');
279 d2 = strrchr(v->id, '.');
284 r = strcasecmp(d1, d2);
289 return strcasecmp(u->id, v->id);
292 static bool output_show_unit(const struct unit_info *u) {
296 return streq(u->active_state, "failed");
298 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
299 streq(dot+1, arg_type))) &&
300 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
301 (arg_all || !(streq(u->active_state, "inactive")
302 || u->following[0]) || u->job_id > 0);
305 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
306 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
307 const struct unit_info *u;
310 max_id_len = sizeof("UNIT")-1;
311 active_len = sizeof("ACTIVE")-1;
312 sub_len = sizeof("SUB")-1;
313 job_len = sizeof("JOB")-1;
316 for (u = unit_infos; u < unit_infos + c; u++) {
317 if (!output_show_unit(u))
320 max_id_len = MAX(max_id_len, strlen(u->id));
321 active_len = MAX(active_len, strlen(u->active_state));
322 sub_len = MAX(sub_len, strlen(u->sub_state));
323 if (u->job_id != 0) {
324 job_len = MAX(job_len, strlen(u->job_type));
331 id_len = MIN(max_id_len, 25);
332 basic_len = 5 + id_len + 5 + active_len + sub_len;
334 basic_len += job_len + 1;
335 if (basic_len < (unsigned) columns()) {
336 unsigned extra_len, incr;
337 extra_len = columns() - basic_len;
338 /* Either UNIT already got 25, or is fully satisfied.
339 * Grant up to 25 to DESC now. */
340 incr = MIN(extra_len, 25);
343 /* split the remaining space between UNIT and DESC,
344 * but do not give UNIT more than it needs. */
346 incr = MIN(extra_len / 2, max_id_len - id_len);
348 desc_len += extra_len - incr;
354 for (u = unit_infos; u < unit_infos + c; u++) {
355 char _cleanup_free_ *e = NULL;
356 const char *on_loaded, *off_loaded;
357 const char *on_active, *off_active;
359 if (!output_show_unit(u))
362 if (!n_shown && !arg_no_legend) {
363 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
364 active_len, "ACTIVE", sub_len, "SUB");
366 printf("%-*s ", job_len, "JOB");
367 if (!arg_full && arg_no_pager)
368 printf("%.*s\n", desc_len, "DESCRIPTION");
370 printf("%s\n", "DESCRIPTION");
375 if (streq(u->load_state, "error")) {
376 on_loaded = ansi_highlight_red(true);
377 off_loaded = ansi_highlight_red(false);
379 on_loaded = off_loaded = "";
381 if (streq(u->active_state, "failed")) {
382 on_active = ansi_highlight_red(true);
383 off_active = ansi_highlight_red(false);
385 on_active = off_active = "";
387 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
389 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s",
390 id_len, e ? e : u->id,
391 on_loaded, u->load_state, off_loaded,
392 on_active, active_len, u->active_state,
393 sub_len, u->sub_state, off_active,
394 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
395 if (!arg_full && arg_no_pager)
396 printf("%.*s\n", desc_len, u->description);
398 printf("%s\n", u->description);
401 if (!arg_no_legend) {
402 const char *on, *off;
405 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
406 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
407 "SUB = The low-level unit activation state, values depend on unit type.\n");
409 printf("JOB = Pending job for the unit.\n");
411 on = ansi_highlight(true);
412 off = ansi_highlight(false);
414 on = ansi_highlight_red(true);
415 off = ansi_highlight_red(false);
419 printf("%s%u loaded units listed.%s\n"
420 "To show all installed unit files use 'systemctl list-unit-files'.\n",
423 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
424 "To show all installed unit files use 'systemctl list-unit-files'.\n",
429 static int list_units(DBusConnection *bus, char **args) {
430 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
431 _cleanup_free_ struct unit_info *unit_infos = NULL;
432 DBusMessageIter iter, sub;
433 unsigned c = 0, n_units = 0;
436 pager_open_if_enabled();
438 r = bus_method_call_with_reply(
440 "org.freedesktop.systemd1",
441 "/org/freedesktop/systemd1",
442 "org.freedesktop.systemd1.Manager",
450 if (!dbus_message_iter_init(reply, &iter) ||
451 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
452 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
453 log_error("Failed to parse reply.");
457 dbus_message_iter_recurse(&iter, &sub);
459 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
465 n_units = MAX(2*c, 16);
466 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
475 bus_parse_unit_info(&sub, u);
477 dbus_message_iter_next(&sub);
482 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
483 output_units_list(unit_infos, c);
489 static int compare_unit_file_list(const void *a, const void *b) {
491 const UnitFileList *u = a, *v = b;
493 d1 = strrchr(u->path, '.');
494 d2 = strrchr(v->path, '.');
499 r = strcasecmp(d1, d2);
504 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
507 static bool output_show_unit_file(const UnitFileList *u) {
510 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
513 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
514 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
515 const UnitFileList *u;
517 max_id_len = sizeof("UNIT FILE")-1;
518 state_cols = sizeof("STATE")-1;
519 for (u = units; u < units + c; u++) {
520 if (!output_show_unit_file(u))
523 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
524 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
529 id_cols = MIN(max_id_len, 25);
530 basic_cols = 1 + id_cols + state_cols;
531 if (basic_cols < (unsigned) columns())
532 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
534 id_cols = max_id_len;
537 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
539 for (u = units; u < units + c; u++) {
540 char _cleanup_free_ *e = NULL;
541 const char *on, *off;
544 if (!output_show_unit_file(u))
549 if (u->state == UNIT_FILE_MASKED ||
550 u->state == UNIT_FILE_MASKED_RUNTIME ||
551 u->state == UNIT_FILE_DISABLED ||
552 u->state == UNIT_FILE_INVALID) {
553 on = ansi_highlight_red(true);
554 off = ansi_highlight_red(false);
555 } else if (u->state == UNIT_FILE_ENABLED) {
556 on = ansi_highlight_green(true);
557 off = ansi_highlight_green(false);
561 id = path_get_file_name(u->path);
563 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
565 printf("%-*s %s%-*s%s\n",
567 on, state_cols, unit_file_state_to_string(u->state), off);
571 printf("\n%u unit files listed.\n", n_shown);
574 static int list_unit_files(DBusConnection *bus, char **args) {
575 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
576 _cleanup_free_ UnitFileList *units = NULL;
577 DBusMessageIter iter, sub, sub2;
578 unsigned c = 0, n_units = 0;
581 pager_open_if_enabled();
588 h = hashmap_new(string_hash_func, string_compare_func);
592 r = unit_file_get_list(arg_scope, arg_root, h);
594 unit_file_list_free(h);
595 log_error("Failed to get unit file list: %s", strerror(-r));
599 n_units = hashmap_size(h);
600 units = new(UnitFileList, n_units);
602 unit_file_list_free(h);
606 HASHMAP_FOREACH(u, h, i) {
607 memcpy(units + c++, u, sizeof(UnitFileList));
613 r = bus_method_call_with_reply(
615 "org.freedesktop.systemd1",
616 "/org/freedesktop/systemd1",
617 "org.freedesktop.systemd1.Manager",
625 if (!dbus_message_iter_init(reply, &iter) ||
626 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
627 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
628 log_error("Failed to parse reply.");
632 dbus_message_iter_recurse(&iter, &sub);
634 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
638 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
643 n_units = MAX(2*c, 16);
644 w = realloc(units, sizeof(struct UnitFileList) * n_units);
653 dbus_message_iter_recurse(&sub, &sub2);
655 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
656 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
657 log_error("Failed to parse reply.");
661 u->state = unit_file_state_from_string(state);
663 dbus_message_iter_next(&sub);
669 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
670 output_unit_file_list(units, c);
676 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
678 _cleanup_free_ char *n = NULL;
680 size_t max_len = MAX(columns(),20);
682 for (i = level - 1; i >= 0; i--) {
684 if(len > max_len - 3 && !arg_full) {
685 printf("%s...\n",max_len % 2 ? "" : " ");
688 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
691 if(len > max_len - 3 && !arg_full) {
692 printf("%s...\n",max_len % 2 ? "" : " ");
695 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
698 printf("%s\n", name);
702 n = ellipsize(name, max_len-len, 100);
710 static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
711 static const char dependencies[] =
713 "RequiresOverridable\0"
715 "RequisiteOverridable\0"
718 _cleanup_free_ char *path;
719 const char *interface = "org.freedesktop.systemd1.Unit";
721 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
722 DBusMessageIter iter, sub, sub2, sub3;
731 path = unit_dbus_path_from_name(name);
737 r = bus_method_call_with_reply(
739 "org.freedesktop.systemd1",
741 "org.freedesktop.DBus.Properties",
745 DBUS_TYPE_STRING, &interface,
750 if (!dbus_message_iter_init(reply, &iter) ||
751 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
752 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
753 log_error("Failed to parse reply.");
758 dbus_message_iter_recurse(&iter, &sub);
760 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
763 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
764 dbus_message_iter_recurse(&sub, &sub2);
766 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
767 log_error("Failed to parse reply.");
772 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
773 log_error("Failed to parse reply.");
778 dbus_message_iter_recurse(&sub2, &sub3);
779 dbus_message_iter_next(&sub);
781 if (!nulstr_contains(dependencies, prop))
784 if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
785 if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
786 DBusMessageIter sub4;
787 dbus_message_iter_recurse(&sub3, &sub4);
789 while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
792 assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
793 dbus_message_iter_get_basic(&sub4, &s);
795 r = strv_extend(&ret, s);
801 dbus_message_iter_next(&sub4);
814 static int list_dependencies_compare(const void *_a, const void *_b) {
815 const char **a = (const char**) _a, **b = (const char**) _b;
816 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
818 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
820 return strcasecmp(*a, *b);
823 static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char **units, unsigned int branches) {
824 char _cleanup_strv_free_ **deps = NULL, **u;
828 u = strv_append(units, name);
832 r = list_dependencies_get_dependencies(bus, name, &deps);
836 qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
838 STRV_FOREACH(c, deps) {
839 if (strv_contains(u, *c)) {
840 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
846 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
850 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
851 r = list_dependencies_one(bus, *c, level + 1, u, (branches << 1) | (c[1] == NULL ? 0 : 1));
860 static int list_dependencies(DBusConnection *bus, char **args) {
861 _cleanup_free_ char *unit = NULL;
867 unit = unit_name_mangle(args[1]);
872 u = SPECIAL_DEFAULT_TARGET;
874 pager_open_if_enabled();
878 return list_dependencies_one(bus, u, 0, NULL, 0);
881 static int list_jobs(DBusConnection *bus, char **args) {
882 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
883 DBusMessageIter iter, sub, sub2;
887 pager_open_if_enabled();
889 r = bus_method_call_with_reply(
891 "org.freedesktop.systemd1",
892 "/org/freedesktop/systemd1",
893 "org.freedesktop.systemd1.Manager",
901 if (!dbus_message_iter_init(reply, &iter) ||
902 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
903 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
904 log_error("Failed to parse reply.");
908 dbus_message_iter_recurse(&iter, &sub);
911 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
913 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
914 const char *name, *type, *state, *job_path, *unit_path;
916 char _cleanup_free_ *e = NULL;
918 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
919 log_error("Failed to parse reply.");
923 dbus_message_iter_recurse(&sub, &sub2);
925 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
926 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
927 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
928 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
929 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
930 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
931 log_error("Failed to parse reply.");
935 e = arg_full ? NULL : ellipsize(name, 25, 33);
936 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
940 dbus_message_iter_next(&sub);
944 printf("\n%u jobs listed.\n", k);
949 static int load_unit(DBusConnection *bus, char **args) {
954 STRV_FOREACH(name, args+1) {
955 _cleanup_free_ char *n = NULL;
958 n = unit_name_mangle(*name);
962 r = bus_method_call_with_reply(
964 "org.freedesktop.systemd1",
965 "/org/freedesktop/systemd1",
966 "org.freedesktop.systemd1.Manager",
970 DBUS_TYPE_STRING, &n,
979 static int cancel_job(DBusConnection *bus, char **args) {
984 if (strv_length(args) <= 1)
985 return daemon_reload(bus, args);
987 STRV_FOREACH(name, args+1) {
991 r = safe_atou32(*name, &id);
993 log_error("Failed to parse job id: %s", strerror(-r));
997 r = bus_method_call_with_reply(
999 "org.freedesktop.systemd1",
1000 "/org/freedesktop/systemd1",
1001 "org.freedesktop.systemd1.Manager",
1005 DBUS_TYPE_UINT32, &id,
1014 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1015 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1016 dbus_bool_t b = FALSE;
1017 DBusMessageIter iter, sub;
1019 *interface = "org.freedesktop.systemd1.Unit",
1020 *property = "NeedDaemonReload",
1022 _cleanup_free_ char *n = NULL;
1025 /* We ignore all errors here, since this is used to show a warning only */
1027 n = unit_name_mangle(unit);
1031 r = bus_method_call_with_reply (
1033 "org.freedesktop.systemd1",
1034 "/org/freedesktop/systemd1",
1035 "org.freedesktop.systemd1.Manager",
1039 DBUS_TYPE_STRING, &n,
1044 if (!dbus_message_get_args(reply, NULL,
1045 DBUS_TYPE_OBJECT_PATH, &path,
1049 dbus_message_unref(reply);
1052 r = bus_method_call_with_reply(
1054 "org.freedesktop.systemd1",
1056 "org.freedesktop.DBus.Properties",
1060 DBUS_TYPE_STRING, &interface,
1061 DBUS_TYPE_STRING, &property,
1066 if (!dbus_message_iter_init(reply, &iter) ||
1067 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1070 dbus_message_iter_recurse(&iter, &sub);
1071 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1074 dbus_message_iter_get_basic(&sub, &b);
1078 typedef struct WaitData {
1085 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1086 DBusError _cleanup_dbus_error_free_ error;
1089 dbus_error_init(&error);
1095 log_debug("Got D-Bus request: %s.%s() on %s",
1096 dbus_message_get_interface(message),
1097 dbus_message_get_member(message),
1098 dbus_message_get_path(message));
1100 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1101 log_error("Warning! D-Bus connection terminated.");
1102 dbus_connection_close(connection);
1104 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1106 const char *path, *result, *unit;
1108 if (dbus_message_get_args(message, &error,
1109 DBUS_TYPE_UINT32, &id,
1110 DBUS_TYPE_OBJECT_PATH, &path,
1111 DBUS_TYPE_STRING, &unit,
1112 DBUS_TYPE_STRING, &result,
1113 DBUS_TYPE_INVALID)) {
1115 free(set_remove(d->set, (char*) path));
1117 if (!isempty(result))
1118 d->result = strdup(result);
1121 d->name = strdup(unit);
1123 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1126 dbus_error_free(&error);
1127 if (dbus_message_get_args(message, &error,
1128 DBUS_TYPE_UINT32, &id,
1129 DBUS_TYPE_OBJECT_PATH, &path,
1130 DBUS_TYPE_STRING, &result,
1131 DBUS_TYPE_INVALID)) {
1132 /* Compatibility with older systemd versions <
1133 * 183 during upgrades. This should be dropped
1135 free(set_remove(d->set, (char*) path));
1138 d->result = strdup(result);
1140 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1144 log_error("Failed to parse message: %s", bus_error_message(&error));
1147 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1150 static int enable_wait_for_jobs(DBusConnection *bus) {
1158 dbus_error_init(&error);
1159 dbus_bus_add_match(bus,
1161 "sender='org.freedesktop.systemd1',"
1162 "interface='org.freedesktop.systemd1.Manager',"
1163 "member='JobRemoved',"
1164 "path='/org/freedesktop/systemd1'",
1167 if (dbus_error_is_set(&error)) {
1168 log_error("Failed to add match: %s", bus_error_message(&error));
1169 dbus_error_free(&error);
1173 /* This is slightly dirty, since we don't undo the match registrations. */
1177 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1187 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1190 while (!set_isempty(s)) {
1192 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1193 log_error("Disconnected from bus.");
1194 return -ECONNREFUSED;
1201 if (streq(d.result, "timeout"))
1202 log_error("Job for %s timed out.", strna(d.name));
1203 else if (streq(d.result, "canceled"))
1204 log_error("Job for %s canceled.", strna(d.name));
1205 else if (streq(d.result, "dependency"))
1206 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1207 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1208 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1211 if (streq_ptr(d.result, "timeout"))
1213 else if (streq_ptr(d.result, "canceled"))
1215 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1226 dbus_connection_remove_filter(bus, wait_filter, &d);
1230 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1231 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1232 _cleanup_free_ char *n = NULL;
1233 DBusMessageIter iter, sub;
1235 *interface = "org.freedesktop.systemd1.Unit",
1236 *property = "ActiveState";
1237 const char *state, *path;
1243 dbus_error_init(&error);
1245 n = unit_name_mangle(name);
1249 r = bus_method_call_with_reply (
1251 "org.freedesktop.systemd1",
1252 "/org/freedesktop/systemd1",
1253 "org.freedesktop.systemd1.Manager",
1257 DBUS_TYPE_STRING, &n,
1260 dbus_error_free(&error);
1267 if (!dbus_message_get_args(reply, NULL,
1268 DBUS_TYPE_OBJECT_PATH, &path,
1269 DBUS_TYPE_INVALID)) {
1270 log_error("Failed to parse reply.");
1274 dbus_message_unref(reply);
1277 r = bus_method_call_with_reply(
1279 "org.freedesktop.systemd1",
1281 "org.freedesktop.DBus.Properties",
1285 DBUS_TYPE_STRING, &interface,
1286 DBUS_TYPE_STRING, &property,
1294 if (!dbus_message_iter_init(reply, &iter) ||
1295 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1296 log_error("Failed to parse reply.");
1300 dbus_message_iter_recurse(&iter, &sub);
1302 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1303 log_error("Failed to parse reply.");
1307 dbus_message_iter_get_basic(&sub, &state);
1312 return strv_find(check_states, state) ? 1 : 0;
1315 static void check_triggering_units(
1316 DBusConnection *bus,
1317 const char *unit_name) {
1319 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1320 DBusMessageIter iter, sub;
1321 const char *interface = "org.freedesktop.systemd1.Unit",
1322 *triggered_by_property = "TriggeredBy";
1323 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1324 bool print_warning_label = true;
1327 n = unit_name_mangle(unit_name);
1333 unit_path = unit_dbus_path_from_name(n);
1339 r = bus_method_call_with_reply(
1341 "org.freedesktop.systemd1",
1343 "org.freedesktop.DBus.Properties",
1347 DBUS_TYPE_STRING, &interface,
1348 DBUS_TYPE_STRING, &triggered_by_property,
1353 if (!dbus_message_iter_init(reply, &iter) ||
1354 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1355 log_error("Failed to parse reply.");
1359 dbus_message_iter_recurse(&iter, &sub);
1360 dbus_message_iter_recurse(&sub, &iter);
1363 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1364 const char * const check_states[] = {
1369 const char *service_trigger;
1371 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1372 log_error("Failed to parse reply.");
1376 dbus_message_iter_get_basic(&sub, &service_trigger);
1378 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1382 if (print_warning_label) {
1383 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1384 print_warning_label = false;
1387 log_warning(" %s", service_trigger);
1390 dbus_message_iter_next(&sub);
1394 static int start_unit_one(
1395 DBusConnection *bus,
1402 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1403 _cleanup_free_ char *n;
1412 n = unit_name_mangle(name);
1416 r = bus_method_call_with_reply(
1418 "org.freedesktop.systemd1",
1419 "/org/freedesktop/systemd1",
1420 "org.freedesktop.systemd1.Manager",
1424 DBUS_TYPE_STRING, &n,
1425 DBUS_TYPE_STRING, &mode,
1428 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1429 /* There's always a fallback possible for
1430 * legacy actions. */
1433 log_error("Failed to issue method call: %s", bus_error_message(error));
1438 if (!dbus_message_get_args(reply, error,
1439 DBUS_TYPE_OBJECT_PATH, &path,
1440 DBUS_TYPE_INVALID)) {
1441 log_error("Failed to parse reply: %s", bus_error_message(error));
1445 if (need_daemon_reload(bus, n))
1446 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1447 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1459 log_error("Failed to add path to set.");
1467 static enum action verb_to_action(const char *verb) {
1468 if (streq(verb, "halt"))
1470 else if (streq(verb, "poweroff"))
1471 return ACTION_POWEROFF;
1472 else if (streq(verb, "reboot"))
1473 return ACTION_REBOOT;
1474 else if (streq(verb, "kexec"))
1475 return ACTION_KEXEC;
1476 else if (streq(verb, "rescue"))
1477 return ACTION_RESCUE;
1478 else if (streq(verb, "emergency"))
1479 return ACTION_EMERGENCY;
1480 else if (streq(verb, "default"))
1481 return ACTION_DEFAULT;
1482 else if (streq(verb, "exit"))
1484 else if (streq(verb, "suspend"))
1485 return ACTION_SUSPEND;
1486 else if (streq(verb, "hibernate"))
1487 return ACTION_HIBERNATE;
1488 else if (streq(verb, "hybrid-sleep"))
1489 return ACTION_HYBRID_SLEEP;
1491 return ACTION_INVALID;
1494 static int start_unit(DBusConnection *bus, char **args) {
1496 static const char * const table[_ACTION_MAX] = {
1497 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1498 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1499 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1500 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1501 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1502 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1503 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1504 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1505 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1506 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1507 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1508 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1509 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1510 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
1511 [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
1515 const char *method, *mode, *one_name;
1516 Set _cleanup_set_free_free_ *s = NULL;
1517 DBusError _cleanup_dbus_error_free_ error;
1520 dbus_error_init(&error);
1524 ask_password_agent_open_if_enabled();
1526 if (arg_action == ACTION_SYSTEMCTL) {
1528 streq(args[0], "stop") ||
1529 streq(args[0], "condstop") ? "StopUnit" :
1530 streq(args[0], "reload") ? "ReloadUnit" :
1531 streq(args[0], "restart") ? "RestartUnit" :
1533 streq(args[0], "try-restart") ||
1534 streq(args[0], "condrestart") ? "TryRestartUnit" :
1536 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1538 streq(args[0], "reload-or-try-restart") ||
1539 streq(args[0], "condreload") ||
1541 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1545 (streq(args[0], "isolate") ||
1546 streq(args[0], "rescue") ||
1547 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1549 one_name = table[verb_to_action(args[0])];
1552 assert(arg_action < ELEMENTSOF(table));
1553 assert(table[arg_action]);
1555 method = "StartUnit";
1557 mode = (arg_action == ACTION_EMERGENCY ||
1558 arg_action == ACTION_RESCUE ||
1559 arg_action == ACTION_RUNLEVEL2 ||
1560 arg_action == ACTION_RUNLEVEL3 ||
1561 arg_action == ACTION_RUNLEVEL4 ||
1562 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1564 one_name = table[arg_action];
1567 if (!arg_no_block) {
1568 ret = enable_wait_for_jobs(bus);
1570 log_error("Could not watch jobs: %s", strerror(-ret));
1574 s = set_new(string_hash_func, string_compare_func);
1580 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1582 ret = translate_bus_error_to_exit_status(ret, &error);
1584 STRV_FOREACH(name, args+1) {
1585 r = start_unit_one(bus, method, *name, mode, &error, s);
1587 ret = translate_bus_error_to_exit_status(r, &error);
1588 dbus_error_free(&error);
1593 if (!arg_no_block) {
1594 r = wait_for_jobs(bus, s);
1598 /* When stopping units, warn if they can still be triggered by
1599 * another active unit (socket, path, timer) */
1600 if (!arg_quiet && streq(method, "StopUnit")) {
1602 check_triggering_units(bus, one_name);
1604 STRV_FOREACH(name, args+1)
1605 check_triggering_units(bus, *name);
1612 /* Ask systemd-logind, which might grant access to unprivileged users
1613 * through PolicyKit */
1614 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1617 dbus_bool_t interactive = true;
1622 polkit_agent_open_if_enabled();
1630 case ACTION_POWEROFF:
1631 method = "PowerOff";
1634 case ACTION_SUSPEND:
1638 case ACTION_HIBERNATE:
1639 method = "Hibernate";
1642 case ACTION_HYBRID_SLEEP:
1643 method = "HybridSleep";
1650 return bus_method_call_with_reply(
1652 "org.freedesktop.login1",
1653 "/org/freedesktop/login1",
1654 "org.freedesktop.login1.Manager",
1658 DBUS_TYPE_BOOLEAN, &interactive,
1665 static int check_inhibitors(DBusConnection *bus, enum action a) {
1667 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1668 DBusMessageIter iter, sub, sub2;
1671 _cleanup_strv_free_ char **sessions = NULL;
1677 if (arg_ignore_inhibitors || arg_force > 0)
1689 r = bus_method_call_with_reply(
1691 "org.freedesktop.login1",
1692 "/org/freedesktop/login1",
1693 "org.freedesktop.login1.Manager",
1699 /* If logind is not around, then there are no inhibitors... */
1702 if (!dbus_message_iter_init(reply, &iter) ||
1703 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1704 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1705 log_error("Failed to parse reply.");
1709 dbus_message_iter_recurse(&iter, &sub);
1710 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1711 const char *what, *who, *why, *mode;
1713 _cleanup_strv_free_ char **sv = NULL;
1714 _cleanup_free_ char *comm = NULL, *user = NULL;
1716 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1717 log_error("Failed to parse reply.");
1721 dbus_message_iter_recurse(&sub, &sub2);
1723 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
1724 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
1725 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
1726 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
1727 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
1728 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
1729 log_error("Failed to parse reply.");
1733 if (!streq(mode, "block"))
1736 sv = strv_split(what, ":");
1740 if (!strv_contains(sv,
1742 a == ACTION_POWEROFF ||
1743 a == ACTION_REBOOT ||
1744 a == ACTION_KEXEC ? "shutdown" : "sleep"))
1747 get_process_comm(pid, &comm);
1748 user = uid_to_name(uid);
1749 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
1750 who, (unsigned long) pid, strna(comm), strna(user), why);
1754 dbus_message_iter_next(&sub);
1757 dbus_message_iter_recurse(&iter, &sub);
1759 /* Check for current sessions */
1760 sd_get_sessions(&sessions);
1761 STRV_FOREACH(s, sessions) {
1763 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
1765 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
1768 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
1771 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
1774 sd_session_get_tty(*s, &tty);
1775 sd_session_get_seat(*s, &seat);
1776 sd_session_get_service(*s, &service);
1777 user = uid_to_name(uid);
1779 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
1786 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
1787 a == ACTION_HALT ? "halt" :
1788 a == ACTION_POWEROFF ? "poweroff" :
1789 a == ACTION_REBOOT ? "reboot" :
1790 a == ACTION_KEXEC ? "kexec" :
1791 a == ACTION_SUSPEND ? "suspend" :
1792 a == ACTION_HIBERNATE ? "hibernate" : "hybrid-sleep");
1800 static int start_special(DBusConnection *bus, char **args) {
1806 a = verb_to_action(args[0]);
1808 r = check_inhibitors(bus, a);
1812 if (arg_force >= 2 && geteuid() != 0) {
1813 log_error("Must be root.");
1817 if (arg_force >= 2 &&
1818 (a == ACTION_HALT ||
1819 a == ACTION_POWEROFF ||
1820 a == ACTION_REBOOT))
1823 if (arg_force >= 1 &&
1824 (a == ACTION_HALT ||
1825 a == ACTION_POWEROFF ||
1826 a == ACTION_REBOOT ||
1827 a == ACTION_KEXEC ||
1829 return daemon_reload(bus, args);
1831 /* first try logind, to allow authentication with polkit */
1832 if (geteuid() != 0 &&
1833 (a == ACTION_POWEROFF ||
1834 a == ACTION_REBOOT ||
1835 a == ACTION_SUSPEND ||
1836 a == ACTION_HIBERNATE ||
1837 a == ACTION_HYBRID_SLEEP)) {
1838 r = reboot_with_logind(bus, a);
1843 r = start_unit(bus, args);
1844 if (r == EXIT_SUCCESS)
1850 static int check_unit_active(DBusConnection *bus, char **args) {
1851 const char * const check_states[] = {
1858 int r = 3; /* According to LSB: "program is not running" */
1863 STRV_FOREACH(name, args+1) {
1866 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1876 static int check_unit_failed(DBusConnection *bus, char **args) {
1877 const char * const check_states[] = {
1888 STRV_FOREACH(name, args+1) {
1891 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1901 static int kill_unit(DBusConnection *bus, char **args) {
1909 arg_kill_who = "all";
1911 STRV_FOREACH(name, args+1) {
1912 _cleanup_free_ char *n = NULL;
1914 n = unit_name_mangle(*name);
1918 r = bus_method_call_with_reply(
1920 "org.freedesktop.systemd1",
1921 "/org/freedesktop/systemd1",
1922 "org.freedesktop.systemd1.Manager",
1926 DBUS_TYPE_STRING, &n,
1927 DBUS_TYPE_STRING, &arg_kill_who,
1928 DBUS_TYPE_INT32, &arg_signal,
1936 static int set_cgroup(DBusConnection *bus, char **args) {
1937 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
1940 DBusMessageIter iter;
1942 _cleanup_free_ char *n = NULL;
1943 const char *runtime;
1948 dbus_error_init(&error);
1951 streq(args[0], "set-cgroup") ? "SetUnitControlGroups" :
1952 streq(args[0], "unset-group") ? "UnsetUnitControlGroups"
1953 : "UnsetUnitControlGroupAttributes";
1955 n = unit_name_mangle(args[1]);
1959 m = dbus_message_new_method_call(
1960 "org.freedesktop.systemd1",
1961 "/org/freedesktop/systemd1",
1962 "org.freedesktop.systemd1.Manager",
1967 dbus_message_iter_init_append(m, &iter);
1968 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
1971 r = bus_append_strv_iter(&iter, args + 2);
1975 runtime = arg_runtime ? "runtime" : "persistent";
1976 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
1979 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
1981 log_error("Failed to issue method call: %s", bus_error_message(&error));
1982 dbus_error_free(&error);
1989 static int set_cgroup_attr(DBusConnection *bus, char **args) {
1990 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
1992 DBusMessageIter iter, sub, sub2;
1994 _cleanup_free_ char *n = NULL;
1995 const char *runtime;
2000 dbus_error_init(&error);
2002 if (strv_length(args) % 2 != 0) {
2003 log_error("Expecting an uneven number of arguments!");
2007 n = unit_name_mangle(args[1]);
2011 m = dbus_message_new_method_call(
2012 "org.freedesktop.systemd1",
2013 "/org/freedesktop/systemd1",
2014 "org.freedesktop.systemd1.Manager",
2015 "SetUnitControlGroupAttributes");
2019 dbus_message_iter_init_append(m, &iter);
2020 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2021 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub))
2024 STRV_FOREACH_PAIR(x, y, args + 2) {
2025 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
2026 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, x) ||
2027 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, y) ||
2028 !dbus_message_iter_close_container(&sub, &sub2))
2032 runtime = arg_runtime ? "runtime" : "persistent";
2033 if (!dbus_message_iter_close_container(&iter, &sub) ||
2034 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2037 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2039 log_error("Failed to issue method call: %s", bus_error_message(&error));
2040 dbus_error_free(&error);
2047 static int get_cgroup_attr(DBusConnection *bus, char **args) {
2048 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2050 DBusMessageIter iter;
2052 _cleanup_free_ char *n = NULL;
2053 _cleanup_strv_free_ char **list = NULL;
2059 dbus_error_init(&error);
2061 n = unit_name_mangle(args[1]);
2065 m = dbus_message_new_method_call(
2066 "org.freedesktop.systemd1",
2067 "/org/freedesktop/systemd1",
2068 "org.freedesktop.systemd1.Manager",
2069 "GetUnitControlGroupAttributes");
2073 dbus_message_iter_init_append(m, &iter);
2074 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
2077 r = bus_append_strv_iter(&iter, args + 2);
2081 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2083 log_error("Failed to issue method call: %s", bus_error_message(&error));
2084 dbus_error_free(&error);
2088 dbus_message_iter_init(reply, &iter);
2089 r = bus_parse_strv_iter(&iter, &list);
2091 log_error("Failed to parse value list.");
2095 STRV_FOREACH(a, list) {
2096 if (endswith(*a, "\n"))
2105 typedef struct ExecStatusInfo {
2113 usec_t start_timestamp;
2114 usec_t exit_timestamp;
2119 LIST_FIELDS(struct ExecStatusInfo, exec);
2122 static void exec_status_info_free(ExecStatusInfo *i) {
2131 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2132 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2133 DBusMessageIter sub2, sub3;
2137 int32_t code, status;
2143 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2146 dbus_message_iter_recurse(sub, &sub2);
2148 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2151 i->path = strdup(path);
2155 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2156 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2160 dbus_message_iter_recurse(&sub2, &sub3);
2161 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2162 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2163 dbus_message_iter_next(&sub3);
2167 i->argv = new0(char*, n+1);
2172 dbus_message_iter_recurse(&sub2, &sub3);
2173 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2176 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2177 dbus_message_iter_get_basic(&sub3, &s);
2178 dbus_message_iter_next(&sub3);
2180 i->argv[n] = strdup(s);
2187 if (!dbus_message_iter_next(&sub2) ||
2188 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2189 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2190 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2191 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2192 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2193 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2194 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2195 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2199 i->start_timestamp = (usec_t) start_timestamp;
2200 i->exit_timestamp = (usec_t) exit_timestamp;
2201 i->pid = (pid_t) pid;
2208 typedef struct UnitStatusInfo {
2210 const char *load_state;
2211 const char *active_state;
2212 const char *sub_state;
2213 const char *unit_file_state;
2215 const char *description;
2216 const char *following;
2218 char **documentation;
2220 const char *fragment_path;
2221 const char *source_path;
2222 const char *default_control_group;
2224 const char *load_error;
2227 usec_t inactive_exit_timestamp;
2228 usec_t inactive_exit_timestamp_monotonic;
2229 usec_t active_enter_timestamp;
2230 usec_t active_exit_timestamp;
2231 usec_t inactive_enter_timestamp;
2233 bool need_daemon_reload;
2238 const char *status_text;
2241 usec_t start_timestamp;
2242 usec_t exit_timestamp;
2244 int exit_code, exit_status;
2246 usec_t condition_timestamp;
2247 bool condition_result;
2250 unsigned n_accepted;
2251 unsigned n_connections;
2255 const char *sysfs_path;
2257 /* Mount, Automount */
2263 LIST_HEAD(ExecStatusInfo, exec);
2266 static void print_status_info(UnitStatusInfo *i) {
2268 const char *on, *off, *ss;
2270 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2271 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2274 arg_all * OUTPUT_SHOW_ALL |
2275 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2276 on_tty() * OUTPUT_COLOR |
2277 !arg_quiet * OUTPUT_WARN_CUTOFF |
2278 arg_full * OUTPUT_FULL_WIDTH;
2282 /* This shows pretty information about a unit. See
2283 * print_property() for a low-level property printer */
2285 printf("%s", strna(i->id));
2287 if (i->description && !streq_ptr(i->id, i->description))
2288 printf(" - %s", i->description);
2293 printf("\t Follow: unit currently follows state of %s\n", i->following);
2295 if (streq_ptr(i->load_state, "error")) {
2296 on = ansi_highlight_red(true);
2297 off = ansi_highlight_red(false);
2301 path = i->source_path ? i->source_path : i->fragment_path;
2304 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2305 else if (path && i->unit_file_state)
2306 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2308 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2310 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2312 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2314 if (streq_ptr(i->active_state, "failed")) {
2315 on = ansi_highlight_red(true);
2316 off = ansi_highlight_red(false);
2317 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2318 on = ansi_highlight_green(true);
2319 off = ansi_highlight_green(false);
2324 printf("\t Active: %s%s (%s)%s",
2326 strna(i->active_state),
2330 printf("\t Active: %s%s%s",
2332 strna(i->active_state),
2335 if (!isempty(i->result) && !streq(i->result, "success"))
2336 printf(" (Result: %s)", i->result);
2338 timestamp = (streq_ptr(i->active_state, "active") ||
2339 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2340 (streq_ptr(i->active_state, "inactive") ||
2341 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2342 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2343 i->active_exit_timestamp;
2345 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2346 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2349 printf(" since %s; %s\n", s2, s1);
2351 printf(" since %s\n", s2);
2355 if (!i->condition_result && i->condition_timestamp > 0) {
2356 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2357 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2360 printf("\t start condition failed at %s; %s\n", s2, s1);
2362 printf("\t start condition failed at %s\n", s2);
2366 printf("\t Device: %s\n", i->sysfs_path);
2368 printf("\t Where: %s\n", i->where);
2370 printf("\t What: %s\n", i->what);
2372 if (!strv_isempty(i->documentation)) {
2376 STRV_FOREACH(t, i->documentation) {
2378 printf("\t Docs: %s\n", *t);
2381 printf("\t %s\n", *t);
2386 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2388 LIST_FOREACH(exec, p, i->exec) {
2389 _cleanup_free_ char *t = NULL;
2392 /* Only show exited processes here */
2396 t = strv_join(p->argv, " ");
2397 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2399 good = is_clean_exit_lsb(p->code, p->status, NULL);
2401 on = ansi_highlight_red(true);
2402 off = ansi_highlight_red(false);
2406 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2408 if (p->code == CLD_EXITED) {
2411 printf("status=%i", p->status);
2413 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2418 printf("signal=%s", signal_to_string(p->status));
2420 printf(")%s\n", off);
2422 if (i->main_pid == p->pid &&
2423 i->start_timestamp == p->start_timestamp &&
2424 i->exit_timestamp == p->start_timestamp)
2425 /* Let's not show this twice */
2428 if (p->pid == i->control_pid)
2432 if (i->main_pid > 0 || i->control_pid > 0) {
2435 if (i->main_pid > 0) {
2436 printf("Main PID: %u", (unsigned) i->main_pid);
2439 _cleanup_free_ char *t = NULL;
2440 get_process_comm(i->main_pid, &t);
2443 } else if (i->exit_code > 0) {
2444 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2446 if (i->exit_code == CLD_EXITED) {
2449 printf("status=%i", i->exit_status);
2451 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2456 printf("signal=%s", signal_to_string(i->exit_status));
2461 if (i->main_pid > 0 && i->control_pid > 0)
2464 if (i->control_pid > 0) {
2465 _cleanup_free_ char *t = NULL;
2467 printf(" Control: %u", (unsigned) i->control_pid);
2469 get_process_comm(i->control_pid, &t);
2478 printf("\t Status: \"%s\"\n", i->status_text);
2480 if (i->default_control_group &&
2481 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2484 printf("\t CGroup: %s\n", i->default_control_group);
2486 if (arg_transport != TRANSPORT_SSH) {
2496 if (i->main_pid > 0)
2497 extra[k++] = i->main_pid;
2499 if (i->control_pid > 0)
2500 extra[k++] = i->control_pid;
2502 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, extra, k, flags);
2506 if (i->id && arg_transport != TRANSPORT_SSH) {
2508 if(arg_scope == UNIT_FILE_SYSTEM)
2509 show_journal_by_unit(stdout,
2513 i->inactive_exit_timestamp_monotonic,
2517 show_journal_by_user_unit(stdout,
2521 i->inactive_exit_timestamp_monotonic,
2527 if (i->need_daemon_reload)
2528 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2529 ansi_highlight_red(true),
2530 ansi_highlight_red(false),
2531 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2534 static void show_unit_help(UnitStatusInfo *i) {
2539 if (!i->documentation) {
2540 log_info("Documentation for %s not known.", i->id);
2544 STRV_FOREACH(p, i->documentation) {
2546 if (startswith(*p, "man:")) {
2549 char _cleanup_free_ *page = NULL, *section = NULL;
2550 const char *args[4] = { "man", NULL, NULL, NULL };
2555 if ((*p)[k-1] == ')')
2556 e = strrchr(*p, '(');
2559 page = strndup((*p) + 4, e - *p - 4);
2560 section = strndup(e + 1, *p + k - e - 2);
2561 if (!page || !section) {
2573 log_error("Failed to fork: %m");
2579 execvp(args[0], (char**) args);
2580 log_error("Failed to execute man: %m");
2581 _exit(EXIT_FAILURE);
2584 wait_for_terminate(pid, NULL);
2586 log_info("Can't show: %s", *p);
2590 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2596 switch (dbus_message_iter_get_arg_type(iter)) {
2598 case DBUS_TYPE_STRING: {
2601 dbus_message_iter_get_basic(iter, &s);
2604 if (streq(name, "Id"))
2606 else if (streq(name, "LoadState"))
2608 else if (streq(name, "ActiveState"))
2609 i->active_state = s;
2610 else if (streq(name, "SubState"))
2612 else if (streq(name, "Description"))
2614 else if (streq(name, "FragmentPath"))
2615 i->fragment_path = s;
2616 else if (streq(name, "SourcePath"))
2618 else if (streq(name, "DefaultControlGroup"))
2619 i->default_control_group = s;
2620 else if (streq(name, "StatusText"))
2622 else if (streq(name, "SysFSPath"))
2624 else if (streq(name, "Where"))
2626 else if (streq(name, "What"))
2628 else if (streq(name, "Following"))
2630 else if (streq(name, "UnitFileState"))
2631 i->unit_file_state = s;
2632 else if (streq(name, "Result"))
2639 case DBUS_TYPE_BOOLEAN: {
2642 dbus_message_iter_get_basic(iter, &b);
2644 if (streq(name, "Accept"))
2646 else if (streq(name, "NeedDaemonReload"))
2647 i->need_daemon_reload = b;
2648 else if (streq(name, "ConditionResult"))
2649 i->condition_result = b;
2654 case DBUS_TYPE_UINT32: {
2657 dbus_message_iter_get_basic(iter, &u);
2659 if (streq(name, "MainPID")) {
2661 i->main_pid = (pid_t) u;
2664 } else if (streq(name, "ControlPID"))
2665 i->control_pid = (pid_t) u;
2666 else if (streq(name, "ExecMainPID")) {
2668 i->main_pid = (pid_t) u;
2669 } else if (streq(name, "NAccepted"))
2671 else if (streq(name, "NConnections"))
2672 i->n_connections = u;
2677 case DBUS_TYPE_INT32: {
2680 dbus_message_iter_get_basic(iter, &j);
2682 if (streq(name, "ExecMainCode"))
2683 i->exit_code = (int) j;
2684 else if (streq(name, "ExecMainStatus"))
2685 i->exit_status = (int) j;
2690 case DBUS_TYPE_UINT64: {
2693 dbus_message_iter_get_basic(iter, &u);
2695 if (streq(name, "ExecMainStartTimestamp"))
2696 i->start_timestamp = (usec_t) u;
2697 else if (streq(name, "ExecMainExitTimestamp"))
2698 i->exit_timestamp = (usec_t) u;
2699 else if (streq(name, "ActiveEnterTimestamp"))
2700 i->active_enter_timestamp = (usec_t) u;
2701 else if (streq(name, "InactiveEnterTimestamp"))
2702 i->inactive_enter_timestamp = (usec_t) u;
2703 else if (streq(name, "InactiveExitTimestamp"))
2704 i->inactive_exit_timestamp = (usec_t) u;
2705 else if (streq(name, "InactiveExitTimestampMonotonic"))
2706 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2707 else if (streq(name, "ActiveExitTimestamp"))
2708 i->active_exit_timestamp = (usec_t) u;
2709 else if (streq(name, "ConditionTimestamp"))
2710 i->condition_timestamp = (usec_t) u;
2715 case DBUS_TYPE_ARRAY: {
2717 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2718 startswith(name, "Exec")) {
2719 DBusMessageIter sub;
2721 dbus_message_iter_recurse(iter, &sub);
2722 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2723 ExecStatusInfo *info;
2726 if (!(info = new0(ExecStatusInfo, 1)))
2729 if (!(info->name = strdup(name))) {
2734 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2739 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2741 dbus_message_iter_next(&sub);
2743 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2744 streq(name, "Documentation")) {
2746 DBusMessageIter sub;
2748 dbus_message_iter_recurse(iter, &sub);
2749 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2753 dbus_message_iter_get_basic(&sub, &s);
2755 l = strv_append(i->documentation, s);
2759 strv_free(i->documentation);
2760 i->documentation = l;
2762 dbus_message_iter_next(&sub);
2769 case DBUS_TYPE_STRUCT: {
2771 if (streq(name, "LoadError")) {
2772 DBusMessageIter sub;
2773 const char *n, *message;
2776 dbus_message_iter_recurse(iter, &sub);
2778 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2782 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2786 if (!isempty(message))
2787 i->load_error = message;
2797 static int print_property(const char *name, DBusMessageIter *iter) {
2801 /* This is a low-level property printer, see
2802 * print_status_info() for the nicer output */
2804 if (arg_property && !strv_find(arg_property, name))
2807 switch (dbus_message_iter_get_arg_type(iter)) {
2809 case DBUS_TYPE_STRUCT: {
2810 DBusMessageIter sub;
2811 dbus_message_iter_recurse(iter, &sub);
2813 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2816 dbus_message_iter_get_basic(&sub, &u);
2819 printf("%s=%u\n", name, (unsigned) u);
2821 printf("%s=\n", name);
2824 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2827 dbus_message_iter_get_basic(&sub, &s);
2829 if (arg_all || s[0])
2830 printf("%s=%s\n", name, s);
2833 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2834 const char *a = NULL, *b = NULL;
2836 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2837 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2839 if (arg_all || !isempty(a) || !isempty(b))
2840 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2848 case DBUS_TYPE_ARRAY:
2850 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2851 DBusMessageIter sub, sub2;
2853 dbus_message_iter_recurse(iter, &sub);
2854 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2858 dbus_message_iter_recurse(&sub, &sub2);
2860 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2861 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2862 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2864 dbus_message_iter_next(&sub);
2869 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2870 DBusMessageIter sub, sub2;
2872 dbus_message_iter_recurse(iter, &sub);
2873 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2874 const char *type, *path;
2876 dbus_message_iter_recurse(&sub, &sub2);
2878 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2879 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2880 printf("%s=%s\n", type, path);
2882 dbus_message_iter_next(&sub);
2887 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2888 DBusMessageIter sub, sub2;
2890 dbus_message_iter_recurse(iter, &sub);
2891 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2893 uint64_t value, next_elapse;
2895 dbus_message_iter_recurse(&sub, &sub2);
2897 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2898 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2899 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2900 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2902 printf("%s={ value=%s ; next_elapse=%s }\n",
2904 format_timespan(timespan1, sizeof(timespan1), value),
2905 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2908 dbus_message_iter_next(&sub);
2913 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2914 DBusMessageIter sub, sub2;
2916 dbus_message_iter_recurse(iter, &sub);
2917 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2918 const char *controller, *attr, *value;
2920 dbus_message_iter_recurse(&sub, &sub2);
2922 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2923 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2924 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2926 printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2932 dbus_message_iter_next(&sub);
2937 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2938 DBusMessageIter sub;
2940 dbus_message_iter_recurse(iter, &sub);
2941 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2942 ExecStatusInfo info;
2945 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2946 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2947 char _cleanup_free_ *t;
2949 t = strv_join(info.argv, " ");
2951 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2955 yes_no(info.ignore),
2956 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2957 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2958 (unsigned) info. pid,
2959 sigchld_code_to_string(info.code),
2961 info.code == CLD_EXITED ? "" : "/",
2962 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2966 strv_free(info.argv);
2968 dbus_message_iter_next(&sub);
2977 if (generic_print_property(name, iter, arg_all) > 0)
2981 printf("%s=[unprintable]\n", name);
2986 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2987 _cleanup_free_ DBusMessage *reply = NULL;
2988 const char *interface = "";
2990 DBusMessageIter iter, sub, sub2, sub3;
2991 UnitStatusInfo info;
2999 r = bus_method_call_with_reply(
3001 "org.freedesktop.systemd1",
3003 "org.freedesktop.DBus.Properties",
3007 DBUS_TYPE_STRING, &interface,
3012 if (!dbus_message_iter_init(reply, &iter) ||
3013 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3014 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3015 log_error("Failed to parse reply.");
3019 dbus_message_iter_recurse(&iter, &sub);
3026 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3029 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3030 dbus_message_iter_recurse(&sub, &sub2);
3032 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3033 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3034 log_error("Failed to parse reply.");
3038 dbus_message_iter_recurse(&sub2, &sub3);
3040 if (show_properties)
3041 r = print_property(name, &sub3);
3043 r = status_property(name, &sub3, &info);
3045 log_error("Failed to parse reply.");
3049 dbus_message_iter_next(&sub);
3054 if (!show_properties) {
3055 if (streq(verb, "help"))
3056 show_unit_help(&info);
3058 print_status_info(&info);
3061 strv_free(info.documentation);
3063 if (!streq_ptr(info.active_state, "active") &&
3064 !streq_ptr(info.active_state, "reloading") &&
3065 streq(verb, "status"))
3066 /* According to LSB: "program not running" */
3069 while ((p = info.exec)) {
3070 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3071 exec_status_info_free(p);
3077 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3078 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3079 const char *path = NULL;
3080 DBusError _cleanup_dbus_error_free_ error;
3083 dbus_error_init(&error);
3085 r = bus_method_call_with_reply(
3087 "org.freedesktop.systemd1",
3088 "/org/freedesktop/systemd1",
3089 "org.freedesktop.systemd1.Manager",
3093 DBUS_TYPE_UINT32, &pid,
3098 if (!dbus_message_get_args(reply, &error,
3099 DBUS_TYPE_OBJECT_PATH, &path,
3100 DBUS_TYPE_INVALID)) {
3101 log_error("Failed to parse reply: %s", bus_error_message(&error));
3105 r = show_one(verb, bus, path, false, new_line);
3109 static int show(DBusConnection *bus, char **args) {
3111 bool show_properties, new_line = false;
3117 show_properties = streq(args[0], "show");
3119 if (show_properties)
3120 pager_open_if_enabled();
3122 /* If no argument is specified inspect the manager itself */
3124 if (show_properties && strv_length(args) <= 1)
3125 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3127 STRV_FOREACH(name, args+1) {
3130 if (safe_atou32(*name, &id) < 0) {
3131 _cleanup_free_ char *p = NULL, *n = NULL;
3132 /* Interpret as unit name */
3134 n = unit_name_mangle(*name);
3138 p = unit_dbus_path_from_name(n);
3142 r = show_one(args[0], bus, p, show_properties, &new_line);
3146 } else if (show_properties) {
3147 _cleanup_free_ char *p = NULL;
3149 /* Interpret as job id */
3150 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3153 r = show_one(args[0], bus, p, show_properties, &new_line);
3158 /* Interpret as PID */
3159 r = show_one_by_pid(args[0], bus, id, &new_line);
3168 static int dump(DBusConnection *bus, char **args) {
3169 _cleanup_free_ DBusMessage *reply = NULL;
3174 dbus_error_init(&error);
3176 pager_open_if_enabled();
3178 r = bus_method_call_with_reply(
3180 "org.freedesktop.systemd1",
3181 "/org/freedesktop/systemd1",
3182 "org.freedesktop.systemd1.Manager",
3190 if (!dbus_message_get_args(reply, &error,
3191 DBUS_TYPE_STRING, &text,
3192 DBUS_TYPE_INVALID)) {
3193 log_error("Failed to parse reply: %s", bus_error_message(&error));
3194 dbus_error_free(&error);
3198 fputs(text, stdout);
3202 static int snapshot(DBusConnection *bus, char **args) {
3203 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3206 dbus_bool_t cleanup = FALSE;
3207 DBusMessageIter iter, sub;
3210 *interface = "org.freedesktop.systemd1.Unit",
3212 _cleanup_free_ char *n = NULL;
3214 dbus_error_init(&error);
3216 if (strv_length(args) > 1)
3217 n = snapshot_name_mangle(args[1]);
3223 r = bus_method_call_with_reply (
3225 "org.freedesktop.systemd1",
3226 "/org/freedesktop/systemd1",
3227 "org.freedesktop.systemd1.Manager",
3231 DBUS_TYPE_STRING, &n,
3232 DBUS_TYPE_BOOLEAN, &cleanup,
3237 if (!dbus_message_get_args(reply, &error,
3238 DBUS_TYPE_OBJECT_PATH, &path,
3239 DBUS_TYPE_INVALID)) {
3240 log_error("Failed to parse reply: %s", bus_error_message(&error));
3241 dbus_error_free(&error);
3245 dbus_message_unref(reply);
3248 r = bus_method_call_with_reply (
3250 "org.freedesktop.systemd1",
3252 "org.freedesktop.DBus.Properties",
3256 DBUS_TYPE_STRING, &interface,
3257 DBUS_TYPE_STRING, &property,
3262 if (!dbus_message_iter_init(reply, &iter) ||
3263 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3264 log_error("Failed to parse reply.");
3268 dbus_message_iter_recurse(&iter, &sub);
3270 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3271 log_error("Failed to parse reply.");
3275 dbus_message_iter_get_basic(&sub, &id);
3283 static int delete_snapshot(DBusConnection *bus, char **args) {
3288 STRV_FOREACH(name, args+1) {
3289 _cleanup_free_ char *n = NULL;
3292 n = snapshot_name_mangle(*name);
3296 r = bus_method_call_with_reply(
3298 "org.freedesktop.systemd1",
3299 "/org/freedesktop/systemd1",
3300 "org.freedesktop.systemd1.Manager",
3304 DBUS_TYPE_STRING, &n,
3313 static int daemon_reload(DBusConnection *bus, char **args) {
3318 if (arg_action == ACTION_RELOAD)
3320 else if (arg_action == ACTION_REEXEC)
3321 method = "Reexecute";
3323 assert(arg_action == ACTION_SYSTEMCTL);
3326 streq(args[0], "clear-jobs") ||
3327 streq(args[0], "cancel") ? "ClearJobs" :
3328 streq(args[0], "daemon-reexec") ? "Reexecute" :
3329 streq(args[0], "reset-failed") ? "ResetFailed" :
3330 streq(args[0], "halt") ? "Halt" :
3331 streq(args[0], "poweroff") ? "PowerOff" :
3332 streq(args[0], "reboot") ? "Reboot" :
3333 streq(args[0], "kexec") ? "KExec" :
3334 streq(args[0], "exit") ? "Exit" :
3335 /* "daemon-reload" */ "Reload";
3338 r = bus_method_call_with_reply(
3340 "org.freedesktop.systemd1",
3341 "/org/freedesktop/systemd1",
3342 "org.freedesktop.systemd1.Manager",
3348 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3349 /* There's always a fallback possible for
3350 * legacy actions. */
3352 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3353 /* On reexecution, we expect a disconnect, not
3357 log_error("Failed to issue method call: %s", bus_error_message(&error));
3359 dbus_error_free(&error);
3363 static int reset_failed(DBusConnection *bus, char **args) {
3367 if (strv_length(args) <= 1)
3368 return daemon_reload(bus, args);
3370 STRV_FOREACH(name, args+1) {
3371 _cleanup_free_ char *n;
3373 n = unit_name_mangle(*name);
3377 r = bus_method_call_with_reply(
3379 "org.freedesktop.systemd1",
3380 "/org/freedesktop/systemd1",
3381 "org.freedesktop.systemd1.Manager",
3385 DBUS_TYPE_STRING, &n,
3394 static int show_enviroment(DBusConnection *bus, char **args) {
3395 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3396 DBusMessageIter iter, sub, sub2;
3399 *interface = "org.freedesktop.systemd1.Manager",
3400 *property = "Environment";
3402 pager_open_if_enabled();
3404 r = bus_method_call_with_reply(
3406 "org.freedesktop.systemd1",
3407 "/org/freedesktop/systemd1",
3408 "org.freedesktop.DBus.Properties",
3412 DBUS_TYPE_STRING, &interface,
3413 DBUS_TYPE_STRING, &property,
3418 if (!dbus_message_iter_init(reply, &iter) ||
3419 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3420 log_error("Failed to parse reply.");
3424 dbus_message_iter_recurse(&iter, &sub);
3426 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3427 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3428 log_error("Failed to parse reply.");
3432 dbus_message_iter_recurse(&sub, &sub2);
3434 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3437 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3438 log_error("Failed to parse reply.");
3442 dbus_message_iter_get_basic(&sub2, &text);
3445 dbus_message_iter_next(&sub2);
3451 static int switch_root(DBusConnection *bus, char **args) {
3454 _cleanup_free_ char *init = NULL;
3456 l = strv_length(args);
3457 if (l < 2 || l > 3) {
3458 log_error("Wrong number of arguments.");
3465 init = strdup(args[2]);
3467 parse_env_file("/proc/cmdline", WHITESPACE,
3477 log_debug("switching root - root: %s; init: %s", root, init);
3479 return bus_method_call_with_reply(
3481 "org.freedesktop.systemd1",
3482 "/org/freedesktop/systemd1",
3483 "org.freedesktop.systemd1.Manager",
3487 DBUS_TYPE_STRING, &root,
3488 DBUS_TYPE_STRING, &init,
3492 static int set_environment(DBusConnection *bus, char **args) {
3493 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3496 DBusMessageIter iter;
3502 dbus_error_init(&error);
3504 method = streq(args[0], "set-environment")
3506 : "UnsetEnvironment";
3508 m = dbus_message_new_method_call(
3509 "org.freedesktop.systemd1",
3510 "/org/freedesktop/systemd1",
3511 "org.freedesktop.systemd1.Manager",
3516 dbus_message_iter_init_append(m, &iter);
3518 r = bus_append_strv_iter(&iter, args + 1);
3522 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3524 log_error("Failed to issue method call: %s", bus_error_message(&error));
3525 dbus_error_free(&error);
3532 static int enable_sysv_units(char **args) {
3535 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3536 const char *verb = args[0];
3537 unsigned f = 1, t = 1;
3540 if (arg_scope != UNIT_FILE_SYSTEM)
3543 if (!streq(verb, "enable") &&
3544 !streq(verb, "disable") &&
3545 !streq(verb, "is-enabled"))
3548 /* Processes all SysV units, and reshuffles the array so that
3549 * afterwards only the native units remain */
3552 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3557 for (f = 1; args[f]; f++) {
3560 bool found_native = false, found_sysv;
3562 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3563 char **k, *l, *q = NULL;
3570 if (!endswith(name, ".service"))
3573 if (path_is_absolute(name))
3576 STRV_FOREACH(k, paths.unit_path) {
3579 if (!isempty(arg_root))
3580 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3582 asprintf(&p, "%s/%s", *k, name);
3589 found_native = access(p, F_OK) >= 0;
3600 if (!isempty(arg_root))
3601 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3603 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3609 p[strlen(p) - sizeof(".service") + 1] = 0;
3610 found_sysv = access(p, F_OK) >= 0;
3617 /* Mark this entry, so that we don't try enabling it as native unit */
3618 args[f] = (char*) "";
3620 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3622 if (!isempty(arg_root))
3623 argv[c++] = q = strappend("--root=", arg_root);
3625 argv[c++] = path_get_file_name(p);
3627 streq(verb, "enable") ? "on" :
3628 streq(verb, "disable") ? "off" : "--level=5";
3631 l = strv_join((char**)argv, " ");
3639 log_info("Executing %s", l);
3644 log_error("Failed to fork: %m");
3649 } else if (pid == 0) {
3652 execv(argv[0], (char**) argv);
3653 _exit(EXIT_FAILURE);
3659 j = wait_for_terminate(pid, &status);
3661 log_error("Failed to wait for child: %s", strerror(-r));
3666 if (status.si_code == CLD_EXITED) {
3667 if (streq(verb, "is-enabled")) {
3668 if (status.si_status == 0) {
3677 } else if (status.si_status != 0) {
3688 lookup_paths_free(&paths);
3690 /* Drop all SysV units */
3691 for (f = 1, t = 1; args[f]; f++) {
3693 if (isempty(args[f]))
3696 args[t++] = args[f];
3705 static int mangle_names(char **original_names, char ***mangled_names) {
3706 char **i, **l, **name;
3708 l = new(char*, strv_length(original_names) + 1);
3713 STRV_FOREACH(name, original_names) {
3715 /* When enabling units qualified path names are OK,
3716 * too, hence allow them explicitly. */
3721 *i = unit_name_mangle(*name);
3737 static int enable_unit(DBusConnection *bus, char **args) {
3738 const char *verb = args[0];
3739 UnitFileChange *changes = NULL;
3740 unsigned n_changes = 0, i;
3741 int carries_install_info = -1;
3742 DBusMessage _cleanup_dbus_message_unref_ *m = NULL, *reply = NULL;
3744 DBusError _cleanup_dbus_error_free_ error;
3745 char _cleanup_strv_free_ **mangled_names = NULL;
3747 dbus_error_init(&error);
3749 r = enable_sysv_units(args);
3756 if (!bus || avoid_bus()) {
3757 if (streq(verb, "enable")) {
3758 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3759 carries_install_info = r;
3760 } else if (streq(verb, "disable"))
3761 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3762 else if (streq(verb, "reenable")) {
3763 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3764 carries_install_info = r;
3765 } else if (streq(verb, "link"))
3766 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3767 else if (streq(verb, "preset")) {
3768 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3769 carries_install_info = r;
3770 } else if (streq(verb, "mask"))
3771 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3772 else if (streq(verb, "unmask"))
3773 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3775 assert_not_reached("Unknown verb");
3778 log_error("Operation failed: %s", strerror(-r));
3783 for (i = 0; i < n_changes; i++) {
3784 if (changes[i].type == UNIT_FILE_SYMLINK)
3785 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3787 log_info("rm '%s'", changes[i].path);
3794 bool send_force = true, expect_carries_install_info = false;
3796 DBusMessageIter iter, sub, sub2;
3798 if (streq(verb, "enable")) {
3799 method = "EnableUnitFiles";
3800 expect_carries_install_info = true;
3801 } else if (streq(verb, "disable")) {
3802 method = "DisableUnitFiles";
3804 } else if (streq(verb, "reenable")) {
3805 method = "ReenableUnitFiles";
3806 expect_carries_install_info = true;
3807 } else if (streq(verb, "link"))
3808 method = "LinkUnitFiles";
3809 else if (streq(verb, "preset")) {
3810 method = "PresetUnitFiles";
3811 expect_carries_install_info = true;
3812 } else if (streq(verb, "mask"))
3813 method = "MaskUnitFiles";
3814 else if (streq(verb, "unmask")) {
3815 method = "UnmaskUnitFiles";
3818 assert_not_reached("Unknown verb");
3820 m = dbus_message_new_method_call(
3821 "org.freedesktop.systemd1",
3822 "/org/freedesktop/systemd1",
3823 "org.freedesktop.systemd1.Manager",
3830 dbus_message_iter_init_append(m, &iter);
3832 r = mangle_names(args+1, &mangled_names);
3836 r = bus_append_strv_iter(&iter, mangled_names);
3838 log_error("Failed to append unit files.");
3843 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3844 log_error("Failed to append runtime boolean.");
3852 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3853 log_error("Failed to append force boolean.");
3859 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3861 log_error("Failed to issue method call: %s", bus_error_message(&error));
3866 if (!dbus_message_iter_init(reply, &iter)) {
3867 log_error("Failed to initialize iterator.");
3871 if (expect_carries_install_info) {
3872 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3874 log_error("Failed to parse reply.");
3878 carries_install_info = b;
3881 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3882 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3883 log_error("Failed to parse reply.");
3888 dbus_message_iter_recurse(&iter, &sub);
3889 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3890 const char *type, *path, *source;
3892 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3893 log_error("Failed to parse reply.");
3898 dbus_message_iter_recurse(&sub, &sub2);
3900 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3901 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3902 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3903 log_error("Failed to parse reply.");
3909 if (streq(type, "symlink"))
3910 log_info("ln -s '%s' '%s'", source, path);
3912 log_info("rm '%s'", path);
3915 dbus_message_iter_next(&sub);
3918 /* Try to reload if enabeld */
3920 r = daemon_reload(bus, args);
3923 if (carries_install_info == 0)
3925 "The unit files have no [Install] section. They are not meant to be enabled\n"
3926 "using systemctl.\n"
3927 "Possible reasons for having this kind of units are:\n"
3928 "1) A unit may be statically enabled by being symlinked from another unit's\n"
3929 " .wants/ or .requires/ directory.\n"
3930 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
3931 " a requirement dependency on it.\n"
3932 "3) A unit may be started when needed via activation (socket, path, timer,\n"
3933 " D-Bus, udev, scripted systemctl call, ...).\n");
3936 unit_file_changes_free(changes, n_changes);
3941 static int unit_is_enabled(DBusConnection *bus, char **args) {
3942 DBusError _cleanup_dbus_error_free_ error;
3944 DBusMessage _cleanup_dbus_message_unref_ *reply = NULL;
3948 dbus_error_init(&error);
3950 r = enable_sysv_units(args);
3956 if (!bus || avoid_bus()) {
3958 STRV_FOREACH(name, args+1) {
3959 UnitFileState state;
3961 state = unit_file_get_state(arg_scope, arg_root, *name);
3965 if (state == UNIT_FILE_ENABLED ||
3966 state == UNIT_FILE_ENABLED_RUNTIME ||
3967 state == UNIT_FILE_STATIC)
3971 puts(unit_file_state_to_string(state));
3975 STRV_FOREACH(name, args+1) {
3978 r = bus_method_call_with_reply (
3980 "org.freedesktop.systemd1",
3981 "/org/freedesktop/systemd1",
3982 "org.freedesktop.systemd1.Manager",
3986 DBUS_TYPE_STRING, name,
3991 if (!dbus_message_get_args(reply, &error,
3992 DBUS_TYPE_STRING, &s,
3993 DBUS_TYPE_INVALID)) {
3994 log_error("Failed to parse reply: %s", bus_error_message(&error));
3998 dbus_message_unref(reply);
4001 if (streq(s, "enabled") ||
4002 streq(s, "enabled-runtime") ||
4011 return enabled ? 0 : 1;
4014 static int systemctl_help(void) {
4016 pager_open_if_enabled();
4018 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4019 "Query or send control commands to the systemd manager.\n\n"
4020 " -h --help Show this help\n"
4021 " --version Show package version\n"
4022 " -t --type=TYPE List only units of a particular type\n"
4023 " -p --property=NAME Show only properties by this name\n"
4024 " -a --all Show all units/properties, including dead/empty ones\n"
4025 " --failed Show only failed units\n"
4026 " --full Don't ellipsize unit names on output\n"
4027 " --fail When queueing a new job, fail if conflicting jobs are\n"
4029 " --ignore-dependencies\n"
4030 " When queueing a new job, ignore all its dependencies\n"
4031 " -i --ignore-inhibitors\n"
4032 " When shutting down or sleeping, ignore inhibitors\n"
4033 " --kill-who=WHO Who to send signal to\n"
4034 " -s --signal=SIGNAL Which signal to send\n"
4035 " -H --host=[USER@]HOST\n"
4036 " Show information for remote host\n"
4037 " -P --privileged Acquire privileges before execution\n"
4038 " -q --quiet Suppress output\n"
4039 " --no-block Do not wait until operation finished\n"
4040 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4041 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4043 " --no-legend Do not print a legend (column headers and hints)\n"
4044 " --no-pager Do not pipe output into a pager\n"
4045 " --no-ask-password\n"
4046 " Do not ask for system passwords\n"
4047 " --system Connect to system manager\n"
4048 " --user Connect to user service manager\n"
4049 " --global Enable/disable unit files globally\n"
4050 " -f --force When enabling unit files, override existing symlinks\n"
4051 " When shutting down, execute action immediately\n"
4052 " --root=PATH Enable unit files in the specified root directory\n"
4053 " --runtime Enable unit files only temporarily until next reboot\n"
4054 " -n --lines=INTEGER Journal entries to show\n"
4055 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4056 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4058 " list-units List loaded units\n"
4059 " start [NAME...] Start (activate) one or more units\n"
4060 " stop [NAME...] Stop (deactivate) one or more units\n"
4061 " reload [NAME...] Reload one or more units\n"
4062 " restart [NAME...] Start or restart one or more units\n"
4063 " try-restart [NAME...] Restart one or more units if active\n"
4064 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4065 " otherwise start or restart\n"
4066 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4067 " otherwise restart if active\n"
4068 " isolate [NAME] Start one unit and stop all others\n"
4069 " kill [NAME...] Send signal to processes of a unit\n"
4070 " is-active [NAME...] Check whether units are active\n"
4071 " is-failed [NAME...] Check whether units are failed\n"
4072 " status [NAME...|PID...] Show runtime status of one or more units\n"
4073 " show [NAME...|JOB...] Show properties of one or more\n"
4074 " units/jobs or the manager\n"
4075 " help [NAME...|PID...] Show manual for one or more units\n"
4076 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4078 " get-cgroup-attr [NAME] [ATTR] ...\n"
4079 " Get control group attrubute\n"
4080 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4081 " Set control group attribute\n"
4082 " unset-cgroup-attr [NAME] [ATTR...]\n"
4083 " Unset control group attribute\n"
4084 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4085 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4086 " load [NAME...] Load one or more units\n"
4087 " list-dependencies [NAME] Recursively show units which are required\n"
4088 " or wanted by this unit\n\n"
4089 "Unit File Commands:\n"
4090 " list-unit-files List installed unit files\n"
4091 " enable [NAME...] Enable one or more unit files\n"
4092 " disable [NAME...] Disable one or more unit files\n"
4093 " reenable [NAME...] Reenable one or more unit files\n"
4094 " preset [NAME...] Enable/disable one or more unit files\n"
4095 " based on preset configuration\n"
4096 " mask [NAME...] Mask one or more units\n"
4097 " unmask [NAME...] Unmask one or more units\n"
4098 " link [PATH...] Link one or more units files into\n"
4099 " the search path\n"
4100 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4102 " list-jobs List jobs\n"
4103 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4104 "Status Commands:\n"
4105 " dump Dump server status\n"
4106 "Snapshot Commands:\n"
4107 " snapshot [NAME] Create a snapshot\n"
4108 " delete [NAME...] Remove one or more snapshots\n\n"
4109 "Environment Commands:\n"
4110 " show-environment Dump environment\n"
4111 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4112 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4113 "Manager Lifecycle Commands:\n"
4114 " daemon-reload Reload systemd manager configuration\n"
4115 " daemon-reexec Reexecute systemd manager\n\n"
4116 "System Commands:\n"
4117 " default Enter system default mode\n"
4118 " rescue Enter system rescue mode\n"
4119 " emergency Enter system emergency mode\n"
4120 " halt Shut down and halt the system\n"
4121 " poweroff Shut down and power-off the system\n"
4122 " reboot Shut down and reboot the system\n"
4123 " kexec Shut down and reboot the system with kexec\n"
4124 " exit Request user instance exit\n"
4125 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4126 " suspend Suspend the system\n"
4127 " hibernate Hibernate the system\n"
4128 " hybrid-sleep Hibernate and suspend the system\n",
4129 program_invocation_short_name);
4134 static int halt_help(void) {
4136 printf("%s [OPTIONS...]\n\n"
4137 "%s the system.\n\n"
4138 " --help Show this help\n"
4139 " --halt Halt the machine\n"
4140 " -p --poweroff Switch off the machine\n"
4141 " --reboot Reboot the machine\n"
4142 " -f --force Force immediate halt/power-off/reboot\n"
4143 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4144 " -d --no-wtmp Don't write wtmp record\n"
4145 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4146 program_invocation_short_name,
4147 arg_action == ACTION_REBOOT ? "Reboot" :
4148 arg_action == ACTION_POWEROFF ? "Power off" :
4154 static int shutdown_help(void) {
4156 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4157 "Shut down the system.\n\n"
4158 " --help Show this help\n"
4159 " -H --halt Halt the machine\n"
4160 " -P --poweroff Power-off the machine\n"
4161 " -r --reboot Reboot the machine\n"
4162 " -h Equivalent to --poweroff, overridden by --halt\n"
4163 " -k Don't halt/power-off/reboot, just send warnings\n"
4164 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4165 " -c Cancel a pending shutdown\n",
4166 program_invocation_short_name);
4171 static int telinit_help(void) {
4173 printf("%s [OPTIONS...] {COMMAND}\n\n"
4174 "Send control commands to the init daemon.\n\n"
4175 " --help Show this help\n"
4176 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4178 " 0 Power-off the machine\n"
4179 " 6 Reboot the machine\n"
4180 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4181 " 1, s, S Enter rescue mode\n"
4182 " q, Q Reload init daemon configuration\n"
4183 " u, U Reexecute init daemon\n",
4184 program_invocation_short_name);
4189 static int runlevel_help(void) {
4191 printf("%s [OPTIONS...]\n\n"
4192 "Prints the previous and current runlevel of the init system.\n\n"
4193 " --help Show this help\n",
4194 program_invocation_short_name);
4199 static int help_types(void) {
4202 puts("Available unit types:");
4203 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4204 if (unit_type_table[i])
4205 puts(unit_type_table[i]);
4207 puts("\nAvailable unit load states: ");
4208 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4209 if (unit_type_table[i])
4210 puts(unit_load_state_table[i]);
4215 static int systemctl_parse_argv(int argc, char *argv[]) {
4219 ARG_IGNORE_DEPENDENCIES,
4232 ARG_NO_ASK_PASSWORD,
4238 static const struct option options[] = {
4239 { "help", no_argument, NULL, 'h' },
4240 { "version", no_argument, NULL, ARG_VERSION },
4241 { "type", required_argument, NULL, 't' },
4242 { "property", required_argument, NULL, 'p' },
4243 { "all", no_argument, NULL, 'a' },
4244 { "failed", no_argument, NULL, ARG_FAILED },
4245 { "full", no_argument, NULL, ARG_FULL },
4246 { "fail", no_argument, NULL, ARG_FAIL },
4247 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4248 { "ignore-inhibitors", no_argument, NULL, 'i' },
4249 { "user", no_argument, NULL, ARG_USER },
4250 { "system", no_argument, NULL, ARG_SYSTEM },
4251 { "global", no_argument, NULL, ARG_GLOBAL },
4252 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4253 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4254 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4255 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4256 { "quiet", no_argument, NULL, 'q' },
4257 { "root", required_argument, NULL, ARG_ROOT },
4258 { "force", no_argument, NULL, ARG_FORCE },
4259 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4260 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4261 { "signal", required_argument, NULL, 's' },
4262 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4263 { "host", required_argument, NULL, 'H' },
4264 { "privileged",no_argument, NULL, 'P' },
4265 { "runtime", no_argument, NULL, ARG_RUNTIME },
4266 { "lines", required_argument, NULL, 'n' },
4267 { "output", required_argument, NULL, 'o' },
4268 { NULL, 0, NULL, 0 }
4276 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4285 puts(PACKAGE_STRING);
4286 puts(SYSTEMD_FEATURES);
4290 if (streq(optarg, "help")) {
4295 if (unit_type_from_string(optarg) >= 0) {
4299 if (unit_load_state_from_string(optarg) >= 0) {
4300 arg_load_state = optarg;
4303 log_error("Unkown unit type or load state '%s'.",
4305 log_info("Use -t help to see a list of allowed values.");
4310 if (!(l = strv_append(arg_property, optarg)))
4313 strv_free(arg_property);
4316 /* If the user asked for a particular
4317 * property, show it to him, even if it is
4328 arg_job_mode = "fail";
4331 case ARG_IGNORE_DEPENDENCIES:
4332 arg_job_mode = "ignore-dependencies";
4336 arg_scope = UNIT_FILE_USER;
4340 arg_scope = UNIT_FILE_SYSTEM;
4344 arg_scope = UNIT_FILE_GLOBAL;
4348 arg_no_block = true;
4352 arg_no_legend = true;
4356 arg_no_pager = true;
4388 arg_no_reload = true;
4392 arg_kill_who = optarg;
4396 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4397 log_error("Failed to parse signal string %s.", optarg);
4402 case ARG_NO_ASK_PASSWORD:
4403 arg_ask_password = false;
4407 arg_transport = TRANSPORT_POLKIT;
4411 arg_transport = TRANSPORT_SSH;
4420 if (safe_atou(optarg, &arg_lines) < 0) {
4421 log_error("Failed to parse lines '%s'", optarg);
4427 arg_output = output_mode_from_string(optarg);
4428 if (arg_output < 0) {
4429 log_error("Unknown output '%s'.", optarg);
4435 arg_ignore_inhibitors = true;
4442 log_error("Unknown option code '%c'.", c);
4447 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4448 log_error("Cannot access user instance remotely.");
4455 static int halt_parse_argv(int argc, char *argv[]) {
4464 static const struct option options[] = {
4465 { "help", no_argument, NULL, ARG_HELP },
4466 { "halt", no_argument, NULL, ARG_HALT },
4467 { "poweroff", no_argument, NULL, 'p' },
4468 { "reboot", no_argument, NULL, ARG_REBOOT },
4469 { "force", no_argument, NULL, 'f' },
4470 { "wtmp-only", no_argument, NULL, 'w' },
4471 { "no-wtmp", no_argument, NULL, 'd' },
4472 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4473 { NULL, 0, NULL, 0 }
4481 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4482 if (runlevel == '0' || runlevel == '6')
4485 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4493 arg_action = ACTION_HALT;
4497 if (arg_action != ACTION_REBOOT)
4498 arg_action = ACTION_POWEROFF;
4502 arg_action = ACTION_REBOOT;
4524 /* Compatibility nops */
4531 log_error("Unknown option code '%c'.", c);
4536 if (optind < argc) {
4537 log_error("Too many arguments.");
4544 static int parse_time_spec(const char *t, usec_t *_u) {
4548 if (streq(t, "now"))
4550 else if (!strchr(t, ':')) {
4553 if (safe_atou64(t, &u) < 0)
4556 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4565 hour = strtol(t, &e, 10);
4566 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4569 minute = strtol(e+1, &e, 10);
4570 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4573 n = now(CLOCK_REALTIME);
4574 s = (time_t) (n / USEC_PER_SEC);
4577 assert_se(localtime_r(&s, &tm));
4579 tm.tm_hour = (int) hour;
4580 tm.tm_min = (int) minute;
4583 assert_se(s = mktime(&tm));
4585 *_u = (usec_t) s * USEC_PER_SEC;
4588 *_u += USEC_PER_DAY;
4594 static int shutdown_parse_argv(int argc, char *argv[]) {
4601 static const struct option options[] = {
4602 { "help", no_argument, NULL, ARG_HELP },
4603 { "halt", no_argument, NULL, 'H' },
4604 { "poweroff", no_argument, NULL, 'P' },
4605 { "reboot", no_argument, NULL, 'r' },
4606 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4607 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4608 { NULL, 0, NULL, 0 }
4616 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4624 arg_action = ACTION_HALT;
4628 arg_action = ACTION_POWEROFF;
4633 arg_action = ACTION_KEXEC;
4635 arg_action = ACTION_REBOOT;
4639 arg_action = ACTION_KEXEC;
4643 if (arg_action != ACTION_HALT)
4644 arg_action = ACTION_POWEROFF;
4657 /* Compatibility nops */
4661 arg_action = ACTION_CANCEL_SHUTDOWN;
4668 log_error("Unknown option code '%c'.", c);
4673 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4674 r = parse_time_spec(argv[optind], &arg_when);
4676 log_error("Failed to parse time specification: %s", argv[optind]);
4680 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4682 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4683 /* No time argument for shutdown cancel */
4684 arg_wall = argv + optind;
4685 else if (argc > optind + 1)
4686 /* We skip the time argument */
4687 arg_wall = argv + optind + 1;
4694 static int telinit_parse_argv(int argc, char *argv[]) {
4701 static const struct option options[] = {
4702 { "help", no_argument, NULL, ARG_HELP },
4703 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4704 { NULL, 0, NULL, 0 }
4707 static const struct {
4711 { '0', ACTION_POWEROFF },
4712 { '6', ACTION_REBOOT },
4713 { '1', ACTION_RESCUE },
4714 { '2', ACTION_RUNLEVEL2 },
4715 { '3', ACTION_RUNLEVEL3 },
4716 { '4', ACTION_RUNLEVEL4 },
4717 { '5', ACTION_RUNLEVEL5 },
4718 { 's', ACTION_RESCUE },
4719 { 'S', ACTION_RESCUE },
4720 { 'q', ACTION_RELOAD },
4721 { 'Q', ACTION_RELOAD },
4722 { 'u', ACTION_REEXEC },
4723 { 'U', ACTION_REEXEC }
4732 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4747 log_error("Unknown option code '%c'.", c);
4752 if (optind >= argc) {
4757 if (optind + 1 < argc) {
4758 log_error("Too many arguments.");
4762 if (strlen(argv[optind]) != 1) {
4763 log_error("Expected single character argument.");
4767 for (i = 0; i < ELEMENTSOF(table); i++)
4768 if (table[i].from == argv[optind][0])
4771 if (i >= ELEMENTSOF(table)) {
4772 log_error("Unknown command '%s'.", argv[optind]);
4776 arg_action = table[i].to;
4783 static int runlevel_parse_argv(int argc, char *argv[]) {
4789 static const struct option options[] = {
4790 { "help", no_argument, NULL, ARG_HELP },
4791 { NULL, 0, NULL, 0 }
4799 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4810 log_error("Unknown option code '%c'.", c);
4815 if (optind < argc) {
4816 log_error("Too many arguments.");
4823 static int parse_argv(int argc, char *argv[]) {
4827 if (program_invocation_short_name) {
4829 if (strstr(program_invocation_short_name, "halt")) {
4830 arg_action = ACTION_HALT;
4831 return halt_parse_argv(argc, argv);
4832 } else if (strstr(program_invocation_short_name, "poweroff")) {
4833 arg_action = ACTION_POWEROFF;
4834 return halt_parse_argv(argc, argv);
4835 } else if (strstr(program_invocation_short_name, "reboot")) {
4837 arg_action = ACTION_KEXEC;
4839 arg_action = ACTION_REBOOT;
4840 return halt_parse_argv(argc, argv);
4841 } else if (strstr(program_invocation_short_name, "shutdown")) {
4842 arg_action = ACTION_POWEROFF;
4843 return shutdown_parse_argv(argc, argv);
4844 } else if (strstr(program_invocation_short_name, "init")) {
4846 if (sd_booted() > 0) {
4847 arg_action = ACTION_INVALID;
4848 return telinit_parse_argv(argc, argv);
4850 /* Hmm, so some other init system is
4851 * running, we need to forward this
4852 * request to it. For now we simply
4853 * guess that it is Upstart. */
4855 execv("/lib/upstart/telinit", argv);
4857 log_error("Couldn't find an alternative telinit implementation to spawn.");
4861 } else if (strstr(program_invocation_short_name, "runlevel")) {
4862 arg_action = ACTION_RUNLEVEL;
4863 return runlevel_parse_argv(argc, argv);
4867 arg_action = ACTION_SYSTEMCTL;
4868 return systemctl_parse_argv(argc, argv);
4871 static int action_to_runlevel(void) {
4873 static const char table[_ACTION_MAX] = {
4874 [ACTION_HALT] = '0',
4875 [ACTION_POWEROFF] = '0',
4876 [ACTION_REBOOT] = '6',
4877 [ACTION_RUNLEVEL2] = '2',
4878 [ACTION_RUNLEVEL3] = '3',
4879 [ACTION_RUNLEVEL4] = '4',
4880 [ACTION_RUNLEVEL5] = '5',
4881 [ACTION_RESCUE] = '1'
4884 assert(arg_action < _ACTION_MAX);
4886 return table[arg_action];
4889 static int talk_upstart(void) {
4890 DBusMessage _cleanup_dbus_message_unref_ *m = NULL, *reply = NULL;
4891 DBusError _cleanup_dbus_error_free_ error;
4892 int previous, rl, r;
4894 env1_buf[] = "RUNLEVEL=X",
4895 env2_buf[] = "PREVLEVEL=X";
4896 char *env1 = env1_buf, *env2 = env2_buf;
4897 const char *emit = "runlevel";
4898 dbus_bool_t b_false = FALSE;
4899 DBusMessageIter iter, sub;
4900 DBusConnection *bus;
4902 dbus_error_init(&error);
4904 if (!(rl = action_to_runlevel()))
4907 if (utmp_get_runlevel(&previous, NULL) < 0)
4910 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4911 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4916 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4921 if ((r = bus_check_peercred(bus)) < 0) {
4922 log_error("Failed to verify owner of bus.");
4926 if (!(m = dbus_message_new_method_call(
4927 "com.ubuntu.Upstart",
4928 "/com/ubuntu/Upstart",
4929 "com.ubuntu.Upstart0_6",
4932 log_error("Could not allocate message.");
4937 dbus_message_iter_init_append(m, &iter);
4939 env1_buf[sizeof(env1_buf)-2] = rl;
4940 env2_buf[sizeof(env2_buf)-2] = previous;
4942 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4943 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4944 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4945 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4946 !dbus_message_iter_close_container(&iter, &sub) ||
4947 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4948 log_error("Could not append arguments to message.");
4953 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4955 if (bus_error_is_no_service(&error)) {
4960 log_error("Failed to issue method call: %s", bus_error_message(&error));
4969 dbus_connection_flush(bus);
4970 dbus_connection_close(bus);
4971 dbus_connection_unref(bus);
4977 static int talk_initctl(void) {
4978 struct init_request request;
4982 if (!(rl = action_to_runlevel()))
4986 request.magic = INIT_MAGIC;
4987 request.sleeptime = 0;
4988 request.cmd = INIT_CMD_RUNLVL;
4989 request.runlevel = rl;
4991 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4993 if (errno == ENOENT)
4996 log_error("Failed to open "INIT_FIFO": %m");
5001 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5002 close_nointr_nofail(fd);
5005 log_error("Failed to write to "INIT_FIFO": %m");
5006 return errno ? -errno : -EIO;
5012 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5014 static const struct {
5022 int (* const dispatch)(DBusConnection *bus, char **args);
5024 { "list-units", LESS, 1, list_units },
5025 { "list-unit-files", EQUAL, 1, list_unit_files },
5026 { "list-jobs", EQUAL, 1, list_jobs },
5027 { "clear-jobs", EQUAL, 1, daemon_reload },
5028 { "load", MORE, 2, load_unit },
5029 { "cancel", MORE, 2, cancel_job },
5030 { "start", MORE, 2, start_unit },
5031 { "stop", MORE, 2, start_unit },
5032 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5033 { "reload", MORE, 2, start_unit },
5034 { "restart", MORE, 2, start_unit },
5035 { "try-restart", MORE, 2, start_unit },
5036 { "reload-or-restart", MORE, 2, start_unit },
5037 { "reload-or-try-restart", MORE, 2, start_unit },
5038 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5039 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5040 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5041 { "isolate", EQUAL, 2, start_unit },
5042 { "set-cgroup", MORE, 2, set_cgroup },
5043 { "unset-cgroup", MORE, 2, set_cgroup },
5044 { "get-cgroup-attr", MORE, 2, get_cgroup_attr },
5045 { "set-cgroup-attr", MORE, 2, set_cgroup_attr },
5046 { "unset-cgroup-attr", MORE, 2, set_cgroup },
5047 { "kill", MORE, 2, kill_unit },
5048 { "is-active", MORE, 2, check_unit_active },
5049 { "check", MORE, 2, check_unit_active },
5050 { "is-failed", MORE, 2, check_unit_failed },
5051 { "show", MORE, 1, show },
5052 { "status", MORE, 2, show },
5053 { "help", MORE, 2, show },
5054 { "dump", EQUAL, 1, dump },
5055 { "snapshot", LESS, 2, snapshot },
5056 { "delete", MORE, 2, delete_snapshot },
5057 { "daemon-reload", EQUAL, 1, daemon_reload },
5058 { "daemon-reexec", EQUAL, 1, daemon_reload },
5059 { "show-environment", EQUAL, 1, show_enviroment },
5060 { "set-environment", MORE, 2, set_environment },
5061 { "unset-environment", MORE, 2, set_environment },
5062 { "halt", EQUAL, 1, start_special },
5063 { "poweroff", EQUAL, 1, start_special },
5064 { "reboot", EQUAL, 1, start_special },
5065 { "kexec", EQUAL, 1, start_special },
5066 { "suspend", EQUAL, 1, start_special },
5067 { "hibernate", EQUAL, 1, start_special },
5068 { "hybrid-sleep", EQUAL, 1, start_special },
5069 { "default", EQUAL, 1, start_special },
5070 { "rescue", EQUAL, 1, start_special },
5071 { "emergency", EQUAL, 1, start_special },
5072 { "exit", EQUAL, 1, start_special },
5073 { "reset-failed", MORE, 1, reset_failed },
5074 { "enable", MORE, 2, enable_unit },
5075 { "disable", MORE, 2, enable_unit },
5076 { "is-enabled", MORE, 2, unit_is_enabled },
5077 { "reenable", MORE, 2, enable_unit },
5078 { "preset", MORE, 2, enable_unit },
5079 { "mask", MORE, 2, enable_unit },
5080 { "unmask", MORE, 2, enable_unit },
5081 { "link", MORE, 2, enable_unit },
5082 { "switch-root", MORE, 2, switch_root },
5083 { "list-dependencies", LESS, 2, list_dependencies },
5093 left = argc - optind;
5096 /* Special rule: no arguments means "list-units" */
5099 if (streq(argv[optind], "help") && !argv[optind+1]) {
5100 log_error("This command expects one or more "
5101 "unit names. Did you mean --help?");
5105 for (i = 0; i < ELEMENTSOF(verbs); i++)
5106 if (streq(argv[optind], verbs[i].verb))
5109 if (i >= ELEMENTSOF(verbs)) {
5110 log_error("Unknown operation '%s'.", argv[optind]);
5115 switch (verbs[i].argc_cmp) {
5118 if (left != verbs[i].argc) {
5119 log_error("Invalid number of arguments.");
5126 if (left < verbs[i].argc) {
5127 log_error("Too few arguments.");
5134 if (left > verbs[i].argc) {
5135 log_error("Too many arguments.");
5142 assert_not_reached("Unknown comparison operator.");
5145 /* Require a bus connection for all operations but
5147 if (!streq(verbs[i].verb, "enable") &&
5148 !streq(verbs[i].verb, "disable") &&
5149 !streq(verbs[i].verb, "is-enabled") &&
5150 !streq(verbs[i].verb, "list-unit-files") &&
5151 !streq(verbs[i].verb, "reenable") &&
5152 !streq(verbs[i].verb, "preset") &&
5153 !streq(verbs[i].verb, "mask") &&
5154 !streq(verbs[i].verb, "unmask") &&
5155 !streq(verbs[i].verb, "link")) {
5157 if (running_in_chroot() > 0) {
5158 log_info("Running in chroot, ignoring request.");
5162 if (((!streq(verbs[i].verb, "reboot") &&
5163 !streq(verbs[i].verb, "halt") &&
5164 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5165 log_error("Failed to get D-Bus connection: %s",
5166 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5172 if (!bus && !avoid_bus()) {
5173 log_error("Failed to get D-Bus connection: %s",
5174 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5179 return verbs[i].dispatch(bus, argv + optind);
5182 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5183 int _cleanup_close_ fd;
5184 struct msghdr msghdr;
5185 struct iovec iovec[2];
5186 union sockaddr_union sockaddr;
5187 struct sd_shutdown_command c;
5189 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5196 c.dry_run = dry_run;
5200 sockaddr.sa.sa_family = AF_UNIX;
5201 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5204 msghdr.msg_name = &sockaddr;
5205 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5208 iovec[0].iov_base = (char*) &c;
5209 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5211 if (isempty(message))
5212 msghdr.msg_iovlen = 1;
5214 iovec[1].iov_base = (char*) message;
5215 iovec[1].iov_len = strlen(message);
5216 msghdr.msg_iovlen = 2;
5218 msghdr.msg_iov = iovec;
5220 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5226 static int reload_with_fallback(DBusConnection *bus) {
5229 /* First, try systemd via D-Bus. */
5230 if (daemon_reload(bus, NULL) >= 0)
5234 /* Nothing else worked, so let's try signals */
5235 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5237 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5238 log_error("kill() failed: %m");
5245 static int start_with_fallback(DBusConnection *bus) {
5248 /* First, try systemd via D-Bus. */
5249 if (start_unit(bus, NULL) >= 0)
5253 /* Hmm, talking to systemd via D-Bus didn't work. Then
5254 * let's try to talk to Upstart via D-Bus. */
5255 if (talk_upstart() > 0)
5258 /* Nothing else worked, so let's try
5260 if (talk_initctl() > 0)
5263 log_error("Failed to talk to init daemon.");
5267 warn_wall(arg_action);
5271 static _noreturn_ void halt_now(enum action a) {
5273 /* Make sure C-A-D is handled by the kernel from this
5275 reboot(RB_ENABLE_CAD);
5280 log_info("Halting.");
5281 reboot(RB_HALT_SYSTEM);
5284 case ACTION_POWEROFF:
5285 log_info("Powering off.");
5286 reboot(RB_POWER_OFF);
5290 log_info("Rebooting.");
5291 reboot(RB_AUTOBOOT);
5295 assert_not_reached("Unknown halt action.");
5298 assert_not_reached("Uh? This shouldn't happen.");
5301 static int halt_main(DBusConnection *bus) {
5304 r = check_inhibitors(bus, arg_action);
5308 if (geteuid() != 0) {
5309 /* Try logind if we are a normal user and no special
5310 * mode applies. Maybe PolicyKit allows us to shutdown
5313 if (arg_when <= 0 &&
5316 (arg_action == ACTION_POWEROFF ||
5317 arg_action == ACTION_REBOOT)) {
5318 r = reboot_with_logind(bus, arg_action);
5323 log_error("Must be root.");
5328 char _cleanup_free_ *m;
5330 m = strv_join(arg_wall, " ");
5331 r = send_shutdownd(arg_when,
5332 arg_action == ACTION_HALT ? 'H' :
5333 arg_action == ACTION_POWEROFF ? 'P' :
5334 arg_action == ACTION_KEXEC ? 'K' :
5341 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5343 char date[FORMAT_TIMESTAMP_MAX];
5345 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5346 format_timestamp(date, sizeof(date), arg_when));
5351 if (!arg_dry && !arg_force)
5352 return start_with_fallback(bus);
5355 if (sd_booted() > 0)
5356 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5358 r = utmp_put_shutdown();
5360 log_warning("Failed to write utmp record: %s", strerror(-r));
5367 halt_now(arg_action);
5368 /* We should never reach this. */
5372 static int runlevel_main(void) {
5373 int r, runlevel, previous;
5375 r = utmp_get_runlevel(&runlevel, &previous);
5382 previous <= 0 ? 'N' : previous,
5383 runlevel <= 0 ? 'N' : runlevel);
5388 int main(int argc, char*argv[]) {
5389 int r, retval = EXIT_FAILURE;
5390 DBusConnection *bus = NULL;
5391 DBusError _cleanup_dbus_error_free_ error;
5393 dbus_error_init(&error);
5395 setlocale(LC_ALL, "");
5396 log_parse_environment();
5399 r = parse_argv(argc, argv);
5403 retval = EXIT_SUCCESS;
5407 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5408 * let's shortcut this */
5409 if (arg_action == ACTION_RUNLEVEL) {
5410 r = runlevel_main();
5411 retval = r < 0 ? EXIT_FAILURE : r;
5415 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5416 log_info("Running in chroot, ignoring request.");
5422 if (arg_transport == TRANSPORT_NORMAL)
5423 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5424 else if (arg_transport == TRANSPORT_POLKIT) {
5425 bus_connect_system_polkit(&bus, &error);
5426 private_bus = false;
5427 } else if (arg_transport == TRANSPORT_SSH) {
5428 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5429 private_bus = false;
5431 assert_not_reached("Uh, invalid transport...");
5434 switch (arg_action) {
5436 case ACTION_SYSTEMCTL:
5437 r = systemctl_main(bus, argc, argv, &error);
5441 case ACTION_POWEROFF:
5447 case ACTION_RUNLEVEL2:
5448 case ACTION_RUNLEVEL3:
5449 case ACTION_RUNLEVEL4:
5450 case ACTION_RUNLEVEL5:
5452 case ACTION_EMERGENCY:
5453 case ACTION_DEFAULT:
5454 r = start_with_fallback(bus);
5459 r = reload_with_fallback(bus);
5462 case ACTION_CANCEL_SHUTDOWN: {
5466 m = strv_join(arg_wall, " ");
5468 retval = EXIT_FAILURE;
5472 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5474 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5479 case ACTION_INVALID:
5480 case ACTION_RUNLEVEL:
5482 assert_not_reached("Unknown action");
5485 retval = r < 0 ? EXIT_FAILURE : r;
5489 dbus_connection_flush(bus);
5490 dbus_connection_close(bus);
5491 dbus_connection_unref(bus);
5496 strv_free(arg_property);
5499 ask_password_agent_close();
5500 polkit_agent_close();