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, 25u);
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, 25u);
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 get_unit_list(DBusConnection *bus, DBusMessage **reply,
430 struct unit_info **unit_infos, unsigned *c) {
431 DBusMessageIter iter, sub;
432 unsigned n_units = 0;
439 r = bus_method_call_with_reply(
441 "org.freedesktop.systemd1",
442 "/org/freedesktop/systemd1",
443 "org.freedesktop.systemd1.Manager",
451 if (!dbus_message_iter_init(*reply, &iter) ||
452 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
453 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
454 log_error("Failed to parse reply.");
458 dbus_message_iter_recurse(&iter, &sub);
460 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
466 n_units = MAX(2 * *c, 16u);
467 w = realloc(*unit_infos, sizeof(struct unit_info) * n_units);
474 u = *unit_infos + *c;
476 bus_parse_unit_info(&sub, u);
478 dbus_message_iter_next(&sub);
483 qsort(*unit_infos, *c, sizeof(struct unit_info), compare_unit_info);
488 static int list_units(DBusConnection *bus, char **args) {
489 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
490 _cleanup_free_ struct unit_info *unit_infos = NULL;
494 pager_open_if_enabled();
496 r = get_unit_list(bus, &reply, &unit_infos, &c);
501 output_units_list(unit_infos, c);
506 static int compare_unit_file_list(const void *a, const void *b) {
508 const UnitFileList *u = a, *v = b;
510 d1 = strrchr(u->path, '.');
511 d2 = strrchr(v->path, '.');
516 r = strcasecmp(d1, d2);
521 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
524 static bool output_show_unit_file(const UnitFileList *u) {
527 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
530 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
531 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
532 const UnitFileList *u;
534 max_id_len = sizeof("UNIT FILE")-1;
535 state_cols = sizeof("STATE")-1;
536 for (u = units; u < units + c; u++) {
537 if (!output_show_unit_file(u))
540 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
541 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
546 id_cols = MIN(max_id_len, 25u);
547 basic_cols = 1 + id_cols + state_cols;
548 if (basic_cols < (unsigned) columns())
549 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
551 id_cols = max_id_len;
554 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
556 for (u = units; u < units + c; u++) {
557 char _cleanup_free_ *e = NULL;
558 const char *on, *off;
561 if (!output_show_unit_file(u))
566 if (u->state == UNIT_FILE_MASKED ||
567 u->state == UNIT_FILE_MASKED_RUNTIME ||
568 u->state == UNIT_FILE_DISABLED ||
569 u->state == UNIT_FILE_INVALID) {
570 on = ansi_highlight_red(true);
571 off = ansi_highlight_red(false);
572 } else if (u->state == UNIT_FILE_ENABLED) {
573 on = ansi_highlight_green(true);
574 off = ansi_highlight_green(false);
578 id = path_get_file_name(u->path);
580 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
582 printf("%-*s %s%-*s%s\n",
584 on, state_cols, unit_file_state_to_string(u->state), off);
588 printf("\n%u unit files listed.\n", n_shown);
591 static int list_unit_files(DBusConnection *bus, char **args) {
592 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
593 _cleanup_free_ UnitFileList *units = NULL;
594 DBusMessageIter iter, sub, sub2;
595 unsigned c = 0, n_units = 0;
598 pager_open_if_enabled();
605 h = hashmap_new(string_hash_func, string_compare_func);
609 r = unit_file_get_list(arg_scope, arg_root, h);
611 unit_file_list_free(h);
612 log_error("Failed to get unit file list: %s", strerror(-r));
616 n_units = hashmap_size(h);
617 units = new(UnitFileList, n_units);
619 unit_file_list_free(h);
623 HASHMAP_FOREACH(u, h, i) {
624 memcpy(units + c++, u, sizeof(UnitFileList));
630 r = bus_method_call_with_reply(
632 "org.freedesktop.systemd1",
633 "/org/freedesktop/systemd1",
634 "org.freedesktop.systemd1.Manager",
642 if (!dbus_message_iter_init(reply, &iter) ||
643 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
644 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
645 log_error("Failed to parse reply.");
649 dbus_message_iter_recurse(&iter, &sub);
651 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
655 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
660 n_units = MAX(2*c, 16u);
661 w = realloc(units, sizeof(struct UnitFileList) * n_units);
670 dbus_message_iter_recurse(&sub, &sub2);
672 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
673 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
674 log_error("Failed to parse reply.");
678 u->state = unit_file_state_from_string(state);
680 dbus_message_iter_next(&sub);
686 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
687 output_unit_file_list(units, c);
693 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
695 _cleanup_free_ char *n = NULL;
697 size_t max_len = MAX(columns(),20u);
699 for (i = level - 1; i >= 0; i--) {
701 if(len > max_len - 3 && !arg_full) {
702 printf("%s...\n",max_len % 2 ? "" : " ");
705 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
708 if(len > max_len - 3 && !arg_full) {
709 printf("%s...\n",max_len % 2 ? "" : " ");
712 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
715 printf("%s\n", name);
719 n = ellipsize(name, max_len-len, 100);
727 static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
728 static const char dependencies[] =
730 "RequiresOverridable\0"
732 "RequisiteOverridable\0"
735 _cleanup_free_ char *path;
736 const char *interface = "org.freedesktop.systemd1.Unit";
738 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
739 DBusMessageIter iter, sub, sub2, sub3;
748 path = unit_dbus_path_from_name(name);
754 r = bus_method_call_with_reply(
756 "org.freedesktop.systemd1",
758 "org.freedesktop.DBus.Properties",
762 DBUS_TYPE_STRING, &interface,
767 if (!dbus_message_iter_init(reply, &iter) ||
768 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
769 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
770 log_error("Failed to parse reply.");
775 dbus_message_iter_recurse(&iter, &sub);
777 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
780 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
781 dbus_message_iter_recurse(&sub, &sub2);
783 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
784 log_error("Failed to parse reply.");
789 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
790 log_error("Failed to parse reply.");
795 dbus_message_iter_recurse(&sub2, &sub3);
796 dbus_message_iter_next(&sub);
798 if (!nulstr_contains(dependencies, prop))
801 if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
802 if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
803 DBusMessageIter sub4;
804 dbus_message_iter_recurse(&sub3, &sub4);
806 while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
809 assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
810 dbus_message_iter_get_basic(&sub4, &s);
812 r = strv_extend(&ret, s);
818 dbus_message_iter_next(&sub4);
831 static int list_dependencies_compare(const void *_a, const void *_b) {
832 const char **a = (const char**) _a, **b = (const char**) _b;
833 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
835 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
837 return strcasecmp(*a, *b);
840 static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char **units, unsigned int branches) {
841 char _cleanup_strv_free_ **deps = NULL, **u;
845 u = strv_append(units, name);
849 r = list_dependencies_get_dependencies(bus, name, &deps);
853 qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
855 STRV_FOREACH(c, deps) {
856 if (strv_contains(u, *c)) {
857 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
863 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
867 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
868 r = list_dependencies_one(bus, *c, level + 1, u, (branches << 1) | (c[1] == NULL ? 0 : 1));
877 static int list_dependencies(DBusConnection *bus, char **args) {
878 _cleanup_free_ char *unit = NULL;
884 unit = unit_name_mangle(args[1]);
889 u = SPECIAL_DEFAULT_TARGET;
891 pager_open_if_enabled();
895 return list_dependencies_one(bus, u, 0, NULL, 0);
898 static int list_jobs(DBusConnection *bus, char **args) {
899 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
900 DBusMessageIter iter, sub, sub2;
904 pager_open_if_enabled();
906 r = bus_method_call_with_reply(
908 "org.freedesktop.systemd1",
909 "/org/freedesktop/systemd1",
910 "org.freedesktop.systemd1.Manager",
918 if (!dbus_message_iter_init(reply, &iter) ||
919 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
920 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
921 log_error("Failed to parse reply.");
925 dbus_message_iter_recurse(&iter, &sub);
928 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
930 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
931 const char *name, *type, *state, *job_path, *unit_path;
933 char _cleanup_free_ *e = NULL;
935 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
936 log_error("Failed to parse reply.");
940 dbus_message_iter_recurse(&sub, &sub2);
942 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
943 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
944 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
945 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
946 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
947 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
948 log_error("Failed to parse reply.");
952 e = arg_full ? NULL : ellipsize(name, 25, 33);
953 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
957 dbus_message_iter_next(&sub);
961 printf("\n%u jobs listed.\n", k);
966 static int load_unit(DBusConnection *bus, char **args) {
971 STRV_FOREACH(name, args+1) {
972 _cleanup_free_ char *n = NULL;
975 n = unit_name_mangle(*name);
979 r = bus_method_call_with_reply(
981 "org.freedesktop.systemd1",
982 "/org/freedesktop/systemd1",
983 "org.freedesktop.systemd1.Manager",
987 DBUS_TYPE_STRING, &n,
996 static int cancel_job(DBusConnection *bus, char **args) {
1001 if (strv_length(args) <= 1)
1002 return daemon_reload(bus, args);
1004 STRV_FOREACH(name, args+1) {
1008 r = safe_atou32(*name, &id);
1010 log_error("Failed to parse job id: %s", strerror(-r));
1014 r = bus_method_call_with_reply(
1016 "org.freedesktop.systemd1",
1017 "/org/freedesktop/systemd1",
1018 "org.freedesktop.systemd1.Manager",
1022 DBUS_TYPE_UINT32, &id,
1031 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1032 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1033 dbus_bool_t b = FALSE;
1034 DBusMessageIter iter, sub;
1036 *interface = "org.freedesktop.systemd1.Unit",
1037 *property = "NeedDaemonReload",
1039 _cleanup_free_ char *n = NULL;
1042 /* We ignore all errors here, since this is used to show a warning only */
1044 n = unit_name_mangle(unit);
1048 r = bus_method_call_with_reply(
1050 "org.freedesktop.systemd1",
1051 "/org/freedesktop/systemd1",
1052 "org.freedesktop.systemd1.Manager",
1056 DBUS_TYPE_STRING, &n,
1061 if (!dbus_message_get_args(reply, NULL,
1062 DBUS_TYPE_OBJECT_PATH, &path,
1066 dbus_message_unref(reply);
1069 r = bus_method_call_with_reply(
1071 "org.freedesktop.systemd1",
1073 "org.freedesktop.DBus.Properties",
1077 DBUS_TYPE_STRING, &interface,
1078 DBUS_TYPE_STRING, &property,
1083 if (!dbus_message_iter_init(reply, &iter) ||
1084 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1087 dbus_message_iter_recurse(&iter, &sub);
1088 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1091 dbus_message_iter_get_basic(&sub, &b);
1095 typedef struct WaitData {
1102 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1103 DBusError _cleanup_dbus_error_free_ error;
1106 dbus_error_init(&error);
1112 log_debug("Got D-Bus request: %s.%s() on %s",
1113 dbus_message_get_interface(message),
1114 dbus_message_get_member(message),
1115 dbus_message_get_path(message));
1117 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1118 log_error("Warning! D-Bus connection terminated.");
1119 dbus_connection_close(connection);
1121 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1123 const char *path, *result, *unit;
1125 if (dbus_message_get_args(message, &error,
1126 DBUS_TYPE_UINT32, &id,
1127 DBUS_TYPE_OBJECT_PATH, &path,
1128 DBUS_TYPE_STRING, &unit,
1129 DBUS_TYPE_STRING, &result,
1130 DBUS_TYPE_INVALID)) {
1132 free(set_remove(d->set, (char*) path));
1134 if (!isempty(result))
1135 d->result = strdup(result);
1138 d->name = strdup(unit);
1140 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1143 dbus_error_free(&error);
1144 if (dbus_message_get_args(message, &error,
1145 DBUS_TYPE_UINT32, &id,
1146 DBUS_TYPE_OBJECT_PATH, &path,
1147 DBUS_TYPE_STRING, &result,
1148 DBUS_TYPE_INVALID)) {
1149 /* Compatibility with older systemd versions <
1150 * 183 during upgrades. This should be dropped
1152 free(set_remove(d->set, (char*) path));
1155 d->result = strdup(result);
1157 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1161 log_error("Failed to parse message: %s", bus_error_message(&error));
1164 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1167 static int enable_wait_for_jobs(DBusConnection *bus) {
1175 dbus_error_init(&error);
1176 dbus_bus_add_match(bus,
1178 "sender='org.freedesktop.systemd1',"
1179 "interface='org.freedesktop.systemd1.Manager',"
1180 "member='JobRemoved',"
1181 "path='/org/freedesktop/systemd1'",
1184 if (dbus_error_is_set(&error)) {
1185 log_error("Failed to add match: %s", bus_error_message(&error));
1186 dbus_error_free(&error);
1190 /* This is slightly dirty, since we don't undo the match registrations. */
1194 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1204 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1207 while (!set_isempty(s)) {
1209 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1210 log_error("Disconnected from bus.");
1211 return -ECONNREFUSED;
1218 if (streq(d.result, "timeout"))
1219 log_error("Job for %s timed out.", strna(d.name));
1220 else if (streq(d.result, "canceled"))
1221 log_error("Job for %s canceled.", strna(d.name));
1222 else if (streq(d.result, "dependency"))
1223 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1224 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1225 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1228 if (streq_ptr(d.result, "timeout"))
1230 else if (streq_ptr(d.result, "canceled"))
1232 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1243 dbus_connection_remove_filter(bus, wait_filter, &d);
1247 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1248 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1249 _cleanup_free_ char *n = NULL;
1250 DBusMessageIter iter, sub;
1252 *interface = "org.freedesktop.systemd1.Unit",
1253 *property = "ActiveState";
1254 const char *state, *path;
1260 dbus_error_init(&error);
1262 n = unit_name_mangle(name);
1266 r = bus_method_call_with_reply (
1268 "org.freedesktop.systemd1",
1269 "/org/freedesktop/systemd1",
1270 "org.freedesktop.systemd1.Manager",
1274 DBUS_TYPE_STRING, &n,
1277 dbus_error_free(&error);
1284 if (!dbus_message_get_args(reply, NULL,
1285 DBUS_TYPE_OBJECT_PATH, &path,
1286 DBUS_TYPE_INVALID)) {
1287 log_error("Failed to parse reply.");
1291 dbus_message_unref(reply);
1294 r = bus_method_call_with_reply(
1296 "org.freedesktop.systemd1",
1298 "org.freedesktop.DBus.Properties",
1302 DBUS_TYPE_STRING, &interface,
1303 DBUS_TYPE_STRING, &property,
1311 if (!dbus_message_iter_init(reply, &iter) ||
1312 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1313 log_error("Failed to parse reply.");
1317 dbus_message_iter_recurse(&iter, &sub);
1319 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1320 log_error("Failed to parse reply.");
1324 dbus_message_iter_get_basic(&sub, &state);
1329 return strv_find(check_states, state) ? 1 : 0;
1332 static void check_triggering_units(
1333 DBusConnection *bus,
1334 const char *unit_name) {
1336 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1337 DBusMessageIter iter, sub;
1338 const char *interface = "org.freedesktop.systemd1.Unit",
1339 *load_state_property = "LoadState",
1340 *triggered_by_property = "TriggeredBy",
1342 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1343 bool print_warning_label = true;
1346 n = unit_name_mangle(unit_name);
1352 unit_path = unit_dbus_path_from_name(n);
1358 r = bus_method_call_with_reply(
1360 "org.freedesktop.systemd1",
1362 "org.freedesktop.DBus.Properties",
1366 DBUS_TYPE_STRING, &interface,
1367 DBUS_TYPE_STRING, &load_state_property,
1372 if (!dbus_message_iter_init(reply, &iter) ||
1373 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1374 log_error("Failed to parse reply.");
1378 dbus_message_iter_recurse(&iter, &sub);
1380 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1381 log_error("Failed to parse reply.");
1385 dbus_message_iter_get_basic(&sub, &state);
1387 if (streq(state, "masked"))
1390 dbus_message_unref(reply);
1393 r = bus_method_call_with_reply(
1395 "org.freedesktop.systemd1",
1397 "org.freedesktop.DBus.Properties",
1401 DBUS_TYPE_STRING, &interface,
1402 DBUS_TYPE_STRING, &triggered_by_property,
1407 if (!dbus_message_iter_init(reply, &iter) ||
1408 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1409 log_error("Failed to parse reply.");
1413 dbus_message_iter_recurse(&iter, &sub);
1414 dbus_message_iter_recurse(&sub, &iter);
1417 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1418 const char * const check_states[] = {
1423 const char *service_trigger;
1425 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1426 log_error("Failed to parse reply.");
1430 dbus_message_iter_get_basic(&sub, &service_trigger);
1432 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1436 if (print_warning_label) {
1437 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1438 print_warning_label = false;
1441 log_warning(" %s", service_trigger);
1444 dbus_message_iter_next(&sub);
1448 static int start_unit_one(
1449 DBusConnection *bus,
1456 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1457 _cleanup_free_ char *n;
1466 n = unit_name_mangle(name);
1470 r = bus_method_call_with_reply(
1472 "org.freedesktop.systemd1",
1473 "/org/freedesktop/systemd1",
1474 "org.freedesktop.systemd1.Manager",
1478 DBUS_TYPE_STRING, &n,
1479 DBUS_TYPE_STRING, &mode,
1482 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1483 /* There's always a fallback possible for
1484 * legacy actions. */
1487 log_error("Failed to issue method call: %s", bus_error_message(error));
1492 if (!dbus_message_get_args(reply, error,
1493 DBUS_TYPE_OBJECT_PATH, &path,
1494 DBUS_TYPE_INVALID)) {
1495 log_error("Failed to parse reply: %s", bus_error_message(error));
1499 if (need_daemon_reload(bus, n))
1500 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1501 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1513 log_error("Failed to add path to set.");
1521 static const struct {
1525 } action_table[_ACTION_MAX] = {
1526 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
1527 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
1528 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
1529 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
1530 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
1531 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
1532 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
1533 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
1534 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
1535 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
1536 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
1537 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
1538 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
1539 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
1540 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1543 static enum action verb_to_action(const char *verb) {
1546 for (i = ACTION_INVALID; i < _ACTION_MAX; i++)
1547 if (action_table[i].verb && streq(verb, action_table[i].verb))
1549 return ACTION_INVALID;
1552 static int start_unit(DBusConnection *bus, char **args) {
1555 const char *method, *mode, *one_name;
1556 Set _cleanup_set_free_free_ *s = NULL;
1557 DBusError _cleanup_dbus_error_free_ error;
1560 dbus_error_init(&error);
1564 ask_password_agent_open_if_enabled();
1566 if (arg_action == ACTION_SYSTEMCTL) {
1569 streq(args[0], "stop") ||
1570 streq(args[0], "condstop") ? "StopUnit" :
1571 streq(args[0], "reload") ? "ReloadUnit" :
1572 streq(args[0], "restart") ? "RestartUnit" :
1574 streq(args[0], "try-restart") ||
1575 streq(args[0], "condrestart") ? "TryRestartUnit" :
1577 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1579 streq(args[0], "reload-or-try-restart") ||
1580 streq(args[0], "condreload") ||
1582 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1584 action = verb_to_action(args[0]);
1586 mode = streq(args[0], "isolate") ? "isolate" :
1587 action_table[action].mode ?: arg_job_mode;
1589 one_name = action_table[action].target;
1592 assert(arg_action < ELEMENTSOF(action_table));
1593 assert(action_table[arg_action].target);
1595 method = "StartUnit";
1597 mode = action_table[arg_action].mode;
1598 one_name = action_table[arg_action].target;
1601 if (!arg_no_block) {
1602 ret = enable_wait_for_jobs(bus);
1604 log_error("Could not watch jobs: %s", strerror(-ret));
1608 s = set_new(string_hash_func, string_compare_func);
1614 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1616 ret = translate_bus_error_to_exit_status(ret, &error);
1618 STRV_FOREACH(name, args+1) {
1619 r = start_unit_one(bus, method, *name, mode, &error, s);
1621 ret = translate_bus_error_to_exit_status(r, &error);
1622 dbus_error_free(&error);
1627 if (!arg_no_block) {
1628 r = wait_for_jobs(bus, s);
1632 /* When stopping units, warn if they can still be triggered by
1633 * another active unit (socket, path, timer) */
1634 if (!arg_quiet && streq(method, "StopUnit")) {
1636 check_triggering_units(bus, one_name);
1638 STRV_FOREACH(name, args+1)
1639 check_triggering_units(bus, *name);
1646 /* Ask systemd-logind, which might grant access to unprivileged users
1647 * through PolicyKit */
1648 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1651 dbus_bool_t interactive = true;
1656 polkit_agent_open_if_enabled();
1664 case ACTION_POWEROFF:
1665 method = "PowerOff";
1668 case ACTION_SUSPEND:
1672 case ACTION_HIBERNATE:
1673 method = "Hibernate";
1676 case ACTION_HYBRID_SLEEP:
1677 method = "HybridSleep";
1684 return bus_method_call_with_reply(
1686 "org.freedesktop.login1",
1687 "/org/freedesktop/login1",
1688 "org.freedesktop.login1.Manager",
1692 DBUS_TYPE_BOOLEAN, &interactive,
1699 static int check_inhibitors(DBusConnection *bus, enum action a) {
1701 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1702 DBusMessageIter iter, sub, sub2;
1705 _cleanup_strv_free_ char **sessions = NULL;
1711 if (arg_ignore_inhibitors || arg_force > 0)
1723 r = bus_method_call_with_reply(
1725 "org.freedesktop.login1",
1726 "/org/freedesktop/login1",
1727 "org.freedesktop.login1.Manager",
1733 /* If logind is not around, then there are no inhibitors... */
1736 if (!dbus_message_iter_init(reply, &iter) ||
1737 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1738 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1739 log_error("Failed to parse reply.");
1743 dbus_message_iter_recurse(&iter, &sub);
1744 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1745 const char *what, *who, *why, *mode;
1747 _cleanup_strv_free_ char **sv = NULL;
1748 _cleanup_free_ char *comm = NULL, *user = NULL;
1750 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1751 log_error("Failed to parse reply.");
1755 dbus_message_iter_recurse(&sub, &sub2);
1757 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
1758 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
1759 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
1760 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
1761 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
1762 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
1763 log_error("Failed to parse reply.");
1767 if (!streq(mode, "block"))
1770 sv = strv_split(what, ":");
1774 if (!strv_contains(sv,
1776 a == ACTION_POWEROFF ||
1777 a == ACTION_REBOOT ||
1778 a == ACTION_KEXEC ? "shutdown" : "sleep"))
1781 get_process_comm(pid, &comm);
1782 user = uid_to_name(uid);
1783 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
1784 who, (unsigned long) pid, strna(comm), strna(user), why);
1788 dbus_message_iter_next(&sub);
1791 dbus_message_iter_recurse(&iter, &sub);
1793 /* Check for current sessions */
1794 sd_get_sessions(&sessions);
1795 STRV_FOREACH(s, sessions) {
1797 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
1799 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
1802 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
1805 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
1808 sd_session_get_tty(*s, &tty);
1809 sd_session_get_seat(*s, &seat);
1810 sd_session_get_service(*s, &service);
1811 user = uid_to_name(uid);
1813 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
1820 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
1821 action_table[a].verb);
1829 static int start_special(DBusConnection *bus, char **args) {
1835 a = verb_to_action(args[0]);
1837 r = check_inhibitors(bus, a);
1841 if (arg_force >= 2 && geteuid() != 0) {
1842 log_error("Must be root.");
1846 if (arg_force >= 2 &&
1847 (a == ACTION_HALT ||
1848 a == ACTION_POWEROFF ||
1849 a == ACTION_REBOOT))
1852 if (arg_force >= 1 &&
1853 (a == ACTION_HALT ||
1854 a == ACTION_POWEROFF ||
1855 a == ACTION_REBOOT ||
1856 a == ACTION_KEXEC ||
1858 return daemon_reload(bus, args);
1860 /* first try logind, to allow authentication with polkit */
1861 if (geteuid() != 0 &&
1862 (a == ACTION_POWEROFF ||
1863 a == ACTION_REBOOT ||
1864 a == ACTION_SUSPEND ||
1865 a == ACTION_HIBERNATE ||
1866 a == ACTION_HYBRID_SLEEP)) {
1867 r = reboot_with_logind(bus, a);
1872 r = start_unit(bus, args);
1873 if (r == EXIT_SUCCESS)
1879 static int check_unit_active(DBusConnection *bus, char **args) {
1880 const char * const check_states[] = {
1887 int r = 3; /* According to LSB: "program is not running" */
1892 STRV_FOREACH(name, args+1) {
1895 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1905 static int check_unit_failed(DBusConnection *bus, char **args) {
1906 const char * const check_states[] = {
1917 STRV_FOREACH(name, args+1) {
1920 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1930 static int kill_unit(DBusConnection *bus, char **args) {
1938 arg_kill_who = "all";
1940 STRV_FOREACH(name, args+1) {
1941 _cleanup_free_ char *n = NULL;
1943 n = unit_name_mangle(*name);
1947 r = bus_method_call_with_reply(
1949 "org.freedesktop.systemd1",
1950 "/org/freedesktop/systemd1",
1951 "org.freedesktop.systemd1.Manager",
1955 DBUS_TYPE_STRING, &n,
1956 DBUS_TYPE_STRING, &arg_kill_who,
1957 DBUS_TYPE_INT32, &arg_signal,
1965 static int set_cgroup(DBusConnection *bus, char **args) {
1966 _cleanup_free_ char *n = NULL;
1967 const char *method, *runtime;
1975 streq(args[0], "set-cgroup") ? "SetUnitControlGroup" :
1976 streq(args[0], "unset-cgroup") ? "UnsetUnitControlGroup"
1977 : "UnsetUnitControlGroupAttribute";
1979 runtime = arg_runtime ? "runtime" : "persistent";
1981 n = unit_name_mangle(args[1]);
1985 STRV_FOREACH(argument, args + 2) {
1987 r = bus_method_call_with_reply(
1989 "org.freedesktop.systemd1",
1990 "/org/freedesktop/systemd1",
1991 "org.freedesktop.systemd1.Manager",
1995 DBUS_TYPE_STRING, &n,
1996 DBUS_TYPE_STRING, argument,
1997 DBUS_TYPE_STRING, &runtime,
2006 static int set_cgroup_attr(DBusConnection *bus, char **args) {
2007 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2009 DBusMessageIter iter;
2010 _cleanup_free_ char *n = NULL;
2011 const char *runtime;
2017 dbus_error_init(&error);
2019 runtime = arg_runtime ? "runtime" : "persistent";
2021 n = unit_name_mangle(args[1]);
2025 m = dbus_message_new_method_call(
2026 "org.freedesktop.systemd1",
2027 "/org/freedesktop/systemd1",
2028 "org.freedesktop.systemd1.Manager",
2029 "SetUnitControlGroupAttribute");
2033 dbus_message_iter_init_append(m, &iter);
2034 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2035 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[2]))
2038 r = bus_append_strv_iter(&iter, args + 3);
2042 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2045 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2047 log_error("Failed to issue method call: %s", bus_error_message(&error));
2048 dbus_error_free(&error);
2055 static int get_cgroup_attr(DBusConnection *bus, char **args) {
2056 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2057 _cleanup_free_ char *n = NULL;
2064 n = unit_name_mangle(args[1]);
2068 STRV_FOREACH(argument, args + 2) {
2069 _cleanup_strv_free_ char **list = NULL;
2070 DBusMessageIter iter;
2073 r = bus_method_call_with_reply(
2075 "org.freedesktop.systemd1",
2076 "/org/freedesktop/systemd1",
2077 "org.freedesktop.systemd1.Manager",
2078 "GetUnitControlGroupAttribute",
2081 DBUS_TYPE_STRING, &n,
2082 DBUS_TYPE_STRING, argument,
2087 if (!dbus_message_iter_init(reply, &iter)) {
2088 log_error("Failed to initialize iterator.");
2092 r = bus_parse_strv_iter(&iter, &list);
2094 log_error("Failed to parse value list.");
2098 STRV_FOREACH(a, list) {
2099 if (endswith(*a, "\n"))
2109 typedef struct ExecStatusInfo {
2117 usec_t start_timestamp;
2118 usec_t exit_timestamp;
2123 LIST_FIELDS(struct ExecStatusInfo, exec);
2126 static void exec_status_info_free(ExecStatusInfo *i) {
2135 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2136 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2137 DBusMessageIter sub2, sub3;
2141 int32_t code, status;
2147 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2150 dbus_message_iter_recurse(sub, &sub2);
2152 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2155 i->path = strdup(path);
2159 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2160 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2164 dbus_message_iter_recurse(&sub2, &sub3);
2165 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2166 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2167 dbus_message_iter_next(&sub3);
2171 i->argv = new0(char*, n+1);
2176 dbus_message_iter_recurse(&sub2, &sub3);
2177 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2180 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2181 dbus_message_iter_get_basic(&sub3, &s);
2182 dbus_message_iter_next(&sub3);
2184 i->argv[n] = strdup(s);
2191 if (!dbus_message_iter_next(&sub2) ||
2192 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2193 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2194 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2195 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2196 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2197 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2198 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2199 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2203 i->start_timestamp = (usec_t) start_timestamp;
2204 i->exit_timestamp = (usec_t) exit_timestamp;
2205 i->pid = (pid_t) pid;
2212 typedef struct UnitStatusInfo {
2214 const char *load_state;
2215 const char *active_state;
2216 const char *sub_state;
2217 const char *unit_file_state;
2219 const char *description;
2220 const char *following;
2222 char **documentation;
2224 const char *fragment_path;
2225 const char *source_path;
2226 const char *default_control_group;
2228 const char *load_error;
2231 usec_t inactive_exit_timestamp;
2232 usec_t inactive_exit_timestamp_monotonic;
2233 usec_t active_enter_timestamp;
2234 usec_t active_exit_timestamp;
2235 usec_t inactive_enter_timestamp;
2237 bool need_daemon_reload;
2242 const char *status_text;
2245 usec_t start_timestamp;
2246 usec_t exit_timestamp;
2248 int exit_code, exit_status;
2250 usec_t condition_timestamp;
2251 bool condition_result;
2254 unsigned n_accepted;
2255 unsigned n_connections;
2258 /* Pairs of type, path */
2262 const char *sysfs_path;
2264 /* Mount, Automount */
2270 LIST_HEAD(ExecStatusInfo, exec);
2273 static void print_status_info(UnitStatusInfo *i) {
2275 const char *on, *off, *ss;
2277 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2278 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2281 arg_all * OUTPUT_SHOW_ALL |
2282 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2283 on_tty() * OUTPUT_COLOR |
2284 !arg_quiet * OUTPUT_WARN_CUTOFF |
2285 arg_full * OUTPUT_FULL_WIDTH;
2286 int maxlen = 8; /* a value that'll suffice most of the time */
2291 STRV_FOREACH_PAIR(t, t2, i->listen)
2292 maxlen = MAX(maxlen, (int)(sizeof("Listen") - 1 + strlen(*t)));
2294 maxlen = MAX(maxlen, (int)sizeof("Accept") - 1);
2295 if (i->main_pid > 0)
2296 maxlen = MAX(maxlen, (int)sizeof("Main PID") - 1);
2297 else if (i->control_pid > 0)
2298 maxlen = MAX(maxlen, (int)sizeof("Control") - 1);
2300 /* This shows pretty information about a unit. See
2301 * print_property() for a low-level property printer */
2303 printf("%s", strna(i->id));
2305 if (i->description && !streq_ptr(i->id, i->description))
2306 printf(" - %s", i->description);
2311 printf(" %*s: unit currently follows state of %s\n", maxlen, "Follow", i->following);
2313 if (streq_ptr(i->load_state, "error")) {
2314 on = ansi_highlight_red(true);
2315 off = ansi_highlight_red(false);
2319 path = i->source_path ? i->source_path : i->fragment_path;
2322 printf(" %*s: %s%s%s (Reason: %s)\n",
2323 maxlen, "Loaded", on, strna(i->load_state), off, i->load_error);
2324 else if (path && i->unit_file_state)
2325 printf(" %*s: %s%s%s (%s; %s)\n",
2326 maxlen, "Loaded", on, strna(i->load_state), off, path, i->unit_file_state);
2328 printf(" %*s: %s%s%s (%s)\n",
2329 maxlen, "Loaded", on, strna(i->load_state), off, path);
2331 printf(" %*s: %s%s%s\n",
2332 maxlen, "Loaded", on, strna(i->load_state), off);
2334 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2336 if (streq_ptr(i->active_state, "failed")) {
2337 on = ansi_highlight_red(true);
2338 off = ansi_highlight_red(false);
2339 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2340 on = ansi_highlight_green(true);
2341 off = ansi_highlight_green(false);
2346 printf(" %*s: %s%s (%s)%s",
2347 maxlen, "Active", on, strna(i->active_state), ss, off);
2349 printf(" %*s: %s%s%s",
2350 maxlen, "Active", on, strna(i->active_state), off);
2352 if (!isempty(i->result) && !streq(i->result, "success"))
2353 printf(" (Result: %s)", i->result);
2355 timestamp = (streq_ptr(i->active_state, "active") ||
2356 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2357 (streq_ptr(i->active_state, "inactive") ||
2358 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2359 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2360 i->active_exit_timestamp;
2362 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2363 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2366 printf(" since %s; %s\n", s2, s1);
2368 printf(" since %s\n", s2);
2372 if (!i->condition_result && i->condition_timestamp > 0) {
2373 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2374 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2377 printf(" %*s start condition failed at %s; %s\n", maxlen, "", s2, s1);
2379 printf(" %*s start condition failed at %s\n", maxlen, "", s2);
2383 printf(" %*s: %s\n", maxlen, "Device", i->sysfs_path);
2385 printf(" %*s: %s\n", maxlen, "Where", i->where);
2387 printf(" %*s: %s\n", maxlen, "What", i->what);
2389 STRV_FOREACH(t, i->documentation)
2390 printf(" %*s %s\n", maxlen+1, t == i->documentation ? "Docs:" : "", *t);
2392 STRV_FOREACH_PAIR(t, t2, i->listen)
2393 printf(" %*s%s: %s\n", maxlen - (int)strlen(*t), "Listen", *t, *t2);
2396 printf(" %*s: %u; Connected: %u\n", maxlen, "Accepted", i->n_accepted, i->n_connections);
2398 LIST_FOREACH(exec, p, i->exec) {
2399 _cleanup_free_ char *argv = NULL;
2402 /* Only show exited processes here */
2406 argv = strv_join(p->argv, " ");
2407 printf(" %*s: %u %s=%s ", maxlen, "Process", p->pid, p->name, strna(argv));
2409 good = is_clean_exit_lsb(p->code, p->status, NULL);
2411 on = ansi_highlight_red(true);
2412 off = ansi_highlight_red(false);
2416 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2418 if (p->code == CLD_EXITED) {
2421 printf("status=%i", p->status);
2423 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2428 printf("signal=%s", signal_to_string(p->status));
2430 printf(")%s\n", off);
2432 if (i->main_pid == p->pid &&
2433 i->start_timestamp == p->start_timestamp &&
2434 i->exit_timestamp == p->start_timestamp)
2435 /* Let's not show this twice */
2438 if (p->pid == i->control_pid)
2442 if (i->main_pid > 0 || i->control_pid > 0) {
2443 if (i->main_pid > 0) {
2444 printf(" %*s: %u", maxlen, "Main PID", (unsigned) i->main_pid);
2447 _cleanup_free_ char *comm = NULL;
2448 get_process_comm(i->main_pid, &comm);
2450 printf(" (%s)", comm);
2451 } else if (i->exit_code > 0) {
2452 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2454 if (i->exit_code == CLD_EXITED) {
2457 printf("status=%i", i->exit_status);
2459 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2464 printf("signal=%s", signal_to_string(i->exit_status));
2468 if (i->control_pid > 0)
2472 if (i->control_pid > 0) {
2473 _cleanup_free_ char *c = NULL;
2475 printf(" %*s: %u", i->main_pid ? 0 : maxlen, "Control", (unsigned) i->control_pid);
2477 get_process_comm(i->control_pid, &c);
2486 printf(" %*s: \"%s\"\n", maxlen, "Status", i->status_text);
2488 if (i->default_control_group &&
2489 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2492 printf(" %*s: %s\n", maxlen, "CGroup", i->default_control_group);
2494 if (arg_transport != TRANSPORT_SSH) {
2497 char prefix[maxlen + 4];
2498 memset(prefix, ' ', sizeof(prefix) - 1);
2499 prefix[sizeof(prefix) - 1] = '\0';
2502 if (c > sizeof(prefix) - 1)
2503 c -= sizeof(prefix) - 1;
2507 if (i->main_pid > 0)
2508 extra[k++] = i->main_pid;
2510 if (i->control_pid > 0)
2511 extra[k++] = i->control_pid;
2513 show_cgroup_and_extra_by_spec(i->default_control_group, prefix,
2514 c, false, extra, k, flags);
2518 if (i->id && arg_transport != TRANSPORT_SSH) {
2520 show_journal_by_unit(stdout,
2524 i->inactive_exit_timestamp_monotonic,
2528 arg_scope == UNIT_FILE_SYSTEM);
2531 if (i->need_daemon_reload)
2532 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2533 ansi_highlight_red(true),
2534 ansi_highlight_red(false),
2535 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2538 static void show_unit_help(UnitStatusInfo *i) {
2543 if (!i->documentation) {
2544 log_info("Documentation for %s not known.", i->id);
2548 STRV_FOREACH(p, i->documentation) {
2550 if (startswith(*p, "man:")) {
2553 char _cleanup_free_ *page = NULL, *section = NULL;
2554 const char *args[4] = { "man", NULL, NULL, NULL };
2559 if ((*p)[k-1] == ')')
2560 e = strrchr(*p, '(');
2563 page = strndup((*p) + 4, e - *p - 4);
2564 section = strndup(e + 1, *p + k - e - 2);
2565 if (!page || !section) {
2577 log_error("Failed to fork: %m");
2583 execvp(args[0], (char**) args);
2584 log_error("Failed to execute man: %m");
2585 _exit(EXIT_FAILURE);
2588 wait_for_terminate(pid, NULL);
2590 log_info("Can't show: %s", *p);
2594 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2600 switch (dbus_message_iter_get_arg_type(iter)) {
2602 case DBUS_TYPE_STRING: {
2605 dbus_message_iter_get_basic(iter, &s);
2608 if (streq(name, "Id"))
2610 else if (streq(name, "LoadState"))
2612 else if (streq(name, "ActiveState"))
2613 i->active_state = s;
2614 else if (streq(name, "SubState"))
2616 else if (streq(name, "Description"))
2618 else if (streq(name, "FragmentPath"))
2619 i->fragment_path = s;
2620 else if (streq(name, "SourcePath"))
2622 else if (streq(name, "DefaultControlGroup"))
2623 i->default_control_group = s;
2624 else if (streq(name, "StatusText"))
2626 else if (streq(name, "SysFSPath"))
2628 else if (streq(name, "Where"))
2630 else if (streq(name, "What"))
2632 else if (streq(name, "Following"))
2634 else if (streq(name, "UnitFileState"))
2635 i->unit_file_state = s;
2636 else if (streq(name, "Result"))
2643 case DBUS_TYPE_BOOLEAN: {
2646 dbus_message_iter_get_basic(iter, &b);
2648 if (streq(name, "Accept"))
2650 else if (streq(name, "NeedDaemonReload"))
2651 i->need_daemon_reload = b;
2652 else if (streq(name, "ConditionResult"))
2653 i->condition_result = b;
2658 case DBUS_TYPE_UINT32: {
2661 dbus_message_iter_get_basic(iter, &u);
2663 if (streq(name, "MainPID")) {
2665 i->main_pid = (pid_t) u;
2668 } else if (streq(name, "ControlPID"))
2669 i->control_pid = (pid_t) u;
2670 else if (streq(name, "ExecMainPID")) {
2672 i->main_pid = (pid_t) u;
2673 } else if (streq(name, "NAccepted"))
2675 else if (streq(name, "NConnections"))
2676 i->n_connections = u;
2681 case DBUS_TYPE_INT32: {
2684 dbus_message_iter_get_basic(iter, &j);
2686 if (streq(name, "ExecMainCode"))
2687 i->exit_code = (int) j;
2688 else if (streq(name, "ExecMainStatus"))
2689 i->exit_status = (int) j;
2694 case DBUS_TYPE_UINT64: {
2697 dbus_message_iter_get_basic(iter, &u);
2699 if (streq(name, "ExecMainStartTimestamp"))
2700 i->start_timestamp = (usec_t) u;
2701 else if (streq(name, "ExecMainExitTimestamp"))
2702 i->exit_timestamp = (usec_t) u;
2703 else if (streq(name, "ActiveEnterTimestamp"))
2704 i->active_enter_timestamp = (usec_t) u;
2705 else if (streq(name, "InactiveEnterTimestamp"))
2706 i->inactive_enter_timestamp = (usec_t) u;
2707 else if (streq(name, "InactiveExitTimestamp"))
2708 i->inactive_exit_timestamp = (usec_t) u;
2709 else if (streq(name, "InactiveExitTimestampMonotonic"))
2710 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2711 else if (streq(name, "ActiveExitTimestamp"))
2712 i->active_exit_timestamp = (usec_t) u;
2713 else if (streq(name, "ConditionTimestamp"))
2714 i->condition_timestamp = (usec_t) u;
2719 case DBUS_TYPE_ARRAY: {
2721 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2722 startswith(name, "Exec")) {
2723 DBusMessageIter sub;
2725 dbus_message_iter_recurse(iter, &sub);
2726 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2727 ExecStatusInfo *info;
2730 if (!(info = new0(ExecStatusInfo, 1)))
2733 if (!(info->name = strdup(name))) {
2738 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2743 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2745 dbus_message_iter_next(&sub);
2748 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
2749 DBusMessageIter sub, sub2;
2751 dbus_message_iter_recurse(iter, &sub);
2752 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2753 const char *type, *path;
2755 dbus_message_iter_recurse(&sub, &sub2);
2757 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2758 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
2761 r = strv_extend(&i->listen, type);
2764 r = strv_extend(&i->listen, path);
2769 dbus_message_iter_next(&sub);
2774 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2775 streq(name, "Documentation")) {
2777 DBusMessageIter sub;
2779 dbus_message_iter_recurse(iter, &sub);
2780 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2784 dbus_message_iter_get_basic(&sub, &s);
2786 r = strv_extend(&i->documentation, s);
2790 dbus_message_iter_next(&sub);
2797 case DBUS_TYPE_STRUCT: {
2799 if (streq(name, "LoadError")) {
2800 DBusMessageIter sub;
2801 const char *n, *message;
2804 dbus_message_iter_recurse(iter, &sub);
2806 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2810 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2814 if (!isempty(message))
2815 i->load_error = message;
2825 static int print_property(const char *name, DBusMessageIter *iter) {
2829 /* This is a low-level property printer, see
2830 * print_status_info() for the nicer output */
2832 if (arg_property && !strv_find(arg_property, name))
2835 switch (dbus_message_iter_get_arg_type(iter)) {
2837 case DBUS_TYPE_STRUCT: {
2838 DBusMessageIter sub;
2839 dbus_message_iter_recurse(iter, &sub);
2841 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2844 dbus_message_iter_get_basic(&sub, &u);
2847 printf("%s=%u\n", name, (unsigned) u);
2849 printf("%s=\n", name);
2852 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2855 dbus_message_iter_get_basic(&sub, &s);
2857 if (arg_all || s[0])
2858 printf("%s=%s\n", name, s);
2861 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2862 const char *a = NULL, *b = NULL;
2864 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2865 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2867 if (arg_all || !isempty(a) || !isempty(b))
2868 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2876 case DBUS_TYPE_ARRAY:
2878 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2879 DBusMessageIter sub, sub2;
2881 dbus_message_iter_recurse(iter, &sub);
2882 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2886 dbus_message_iter_recurse(&sub, &sub2);
2888 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2889 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2890 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2892 dbus_message_iter_next(&sub);
2897 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2898 DBusMessageIter sub, sub2;
2900 dbus_message_iter_recurse(iter, &sub);
2902 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2903 const char *type, *path;
2905 dbus_message_iter_recurse(&sub, &sub2);
2907 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2908 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2909 printf("%s=%s\n", type, path);
2911 dbus_message_iter_next(&sub);
2916 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
2917 DBusMessageIter sub, sub2;
2919 dbus_message_iter_recurse(iter, &sub);
2920 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2921 const char *type, *path;
2923 dbus_message_iter_recurse(&sub, &sub2);
2925 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2926 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2927 printf("Listen%s=%s\n", type, path);
2929 dbus_message_iter_next(&sub);
2934 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2935 DBusMessageIter sub, sub2;
2937 dbus_message_iter_recurse(iter, &sub);
2938 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2940 uint64_t value, next_elapse;
2942 dbus_message_iter_recurse(&sub, &sub2);
2944 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2945 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2946 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2947 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2949 printf("%s={ value=%s ; next_elapse=%s }\n",
2951 format_timespan(timespan1, sizeof(timespan1), value, 0),
2952 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
2955 dbus_message_iter_next(&sub);
2960 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2961 DBusMessageIter sub, sub2;
2963 dbus_message_iter_recurse(iter, &sub);
2964 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2965 const char *controller, *attr, *value;
2967 dbus_message_iter_recurse(&sub, &sub2);
2969 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2970 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2971 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2973 printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2979 dbus_message_iter_next(&sub);
2984 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2985 DBusMessageIter sub;
2987 dbus_message_iter_recurse(iter, &sub);
2988 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2989 ExecStatusInfo info;
2992 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2993 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2994 char _cleanup_free_ *t;
2996 t = strv_join(info.argv, " ");
2998 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3002 yes_no(info.ignore),
3003 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3004 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3005 (unsigned) info. pid,
3006 sigchld_code_to_string(info.code),
3008 info.code == CLD_EXITED ? "" : "/",
3009 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3013 strv_free(info.argv);
3015 dbus_message_iter_next(&sub);
3024 if (generic_print_property(name, iter, arg_all) > 0)
3028 printf("%s=[unprintable]\n", name);
3033 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3034 DBusMessage _cleanup_free_ *reply = NULL;
3035 const char *interface = "";
3037 DBusMessageIter iter, sub, sub2, sub3;
3038 UnitStatusInfo info;
3046 r = bus_method_call_with_reply(
3048 "org.freedesktop.systemd1",
3050 "org.freedesktop.DBus.Properties",
3054 DBUS_TYPE_STRING, &interface,
3059 if (!dbus_message_iter_init(reply, &iter) ||
3060 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3061 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3062 log_error("Failed to parse reply.");
3066 dbus_message_iter_recurse(&iter, &sub);
3073 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3076 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3077 dbus_message_iter_recurse(&sub, &sub2);
3079 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3080 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3081 log_error("Failed to parse reply.");
3085 dbus_message_iter_recurse(&sub2, &sub3);
3087 if (show_properties)
3088 r = print_property(name, &sub3);
3090 r = status_property(name, &sub3, &info);
3092 log_error("Failed to parse reply.");
3096 dbus_message_iter_next(&sub);
3101 if (!show_properties) {
3102 if (streq(verb, "help"))
3103 show_unit_help(&info);
3105 print_status_info(&info);
3108 strv_free(info.documentation);
3109 strv_free(info.listen);
3111 if (!streq_ptr(info.active_state, "active") &&
3112 !streq_ptr(info.active_state, "reloading") &&
3113 streq(verb, "status"))
3114 /* According to LSB: "program not running" */
3117 while ((p = info.exec)) {
3118 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3119 exec_status_info_free(p);
3125 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3126 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3127 const char *path = NULL;
3128 DBusError _cleanup_dbus_error_free_ error;
3131 dbus_error_init(&error);
3133 r = bus_method_call_with_reply(
3135 "org.freedesktop.systemd1",
3136 "/org/freedesktop/systemd1",
3137 "org.freedesktop.systemd1.Manager",
3141 DBUS_TYPE_UINT32, &pid,
3146 if (!dbus_message_get_args(reply, &error,
3147 DBUS_TYPE_OBJECT_PATH, &path,
3148 DBUS_TYPE_INVALID)) {
3149 log_error("Failed to parse reply: %s", bus_error_message(&error));
3153 r = show_one(verb, bus, path, false, new_line);
3157 static int show_all(const char* verb, DBusConnection *bus, bool show_properties, bool *new_line) {
3158 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3159 _cleanup_free_ struct unit_info *unit_infos = NULL;
3161 const struct unit_info *u;
3164 r = get_unit_list(bus, &reply, &unit_infos, &c);
3168 for (u = unit_infos; u < unit_infos + c; u++) {
3169 char _cleanup_free_ *p = NULL;
3171 if (!output_show_unit(u))
3174 p = unit_dbus_path_from_name(u->id);
3178 printf("%s -> '%s'\n", u->id, p);
3180 r = show_one(verb, bus, p, show_properties, new_line);
3188 static int show(DBusConnection *bus, char **args) {
3190 bool show_properties, show_status, new_line = false;
3196 show_properties = streq(args[0], "show");
3197 show_status = streq(args[0], "status");
3199 if (show_properties)
3200 pager_open_if_enabled();
3202 /* If no argument is specified inspect the manager itself */
3204 if (show_properties && strv_length(args) <= 1)
3205 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3207 if (show_status && strv_length(args) <= 1)
3208 return show_all(args[0], bus, false, &new_line);
3210 STRV_FOREACH(name, args+1) {
3213 if (safe_atou32(*name, &id) < 0) {
3214 _cleanup_free_ char *p = NULL, *n = NULL;
3215 /* Interpret as unit name */
3217 n = unit_name_mangle(*name);
3221 p = unit_dbus_path_from_name(n);
3225 r = show_one(args[0], bus, p, show_properties, &new_line);
3229 } else if (show_properties) {
3230 _cleanup_free_ char *p = NULL;
3232 /* Interpret as job id */
3233 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3236 r = show_one(args[0], bus, p, show_properties, &new_line);
3241 /* Interpret as PID */
3242 r = show_one_by_pid(args[0], bus, id, &new_line);
3251 static int dump(DBusConnection *bus, char **args) {
3252 _cleanup_free_ DBusMessage *reply = NULL;
3257 dbus_error_init(&error);
3259 pager_open_if_enabled();
3261 r = bus_method_call_with_reply(
3263 "org.freedesktop.systemd1",
3264 "/org/freedesktop/systemd1",
3265 "org.freedesktop.systemd1.Manager",
3273 if (!dbus_message_get_args(reply, &error,
3274 DBUS_TYPE_STRING, &text,
3275 DBUS_TYPE_INVALID)) {
3276 log_error("Failed to parse reply: %s", bus_error_message(&error));
3277 dbus_error_free(&error);
3281 fputs(text, stdout);
3285 static int snapshot(DBusConnection *bus, char **args) {
3286 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3289 dbus_bool_t cleanup = FALSE;
3290 DBusMessageIter iter, sub;
3293 *interface = "org.freedesktop.systemd1.Unit",
3295 _cleanup_free_ char *n = NULL;
3297 dbus_error_init(&error);
3299 if (strv_length(args) > 1)
3300 n = snapshot_name_mangle(args[1]);
3306 r = bus_method_call_with_reply (
3308 "org.freedesktop.systemd1",
3309 "/org/freedesktop/systemd1",
3310 "org.freedesktop.systemd1.Manager",
3314 DBUS_TYPE_STRING, &n,
3315 DBUS_TYPE_BOOLEAN, &cleanup,
3320 if (!dbus_message_get_args(reply, &error,
3321 DBUS_TYPE_OBJECT_PATH, &path,
3322 DBUS_TYPE_INVALID)) {
3323 log_error("Failed to parse reply: %s", bus_error_message(&error));
3324 dbus_error_free(&error);
3328 dbus_message_unref(reply);
3331 r = bus_method_call_with_reply (
3333 "org.freedesktop.systemd1",
3335 "org.freedesktop.DBus.Properties",
3339 DBUS_TYPE_STRING, &interface,
3340 DBUS_TYPE_STRING, &property,
3345 if (!dbus_message_iter_init(reply, &iter) ||
3346 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3347 log_error("Failed to parse reply.");
3351 dbus_message_iter_recurse(&iter, &sub);
3353 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3354 log_error("Failed to parse reply.");
3358 dbus_message_iter_get_basic(&sub, &id);
3366 static int delete_snapshot(DBusConnection *bus, char **args) {
3371 STRV_FOREACH(name, args+1) {
3372 _cleanup_free_ char *n = NULL;
3375 n = snapshot_name_mangle(*name);
3379 r = bus_method_call_with_reply(
3381 "org.freedesktop.systemd1",
3382 "/org/freedesktop/systemd1",
3383 "org.freedesktop.systemd1.Manager",
3387 DBUS_TYPE_STRING, &n,
3396 static int daemon_reload(DBusConnection *bus, char **args) {
3401 if (arg_action == ACTION_RELOAD)
3403 else if (arg_action == ACTION_REEXEC)
3404 method = "Reexecute";
3406 assert(arg_action == ACTION_SYSTEMCTL);
3409 streq(args[0], "clear-jobs") ||
3410 streq(args[0], "cancel") ? "ClearJobs" :
3411 streq(args[0], "daemon-reexec") ? "Reexecute" :
3412 streq(args[0], "reset-failed") ? "ResetFailed" :
3413 streq(args[0], "halt") ? "Halt" :
3414 streq(args[0], "poweroff") ? "PowerOff" :
3415 streq(args[0], "reboot") ? "Reboot" :
3416 streq(args[0], "kexec") ? "KExec" :
3417 streq(args[0], "exit") ? "Exit" :
3418 /* "daemon-reload" */ "Reload";
3421 r = bus_method_call_with_reply(
3423 "org.freedesktop.systemd1",
3424 "/org/freedesktop/systemd1",
3425 "org.freedesktop.systemd1.Manager",
3431 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3432 /* There's always a fallback possible for
3433 * legacy actions. */
3435 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3436 /* On reexecution, we expect a disconnect, not
3440 log_error("Failed to issue method call: %s", bus_error_message(&error));
3442 dbus_error_free(&error);
3446 static int reset_failed(DBusConnection *bus, char **args) {
3450 if (strv_length(args) <= 1)
3451 return daemon_reload(bus, args);
3453 STRV_FOREACH(name, args+1) {
3454 _cleanup_free_ char *n;
3456 n = unit_name_mangle(*name);
3460 r = bus_method_call_with_reply(
3462 "org.freedesktop.systemd1",
3463 "/org/freedesktop/systemd1",
3464 "org.freedesktop.systemd1.Manager",
3468 DBUS_TYPE_STRING, &n,
3477 static int show_enviroment(DBusConnection *bus, char **args) {
3478 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3479 DBusMessageIter iter, sub, sub2;
3482 *interface = "org.freedesktop.systemd1.Manager",
3483 *property = "Environment";
3485 pager_open_if_enabled();
3487 r = bus_method_call_with_reply(
3489 "org.freedesktop.systemd1",
3490 "/org/freedesktop/systemd1",
3491 "org.freedesktop.DBus.Properties",
3495 DBUS_TYPE_STRING, &interface,
3496 DBUS_TYPE_STRING, &property,
3501 if (!dbus_message_iter_init(reply, &iter) ||
3502 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3503 log_error("Failed to parse reply.");
3507 dbus_message_iter_recurse(&iter, &sub);
3509 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3510 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3511 log_error("Failed to parse reply.");
3515 dbus_message_iter_recurse(&sub, &sub2);
3517 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3520 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3521 log_error("Failed to parse reply.");
3525 dbus_message_iter_get_basic(&sub2, &text);
3528 dbus_message_iter_next(&sub2);
3534 static int switch_root(DBusConnection *bus, char **args) {
3537 _cleanup_free_ char *init = NULL;
3539 l = strv_length(args);
3540 if (l < 2 || l > 3) {
3541 log_error("Wrong number of arguments.");
3548 init = strdup(args[2]);
3550 parse_env_file("/proc/cmdline", WHITESPACE,
3560 log_debug("switching root - root: %s; init: %s", root, init);
3562 return bus_method_call_with_reply(
3564 "org.freedesktop.systemd1",
3565 "/org/freedesktop/systemd1",
3566 "org.freedesktop.systemd1.Manager",
3570 DBUS_TYPE_STRING, &root,
3571 DBUS_TYPE_STRING, &init,
3575 static int set_environment(DBusConnection *bus, char **args) {
3576 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3579 DBusMessageIter iter;
3585 dbus_error_init(&error);
3587 method = streq(args[0], "set-environment")
3589 : "UnsetEnvironment";
3591 m = dbus_message_new_method_call(
3592 "org.freedesktop.systemd1",
3593 "/org/freedesktop/systemd1",
3594 "org.freedesktop.systemd1.Manager",
3599 dbus_message_iter_init_append(m, &iter);
3601 r = bus_append_strv_iter(&iter, args + 1);
3605 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3607 log_error("Failed to issue method call: %s", bus_error_message(&error));
3608 dbus_error_free(&error);
3615 static int enable_sysv_units(char **args) {
3618 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3619 const char *verb = args[0];
3620 unsigned f = 1, t = 1;
3623 if (arg_scope != UNIT_FILE_SYSTEM)
3626 if (!streq(verb, "enable") &&
3627 !streq(verb, "disable") &&
3628 !streq(verb, "is-enabled"))
3631 /* Processes all SysV units, and reshuffles the array so that
3632 * afterwards only the native units remain */
3635 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3640 for (f = 1; args[f]; f++) {
3643 bool found_native = false, found_sysv;
3645 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3646 char **k, *l, *q = NULL;
3653 if (!endswith(name, ".service"))
3656 if (path_is_absolute(name))
3659 STRV_FOREACH(k, paths.unit_path) {
3662 if (!isempty(arg_root))
3663 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3665 asprintf(&p, "%s/%s", *k, name);
3672 found_native = access(p, F_OK) >= 0;
3683 if (!isempty(arg_root))
3684 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3686 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3692 p[strlen(p) - sizeof(".service") + 1] = 0;
3693 found_sysv = access(p, F_OK) >= 0;
3700 /* Mark this entry, so that we don't try enabling it as native unit */
3701 args[f] = (char*) "";
3703 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3705 if (!isempty(arg_root))
3706 argv[c++] = q = strappend("--root=", arg_root);
3708 argv[c++] = path_get_file_name(p);
3710 streq(verb, "enable") ? "on" :
3711 streq(verb, "disable") ? "off" : "--level=5";
3714 l = strv_join((char**)argv, " ");
3722 log_info("Executing %s", l);
3727 log_error("Failed to fork: %m");
3732 } else if (pid == 0) {
3735 execv(argv[0], (char**) argv);
3736 _exit(EXIT_FAILURE);
3742 j = wait_for_terminate(pid, &status);
3744 log_error("Failed to wait for child: %s", strerror(-r));
3749 if (status.si_code == CLD_EXITED) {
3750 if (streq(verb, "is-enabled")) {
3751 if (status.si_status == 0) {
3760 } else if (status.si_status != 0) {
3771 lookup_paths_free(&paths);
3773 /* Drop all SysV units */
3774 for (f = 1, t = 1; args[f]; f++) {
3776 if (isempty(args[f]))
3779 args[t++] = args[f];
3788 static int mangle_names(char **original_names, char ***mangled_names) {
3789 char **i, **l, **name;
3791 l = new(char*, strv_length(original_names) + 1);
3796 STRV_FOREACH(name, original_names) {
3798 /* When enabling units qualified path names are OK,
3799 * too, hence allow them explicitly. */
3804 *i = unit_name_mangle(*name);
3820 static int enable_unit(DBusConnection *bus, char **args) {
3821 const char *verb = args[0];
3822 UnitFileChange *changes = NULL;
3823 unsigned n_changes = 0, i;
3824 int carries_install_info = -1;
3825 DBusMessage _cleanup_dbus_message_unref_ *m = NULL, *reply = NULL;
3827 DBusError _cleanup_dbus_error_free_ error;
3828 char _cleanup_strv_free_ **mangled_names = NULL;
3830 dbus_error_init(&error);
3832 r = enable_sysv_units(args);
3839 if (!bus || avoid_bus()) {
3840 if (streq(verb, "enable")) {
3841 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3842 carries_install_info = r;
3843 } else if (streq(verb, "disable"))
3844 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3845 else if (streq(verb, "reenable")) {
3846 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3847 carries_install_info = r;
3848 } else if (streq(verb, "link"))
3849 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3850 else if (streq(verb, "preset")) {
3851 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3852 carries_install_info = r;
3853 } else if (streq(verb, "mask"))
3854 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3855 else if (streq(verb, "unmask"))
3856 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3858 assert_not_reached("Unknown verb");
3861 log_error("Operation failed: %s", strerror(-r));
3866 for (i = 0; i < n_changes; i++) {
3867 if (changes[i].type == UNIT_FILE_SYMLINK)
3868 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3870 log_info("rm '%s'", changes[i].path);
3877 bool send_force = true, expect_carries_install_info = false;
3879 DBusMessageIter iter, sub, sub2;
3881 if (streq(verb, "enable")) {
3882 method = "EnableUnitFiles";
3883 expect_carries_install_info = true;
3884 } else if (streq(verb, "disable")) {
3885 method = "DisableUnitFiles";
3887 } else if (streq(verb, "reenable")) {
3888 method = "ReenableUnitFiles";
3889 expect_carries_install_info = true;
3890 } else if (streq(verb, "link"))
3891 method = "LinkUnitFiles";
3892 else if (streq(verb, "preset")) {
3893 method = "PresetUnitFiles";
3894 expect_carries_install_info = true;
3895 } else if (streq(verb, "mask"))
3896 method = "MaskUnitFiles";
3897 else if (streq(verb, "unmask")) {
3898 method = "UnmaskUnitFiles";
3901 assert_not_reached("Unknown verb");
3903 m = dbus_message_new_method_call(
3904 "org.freedesktop.systemd1",
3905 "/org/freedesktop/systemd1",
3906 "org.freedesktop.systemd1.Manager",
3913 dbus_message_iter_init_append(m, &iter);
3915 r = mangle_names(args+1, &mangled_names);
3919 r = bus_append_strv_iter(&iter, mangled_names);
3921 log_error("Failed to append unit files.");
3926 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3927 log_error("Failed to append runtime boolean.");
3935 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3936 log_error("Failed to append force boolean.");
3942 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3944 log_error("Failed to issue method call: %s", bus_error_message(&error));
3949 if (!dbus_message_iter_init(reply, &iter)) {
3950 log_error("Failed to initialize iterator.");
3954 if (expect_carries_install_info) {
3955 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3957 log_error("Failed to parse reply.");
3961 carries_install_info = b;
3964 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3965 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3966 log_error("Failed to parse reply.");
3971 dbus_message_iter_recurse(&iter, &sub);
3972 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3973 const char *type, *path, *source;
3975 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3976 log_error("Failed to parse reply.");
3981 dbus_message_iter_recurse(&sub, &sub2);
3983 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3984 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3985 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3986 log_error("Failed to parse reply.");
3992 if (streq(type, "symlink"))
3993 log_info("ln -s '%s' '%s'", source, path);
3995 log_info("rm '%s'", path);
3998 dbus_message_iter_next(&sub);
4001 /* Try to reload if enabeld */
4003 r = daemon_reload(bus, args);
4006 if (carries_install_info == 0)
4007 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4008 "using systemctl.\n"
4009 "Possible reasons for having this kind of units are:\n"
4010 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4011 " .wants/ or .requires/ directory.\n"
4012 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4013 " a requirement dependency on it.\n"
4014 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4015 " D-Bus, udev, scripted systemctl call, ...).\n");
4018 unit_file_changes_free(changes, n_changes);
4023 static int unit_is_enabled(DBusConnection *bus, char **args) {
4024 DBusError _cleanup_dbus_error_free_ error;
4026 DBusMessage _cleanup_dbus_message_unref_ *reply = NULL;
4031 dbus_error_init(&error);
4033 r = enable_sysv_units(args);
4039 if (!bus || avoid_bus()) {
4041 STRV_FOREACH(name, args+1) {
4042 UnitFileState state;
4044 n = unit_name_mangle(*name);
4048 state = unit_file_get_state(arg_scope, arg_root, n);
4055 if (state == UNIT_FILE_ENABLED ||
4056 state == UNIT_FILE_ENABLED_RUNTIME ||
4057 state == UNIT_FILE_STATIC)
4061 puts(unit_file_state_to_string(state));
4065 STRV_FOREACH(name, args+1) {
4068 n = unit_name_mangle(*name);
4072 r = bus_method_call_with_reply (
4074 "org.freedesktop.systemd1",
4075 "/org/freedesktop/systemd1",
4076 "org.freedesktop.systemd1.Manager",
4080 DBUS_TYPE_STRING, &n,
4088 if (!dbus_message_get_args(reply, &error,
4089 DBUS_TYPE_STRING, &s,
4090 DBUS_TYPE_INVALID)) {
4091 log_error("Failed to parse reply: %s", bus_error_message(&error));
4095 dbus_message_unref(reply);
4098 if (streq(s, "enabled") ||
4099 streq(s, "enabled-runtime") ||
4108 return enabled ? 0 : 1;
4111 static int systemctl_help(void) {
4113 pager_open_if_enabled();
4115 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4116 "Query or send control commands to the systemd manager.\n\n"
4117 " -h --help Show this help\n"
4118 " --version Show package version\n"
4119 " -t --type=TYPE List only units of a particular type\n"
4120 " -p --property=NAME Show only properties by this name\n"
4121 " -a --all Show all units/properties, including dead/empty ones\n"
4122 " --failed Show only failed units\n"
4123 " --full Don't ellipsize unit names on output\n"
4124 " --fail When queueing a new job, fail if conflicting jobs are\n"
4126 " --ignore-dependencies\n"
4127 " When queueing a new job, ignore all its dependencies\n"
4128 " -i --ignore-inhibitors\n"
4129 " When shutting down or sleeping, ignore inhibitors\n"
4130 " --kill-who=WHO Who to send signal to\n"
4131 " -s --signal=SIGNAL Which signal to send\n"
4132 " -H --host=[USER@]HOST\n"
4133 " Show information for remote host\n"
4134 " -P --privileged Acquire privileges before execution\n"
4135 " -q --quiet Suppress output\n"
4136 " --no-block Do not wait until operation finished\n"
4137 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4138 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4140 " --no-legend Do not print a legend (column headers and hints)\n"
4141 " --no-pager Do not pipe output into a pager\n"
4142 " --no-ask-password\n"
4143 " Do not ask for system passwords\n"
4144 " --system Connect to system manager\n"
4145 " --user Connect to user service manager\n"
4146 " --global Enable/disable unit files globally\n"
4147 " -f --force When enabling unit files, override existing symlinks\n"
4148 " When shutting down, execute action immediately\n"
4149 " --root=PATH Enable unit files in the specified root directory\n"
4150 " --runtime Enable unit files only temporarily until next reboot\n"
4151 " -n --lines=INTEGER Journal entries to show\n"
4152 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4153 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4155 " list-units List loaded units\n"
4156 " start [NAME...] Start (activate) one or more units\n"
4157 " stop [NAME...] Stop (deactivate) one or more units\n"
4158 " reload [NAME...] Reload one or more units\n"
4159 " restart [NAME...] Start or restart one or more units\n"
4160 " try-restart [NAME...] Restart one or more units if active\n"
4161 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4162 " otherwise start or restart\n"
4163 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4164 " otherwise restart if active\n"
4165 " isolate [NAME] Start one unit and stop all others\n"
4166 " kill [NAME...] Send signal to processes of a unit\n"
4167 " is-active [NAME...] Check whether units are active\n"
4168 " is-failed [NAME...] Check whether units are failed\n"
4169 " status [NAME...|PID...] Show runtime status of one or more units\n"
4170 " show [NAME...|JOB...] Show properties of one or more\n"
4171 " units/jobs or the manager\n"
4172 " help [NAME...|PID...] Show manual for one or more units\n"
4173 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4175 " get-cgroup-attr [NAME] [ATTR] ...\n"
4176 " Get control group attrubute\n"
4177 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4178 " Set control group attribute\n"
4179 " unset-cgroup-attr [NAME] [ATTR...]\n"
4180 " Unset control group attribute\n"
4181 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4182 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4183 " load [NAME...] Load one or more units\n"
4184 " list-dependencies [NAME] Recursively show units which are required\n"
4185 " or wanted by this unit\n\n"
4186 "Unit File Commands:\n"
4187 " list-unit-files List installed unit files\n"
4188 " enable [NAME...] Enable one or more unit files\n"
4189 " disable [NAME...] Disable one or more unit files\n"
4190 " reenable [NAME...] Reenable one or more unit files\n"
4191 " preset [NAME...] Enable/disable one or more unit files\n"
4192 " based on preset configuration\n"
4193 " mask [NAME...] Mask one or more units\n"
4194 " unmask [NAME...] Unmask one or more units\n"
4195 " link [PATH...] Link one or more units files into\n"
4196 " the search path\n"
4197 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4199 " list-jobs List jobs\n"
4200 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4201 "Status Commands:\n"
4202 " dump Dump server status\n"
4203 "Snapshot Commands:\n"
4204 " snapshot [NAME] Create a snapshot\n"
4205 " delete [NAME...] Remove one or more snapshots\n\n"
4206 "Environment Commands:\n"
4207 " show-environment Dump environment\n"
4208 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4209 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4210 "Manager Lifecycle Commands:\n"
4211 " daemon-reload Reload systemd manager configuration\n"
4212 " daemon-reexec Reexecute systemd manager\n\n"
4213 "System Commands:\n"
4214 " default Enter system default mode\n"
4215 " rescue Enter system rescue mode\n"
4216 " emergency Enter system emergency mode\n"
4217 " halt Shut down and halt the system\n"
4218 " poweroff Shut down and power-off the system\n"
4219 " reboot Shut down and reboot the system\n"
4220 " kexec Shut down and reboot the system with kexec\n"
4221 " exit Request user instance exit\n"
4222 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4223 " suspend Suspend the system\n"
4224 " hibernate Hibernate the system\n"
4225 " hybrid-sleep Hibernate and suspend the system\n",
4226 program_invocation_short_name);
4231 static int halt_help(void) {
4233 printf("%s [OPTIONS...]\n\n"
4234 "%s the system.\n\n"
4235 " --help Show this help\n"
4236 " --halt Halt the machine\n"
4237 " -p --poweroff Switch off the machine\n"
4238 " --reboot Reboot the machine\n"
4239 " -f --force Force immediate halt/power-off/reboot\n"
4240 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4241 " -d --no-wtmp Don't write wtmp record\n"
4242 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4243 program_invocation_short_name,
4244 arg_action == ACTION_REBOOT ? "Reboot" :
4245 arg_action == ACTION_POWEROFF ? "Power off" :
4251 static int shutdown_help(void) {
4253 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4254 "Shut down the system.\n\n"
4255 " --help Show this help\n"
4256 " -H --halt Halt the machine\n"
4257 " -P --poweroff Power-off the machine\n"
4258 " -r --reboot Reboot the machine\n"
4259 " -h Equivalent to --poweroff, overridden by --halt\n"
4260 " -k Don't halt/power-off/reboot, just send warnings\n"
4261 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4262 " -c Cancel a pending shutdown\n",
4263 program_invocation_short_name);
4268 static int telinit_help(void) {
4270 printf("%s [OPTIONS...] {COMMAND}\n\n"
4271 "Send control commands to the init daemon.\n\n"
4272 " --help Show this help\n"
4273 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4275 " 0 Power-off the machine\n"
4276 " 6 Reboot the machine\n"
4277 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4278 " 1, s, S Enter rescue mode\n"
4279 " q, Q Reload init daemon configuration\n"
4280 " u, U Reexecute init daemon\n",
4281 program_invocation_short_name);
4286 static int runlevel_help(void) {
4288 printf("%s [OPTIONS...]\n\n"
4289 "Prints the previous and current runlevel of the init system.\n\n"
4290 " --help Show this help\n",
4291 program_invocation_short_name);
4296 static int help_types(void) {
4300 puts("Available unit types:");
4301 for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4302 t = unit_type_to_string(i);
4307 puts("\nAvailable unit load states: ");
4308 for(i = 0; i < _UNIT_LOAD_STATE_MAX; i++) {
4309 t = unit_load_state_to_string(i);
4317 static int systemctl_parse_argv(int argc, char *argv[]) {
4322 ARG_IGNORE_DEPENDENCIES,
4335 ARG_NO_ASK_PASSWORD,
4341 static const struct option options[] = {
4342 { "help", no_argument, NULL, 'h' },
4343 { "version", no_argument, NULL, ARG_VERSION },
4344 { "type", required_argument, NULL, 't' },
4345 { "property", required_argument, NULL, 'p' },
4346 { "all", no_argument, NULL, 'a' },
4347 { "failed", no_argument, NULL, ARG_FAILED },
4348 { "full", no_argument, NULL, ARG_FULL },
4349 { "fail", no_argument, NULL, ARG_FAIL },
4350 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4351 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4352 { "ignore-inhibitors", no_argument, NULL, 'i' },
4353 { "user", no_argument, NULL, ARG_USER },
4354 { "system", no_argument, NULL, ARG_SYSTEM },
4355 { "global", no_argument, NULL, ARG_GLOBAL },
4356 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4357 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4358 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4359 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4360 { "quiet", no_argument, NULL, 'q' },
4361 { "root", required_argument, NULL, ARG_ROOT },
4362 { "force", no_argument, NULL, ARG_FORCE },
4363 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4364 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4365 { "signal", required_argument, NULL, 's' },
4366 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4367 { "host", required_argument, NULL, 'H' },
4368 { "privileged",no_argument, NULL, 'P' },
4369 { "runtime", no_argument, NULL, ARG_RUNTIME },
4370 { "lines", required_argument, NULL, 'n' },
4371 { "output", required_argument, NULL, 'o' },
4372 { NULL, 0, NULL, 0 }
4380 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4389 puts(PACKAGE_STRING);
4390 puts(SYSTEMD_FEATURES);
4394 if (streq(optarg, "help")) {
4399 if (unit_type_from_string(optarg) >= 0) {
4403 if (unit_load_state_from_string(optarg) >= 0) {
4404 arg_load_state = optarg;
4407 log_error("Unkown unit type or load state '%s'.",
4409 log_info("Use -t help to see a list of allowed values.");
4414 /* Make sure that if the empty property list
4415 was specified, we won't show any properties. */
4416 const char *source = isempty(optarg) ? " " : optarg;
4418 FOREACH_WORD_SEPARATOR(word, size, source, ",", state) {
4419 char _cleanup_free_ *prop;
4422 prop = strndup(word, size);
4426 tmp = strv_append(arg_property, prop);
4430 strv_free(arg_property);
4434 /* If the user asked for a particular
4435 * property, show it to him, even if it is
4447 arg_job_mode = "fail";
4450 case ARG_IRREVERSIBLE:
4451 arg_job_mode = "replace-irreversibly";
4454 case ARG_IGNORE_DEPENDENCIES:
4455 arg_job_mode = "ignore-dependencies";
4459 arg_scope = UNIT_FILE_USER;
4463 arg_scope = UNIT_FILE_SYSTEM;
4467 arg_scope = UNIT_FILE_GLOBAL;
4471 arg_no_block = true;
4475 arg_no_legend = true;
4479 arg_no_pager = true;
4511 arg_no_reload = true;
4515 arg_kill_who = optarg;
4519 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4520 log_error("Failed to parse signal string %s.", optarg);
4525 case ARG_NO_ASK_PASSWORD:
4526 arg_ask_password = false;
4530 arg_transport = TRANSPORT_POLKIT;
4534 arg_transport = TRANSPORT_SSH;
4543 if (safe_atou(optarg, &arg_lines) < 0) {
4544 log_error("Failed to parse lines '%s'", optarg);
4550 arg_output = output_mode_from_string(optarg);
4551 if (arg_output < 0) {
4552 log_error("Unknown output '%s'.", optarg);
4558 arg_ignore_inhibitors = true;
4565 log_error("Unknown option code '%c'.", c);
4570 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4571 log_error("Cannot access user instance remotely.");
4578 static int halt_parse_argv(int argc, char *argv[]) {
4587 static const struct option options[] = {
4588 { "help", no_argument, NULL, ARG_HELP },
4589 { "halt", no_argument, NULL, ARG_HALT },
4590 { "poweroff", no_argument, NULL, 'p' },
4591 { "reboot", no_argument, NULL, ARG_REBOOT },
4592 { "force", no_argument, NULL, 'f' },
4593 { "wtmp-only", no_argument, NULL, 'w' },
4594 { "no-wtmp", no_argument, NULL, 'd' },
4595 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4596 { NULL, 0, NULL, 0 }
4604 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4605 if (runlevel == '0' || runlevel == '6')
4608 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4616 arg_action = ACTION_HALT;
4620 if (arg_action != ACTION_REBOOT)
4621 arg_action = ACTION_POWEROFF;
4625 arg_action = ACTION_REBOOT;
4647 /* Compatibility nops */
4654 log_error("Unknown option code '%c'.", c);
4659 if (optind < argc) {
4660 log_error("Too many arguments.");
4667 static int parse_time_spec(const char *t, usec_t *_u) {
4671 if (streq(t, "now"))
4673 else if (!strchr(t, ':')) {
4676 if (safe_atou64(t, &u) < 0)
4679 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4688 hour = strtol(t, &e, 10);
4689 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
4692 minute = strtol(e+1, &e, 10);
4693 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
4696 n = now(CLOCK_REALTIME);
4697 s = (time_t) (n / USEC_PER_SEC);
4700 assert_se(localtime_r(&s, &tm));
4702 tm.tm_hour = (int) hour;
4703 tm.tm_min = (int) minute;
4706 assert_se(s = mktime(&tm));
4708 *_u = (usec_t) s * USEC_PER_SEC;
4711 *_u += USEC_PER_DAY;
4717 static int shutdown_parse_argv(int argc, char *argv[]) {
4724 static const struct option options[] = {
4725 { "help", no_argument, NULL, ARG_HELP },
4726 { "halt", no_argument, NULL, 'H' },
4727 { "poweroff", no_argument, NULL, 'P' },
4728 { "reboot", no_argument, NULL, 'r' },
4729 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4730 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4731 { NULL, 0, NULL, 0 }
4739 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4747 arg_action = ACTION_HALT;
4751 arg_action = ACTION_POWEROFF;
4756 arg_action = ACTION_KEXEC;
4758 arg_action = ACTION_REBOOT;
4762 arg_action = ACTION_KEXEC;
4766 if (arg_action != ACTION_HALT)
4767 arg_action = ACTION_POWEROFF;
4780 /* Compatibility nops */
4784 arg_action = ACTION_CANCEL_SHUTDOWN;
4791 log_error("Unknown option code '%c'.", c);
4796 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4797 r = parse_time_spec(argv[optind], &arg_when);
4799 log_error("Failed to parse time specification: %s", argv[optind]);
4803 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4805 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4806 /* No time argument for shutdown cancel */
4807 arg_wall = argv + optind;
4808 else if (argc > optind + 1)
4809 /* We skip the time argument */
4810 arg_wall = argv + optind + 1;
4817 static int telinit_parse_argv(int argc, char *argv[]) {
4824 static const struct option options[] = {
4825 { "help", no_argument, NULL, ARG_HELP },
4826 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4827 { NULL, 0, NULL, 0 }
4830 static const struct {
4834 { '0', ACTION_POWEROFF },
4835 { '6', ACTION_REBOOT },
4836 { '1', ACTION_RESCUE },
4837 { '2', ACTION_RUNLEVEL2 },
4838 { '3', ACTION_RUNLEVEL3 },
4839 { '4', ACTION_RUNLEVEL4 },
4840 { '5', ACTION_RUNLEVEL5 },
4841 { 's', ACTION_RESCUE },
4842 { 'S', ACTION_RESCUE },
4843 { 'q', ACTION_RELOAD },
4844 { 'Q', ACTION_RELOAD },
4845 { 'u', ACTION_REEXEC },
4846 { 'U', ACTION_REEXEC }
4855 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4870 log_error("Unknown option code '%c'.", c);
4875 if (optind >= argc) {
4880 if (optind + 1 < argc) {
4881 log_error("Too many arguments.");
4885 if (strlen(argv[optind]) != 1) {
4886 log_error("Expected single character argument.");
4890 for (i = 0; i < ELEMENTSOF(table); i++)
4891 if (table[i].from == argv[optind][0])
4894 if (i >= ELEMENTSOF(table)) {
4895 log_error("Unknown command '%s'.", argv[optind]);
4899 arg_action = table[i].to;
4906 static int runlevel_parse_argv(int argc, char *argv[]) {
4912 static const struct option options[] = {
4913 { "help", no_argument, NULL, ARG_HELP },
4914 { NULL, 0, NULL, 0 }
4922 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4933 log_error("Unknown option code '%c'.", c);
4938 if (optind < argc) {
4939 log_error("Too many arguments.");
4946 static int parse_argv(int argc, char *argv[]) {
4950 if (program_invocation_short_name) {
4952 if (strstr(program_invocation_short_name, "halt")) {
4953 arg_action = ACTION_HALT;
4954 return halt_parse_argv(argc, argv);
4955 } else if (strstr(program_invocation_short_name, "poweroff")) {
4956 arg_action = ACTION_POWEROFF;
4957 return halt_parse_argv(argc, argv);
4958 } else if (strstr(program_invocation_short_name, "reboot")) {
4960 arg_action = ACTION_KEXEC;
4962 arg_action = ACTION_REBOOT;
4963 return halt_parse_argv(argc, argv);
4964 } else if (strstr(program_invocation_short_name, "shutdown")) {
4965 arg_action = ACTION_POWEROFF;
4966 return shutdown_parse_argv(argc, argv);
4967 } else if (strstr(program_invocation_short_name, "init")) {
4969 if (sd_booted() > 0) {
4970 arg_action = ACTION_INVALID;
4971 return telinit_parse_argv(argc, argv);
4973 /* Hmm, so some other init system is
4974 * running, we need to forward this
4975 * request to it. For now we simply
4976 * guess that it is Upstart. */
4978 execv(TELINIT, argv);
4980 log_error("Couldn't find an alternative telinit implementation to spawn.");
4984 } else if (strstr(program_invocation_short_name, "runlevel")) {
4985 arg_action = ACTION_RUNLEVEL;
4986 return runlevel_parse_argv(argc, argv);
4990 arg_action = ACTION_SYSTEMCTL;
4991 return systemctl_parse_argv(argc, argv);
4994 static int action_to_runlevel(void) {
4996 static const char table[_ACTION_MAX] = {
4997 [ACTION_HALT] = '0',
4998 [ACTION_POWEROFF] = '0',
4999 [ACTION_REBOOT] = '6',
5000 [ACTION_RUNLEVEL2] = '2',
5001 [ACTION_RUNLEVEL3] = '3',
5002 [ACTION_RUNLEVEL4] = '4',
5003 [ACTION_RUNLEVEL5] = '5',
5004 [ACTION_RESCUE] = '1'
5007 assert(arg_action < _ACTION_MAX);
5009 return table[arg_action];
5012 static int talk_upstart(void) {
5013 DBusMessage _cleanup_dbus_message_unref_ *m = NULL, *reply = NULL;
5014 DBusError _cleanup_dbus_error_free_ error;
5015 int previous, rl, r;
5017 env1_buf[] = "RUNLEVEL=X",
5018 env2_buf[] = "PREVLEVEL=X";
5019 char *env1 = env1_buf, *env2 = env2_buf;
5020 const char *emit = "runlevel";
5021 dbus_bool_t b_false = FALSE;
5022 DBusMessageIter iter, sub;
5023 DBusConnection *bus;
5025 dbus_error_init(&error);
5027 if (!(rl = action_to_runlevel()))
5030 if (utmp_get_runlevel(&previous, NULL) < 0)
5033 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5034 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5039 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5044 if ((r = bus_check_peercred(bus)) < 0) {
5045 log_error("Failed to verify owner of bus.");
5049 if (!(m = dbus_message_new_method_call(
5050 "com.ubuntu.Upstart",
5051 "/com/ubuntu/Upstart",
5052 "com.ubuntu.Upstart0_6",
5055 log_error("Could not allocate message.");
5060 dbus_message_iter_init_append(m, &iter);
5062 env1_buf[sizeof(env1_buf)-2] = rl;
5063 env2_buf[sizeof(env2_buf)-2] = previous;
5065 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5066 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5067 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5068 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5069 !dbus_message_iter_close_container(&iter, &sub) ||
5070 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5071 log_error("Could not append arguments to message.");
5076 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5078 if (bus_error_is_no_service(&error)) {
5083 log_error("Failed to issue method call: %s", bus_error_message(&error));
5092 dbus_connection_flush(bus);
5093 dbus_connection_close(bus);
5094 dbus_connection_unref(bus);
5100 static int talk_initctl(void) {
5101 struct init_request request = {0};
5103 int _cleanup_close_ fd = -1;
5106 rl = action_to_runlevel();
5110 request.magic = INIT_MAGIC;
5111 request.sleeptime = 0;
5112 request.cmd = INIT_CMD_RUNLVL;
5113 request.runlevel = rl;
5115 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5117 if (errno == ENOENT)
5120 log_error("Failed to open "INIT_FIFO": %m");
5125 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5127 log_error("Failed to write to "INIT_FIFO": %m");
5128 return errno ? -errno : -EIO;
5134 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5136 static const struct {
5144 int (* const dispatch)(DBusConnection *bus, char **args);
5146 { "list-units", LESS, 1, list_units },
5147 { "list-unit-files", EQUAL, 1, list_unit_files },
5148 { "list-jobs", EQUAL, 1, list_jobs },
5149 { "clear-jobs", EQUAL, 1, daemon_reload },
5150 { "load", MORE, 2, load_unit },
5151 { "cancel", MORE, 2, cancel_job },
5152 { "start", MORE, 2, start_unit },
5153 { "stop", MORE, 2, start_unit },
5154 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5155 { "reload", MORE, 2, start_unit },
5156 { "restart", MORE, 2, start_unit },
5157 { "try-restart", MORE, 2, start_unit },
5158 { "reload-or-restart", MORE, 2, start_unit },
5159 { "reload-or-try-restart", MORE, 2, start_unit },
5160 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5161 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5162 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5163 { "isolate", EQUAL, 2, start_unit },
5164 { "set-cgroup", MORE, 3, set_cgroup },
5165 { "unset-cgroup", MORE, 3, set_cgroup },
5166 { "get-cgroup-attr", MORE, 3, get_cgroup_attr },
5167 { "set-cgroup-attr", MORE, 4, set_cgroup_attr },
5168 { "unset-cgroup-attr", MORE, 3, set_cgroup },
5169 { "kill", MORE, 2, kill_unit },
5170 { "is-active", MORE, 2, check_unit_active },
5171 { "check", MORE, 2, check_unit_active },
5172 { "is-failed", MORE, 2, check_unit_failed },
5173 { "show", MORE, 1, show },
5174 { "status", MORE, 1, show },
5175 { "help", MORE, 2, show },
5176 { "dump", EQUAL, 1, dump },
5177 { "snapshot", LESS, 2, snapshot },
5178 { "delete", MORE, 2, delete_snapshot },
5179 { "daemon-reload", EQUAL, 1, daemon_reload },
5180 { "daemon-reexec", EQUAL, 1, daemon_reload },
5181 { "show-environment", EQUAL, 1, show_enviroment },
5182 { "set-environment", MORE, 2, set_environment },
5183 { "unset-environment", MORE, 2, set_environment },
5184 { "halt", EQUAL, 1, start_special },
5185 { "poweroff", EQUAL, 1, start_special },
5186 { "reboot", EQUAL, 1, start_special },
5187 { "kexec", EQUAL, 1, start_special },
5188 { "suspend", EQUAL, 1, start_special },
5189 { "hibernate", EQUAL, 1, start_special },
5190 { "hybrid-sleep", EQUAL, 1, start_special },
5191 { "default", EQUAL, 1, start_special },
5192 { "rescue", EQUAL, 1, start_special },
5193 { "emergency", EQUAL, 1, start_special },
5194 { "exit", EQUAL, 1, start_special },
5195 { "reset-failed", MORE, 1, reset_failed },
5196 { "enable", MORE, 2, enable_unit },
5197 { "disable", MORE, 2, enable_unit },
5198 { "is-enabled", MORE, 2, unit_is_enabled },
5199 { "reenable", MORE, 2, enable_unit },
5200 { "preset", MORE, 2, enable_unit },
5201 { "mask", MORE, 2, enable_unit },
5202 { "unmask", MORE, 2, enable_unit },
5203 { "link", MORE, 2, enable_unit },
5204 { "switch-root", MORE, 2, switch_root },
5205 { "list-dependencies", LESS, 2, list_dependencies },
5215 left = argc - optind;
5218 /* Special rule: no arguments means "list-units" */
5221 if (streq(argv[optind], "help") && !argv[optind+1]) {
5222 log_error("This command expects one or more "
5223 "unit names. Did you mean --help?");
5227 for (i = 0; i < ELEMENTSOF(verbs); i++)
5228 if (streq(argv[optind], verbs[i].verb))
5231 if (i >= ELEMENTSOF(verbs)) {
5232 log_error("Unknown operation '%s'.", argv[optind]);
5237 switch (verbs[i].argc_cmp) {
5240 if (left != verbs[i].argc) {
5241 log_error("Invalid number of arguments.");
5248 if (left < verbs[i].argc) {
5249 log_error("Too few arguments.");
5256 if (left > verbs[i].argc) {
5257 log_error("Too many arguments.");
5264 assert_not_reached("Unknown comparison operator.");
5267 /* Require a bus connection for all operations but
5269 if (!streq(verbs[i].verb, "enable") &&
5270 !streq(verbs[i].verb, "disable") &&
5271 !streq(verbs[i].verb, "is-enabled") &&
5272 !streq(verbs[i].verb, "list-unit-files") &&
5273 !streq(verbs[i].verb, "reenable") &&
5274 !streq(verbs[i].verb, "preset") &&
5275 !streq(verbs[i].verb, "mask") &&
5276 !streq(verbs[i].verb, "unmask") &&
5277 !streq(verbs[i].verb, "link")) {
5279 if (running_in_chroot() > 0) {
5280 log_info("Running in chroot, ignoring request.");
5284 if (((!streq(verbs[i].verb, "reboot") &&
5285 !streq(verbs[i].verb, "halt") &&
5286 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5287 log_error("Failed to get D-Bus connection: %s",
5288 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5294 if (!bus && !avoid_bus()) {
5295 log_error("Failed to get D-Bus connection: %s",
5296 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5301 return verbs[i].dispatch(bus, argv + optind);
5304 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5305 int _cleanup_close_ fd;
5306 struct msghdr msghdr;
5307 struct iovec iovec[2];
5308 union sockaddr_union sockaddr;
5309 struct sd_shutdown_command c;
5311 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5318 c.dry_run = dry_run;
5322 sockaddr.sa.sa_family = AF_UNIX;
5323 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5326 msghdr.msg_name = &sockaddr;
5327 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5330 iovec[0].iov_base = (char*) &c;
5331 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5333 if (isempty(message))
5334 msghdr.msg_iovlen = 1;
5336 iovec[1].iov_base = (char*) message;
5337 iovec[1].iov_len = strlen(message);
5338 msghdr.msg_iovlen = 2;
5340 msghdr.msg_iov = iovec;
5342 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5348 static int reload_with_fallback(DBusConnection *bus) {
5351 /* First, try systemd via D-Bus. */
5352 if (daemon_reload(bus, NULL) >= 0)
5356 /* Nothing else worked, so let's try signals */
5357 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5359 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5360 log_error("kill() failed: %m");
5367 static int start_with_fallback(DBusConnection *bus) {
5370 /* First, try systemd via D-Bus. */
5371 if (start_unit(bus, NULL) >= 0)
5375 /* Hmm, talking to systemd via D-Bus didn't work. Then
5376 * let's try to talk to Upstart via D-Bus. */
5377 if (talk_upstart() > 0)
5380 /* Nothing else worked, so let's try
5382 if (talk_initctl() > 0)
5385 log_error("Failed to talk to init daemon.");
5389 warn_wall(arg_action);
5393 static _noreturn_ void halt_now(enum action a) {
5395 /* Make sure C-A-D is handled by the kernel from this
5397 reboot(RB_ENABLE_CAD);
5402 log_info("Halting.");
5403 reboot(RB_HALT_SYSTEM);
5406 case ACTION_POWEROFF:
5407 log_info("Powering off.");
5408 reboot(RB_POWER_OFF);
5412 log_info("Rebooting.");
5413 reboot(RB_AUTOBOOT);
5417 assert_not_reached("Unknown halt action.");
5420 assert_not_reached("Uh? This shouldn't happen.");
5423 static int halt_main(DBusConnection *bus) {
5426 r = check_inhibitors(bus, arg_action);
5430 if (geteuid() != 0) {
5431 /* Try logind if we are a normal user and no special
5432 * mode applies. Maybe PolicyKit allows us to shutdown
5435 if (arg_when <= 0 &&
5438 (arg_action == ACTION_POWEROFF ||
5439 arg_action == ACTION_REBOOT)) {
5440 r = reboot_with_logind(bus, arg_action);
5445 log_error("Must be root.");
5450 char _cleanup_free_ *m;
5452 m = strv_join(arg_wall, " ");
5453 r = send_shutdownd(arg_when,
5454 arg_action == ACTION_HALT ? 'H' :
5455 arg_action == ACTION_POWEROFF ? 'P' :
5456 arg_action == ACTION_KEXEC ? 'K' :
5463 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5465 char date[FORMAT_TIMESTAMP_MAX];
5467 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5468 format_timestamp(date, sizeof(date), arg_when));
5473 if (!arg_dry && !arg_force)
5474 return start_with_fallback(bus);
5477 if (sd_booted() > 0)
5478 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5480 r = utmp_put_shutdown();
5482 log_warning("Failed to write utmp record: %s", strerror(-r));
5489 halt_now(arg_action);
5490 /* We should never reach this. */
5494 static int runlevel_main(void) {
5495 int r, runlevel, previous;
5497 r = utmp_get_runlevel(&runlevel, &previous);
5504 previous <= 0 ? 'N' : previous,
5505 runlevel <= 0 ? 'N' : runlevel);
5510 int main(int argc, char*argv[]) {
5511 int r, retval = EXIT_FAILURE;
5512 DBusConnection *bus = NULL;
5513 DBusError _cleanup_dbus_error_free_ error;
5515 dbus_error_init(&error);
5517 setlocale(LC_ALL, "");
5518 log_parse_environment();
5521 r = parse_argv(argc, argv);
5525 retval = EXIT_SUCCESS;
5529 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5530 * let's shortcut this */
5531 if (arg_action == ACTION_RUNLEVEL) {
5532 r = runlevel_main();
5533 retval = r < 0 ? EXIT_FAILURE : r;
5537 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5538 log_info("Running in chroot, ignoring request.");
5544 if (arg_transport == TRANSPORT_NORMAL)
5545 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5546 else if (arg_transport == TRANSPORT_POLKIT) {
5547 bus_connect_system_polkit(&bus, &error);
5548 private_bus = false;
5549 } else if (arg_transport == TRANSPORT_SSH) {
5550 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5551 private_bus = false;
5553 assert_not_reached("Uh, invalid transport...");
5556 switch (arg_action) {
5558 case ACTION_SYSTEMCTL:
5559 r = systemctl_main(bus, argc, argv, &error);
5563 case ACTION_POWEROFF:
5569 case ACTION_RUNLEVEL2:
5570 case ACTION_RUNLEVEL3:
5571 case ACTION_RUNLEVEL4:
5572 case ACTION_RUNLEVEL5:
5574 case ACTION_EMERGENCY:
5575 case ACTION_DEFAULT:
5576 r = start_with_fallback(bus);
5581 r = reload_with_fallback(bus);
5584 case ACTION_CANCEL_SHUTDOWN: {
5588 m = strv_join(arg_wall, " ");
5590 retval = EXIT_FAILURE;
5594 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5596 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5601 case ACTION_INVALID:
5602 case ACTION_RUNLEVEL:
5604 assert_not_reached("Unknown action");
5607 retval = r < 0 ? EXIT_FAILURE : r;
5611 dbus_connection_flush(bus);
5612 dbus_connection_close(bus);
5613 dbus_connection_unref(bus);
5618 strv_free(arg_property);
5621 ask_password_agent_close();
5622 polkit_agent_close();