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) {
1196 WaitData d = { .set = s };
1201 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1204 while (!set_isempty(s)) {
1206 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1207 log_error("Disconnected from bus.");
1208 return -ECONNREFUSED;
1215 if (streq(d.result, "timeout"))
1216 log_error("Job for %s timed out.", strna(d.name));
1217 else if (streq(d.result, "canceled"))
1218 log_error("Job for %s canceled.", strna(d.name));
1219 else if (streq(d.result, "dependency"))
1220 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1221 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1222 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1225 if (streq_ptr(d.result, "timeout"))
1227 else if (streq_ptr(d.result, "canceled"))
1229 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1240 dbus_connection_remove_filter(bus, wait_filter, &d);
1244 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1245 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1246 _cleanup_free_ char *n = NULL;
1247 DBusMessageIter iter, sub;
1249 *interface = "org.freedesktop.systemd1.Unit",
1250 *property = "ActiveState";
1251 const char *state, *path;
1257 dbus_error_init(&error);
1259 n = unit_name_mangle(name);
1263 r = bus_method_call_with_reply (
1265 "org.freedesktop.systemd1",
1266 "/org/freedesktop/systemd1",
1267 "org.freedesktop.systemd1.Manager",
1271 DBUS_TYPE_STRING, &n,
1274 dbus_error_free(&error);
1281 if (!dbus_message_get_args(reply, NULL,
1282 DBUS_TYPE_OBJECT_PATH, &path,
1283 DBUS_TYPE_INVALID)) {
1284 log_error("Failed to parse reply.");
1288 dbus_message_unref(reply);
1291 r = bus_method_call_with_reply(
1293 "org.freedesktop.systemd1",
1295 "org.freedesktop.DBus.Properties",
1299 DBUS_TYPE_STRING, &interface,
1300 DBUS_TYPE_STRING, &property,
1308 if (!dbus_message_iter_init(reply, &iter) ||
1309 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1310 log_error("Failed to parse reply.");
1314 dbus_message_iter_recurse(&iter, &sub);
1316 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1317 log_error("Failed to parse reply.");
1321 dbus_message_iter_get_basic(&sub, &state);
1326 return strv_find(check_states, state) ? 1 : 0;
1329 static void check_triggering_units(
1330 DBusConnection *bus,
1331 const char *unit_name) {
1333 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1334 DBusMessageIter iter, sub;
1335 const char *interface = "org.freedesktop.systemd1.Unit",
1336 *load_state_property = "LoadState",
1337 *triggered_by_property = "TriggeredBy",
1339 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1340 bool print_warning_label = true;
1343 n = unit_name_mangle(unit_name);
1349 unit_path = unit_dbus_path_from_name(n);
1355 r = bus_method_call_with_reply(
1357 "org.freedesktop.systemd1",
1359 "org.freedesktop.DBus.Properties",
1363 DBUS_TYPE_STRING, &interface,
1364 DBUS_TYPE_STRING, &load_state_property,
1369 if (!dbus_message_iter_init(reply, &iter) ||
1370 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1371 log_error("Failed to parse reply.");
1375 dbus_message_iter_recurse(&iter, &sub);
1377 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1378 log_error("Failed to parse reply.");
1382 dbus_message_iter_get_basic(&sub, &state);
1384 if (streq(state, "masked"))
1387 dbus_message_unref(reply);
1390 r = bus_method_call_with_reply(
1392 "org.freedesktop.systemd1",
1394 "org.freedesktop.DBus.Properties",
1398 DBUS_TYPE_STRING, &interface,
1399 DBUS_TYPE_STRING, &triggered_by_property,
1404 if (!dbus_message_iter_init(reply, &iter) ||
1405 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1406 log_error("Failed to parse reply.");
1410 dbus_message_iter_recurse(&iter, &sub);
1411 dbus_message_iter_recurse(&sub, &iter);
1414 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1415 const char * const check_states[] = {
1420 const char *service_trigger;
1422 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1423 log_error("Failed to parse reply.");
1427 dbus_message_iter_get_basic(&sub, &service_trigger);
1429 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1433 if (print_warning_label) {
1434 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1435 print_warning_label = false;
1438 log_warning(" %s", service_trigger);
1441 dbus_message_iter_next(&sub);
1445 static int start_unit_one(
1446 DBusConnection *bus,
1453 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1454 _cleanup_free_ char *n;
1463 n = unit_name_mangle(name);
1467 r = bus_method_call_with_reply(
1469 "org.freedesktop.systemd1",
1470 "/org/freedesktop/systemd1",
1471 "org.freedesktop.systemd1.Manager",
1475 DBUS_TYPE_STRING, &n,
1476 DBUS_TYPE_STRING, &mode,
1479 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1480 /* There's always a fallback possible for
1481 * legacy actions. */
1484 log_error("Failed to issue method call: %s", bus_error_message(error));
1489 if (!dbus_message_get_args(reply, error,
1490 DBUS_TYPE_OBJECT_PATH, &path,
1491 DBUS_TYPE_INVALID)) {
1492 log_error("Failed to parse reply: %s", bus_error_message(error));
1496 if (need_daemon_reload(bus, n))
1497 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1498 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1510 log_error("Failed to add path to set.");
1518 static const struct {
1522 } action_table[_ACTION_MAX] = {
1523 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
1524 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
1525 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
1526 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
1527 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
1528 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
1529 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
1530 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
1531 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
1532 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
1533 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
1534 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
1535 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
1536 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
1537 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1540 static enum action verb_to_action(const char *verb) {
1543 for (i = ACTION_INVALID; i < _ACTION_MAX; i++)
1544 if (action_table[i].verb && streq(verb, action_table[i].verb))
1546 return ACTION_INVALID;
1549 static int start_unit(DBusConnection *bus, char **args) {
1552 const char *method, *mode, *one_name;
1553 Set _cleanup_set_free_free_ *s = NULL;
1554 DBusError _cleanup_dbus_error_free_ error;
1557 dbus_error_init(&error);
1561 ask_password_agent_open_if_enabled();
1563 if (arg_action == ACTION_SYSTEMCTL) {
1566 streq(args[0], "stop") ||
1567 streq(args[0], "condstop") ? "StopUnit" :
1568 streq(args[0], "reload") ? "ReloadUnit" :
1569 streq(args[0], "restart") ? "RestartUnit" :
1571 streq(args[0], "try-restart") ||
1572 streq(args[0], "condrestart") ? "TryRestartUnit" :
1574 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1576 streq(args[0], "reload-or-try-restart") ||
1577 streq(args[0], "condreload") ||
1579 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1581 action = verb_to_action(args[0]);
1583 mode = streq(args[0], "isolate") ? "isolate" :
1584 action_table[action].mode ?: arg_job_mode;
1586 one_name = action_table[action].target;
1589 assert(arg_action < ELEMENTSOF(action_table));
1590 assert(action_table[arg_action].target);
1592 method = "StartUnit";
1594 mode = action_table[arg_action].mode;
1595 one_name = action_table[arg_action].target;
1598 if (!arg_no_block) {
1599 ret = enable_wait_for_jobs(bus);
1601 log_error("Could not watch jobs: %s", strerror(-ret));
1605 s = set_new(string_hash_func, string_compare_func);
1611 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1613 ret = translate_bus_error_to_exit_status(ret, &error);
1615 STRV_FOREACH(name, args+1) {
1616 r = start_unit_one(bus, method, *name, mode, &error, s);
1618 ret = translate_bus_error_to_exit_status(r, &error);
1619 dbus_error_free(&error);
1624 if (!arg_no_block) {
1625 r = wait_for_jobs(bus, s);
1629 /* When stopping units, warn if they can still be triggered by
1630 * another active unit (socket, path, timer) */
1631 if (!arg_quiet && streq(method, "StopUnit")) {
1633 check_triggering_units(bus, one_name);
1635 STRV_FOREACH(name, args+1)
1636 check_triggering_units(bus, *name);
1643 /* Ask systemd-logind, which might grant access to unprivileged users
1644 * through PolicyKit */
1645 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1648 dbus_bool_t interactive = true;
1653 polkit_agent_open_if_enabled();
1661 case ACTION_POWEROFF:
1662 method = "PowerOff";
1665 case ACTION_SUSPEND:
1669 case ACTION_HIBERNATE:
1670 method = "Hibernate";
1673 case ACTION_HYBRID_SLEEP:
1674 method = "HybridSleep";
1681 return bus_method_call_with_reply(
1683 "org.freedesktop.login1",
1684 "/org/freedesktop/login1",
1685 "org.freedesktop.login1.Manager",
1689 DBUS_TYPE_BOOLEAN, &interactive,
1696 static int check_inhibitors(DBusConnection *bus, enum action a) {
1698 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1699 DBusMessageIter iter, sub, sub2;
1702 _cleanup_strv_free_ char **sessions = NULL;
1708 if (arg_ignore_inhibitors || arg_force > 0)
1720 r = bus_method_call_with_reply(
1722 "org.freedesktop.login1",
1723 "/org/freedesktop/login1",
1724 "org.freedesktop.login1.Manager",
1730 /* If logind is not around, then there are no inhibitors... */
1733 if (!dbus_message_iter_init(reply, &iter) ||
1734 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1735 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1736 log_error("Failed to parse reply.");
1740 dbus_message_iter_recurse(&iter, &sub);
1741 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1742 const char *what, *who, *why, *mode;
1744 _cleanup_strv_free_ char **sv = NULL;
1745 _cleanup_free_ char *comm = NULL, *user = NULL;
1747 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1748 log_error("Failed to parse reply.");
1752 dbus_message_iter_recurse(&sub, &sub2);
1754 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
1755 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
1756 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
1757 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
1758 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
1759 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
1760 log_error("Failed to parse reply.");
1764 if (!streq(mode, "block"))
1767 sv = strv_split(what, ":");
1771 if (!strv_contains(sv,
1773 a == ACTION_POWEROFF ||
1774 a == ACTION_REBOOT ||
1775 a == ACTION_KEXEC ? "shutdown" : "sleep"))
1778 get_process_comm(pid, &comm);
1779 user = uid_to_name(uid);
1780 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
1781 who, (unsigned long) pid, strna(comm), strna(user), why);
1785 dbus_message_iter_next(&sub);
1788 dbus_message_iter_recurse(&iter, &sub);
1790 /* Check for current sessions */
1791 sd_get_sessions(&sessions);
1792 STRV_FOREACH(s, sessions) {
1794 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
1796 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
1799 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
1802 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
1805 sd_session_get_tty(*s, &tty);
1806 sd_session_get_seat(*s, &seat);
1807 sd_session_get_service(*s, &service);
1808 user = uid_to_name(uid);
1810 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
1817 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
1818 action_table[a].verb);
1826 static int start_special(DBusConnection *bus, char **args) {
1832 a = verb_to_action(args[0]);
1834 r = check_inhibitors(bus, a);
1838 if (arg_force >= 2 && geteuid() != 0) {
1839 log_error("Must be root.");
1843 if (arg_force >= 2 &&
1844 (a == ACTION_HALT ||
1845 a == ACTION_POWEROFF ||
1846 a == ACTION_REBOOT))
1849 if (arg_force >= 1 &&
1850 (a == ACTION_HALT ||
1851 a == ACTION_POWEROFF ||
1852 a == ACTION_REBOOT ||
1853 a == ACTION_KEXEC ||
1855 return daemon_reload(bus, args);
1857 /* first try logind, to allow authentication with polkit */
1858 if (geteuid() != 0 &&
1859 (a == ACTION_POWEROFF ||
1860 a == ACTION_REBOOT ||
1861 a == ACTION_SUSPEND ||
1862 a == ACTION_HIBERNATE ||
1863 a == ACTION_HYBRID_SLEEP)) {
1864 r = reboot_with_logind(bus, a);
1869 r = start_unit(bus, args);
1870 if (r == EXIT_SUCCESS)
1876 static int check_unit_active(DBusConnection *bus, char **args) {
1877 const char * const check_states[] = {
1884 int r = 3; /* According to LSB: "program is not running" */
1889 STRV_FOREACH(name, args+1) {
1892 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1902 static int check_unit_failed(DBusConnection *bus, char **args) {
1903 const char * const check_states[] = {
1914 STRV_FOREACH(name, args+1) {
1917 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1927 static int kill_unit(DBusConnection *bus, char **args) {
1935 arg_kill_who = "all";
1937 STRV_FOREACH(name, args+1) {
1938 _cleanup_free_ char *n = NULL;
1940 n = unit_name_mangle(*name);
1944 r = bus_method_call_with_reply(
1946 "org.freedesktop.systemd1",
1947 "/org/freedesktop/systemd1",
1948 "org.freedesktop.systemd1.Manager",
1952 DBUS_TYPE_STRING, &n,
1953 DBUS_TYPE_STRING, &arg_kill_who,
1954 DBUS_TYPE_INT32, &arg_signal,
1962 static int set_cgroup(DBusConnection *bus, char **args) {
1963 _cleanup_free_ char *n = NULL;
1964 const char *method, *runtime;
1972 streq(args[0], "set-cgroup") ? "SetUnitControlGroup" :
1973 streq(args[0], "unset-cgroup") ? "UnsetUnitControlGroup"
1974 : "UnsetUnitControlGroupAttribute";
1976 runtime = arg_runtime ? "runtime" : "persistent";
1978 n = unit_name_mangle(args[1]);
1982 STRV_FOREACH(argument, args + 2) {
1984 r = bus_method_call_with_reply(
1986 "org.freedesktop.systemd1",
1987 "/org/freedesktop/systemd1",
1988 "org.freedesktop.systemd1.Manager",
1992 DBUS_TYPE_STRING, &n,
1993 DBUS_TYPE_STRING, argument,
1994 DBUS_TYPE_STRING, &runtime,
2003 static int set_cgroup_attr(DBusConnection *bus, char **args) {
2004 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2006 DBusMessageIter iter;
2007 _cleanup_free_ char *n = NULL;
2008 const char *runtime;
2014 dbus_error_init(&error);
2016 runtime = arg_runtime ? "runtime" : "persistent";
2018 n = unit_name_mangle(args[1]);
2022 m = dbus_message_new_method_call(
2023 "org.freedesktop.systemd1",
2024 "/org/freedesktop/systemd1",
2025 "org.freedesktop.systemd1.Manager",
2026 "SetUnitControlGroupAttribute");
2030 dbus_message_iter_init_append(m, &iter);
2031 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2032 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[2]))
2035 r = bus_append_strv_iter(&iter, args + 3);
2039 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2042 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2044 log_error("Failed to issue method call: %s", bus_error_message(&error));
2045 dbus_error_free(&error);
2052 static int get_cgroup_attr(DBusConnection *bus, char **args) {
2053 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
2054 _cleanup_free_ char *n = NULL;
2061 n = unit_name_mangle(args[1]);
2065 STRV_FOREACH(argument, args + 2) {
2066 _cleanup_strv_free_ char **list = NULL;
2067 DBusMessageIter iter;
2070 r = bus_method_call_with_reply(
2072 "org.freedesktop.systemd1",
2073 "/org/freedesktop/systemd1",
2074 "org.freedesktop.systemd1.Manager",
2075 "GetUnitControlGroupAttribute",
2078 DBUS_TYPE_STRING, &n,
2079 DBUS_TYPE_STRING, argument,
2084 if (!dbus_message_iter_init(reply, &iter)) {
2085 log_error("Failed to initialize iterator.");
2089 r = bus_parse_strv_iter(&iter, &list);
2091 log_error("Failed to parse value list.");
2095 STRV_FOREACH(a, list) {
2096 if (endswith(*a, "\n"))
2106 typedef struct ExecStatusInfo {
2114 usec_t start_timestamp;
2115 usec_t exit_timestamp;
2120 LIST_FIELDS(struct ExecStatusInfo, exec);
2123 static void exec_status_info_free(ExecStatusInfo *i) {
2132 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2133 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2134 DBusMessageIter sub2, sub3;
2138 int32_t code, status;
2144 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2147 dbus_message_iter_recurse(sub, &sub2);
2149 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2152 i->path = strdup(path);
2156 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2157 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2161 dbus_message_iter_recurse(&sub2, &sub3);
2162 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2163 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2164 dbus_message_iter_next(&sub3);
2168 i->argv = new0(char*, n+1);
2173 dbus_message_iter_recurse(&sub2, &sub3);
2174 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2177 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2178 dbus_message_iter_get_basic(&sub3, &s);
2179 dbus_message_iter_next(&sub3);
2181 i->argv[n] = strdup(s);
2188 if (!dbus_message_iter_next(&sub2) ||
2189 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2190 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2191 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2192 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2193 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2194 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2195 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2196 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2200 i->start_timestamp = (usec_t) start_timestamp;
2201 i->exit_timestamp = (usec_t) exit_timestamp;
2202 i->pid = (pid_t) pid;
2209 typedef struct UnitStatusInfo {
2211 const char *load_state;
2212 const char *active_state;
2213 const char *sub_state;
2214 const char *unit_file_state;
2216 const char *description;
2217 const char *following;
2219 char **documentation;
2221 const char *fragment_path;
2222 const char *source_path;
2223 const char *default_control_group;
2225 char **dropin_paths;
2227 const char *load_error;
2230 usec_t inactive_exit_timestamp;
2231 usec_t inactive_exit_timestamp_monotonic;
2232 usec_t active_enter_timestamp;
2233 usec_t active_exit_timestamp;
2234 usec_t inactive_enter_timestamp;
2236 bool need_daemon_reload;
2241 const char *status_text;
2244 usec_t start_timestamp;
2245 usec_t exit_timestamp;
2247 int exit_code, exit_status;
2249 usec_t condition_timestamp;
2250 bool condition_result;
2253 unsigned n_accepted;
2254 unsigned n_connections;
2257 /* Pairs of type, path */
2261 const char *sysfs_path;
2263 /* Mount, Automount */
2269 LIST_HEAD(ExecStatusInfo, exec);
2272 static void print_status_info(UnitStatusInfo *i) {
2274 const char *on, *off, *ss;
2276 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2277 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2280 arg_all * OUTPUT_SHOW_ALL |
2281 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2282 on_tty() * OUTPUT_COLOR |
2283 !arg_quiet * OUTPUT_WARN_CUTOFF |
2284 arg_full * OUTPUT_FULL_WIDTH;
2285 int maxlen = 8; /* a value that'll suffice most of the time */
2290 STRV_FOREACH_PAIR(t, t2, i->listen)
2291 maxlen = MAX(maxlen, (int)(sizeof("Listen") - 1 + strlen(*t)));
2293 maxlen = MAX(maxlen, (int)sizeof("Accept") - 1);
2294 if (i->main_pid > 0)
2295 maxlen = MAX(maxlen, (int)sizeof("Main PID") - 1);
2296 else if (i->control_pid > 0)
2297 maxlen = MAX(maxlen, (int)sizeof("Control") - 1);
2299 /* This shows pretty information about a unit. See
2300 * print_property() for a low-level property printer */
2302 printf("%s", strna(i->id));
2304 if (i->description && !streq_ptr(i->id, i->description))
2305 printf(" - %s", i->description);
2310 printf(" %*s: unit currently follows state of %s\n", maxlen, "Follow", i->following);
2312 if (streq_ptr(i->load_state, "error")) {
2313 on = ansi_highlight_red(true);
2314 off = ansi_highlight_red(false);
2318 path = i->source_path ? i->source_path : i->fragment_path;
2321 printf(" %*s: %s%s%s (Reason: %s)\n",
2322 maxlen, "Loaded", on, strna(i->load_state), off, i->load_error);
2323 else if (path && i->unit_file_state)
2324 printf(" %*s: %s%s%s (%s; %s)\n",
2325 maxlen, "Loaded", on, strna(i->load_state), off, path, i->unit_file_state);
2327 printf(" %*s: %s%s%s (%s)\n",
2328 maxlen, "Loaded", on, strna(i->load_state), off, path);
2330 printf(" %*s: %s%s%s\n",
2331 maxlen, "Loaded", on, strna(i->load_state), off);
2333 if (!strv_isempty(i->dropin_paths)) {
2338 STRV_FOREACH(dropin, i->dropin_paths) {
2339 if (! dir || last) {
2340 printf(" %*s ", maxlen, dir ? "" : "Drop-In:");
2344 if (path_get_parent(*dropin, &dir) < 0) {
2349 printf("%s\n %*s %s", dir, maxlen, "",
2350 draw_special_char(DRAW_TREE_RIGHT));
2353 last = ! (*(dropin + 1) && startswith(*(dropin + 1), dir));
2355 printf("%s%s", path_get_file_name(*dropin), last ? "\n" : ", ");
2361 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2363 if (streq_ptr(i->active_state, "failed")) {
2364 on = ansi_highlight_red(true);
2365 off = ansi_highlight_red(false);
2366 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2367 on = ansi_highlight_green(true);
2368 off = ansi_highlight_green(false);
2373 printf(" %*s: %s%s (%s)%s",
2374 maxlen, "Active", on, strna(i->active_state), ss, off);
2376 printf(" %*s: %s%s%s",
2377 maxlen, "Active", on, strna(i->active_state), off);
2379 if (!isempty(i->result) && !streq(i->result, "success"))
2380 printf(" (Result: %s)", i->result);
2382 timestamp = (streq_ptr(i->active_state, "active") ||
2383 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2384 (streq_ptr(i->active_state, "inactive") ||
2385 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2386 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2387 i->active_exit_timestamp;
2389 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2390 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2393 printf(" since %s; %s\n", s2, s1);
2395 printf(" since %s\n", s2);
2399 if (!i->condition_result && i->condition_timestamp > 0) {
2400 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2401 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2404 printf(" %*s start condition failed at %s; %s\n", maxlen, "", s2, s1);
2406 printf(" %*s start condition failed at %s\n", maxlen, "", s2);
2410 printf(" %*s: %s\n", maxlen, "Device", i->sysfs_path);
2412 printf(" %*s: %s\n", maxlen, "Where", i->where);
2414 printf(" %*s: %s\n", maxlen, "What", i->what);
2416 STRV_FOREACH(t, i->documentation)
2417 printf(" %*s %s\n", maxlen+1, t == i->documentation ? "Docs:" : "", *t);
2419 STRV_FOREACH_PAIR(t, t2, i->listen)
2420 printf(" %*s %s (%s)\n", maxlen+1, t == i->listen ? "Listen:" : "", *t2, *t);
2423 printf(" %*s: %u; Connected: %u\n", maxlen, "Accepted", i->n_accepted, i->n_connections);
2425 LIST_FOREACH(exec, p, i->exec) {
2426 _cleanup_free_ char *argv = NULL;
2429 /* Only show exited processes here */
2433 argv = strv_join(p->argv, " ");
2434 printf(" %*s: %u %s=%s ", maxlen, "Process", p->pid, p->name, strna(argv));
2436 good = is_clean_exit_lsb(p->code, p->status, NULL);
2438 on = ansi_highlight_red(true);
2439 off = ansi_highlight_red(false);
2443 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2445 if (p->code == CLD_EXITED) {
2448 printf("status=%i", p->status);
2450 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2455 printf("signal=%s", signal_to_string(p->status));
2457 printf(")%s\n", off);
2459 if (i->main_pid == p->pid &&
2460 i->start_timestamp == p->start_timestamp &&
2461 i->exit_timestamp == p->start_timestamp)
2462 /* Let's not show this twice */
2465 if (p->pid == i->control_pid)
2469 if (i->main_pid > 0 || i->control_pid > 0) {
2470 if (i->main_pid > 0) {
2471 printf(" %*s: %u", maxlen, "Main PID", (unsigned) i->main_pid);
2474 _cleanup_free_ char *comm = NULL;
2475 get_process_comm(i->main_pid, &comm);
2477 printf(" (%s)", comm);
2478 } else if (i->exit_code > 0) {
2479 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2481 if (i->exit_code == CLD_EXITED) {
2484 printf("status=%i", i->exit_status);
2486 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2491 printf("signal=%s", signal_to_string(i->exit_status));
2495 if (i->control_pid > 0)
2499 if (i->control_pid > 0) {
2500 _cleanup_free_ char *c = NULL;
2502 printf(" %*s: %u", i->main_pid ? 0 : maxlen, "Control", (unsigned) i->control_pid);
2504 get_process_comm(i->control_pid, &c);
2513 printf(" %*s: \"%s\"\n", maxlen, "Status", i->status_text);
2515 if (i->default_control_group &&
2516 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2519 printf(" %*s: %s\n", maxlen, "CGroup", i->default_control_group);
2521 if (arg_transport != TRANSPORT_SSH) {
2524 char prefix[maxlen + 4];
2525 memset(prefix, ' ', sizeof(prefix) - 1);
2526 prefix[sizeof(prefix) - 1] = '\0';
2529 if (c > sizeof(prefix) - 1)
2530 c -= sizeof(prefix) - 1;
2534 if (i->main_pid > 0)
2535 extra[k++] = i->main_pid;
2537 if (i->control_pid > 0)
2538 extra[k++] = i->control_pid;
2540 show_cgroup_and_extra_by_spec(i->default_control_group, prefix,
2541 c, false, extra, k, flags);
2545 if (i->id && arg_transport != TRANSPORT_SSH) {
2547 show_journal_by_unit(stdout,
2551 i->inactive_exit_timestamp_monotonic,
2555 arg_scope == UNIT_FILE_SYSTEM);
2558 if (i->need_daemon_reload)
2559 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2560 ansi_highlight_red(true),
2561 ansi_highlight_red(false),
2562 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2565 static void show_unit_help(UnitStatusInfo *i) {
2570 if (!i->documentation) {
2571 log_info("Documentation for %s not known.", i->id);
2575 STRV_FOREACH(p, i->documentation) {
2577 if (startswith(*p, "man:")) {
2580 char _cleanup_free_ *page = NULL, *section = NULL;
2581 const char *args[4] = { "man", NULL, NULL, NULL };
2586 if ((*p)[k-1] == ')')
2587 e = strrchr(*p, '(');
2590 page = strndup((*p) + 4, e - *p - 4);
2591 section = strndup(e + 1, *p + k - e - 2);
2592 if (!page || !section) {
2604 log_error("Failed to fork: %m");
2610 execvp(args[0], (char**) args);
2611 log_error("Failed to execute man: %m");
2612 _exit(EXIT_FAILURE);
2615 wait_for_terminate(pid, NULL);
2617 log_info("Can't show: %s", *p);
2621 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2627 switch (dbus_message_iter_get_arg_type(iter)) {
2629 case DBUS_TYPE_STRING: {
2632 dbus_message_iter_get_basic(iter, &s);
2635 if (streq(name, "Id"))
2637 else if (streq(name, "LoadState"))
2639 else if (streq(name, "ActiveState"))
2640 i->active_state = s;
2641 else if (streq(name, "SubState"))
2643 else if (streq(name, "Description"))
2645 else if (streq(name, "FragmentPath"))
2646 i->fragment_path = s;
2647 else if (streq(name, "SourcePath"))
2649 else if (streq(name, "DefaultControlGroup"))
2650 i->default_control_group = s;
2651 else if (streq(name, "StatusText"))
2653 else if (streq(name, "SysFSPath"))
2655 else if (streq(name, "Where"))
2657 else if (streq(name, "What"))
2659 else if (streq(name, "Following"))
2661 else if (streq(name, "UnitFileState"))
2662 i->unit_file_state = s;
2663 else if (streq(name, "Result"))
2670 case DBUS_TYPE_BOOLEAN: {
2673 dbus_message_iter_get_basic(iter, &b);
2675 if (streq(name, "Accept"))
2677 else if (streq(name, "NeedDaemonReload"))
2678 i->need_daemon_reload = b;
2679 else if (streq(name, "ConditionResult"))
2680 i->condition_result = b;
2685 case DBUS_TYPE_UINT32: {
2688 dbus_message_iter_get_basic(iter, &u);
2690 if (streq(name, "MainPID")) {
2692 i->main_pid = (pid_t) u;
2695 } else if (streq(name, "ControlPID"))
2696 i->control_pid = (pid_t) u;
2697 else if (streq(name, "ExecMainPID")) {
2699 i->main_pid = (pid_t) u;
2700 } else if (streq(name, "NAccepted"))
2702 else if (streq(name, "NConnections"))
2703 i->n_connections = u;
2708 case DBUS_TYPE_INT32: {
2711 dbus_message_iter_get_basic(iter, &j);
2713 if (streq(name, "ExecMainCode"))
2714 i->exit_code = (int) j;
2715 else if (streq(name, "ExecMainStatus"))
2716 i->exit_status = (int) j;
2721 case DBUS_TYPE_UINT64: {
2724 dbus_message_iter_get_basic(iter, &u);
2726 if (streq(name, "ExecMainStartTimestamp"))
2727 i->start_timestamp = (usec_t) u;
2728 else if (streq(name, "ExecMainExitTimestamp"))
2729 i->exit_timestamp = (usec_t) u;
2730 else if (streq(name, "ActiveEnterTimestamp"))
2731 i->active_enter_timestamp = (usec_t) u;
2732 else if (streq(name, "InactiveEnterTimestamp"))
2733 i->inactive_enter_timestamp = (usec_t) u;
2734 else if (streq(name, "InactiveExitTimestamp"))
2735 i->inactive_exit_timestamp = (usec_t) u;
2736 else if (streq(name, "InactiveExitTimestampMonotonic"))
2737 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2738 else if (streq(name, "ActiveExitTimestamp"))
2739 i->active_exit_timestamp = (usec_t) u;
2740 else if (streq(name, "ConditionTimestamp"))
2741 i->condition_timestamp = (usec_t) u;
2746 case DBUS_TYPE_ARRAY: {
2748 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2749 startswith(name, "Exec")) {
2750 DBusMessageIter sub;
2752 dbus_message_iter_recurse(iter, &sub);
2753 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2754 ExecStatusInfo *info;
2757 if (!(info = new0(ExecStatusInfo, 1)))
2760 if (!(info->name = strdup(name))) {
2765 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2770 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2772 dbus_message_iter_next(&sub);
2775 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
2776 DBusMessageIter sub, sub2;
2778 dbus_message_iter_recurse(iter, &sub);
2779 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2780 const char *type, *path;
2782 dbus_message_iter_recurse(&sub, &sub2);
2784 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2785 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
2788 r = strv_extend(&i->listen, type);
2791 r = strv_extend(&i->listen, path);
2796 dbus_message_iter_next(&sub);
2801 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING && streq(name, "DropInPaths")) {
2802 int r = bus_parse_strv_iter(iter, &i->dropin_paths);
2806 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2807 streq(name, "Documentation")) {
2809 DBusMessageIter sub;
2811 dbus_message_iter_recurse(iter, &sub);
2812 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2816 dbus_message_iter_get_basic(&sub, &s);
2818 r = strv_extend(&i->documentation, s);
2822 dbus_message_iter_next(&sub);
2829 case DBUS_TYPE_STRUCT: {
2831 if (streq(name, "LoadError")) {
2832 DBusMessageIter sub;
2833 const char *n, *message;
2836 dbus_message_iter_recurse(iter, &sub);
2838 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2842 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2846 if (!isempty(message))
2847 i->load_error = message;
2857 static int print_property(const char *name, DBusMessageIter *iter) {
2861 /* This is a low-level property printer, see
2862 * print_status_info() for the nicer output */
2864 if (arg_property && !strv_find(arg_property, name))
2867 switch (dbus_message_iter_get_arg_type(iter)) {
2869 case DBUS_TYPE_STRUCT: {
2870 DBusMessageIter sub;
2871 dbus_message_iter_recurse(iter, &sub);
2873 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2876 dbus_message_iter_get_basic(&sub, &u);
2879 printf("%s=%u\n", name, (unsigned) u);
2881 printf("%s=\n", name);
2884 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2887 dbus_message_iter_get_basic(&sub, &s);
2889 if (arg_all || s[0])
2890 printf("%s=%s\n", name, s);
2893 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2894 const char *a = NULL, *b = NULL;
2896 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2897 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2899 if (arg_all || !isempty(a) || !isempty(b))
2900 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2908 case DBUS_TYPE_ARRAY:
2910 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2911 DBusMessageIter sub, sub2;
2913 dbus_message_iter_recurse(iter, &sub);
2914 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2918 dbus_message_iter_recurse(&sub, &sub2);
2920 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2921 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2922 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2924 dbus_message_iter_next(&sub);
2929 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2930 DBusMessageIter sub, sub2;
2932 dbus_message_iter_recurse(iter, &sub);
2934 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2935 const char *type, *path;
2937 dbus_message_iter_recurse(&sub, &sub2);
2939 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2940 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2941 printf("%s=%s\n", type, path);
2943 dbus_message_iter_next(&sub);
2948 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
2949 DBusMessageIter sub, sub2;
2951 dbus_message_iter_recurse(iter, &sub);
2952 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2953 const char *type, *path;
2955 dbus_message_iter_recurse(&sub, &sub2);
2957 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2958 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2959 printf("Listen%s=%s\n", type, path);
2961 dbus_message_iter_next(&sub);
2966 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2967 DBusMessageIter sub, sub2;
2969 dbus_message_iter_recurse(iter, &sub);
2970 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2972 uint64_t value, next_elapse;
2974 dbus_message_iter_recurse(&sub, &sub2);
2976 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2977 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2978 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2979 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2981 printf("%s={ value=%s ; next_elapse=%s }\n",
2983 format_timespan(timespan1, sizeof(timespan1), value, 0),
2984 format_timespan(timespan2, sizeof(timespan2), next_elapse, 0));
2987 dbus_message_iter_next(&sub);
2992 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2993 DBusMessageIter sub, sub2;
2995 dbus_message_iter_recurse(iter, &sub);
2996 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2997 const char *controller, *attr, *value;
2999 dbus_message_iter_recurse(&sub, &sub2);
3001 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
3002 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
3003 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
3005 printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
3011 dbus_message_iter_next(&sub);
3016 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3017 DBusMessageIter sub;
3019 dbus_message_iter_recurse(iter, &sub);
3020 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3021 ExecStatusInfo info = {};
3023 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3024 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3025 char _cleanup_free_ *t;
3027 t = strv_join(info.argv, " ");
3029 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3033 yes_no(info.ignore),
3034 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3035 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3036 (unsigned) info. pid,
3037 sigchld_code_to_string(info.code),
3039 info.code == CLD_EXITED ? "" : "/",
3040 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3044 strv_free(info.argv);
3046 dbus_message_iter_next(&sub);
3055 if (generic_print_property(name, iter, arg_all) > 0)
3059 printf("%s=[unprintable]\n", name);
3064 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3065 DBusMessage _cleanup_free_ *reply = NULL;
3066 const char *interface = "";
3068 DBusMessageIter iter, sub, sub2, sub3;
3069 UnitStatusInfo info = {};
3075 r = bus_method_call_with_reply(
3077 "org.freedesktop.systemd1",
3079 "org.freedesktop.DBus.Properties",
3083 DBUS_TYPE_STRING, &interface,
3088 if (!dbus_message_iter_init(reply, &iter) ||
3089 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3090 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3091 log_error("Failed to parse reply.");
3095 dbus_message_iter_recurse(&iter, &sub);
3102 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3105 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3106 dbus_message_iter_recurse(&sub, &sub2);
3108 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3109 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3110 log_error("Failed to parse reply.");
3114 dbus_message_iter_recurse(&sub2, &sub3);
3116 if (show_properties)
3117 r = print_property(name, &sub3);
3119 r = status_property(name, &sub3, &info);
3121 log_error("Failed to parse reply.");
3125 dbus_message_iter_next(&sub);
3130 if (!show_properties) {
3131 if (streq(verb, "help"))
3132 show_unit_help(&info);
3134 print_status_info(&info);
3137 strv_free(info.documentation);
3138 strv_free(info.dropin_paths);
3139 strv_free(info.listen);
3141 if (!streq_ptr(info.active_state, "active") &&
3142 !streq_ptr(info.active_state, "reloading") &&
3143 streq(verb, "status"))
3144 /* According to LSB: "program not running" */
3147 while ((p = info.exec)) {
3148 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3149 exec_status_info_free(p);
3155 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3156 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3157 const char *path = NULL;
3158 DBusError _cleanup_dbus_error_free_ error;
3161 dbus_error_init(&error);
3163 r = bus_method_call_with_reply(
3165 "org.freedesktop.systemd1",
3166 "/org/freedesktop/systemd1",
3167 "org.freedesktop.systemd1.Manager",
3171 DBUS_TYPE_UINT32, &pid,
3176 if (!dbus_message_get_args(reply, &error,
3177 DBUS_TYPE_OBJECT_PATH, &path,
3178 DBUS_TYPE_INVALID)) {
3179 log_error("Failed to parse reply: %s", bus_error_message(&error));
3183 r = show_one(verb, bus, path, false, new_line);
3187 static int show_all(const char* verb, DBusConnection *bus, bool show_properties, bool *new_line) {
3188 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3189 _cleanup_free_ struct unit_info *unit_infos = NULL;
3191 const struct unit_info *u;
3194 r = get_unit_list(bus, &reply, &unit_infos, &c);
3198 for (u = unit_infos; u < unit_infos + c; u++) {
3199 char _cleanup_free_ *p = NULL;
3201 if (!output_show_unit(u))
3204 p = unit_dbus_path_from_name(u->id);
3208 printf("%s -> '%s'\n", u->id, p);
3210 r = show_one(verb, bus, p, show_properties, new_line);
3218 static int show(DBusConnection *bus, char **args) {
3220 bool show_properties, show_status, new_line = false;
3226 show_properties = streq(args[0], "show");
3227 show_status = streq(args[0], "status");
3229 if (show_properties)
3230 pager_open_if_enabled();
3232 /* If no argument is specified inspect the manager itself */
3234 if (show_properties && strv_length(args) <= 1)
3235 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3237 if (show_status && strv_length(args) <= 1)
3238 return show_all(args[0], bus, false, &new_line);
3240 STRV_FOREACH(name, args+1) {
3243 if (safe_atou32(*name, &id) < 0) {
3244 _cleanup_free_ char *p = NULL, *n = NULL;
3245 /* Interpret as unit name */
3247 n = unit_name_mangle(*name);
3251 p = unit_dbus_path_from_name(n);
3255 r = show_one(args[0], bus, p, show_properties, &new_line);
3259 } else if (show_properties) {
3260 _cleanup_free_ char *p = NULL;
3262 /* Interpret as job id */
3263 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3266 r = show_one(args[0], bus, p, show_properties, &new_line);
3271 /* Interpret as PID */
3272 r = show_one_by_pid(args[0], bus, id, &new_line);
3281 static int dump(DBusConnection *bus, char **args) {
3282 _cleanup_free_ DBusMessage *reply = NULL;
3287 dbus_error_init(&error);
3289 pager_open_if_enabled();
3291 r = bus_method_call_with_reply(
3293 "org.freedesktop.systemd1",
3294 "/org/freedesktop/systemd1",
3295 "org.freedesktop.systemd1.Manager",
3303 if (!dbus_message_get_args(reply, &error,
3304 DBUS_TYPE_STRING, &text,
3305 DBUS_TYPE_INVALID)) {
3306 log_error("Failed to parse reply: %s", bus_error_message(&error));
3307 dbus_error_free(&error);
3311 fputs(text, stdout);
3315 static int snapshot(DBusConnection *bus, char **args) {
3316 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3319 dbus_bool_t cleanup = FALSE;
3320 DBusMessageIter iter, sub;
3323 *interface = "org.freedesktop.systemd1.Unit",
3325 _cleanup_free_ char *n = NULL;
3327 dbus_error_init(&error);
3329 if (strv_length(args) > 1)
3330 n = snapshot_name_mangle(args[1]);
3336 r = bus_method_call_with_reply (
3338 "org.freedesktop.systemd1",
3339 "/org/freedesktop/systemd1",
3340 "org.freedesktop.systemd1.Manager",
3344 DBUS_TYPE_STRING, &n,
3345 DBUS_TYPE_BOOLEAN, &cleanup,
3350 if (!dbus_message_get_args(reply, &error,
3351 DBUS_TYPE_OBJECT_PATH, &path,
3352 DBUS_TYPE_INVALID)) {
3353 log_error("Failed to parse reply: %s", bus_error_message(&error));
3354 dbus_error_free(&error);
3358 dbus_message_unref(reply);
3361 r = bus_method_call_with_reply (
3363 "org.freedesktop.systemd1",
3365 "org.freedesktop.DBus.Properties",
3369 DBUS_TYPE_STRING, &interface,
3370 DBUS_TYPE_STRING, &property,
3375 if (!dbus_message_iter_init(reply, &iter) ||
3376 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3377 log_error("Failed to parse reply.");
3381 dbus_message_iter_recurse(&iter, &sub);
3383 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3384 log_error("Failed to parse reply.");
3388 dbus_message_iter_get_basic(&sub, &id);
3396 static int delete_snapshot(DBusConnection *bus, char **args) {
3401 STRV_FOREACH(name, args+1) {
3402 _cleanup_free_ char *n = NULL;
3405 n = snapshot_name_mangle(*name);
3409 r = bus_method_call_with_reply(
3411 "org.freedesktop.systemd1",
3412 "/org/freedesktop/systemd1",
3413 "org.freedesktop.systemd1.Manager",
3417 DBUS_TYPE_STRING, &n,
3426 static int daemon_reload(DBusConnection *bus, char **args) {
3431 if (arg_action == ACTION_RELOAD)
3433 else if (arg_action == ACTION_REEXEC)
3434 method = "Reexecute";
3436 assert(arg_action == ACTION_SYSTEMCTL);
3439 streq(args[0], "clear-jobs") ||
3440 streq(args[0], "cancel") ? "ClearJobs" :
3441 streq(args[0], "daemon-reexec") ? "Reexecute" :
3442 streq(args[0], "reset-failed") ? "ResetFailed" :
3443 streq(args[0], "halt") ? "Halt" :
3444 streq(args[0], "poweroff") ? "PowerOff" :
3445 streq(args[0], "reboot") ? "Reboot" :
3446 streq(args[0], "kexec") ? "KExec" :
3447 streq(args[0], "exit") ? "Exit" :
3448 /* "daemon-reload" */ "Reload";
3451 r = bus_method_call_with_reply(
3453 "org.freedesktop.systemd1",
3454 "/org/freedesktop/systemd1",
3455 "org.freedesktop.systemd1.Manager",
3461 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3462 /* There's always a fallback possible for
3463 * legacy actions. */
3465 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3466 /* On reexecution, we expect a disconnect, not
3470 log_error("Failed to issue method call: %s", bus_error_message(&error));
3472 dbus_error_free(&error);
3476 static int reset_failed(DBusConnection *bus, char **args) {
3480 if (strv_length(args) <= 1)
3481 return daemon_reload(bus, args);
3483 STRV_FOREACH(name, args+1) {
3484 _cleanup_free_ char *n;
3486 n = unit_name_mangle(*name);
3490 r = bus_method_call_with_reply(
3492 "org.freedesktop.systemd1",
3493 "/org/freedesktop/systemd1",
3494 "org.freedesktop.systemd1.Manager",
3498 DBUS_TYPE_STRING, &n,
3507 static int show_enviroment(DBusConnection *bus, char **args) {
3508 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3509 DBusMessageIter iter, sub, sub2;
3512 *interface = "org.freedesktop.systemd1.Manager",
3513 *property = "Environment";
3515 pager_open_if_enabled();
3517 r = bus_method_call_with_reply(
3519 "org.freedesktop.systemd1",
3520 "/org/freedesktop/systemd1",
3521 "org.freedesktop.DBus.Properties",
3525 DBUS_TYPE_STRING, &interface,
3526 DBUS_TYPE_STRING, &property,
3531 if (!dbus_message_iter_init(reply, &iter) ||
3532 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3533 log_error("Failed to parse reply.");
3537 dbus_message_iter_recurse(&iter, &sub);
3539 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3540 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3541 log_error("Failed to parse reply.");
3545 dbus_message_iter_recurse(&sub, &sub2);
3547 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3550 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3551 log_error("Failed to parse reply.");
3555 dbus_message_iter_get_basic(&sub2, &text);
3558 dbus_message_iter_next(&sub2);
3564 static int switch_root(DBusConnection *bus, char **args) {
3567 _cleanup_free_ char *init = NULL;
3569 l = strv_length(args);
3570 if (l < 2 || l > 3) {
3571 log_error("Wrong number of arguments.");
3578 init = strdup(args[2]);
3580 parse_env_file("/proc/cmdline", WHITESPACE,
3590 log_debug("switching root - root: %s; init: %s", root, init);
3592 return bus_method_call_with_reply(
3594 "org.freedesktop.systemd1",
3595 "/org/freedesktop/systemd1",
3596 "org.freedesktop.systemd1.Manager",
3600 DBUS_TYPE_STRING, &root,
3601 DBUS_TYPE_STRING, &init,
3605 static int set_environment(DBusConnection *bus, char **args) {
3606 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3609 DBusMessageIter iter;
3615 dbus_error_init(&error);
3617 method = streq(args[0], "set-environment")
3619 : "UnsetEnvironment";
3621 m = dbus_message_new_method_call(
3622 "org.freedesktop.systemd1",
3623 "/org/freedesktop/systemd1",
3624 "org.freedesktop.systemd1.Manager",
3629 dbus_message_iter_init_append(m, &iter);
3631 r = bus_append_strv_iter(&iter, args + 1);
3635 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3637 log_error("Failed to issue method call: %s", bus_error_message(&error));
3638 dbus_error_free(&error);
3645 static int enable_sysv_units(char **args) {
3648 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3649 const char *verb = args[0];
3650 unsigned f = 1, t = 1;
3651 LookupPaths paths = {};
3653 if (arg_scope != UNIT_FILE_SYSTEM)
3656 if (!streq(verb, "enable") &&
3657 !streq(verb, "disable") &&
3658 !streq(verb, "is-enabled"))
3661 /* Processes all SysV units, and reshuffles the array so that
3662 * afterwards only the native units remain */
3664 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3669 for (f = 1; args[f]; f++) {
3672 bool found_native = false, found_sysv;
3674 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3675 char **k, *l, *q = NULL;
3682 if (!endswith(name, ".service"))
3685 if (path_is_absolute(name))
3688 STRV_FOREACH(k, paths.unit_path) {
3691 if (!isempty(arg_root))
3692 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3694 asprintf(&p, "%s/%s", *k, name);
3701 found_native = access(p, F_OK) >= 0;
3712 if (!isempty(arg_root))
3713 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3715 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3721 p[strlen(p) - sizeof(".service") + 1] = 0;
3722 found_sysv = access(p, F_OK) >= 0;
3729 /* Mark this entry, so that we don't try enabling it as native unit */
3730 args[f] = (char*) "";
3732 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3734 if (!isempty(arg_root))
3735 argv[c++] = q = strappend("--root=", arg_root);
3737 argv[c++] = path_get_file_name(p);
3739 streq(verb, "enable") ? "on" :
3740 streq(verb, "disable") ? "off" : "--level=5";
3743 l = strv_join((char**)argv, " ");
3751 log_info("Executing %s", l);
3756 log_error("Failed to fork: %m");
3761 } else if (pid == 0) {
3764 execv(argv[0], (char**) argv);
3765 _exit(EXIT_FAILURE);
3771 j = wait_for_terminate(pid, &status);
3773 log_error("Failed to wait for child: %s", strerror(-r));
3778 if (status.si_code == CLD_EXITED) {
3779 if (streq(verb, "is-enabled")) {
3780 if (status.si_status == 0) {
3789 } else if (status.si_status != 0) {
3800 lookup_paths_free(&paths);
3802 /* Drop all SysV units */
3803 for (f = 1, t = 1; args[f]; f++) {
3805 if (isempty(args[f]))
3808 args[t++] = args[f];
3817 static int mangle_names(char **original_names, char ***mangled_names) {
3818 char **i, **l, **name;
3820 l = new(char*, strv_length(original_names) + 1);
3825 STRV_FOREACH(name, original_names) {
3827 /* When enabling units qualified path names are OK,
3828 * too, hence allow them explicitly. */
3833 *i = unit_name_mangle(*name);
3849 static int enable_unit(DBusConnection *bus, char **args) {
3850 const char *verb = args[0];
3851 UnitFileChange *changes = NULL;
3852 unsigned n_changes = 0, i;
3853 int carries_install_info = -1;
3854 DBusMessage _cleanup_dbus_message_unref_ *m = NULL, *reply = NULL;
3856 DBusError _cleanup_dbus_error_free_ error;
3857 char _cleanup_strv_free_ **mangled_names = NULL;
3859 dbus_error_init(&error);
3861 r = enable_sysv_units(args);
3868 if (!bus || avoid_bus()) {
3869 if (streq(verb, "enable")) {
3870 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3871 carries_install_info = r;
3872 } else if (streq(verb, "disable"))
3873 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3874 else if (streq(verb, "reenable")) {
3875 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3876 carries_install_info = r;
3877 } else if (streq(verb, "link"))
3878 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3879 else if (streq(verb, "preset")) {
3880 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3881 carries_install_info = r;
3882 } else if (streq(verb, "mask"))
3883 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3884 else if (streq(verb, "unmask"))
3885 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3887 assert_not_reached("Unknown verb");
3890 log_error("Operation failed: %s", strerror(-r));
3895 for (i = 0; i < n_changes; i++) {
3896 if (changes[i].type == UNIT_FILE_SYMLINK)
3897 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3899 log_info("rm '%s'", changes[i].path);
3906 bool send_force = true, expect_carries_install_info = false;
3908 DBusMessageIter iter, sub, sub2;
3910 if (streq(verb, "enable")) {
3911 method = "EnableUnitFiles";
3912 expect_carries_install_info = true;
3913 } else if (streq(verb, "disable")) {
3914 method = "DisableUnitFiles";
3916 } else if (streq(verb, "reenable")) {
3917 method = "ReenableUnitFiles";
3918 expect_carries_install_info = true;
3919 } else if (streq(verb, "link"))
3920 method = "LinkUnitFiles";
3921 else if (streq(verb, "preset")) {
3922 method = "PresetUnitFiles";
3923 expect_carries_install_info = true;
3924 } else if (streq(verb, "mask"))
3925 method = "MaskUnitFiles";
3926 else if (streq(verb, "unmask")) {
3927 method = "UnmaskUnitFiles";
3930 assert_not_reached("Unknown verb");
3932 m = dbus_message_new_method_call(
3933 "org.freedesktop.systemd1",
3934 "/org/freedesktop/systemd1",
3935 "org.freedesktop.systemd1.Manager",
3942 dbus_message_iter_init_append(m, &iter);
3944 r = mangle_names(args+1, &mangled_names);
3948 r = bus_append_strv_iter(&iter, mangled_names);
3950 log_error("Failed to append unit files.");
3955 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3956 log_error("Failed to append runtime boolean.");
3964 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3965 log_error("Failed to append force boolean.");
3971 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3973 log_error("Failed to issue method call: %s", bus_error_message(&error));
3978 if (!dbus_message_iter_init(reply, &iter)) {
3979 log_error("Failed to initialize iterator.");
3983 if (expect_carries_install_info) {
3984 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3986 log_error("Failed to parse reply.");
3990 carries_install_info = b;
3993 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3994 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3995 log_error("Failed to parse reply.");
4000 dbus_message_iter_recurse(&iter, &sub);
4001 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4002 const char *type, *path, *source;
4004 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4005 log_error("Failed to parse reply.");
4010 dbus_message_iter_recurse(&sub, &sub2);
4012 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4013 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4014 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4015 log_error("Failed to parse reply.");
4021 if (streq(type, "symlink"))
4022 log_info("ln -s '%s' '%s'", source, path);
4024 log_info("rm '%s'", path);
4027 dbus_message_iter_next(&sub);
4030 /* Try to reload if enabeld */
4032 r = daemon_reload(bus, args);
4035 if (carries_install_info == 0)
4036 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
4037 "using systemctl.\n"
4038 "Possible reasons for having this kind of units are:\n"
4039 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4040 " .wants/ or .requires/ directory.\n"
4041 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4042 " a requirement dependency on it.\n"
4043 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4044 " D-Bus, udev, scripted systemctl call, ...).\n");
4047 unit_file_changes_free(changes, n_changes);
4052 static int unit_is_enabled(DBusConnection *bus, char **args) {
4053 DBusError _cleanup_dbus_error_free_ error;
4055 DBusMessage _cleanup_dbus_message_unref_ *reply = NULL;
4060 dbus_error_init(&error);
4062 r = enable_sysv_units(args);
4068 if (!bus || avoid_bus()) {
4070 STRV_FOREACH(name, args+1) {
4071 UnitFileState state;
4073 n = unit_name_mangle(*name);
4077 state = unit_file_get_state(arg_scope, arg_root, n);
4084 if (state == UNIT_FILE_ENABLED ||
4085 state == UNIT_FILE_ENABLED_RUNTIME ||
4086 state == UNIT_FILE_STATIC)
4090 puts(unit_file_state_to_string(state));
4094 STRV_FOREACH(name, args+1) {
4097 n = unit_name_mangle(*name);
4101 r = bus_method_call_with_reply (
4103 "org.freedesktop.systemd1",
4104 "/org/freedesktop/systemd1",
4105 "org.freedesktop.systemd1.Manager",
4109 DBUS_TYPE_STRING, &n,
4117 if (!dbus_message_get_args(reply, &error,
4118 DBUS_TYPE_STRING, &s,
4119 DBUS_TYPE_INVALID)) {
4120 log_error("Failed to parse reply: %s", bus_error_message(&error));
4124 dbus_message_unref(reply);
4127 if (streq(s, "enabled") ||
4128 streq(s, "enabled-runtime") ||
4137 return enabled ? 0 : 1;
4140 static int systemctl_help(void) {
4142 pager_open_if_enabled();
4144 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4145 "Query or send control commands to the systemd manager.\n\n"
4146 " -h --help Show this help\n"
4147 " --version Show package version\n"
4148 " -t --type=TYPE List only units of a particular type\n"
4149 " -p --property=NAME Show only properties by this name\n"
4150 " -a --all Show all units/properties, including dead/empty ones\n"
4151 " --failed Show only failed units\n"
4152 " --full Don't ellipsize unit names on output\n"
4153 " --fail When queueing a new job, fail if conflicting jobs are\n"
4155 " --ignore-dependencies\n"
4156 " When queueing a new job, ignore all its dependencies\n"
4157 " -i --ignore-inhibitors\n"
4158 " When shutting down or sleeping, ignore inhibitors\n"
4159 " --kill-who=WHO Who to send signal to\n"
4160 " -s --signal=SIGNAL Which signal to send\n"
4161 " -H --host=[USER@]HOST\n"
4162 " Show information for remote host\n"
4163 " -P --privileged Acquire privileges before execution\n"
4164 " -q --quiet Suppress output\n"
4165 " --no-block Do not wait until operation finished\n"
4166 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4167 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4169 " --no-legend Do not print a legend (column headers and hints)\n"
4170 " --no-pager Do not pipe output into a pager\n"
4171 " --no-ask-password\n"
4172 " Do not ask for system passwords\n"
4173 " --system Connect to system manager\n"
4174 " --user Connect to user service manager\n"
4175 " --global Enable/disable unit files globally\n"
4176 " -f --force When enabling unit files, override existing symlinks\n"
4177 " When shutting down, execute action immediately\n"
4178 " --root=PATH Enable unit files in the specified root directory\n"
4179 " --runtime Enable unit files only temporarily until next reboot\n"
4180 " -n --lines=INTEGER Journal entries to show\n"
4181 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4182 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4184 " list-units List loaded units\n"
4185 " start [NAME...] Start (activate) one or more units\n"
4186 " stop [NAME...] Stop (deactivate) one or more units\n"
4187 " reload [NAME...] Reload one or more units\n"
4188 " restart [NAME...] Start or restart one or more units\n"
4189 " try-restart [NAME...] Restart one or more units if active\n"
4190 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4191 " otherwise start or restart\n"
4192 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4193 " otherwise restart if active\n"
4194 " isolate [NAME] Start one unit and stop all others\n"
4195 " kill [NAME...] Send signal to processes of a unit\n"
4196 " is-active [NAME...] Check whether units are active\n"
4197 " is-failed [NAME...] Check whether units are failed\n"
4198 " status [NAME...|PID...] Show runtime status of one or more units\n"
4199 " show [NAME...|JOB...] Show properties of one or more\n"
4200 " units/jobs or the manager\n"
4201 " help [NAME...|PID...] Show manual for one or more units\n"
4202 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4204 " get-cgroup-attr [NAME] [ATTR] ...\n"
4205 " Get control group attrubute\n"
4206 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4207 " Set control group attribute\n"
4208 " unset-cgroup-attr [NAME] [ATTR...]\n"
4209 " Unset control group attribute\n"
4210 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4211 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4212 " load [NAME...] Load one or more units\n"
4213 " list-dependencies [NAME] Recursively show units which are required\n"
4214 " or wanted by this unit\n\n"
4215 "Unit File Commands:\n"
4216 " list-unit-files List installed unit files\n"
4217 " enable [NAME...] Enable one or more unit files\n"
4218 " disable [NAME...] Disable one or more unit files\n"
4219 " reenable [NAME...] Reenable one or more unit files\n"
4220 " preset [NAME...] Enable/disable one or more unit files\n"
4221 " based on preset configuration\n"
4222 " mask [NAME...] Mask one or more units\n"
4223 " unmask [NAME...] Unmask one or more units\n"
4224 " link [PATH...] Link one or more units files into\n"
4225 " the search path\n"
4226 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4228 " list-jobs List jobs\n"
4229 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4230 "Status Commands:\n"
4231 " dump Dump server status\n"
4232 "Snapshot Commands:\n"
4233 " snapshot [NAME] Create a snapshot\n"
4234 " delete [NAME...] Remove one or more snapshots\n\n"
4235 "Environment Commands:\n"
4236 " show-environment Dump environment\n"
4237 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4238 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4239 "Manager Lifecycle Commands:\n"
4240 " daemon-reload Reload systemd manager configuration\n"
4241 " daemon-reexec Reexecute systemd manager\n\n"
4242 "System Commands:\n"
4243 " default Enter system default mode\n"
4244 " rescue Enter system rescue mode\n"
4245 " emergency Enter system emergency mode\n"
4246 " halt Shut down and halt the system\n"
4247 " poweroff Shut down and power-off the system\n"
4248 " reboot Shut down and reboot the system\n"
4249 " kexec Shut down and reboot the system with kexec\n"
4250 " exit Request user instance exit\n"
4251 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4252 " suspend Suspend the system\n"
4253 " hibernate Hibernate the system\n"
4254 " hybrid-sleep Hibernate and suspend the system\n",
4255 program_invocation_short_name);
4260 static int halt_help(void) {
4262 printf("%s [OPTIONS...]\n\n"
4263 "%s the system.\n\n"
4264 " --help Show this help\n"
4265 " --halt Halt the machine\n"
4266 " -p --poweroff Switch off the machine\n"
4267 " --reboot Reboot the machine\n"
4268 " -f --force Force immediate halt/power-off/reboot\n"
4269 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4270 " -d --no-wtmp Don't write wtmp record\n"
4271 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4272 program_invocation_short_name,
4273 arg_action == ACTION_REBOOT ? "Reboot" :
4274 arg_action == ACTION_POWEROFF ? "Power off" :
4280 static int shutdown_help(void) {
4282 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4283 "Shut down the system.\n\n"
4284 " --help Show this help\n"
4285 " -H --halt Halt the machine\n"
4286 " -P --poweroff Power-off the machine\n"
4287 " -r --reboot Reboot the machine\n"
4288 " -h Equivalent to --poweroff, overridden by --halt\n"
4289 " -k Don't halt/power-off/reboot, just send warnings\n"
4290 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4291 " -c Cancel a pending shutdown\n",
4292 program_invocation_short_name);
4297 static int telinit_help(void) {
4299 printf("%s [OPTIONS...] {COMMAND}\n\n"
4300 "Send control commands to the init daemon.\n\n"
4301 " --help Show this help\n"
4302 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4304 " 0 Power-off the machine\n"
4305 " 6 Reboot the machine\n"
4306 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4307 " 1, s, S Enter rescue mode\n"
4308 " q, Q Reload init daemon configuration\n"
4309 " u, U Reexecute init daemon\n",
4310 program_invocation_short_name);
4315 static int runlevel_help(void) {
4317 printf("%s [OPTIONS...]\n\n"
4318 "Prints the previous and current runlevel of the init system.\n\n"
4319 " --help Show this help\n",
4320 program_invocation_short_name);
4325 static int help_types(void) {
4329 puts("Available unit types:");
4330 for(i = 0; i < _UNIT_TYPE_MAX; i++) {
4331 t = unit_type_to_string(i);
4336 puts("\nAvailable unit load states: ");
4337 for(i = 0; i < _UNIT_LOAD_STATE_MAX; i++) {
4338 t = unit_load_state_to_string(i);
4346 static int systemctl_parse_argv(int argc, char *argv[]) {
4351 ARG_IGNORE_DEPENDENCIES,
4364 ARG_NO_ASK_PASSWORD,
4370 static const struct option options[] = {
4371 { "help", no_argument, NULL, 'h' },
4372 { "version", no_argument, NULL, ARG_VERSION },
4373 { "type", required_argument, NULL, 't' },
4374 { "property", required_argument, NULL, 'p' },
4375 { "all", no_argument, NULL, 'a' },
4376 { "failed", no_argument, NULL, ARG_FAILED },
4377 { "full", no_argument, NULL, ARG_FULL },
4378 { "fail", no_argument, NULL, ARG_FAIL },
4379 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4380 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4381 { "ignore-inhibitors", no_argument, NULL, 'i' },
4382 { "user", no_argument, NULL, ARG_USER },
4383 { "system", no_argument, NULL, ARG_SYSTEM },
4384 { "global", no_argument, NULL, ARG_GLOBAL },
4385 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4386 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4387 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4388 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4389 { "quiet", no_argument, NULL, 'q' },
4390 { "root", required_argument, NULL, ARG_ROOT },
4391 { "force", no_argument, NULL, ARG_FORCE },
4392 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4393 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4394 { "signal", required_argument, NULL, 's' },
4395 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4396 { "host", required_argument, NULL, 'H' },
4397 { "privileged",no_argument, NULL, 'P' },
4398 { "runtime", no_argument, NULL, ARG_RUNTIME },
4399 { "lines", required_argument, NULL, 'n' },
4400 { "output", required_argument, NULL, 'o' },
4401 { NULL, 0, NULL, 0 }
4409 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4418 puts(PACKAGE_STRING);
4419 puts(SYSTEMD_FEATURES);
4423 if (streq(optarg, "help")) {
4428 if (unit_type_from_string(optarg) >= 0) {
4432 if (unit_load_state_from_string(optarg) >= 0) {
4433 arg_load_state = optarg;
4436 log_error("Unkown unit type or load state '%s'.",
4438 log_info("Use -t help to see a list of allowed values.");
4443 /* Make sure that if the empty property list
4444 was specified, we won't show any properties. */
4445 const char *source = isempty(optarg) ? " " : optarg;
4447 FOREACH_WORD_SEPARATOR(word, size, source, ",", state) {
4448 char _cleanup_free_ *prop;
4451 prop = strndup(word, size);
4455 tmp = strv_append(arg_property, prop);
4459 strv_free(arg_property);
4463 /* If the user asked for a particular
4464 * property, show it to him, even if it is
4476 arg_job_mode = "fail";
4479 case ARG_IRREVERSIBLE:
4480 arg_job_mode = "replace-irreversibly";
4483 case ARG_IGNORE_DEPENDENCIES:
4484 arg_job_mode = "ignore-dependencies";
4488 arg_scope = UNIT_FILE_USER;
4492 arg_scope = UNIT_FILE_SYSTEM;
4496 arg_scope = UNIT_FILE_GLOBAL;
4500 arg_no_block = true;
4504 arg_no_legend = true;
4508 arg_no_pager = true;
4540 arg_no_reload = true;
4544 arg_kill_who = optarg;
4548 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4549 log_error("Failed to parse signal string %s.", optarg);
4554 case ARG_NO_ASK_PASSWORD:
4555 arg_ask_password = false;
4559 arg_transport = TRANSPORT_POLKIT;
4563 arg_transport = TRANSPORT_SSH;
4572 if (safe_atou(optarg, &arg_lines) < 0) {
4573 log_error("Failed to parse lines '%s'", optarg);
4579 arg_output = output_mode_from_string(optarg);
4580 if (arg_output < 0) {
4581 log_error("Unknown output '%s'.", optarg);
4587 arg_ignore_inhibitors = true;
4594 log_error("Unknown option code '%c'.", c);
4599 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4600 log_error("Cannot access user instance remotely.");
4607 static int halt_parse_argv(int argc, char *argv[]) {
4616 static const struct option options[] = {
4617 { "help", no_argument, NULL, ARG_HELP },
4618 { "halt", no_argument, NULL, ARG_HALT },
4619 { "poweroff", no_argument, NULL, 'p' },
4620 { "reboot", no_argument, NULL, ARG_REBOOT },
4621 { "force", no_argument, NULL, 'f' },
4622 { "wtmp-only", no_argument, NULL, 'w' },
4623 { "no-wtmp", no_argument, NULL, 'd' },
4624 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4625 { NULL, 0, NULL, 0 }
4633 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4634 if (runlevel == '0' || runlevel == '6')
4637 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4645 arg_action = ACTION_HALT;
4649 if (arg_action != ACTION_REBOOT)
4650 arg_action = ACTION_POWEROFF;
4654 arg_action = ACTION_REBOOT;
4676 /* Compatibility nops */
4683 log_error("Unknown option code '%c'.", c);
4688 if (optind < argc) {
4689 log_error("Too many arguments.");
4696 static int parse_time_spec(const char *t, usec_t *_u) {
4700 if (streq(t, "now"))
4702 else if (!strchr(t, ':')) {
4705 if (safe_atou64(t, &u) < 0)
4708 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4717 hour = strtol(t, &e, 10);
4718 if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
4721 minute = strtol(e+1, &e, 10);
4722 if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
4725 n = now(CLOCK_REALTIME);
4726 s = (time_t) (n / USEC_PER_SEC);
4728 assert_se(localtime_r(&s, &tm));
4730 tm.tm_hour = (int) hour;
4731 tm.tm_min = (int) minute;
4734 assert_se(s = mktime(&tm));
4736 *_u = (usec_t) s * USEC_PER_SEC;
4739 *_u += USEC_PER_DAY;
4745 static int shutdown_parse_argv(int argc, char *argv[]) {
4752 static const struct option options[] = {
4753 { "help", no_argument, NULL, ARG_HELP },
4754 { "halt", no_argument, NULL, 'H' },
4755 { "poweroff", no_argument, NULL, 'P' },
4756 { "reboot", no_argument, NULL, 'r' },
4757 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4758 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4759 { NULL, 0, NULL, 0 }
4767 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4775 arg_action = ACTION_HALT;
4779 arg_action = ACTION_POWEROFF;
4784 arg_action = ACTION_KEXEC;
4786 arg_action = ACTION_REBOOT;
4790 arg_action = ACTION_KEXEC;
4794 if (arg_action != ACTION_HALT)
4795 arg_action = ACTION_POWEROFF;
4808 /* Compatibility nops */
4812 arg_action = ACTION_CANCEL_SHUTDOWN;
4819 log_error("Unknown option code '%c'.", c);
4824 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4825 r = parse_time_spec(argv[optind], &arg_when);
4827 log_error("Failed to parse time specification: %s", argv[optind]);
4831 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4833 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4834 /* No time argument for shutdown cancel */
4835 arg_wall = argv + optind;
4836 else if (argc > optind + 1)
4837 /* We skip the time argument */
4838 arg_wall = argv + optind + 1;
4845 static int telinit_parse_argv(int argc, char *argv[]) {
4852 static const struct option options[] = {
4853 { "help", no_argument, NULL, ARG_HELP },
4854 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4855 { NULL, 0, NULL, 0 }
4858 static const struct {
4862 { '0', ACTION_POWEROFF },
4863 { '6', ACTION_REBOOT },
4864 { '1', ACTION_RESCUE },
4865 { '2', ACTION_RUNLEVEL2 },
4866 { '3', ACTION_RUNLEVEL3 },
4867 { '4', ACTION_RUNLEVEL4 },
4868 { '5', ACTION_RUNLEVEL5 },
4869 { 's', ACTION_RESCUE },
4870 { 'S', ACTION_RESCUE },
4871 { 'q', ACTION_RELOAD },
4872 { 'Q', ACTION_RELOAD },
4873 { 'u', ACTION_REEXEC },
4874 { 'U', ACTION_REEXEC }
4883 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4898 log_error("Unknown option code '%c'.", c);
4903 if (optind >= argc) {
4908 if (optind + 1 < argc) {
4909 log_error("Too many arguments.");
4913 if (strlen(argv[optind]) != 1) {
4914 log_error("Expected single character argument.");
4918 for (i = 0; i < ELEMENTSOF(table); i++)
4919 if (table[i].from == argv[optind][0])
4922 if (i >= ELEMENTSOF(table)) {
4923 log_error("Unknown command '%s'.", argv[optind]);
4927 arg_action = table[i].to;
4934 static int runlevel_parse_argv(int argc, char *argv[]) {
4940 static const struct option options[] = {
4941 { "help", no_argument, NULL, ARG_HELP },
4942 { NULL, 0, NULL, 0 }
4950 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4961 log_error("Unknown option code '%c'.", c);
4966 if (optind < argc) {
4967 log_error("Too many arguments.");
4974 static int parse_argv(int argc, char *argv[]) {
4978 if (program_invocation_short_name) {
4980 if (strstr(program_invocation_short_name, "halt")) {
4981 arg_action = ACTION_HALT;
4982 return halt_parse_argv(argc, argv);
4983 } else if (strstr(program_invocation_short_name, "poweroff")) {
4984 arg_action = ACTION_POWEROFF;
4985 return halt_parse_argv(argc, argv);
4986 } else if (strstr(program_invocation_short_name, "reboot")) {
4988 arg_action = ACTION_KEXEC;
4990 arg_action = ACTION_REBOOT;
4991 return halt_parse_argv(argc, argv);
4992 } else if (strstr(program_invocation_short_name, "shutdown")) {
4993 arg_action = ACTION_POWEROFF;
4994 return shutdown_parse_argv(argc, argv);
4995 } else if (strstr(program_invocation_short_name, "init")) {
4997 if (sd_booted() > 0) {
4998 arg_action = ACTION_INVALID;
4999 return telinit_parse_argv(argc, argv);
5001 /* Hmm, so some other init system is
5002 * running, we need to forward this
5003 * request to it. For now we simply
5004 * guess that it is Upstart. */
5006 execv(TELINIT, argv);
5008 log_error("Couldn't find an alternative telinit implementation to spawn.");
5012 } else if (strstr(program_invocation_short_name, "runlevel")) {
5013 arg_action = ACTION_RUNLEVEL;
5014 return runlevel_parse_argv(argc, argv);
5018 arg_action = ACTION_SYSTEMCTL;
5019 return systemctl_parse_argv(argc, argv);
5022 static int action_to_runlevel(void) {
5024 static const char table[_ACTION_MAX] = {
5025 [ACTION_HALT] = '0',
5026 [ACTION_POWEROFF] = '0',
5027 [ACTION_REBOOT] = '6',
5028 [ACTION_RUNLEVEL2] = '2',
5029 [ACTION_RUNLEVEL3] = '3',
5030 [ACTION_RUNLEVEL4] = '4',
5031 [ACTION_RUNLEVEL5] = '5',
5032 [ACTION_RESCUE] = '1'
5035 assert(arg_action < _ACTION_MAX);
5037 return table[arg_action];
5040 static int talk_upstart(void) {
5041 DBusMessage _cleanup_dbus_message_unref_ *m = NULL, *reply = NULL;
5042 DBusError _cleanup_dbus_error_free_ error;
5043 int previous, rl, r;
5045 env1_buf[] = "RUNLEVEL=X",
5046 env2_buf[] = "PREVLEVEL=X";
5047 char *env1 = env1_buf, *env2 = env2_buf;
5048 const char *emit = "runlevel";
5049 dbus_bool_t b_false = FALSE;
5050 DBusMessageIter iter, sub;
5051 DBusConnection *bus;
5053 dbus_error_init(&error);
5055 if (!(rl = action_to_runlevel()))
5058 if (utmp_get_runlevel(&previous, NULL) < 0)
5061 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5062 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5067 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5072 if ((r = bus_check_peercred(bus)) < 0) {
5073 log_error("Failed to verify owner of bus.");
5077 if (!(m = dbus_message_new_method_call(
5078 "com.ubuntu.Upstart",
5079 "/com/ubuntu/Upstart",
5080 "com.ubuntu.Upstart0_6",
5083 log_error("Could not allocate message.");
5088 dbus_message_iter_init_append(m, &iter);
5090 env1_buf[sizeof(env1_buf)-2] = rl;
5091 env2_buf[sizeof(env2_buf)-2] = previous;
5093 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5094 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5095 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5096 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5097 !dbus_message_iter_close_container(&iter, &sub) ||
5098 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5099 log_error("Could not append arguments to message.");
5104 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5106 if (bus_error_is_no_service(&error)) {
5111 log_error("Failed to issue method call: %s", bus_error_message(&error));
5120 dbus_connection_flush(bus);
5121 dbus_connection_close(bus);
5122 dbus_connection_unref(bus);
5128 static int talk_initctl(void) {
5129 struct init_request request = {};
5131 int _cleanup_close_ fd = -1;
5134 rl = action_to_runlevel();
5138 request.magic = INIT_MAGIC;
5139 request.sleeptime = 0;
5140 request.cmd = INIT_CMD_RUNLVL;
5141 request.runlevel = rl;
5143 fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
5145 if (errno == ENOENT)
5148 log_error("Failed to open "INIT_FIFO": %m");
5153 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5155 log_error("Failed to write to "INIT_FIFO": %m");
5156 return errno ? -errno : -EIO;
5162 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5164 static const struct {
5172 int (* const dispatch)(DBusConnection *bus, char **args);
5174 { "list-units", LESS, 1, list_units },
5175 { "list-unit-files", EQUAL, 1, list_unit_files },
5176 { "list-jobs", EQUAL, 1, list_jobs },
5177 { "clear-jobs", EQUAL, 1, daemon_reload },
5178 { "load", MORE, 2, load_unit },
5179 { "cancel", MORE, 2, cancel_job },
5180 { "start", MORE, 2, start_unit },
5181 { "stop", MORE, 2, start_unit },
5182 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5183 { "reload", MORE, 2, start_unit },
5184 { "restart", MORE, 2, start_unit },
5185 { "try-restart", MORE, 2, start_unit },
5186 { "reload-or-restart", MORE, 2, start_unit },
5187 { "reload-or-try-restart", MORE, 2, start_unit },
5188 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5189 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5190 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5191 { "isolate", EQUAL, 2, start_unit },
5192 { "set-cgroup", MORE, 3, set_cgroup },
5193 { "unset-cgroup", MORE, 3, set_cgroup },
5194 { "get-cgroup-attr", MORE, 3, get_cgroup_attr },
5195 { "set-cgroup-attr", MORE, 4, set_cgroup_attr },
5196 { "unset-cgroup-attr", MORE, 3, set_cgroup },
5197 { "kill", MORE, 2, kill_unit },
5198 { "is-active", MORE, 2, check_unit_active },
5199 { "check", MORE, 2, check_unit_active },
5200 { "is-failed", MORE, 2, check_unit_failed },
5201 { "show", MORE, 1, show },
5202 { "status", MORE, 1, show },
5203 { "help", MORE, 2, show },
5204 { "dump", EQUAL, 1, dump },
5205 { "snapshot", LESS, 2, snapshot },
5206 { "delete", MORE, 2, delete_snapshot },
5207 { "daemon-reload", EQUAL, 1, daemon_reload },
5208 { "daemon-reexec", EQUAL, 1, daemon_reload },
5209 { "show-environment", EQUAL, 1, show_enviroment },
5210 { "set-environment", MORE, 2, set_environment },
5211 { "unset-environment", MORE, 2, set_environment },
5212 { "halt", EQUAL, 1, start_special },
5213 { "poweroff", EQUAL, 1, start_special },
5214 { "reboot", EQUAL, 1, start_special },
5215 { "kexec", EQUAL, 1, start_special },
5216 { "suspend", EQUAL, 1, start_special },
5217 { "hibernate", EQUAL, 1, start_special },
5218 { "hybrid-sleep", EQUAL, 1, start_special },
5219 { "default", EQUAL, 1, start_special },
5220 { "rescue", EQUAL, 1, start_special },
5221 { "emergency", EQUAL, 1, start_special },
5222 { "exit", EQUAL, 1, start_special },
5223 { "reset-failed", MORE, 1, reset_failed },
5224 { "enable", MORE, 2, enable_unit },
5225 { "disable", MORE, 2, enable_unit },
5226 { "is-enabled", MORE, 2, unit_is_enabled },
5227 { "reenable", MORE, 2, enable_unit },
5228 { "preset", MORE, 2, enable_unit },
5229 { "mask", MORE, 2, enable_unit },
5230 { "unmask", MORE, 2, enable_unit },
5231 { "link", MORE, 2, enable_unit },
5232 { "switch-root", MORE, 2, switch_root },
5233 { "list-dependencies", LESS, 2, list_dependencies },
5243 left = argc - optind;
5246 /* Special rule: no arguments means "list-units" */
5249 if (streq(argv[optind], "help") && !argv[optind+1]) {
5250 log_error("This command expects one or more "
5251 "unit names. Did you mean --help?");
5255 for (i = 0; i < ELEMENTSOF(verbs); i++)
5256 if (streq(argv[optind], verbs[i].verb))
5259 if (i >= ELEMENTSOF(verbs)) {
5260 log_error("Unknown operation '%s'.", argv[optind]);
5265 switch (verbs[i].argc_cmp) {
5268 if (left != verbs[i].argc) {
5269 log_error("Invalid number of arguments.");
5276 if (left < verbs[i].argc) {
5277 log_error("Too few arguments.");
5284 if (left > verbs[i].argc) {
5285 log_error("Too many arguments.");
5292 assert_not_reached("Unknown comparison operator.");
5295 /* Require a bus connection for all operations but
5297 if (!streq(verbs[i].verb, "enable") &&
5298 !streq(verbs[i].verb, "disable") &&
5299 !streq(verbs[i].verb, "is-enabled") &&
5300 !streq(verbs[i].verb, "list-unit-files") &&
5301 !streq(verbs[i].verb, "reenable") &&
5302 !streq(verbs[i].verb, "preset") &&
5303 !streq(verbs[i].verb, "mask") &&
5304 !streq(verbs[i].verb, "unmask") &&
5305 !streq(verbs[i].verb, "link")) {
5307 if (running_in_chroot() > 0) {
5308 log_info("Running in chroot, ignoring request.");
5312 if (((!streq(verbs[i].verb, "reboot") &&
5313 !streq(verbs[i].verb, "halt") &&
5314 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5315 log_error("Failed to get D-Bus connection: %s",
5316 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5322 if (!bus && !avoid_bus()) {
5323 log_error("Failed to get D-Bus connection: %s",
5324 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5329 return verbs[i].dispatch(bus, argv + optind);
5332 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5333 int _cleanup_close_ fd;
5334 struct sd_shutdown_command c = {
5340 union sockaddr_union sockaddr = {
5341 .un.sun_family = AF_UNIX,
5342 .un.sun_path = "/run/systemd/shutdownd",
5344 struct iovec iovec[2] = {
5345 {.iov_base = (char*) &c,
5346 .iov_len = offsetof(struct sd_shutdown_command, wall_message),
5349 struct msghdr msghdr = {
5350 .msg_name = &sockaddr,
5351 .msg_namelen = offsetof(struct sockaddr_un, sun_path)
5352 + sizeof("/run/systemd/shutdownd") - 1,
5357 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5361 if (!isempty(message)) {
5362 iovec[1].iov_base = (char*) message;
5363 iovec[1].iov_len = strlen(message);
5364 msghdr.msg_iovlen++;
5367 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5373 static int reload_with_fallback(DBusConnection *bus) {
5376 /* First, try systemd via D-Bus. */
5377 if (daemon_reload(bus, NULL) >= 0)
5381 /* Nothing else worked, so let's try signals */
5382 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5384 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5385 log_error("kill() failed: %m");
5392 static int start_with_fallback(DBusConnection *bus) {
5395 /* First, try systemd via D-Bus. */
5396 if (start_unit(bus, NULL) >= 0)
5400 /* Hmm, talking to systemd via D-Bus didn't work. Then
5401 * let's try to talk to Upstart via D-Bus. */
5402 if (talk_upstart() > 0)
5405 /* Nothing else worked, so let's try
5407 if (talk_initctl() > 0)
5410 log_error("Failed to talk to init daemon.");
5414 warn_wall(arg_action);
5418 static _noreturn_ void halt_now(enum action a) {
5420 /* Make sure C-A-D is handled by the kernel from this
5422 reboot(RB_ENABLE_CAD);
5427 log_info("Halting.");
5428 reboot(RB_HALT_SYSTEM);
5431 case ACTION_POWEROFF:
5432 log_info("Powering off.");
5433 reboot(RB_POWER_OFF);
5437 log_info("Rebooting.");
5438 reboot(RB_AUTOBOOT);
5442 assert_not_reached("Unknown halt action.");
5445 assert_not_reached("Uh? This shouldn't happen.");
5448 static int halt_main(DBusConnection *bus) {
5451 r = check_inhibitors(bus, arg_action);
5455 if (geteuid() != 0) {
5456 /* Try logind if we are a normal user and no special
5457 * mode applies. Maybe PolicyKit allows us to shutdown
5460 if (arg_when <= 0 &&
5463 (arg_action == ACTION_POWEROFF ||
5464 arg_action == ACTION_REBOOT)) {
5465 r = reboot_with_logind(bus, arg_action);
5470 log_error("Must be root.");
5475 char _cleanup_free_ *m;
5477 m = strv_join(arg_wall, " ");
5478 r = send_shutdownd(arg_when,
5479 arg_action == ACTION_HALT ? 'H' :
5480 arg_action == ACTION_POWEROFF ? 'P' :
5481 arg_action == ACTION_KEXEC ? 'K' :
5488 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5490 char date[FORMAT_TIMESTAMP_MAX];
5492 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5493 format_timestamp(date, sizeof(date), arg_when));
5498 if (!arg_dry && !arg_force)
5499 return start_with_fallback(bus);
5502 if (sd_booted() > 0)
5503 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5505 r = utmp_put_shutdown();
5507 log_warning("Failed to write utmp record: %s", strerror(-r));
5514 halt_now(arg_action);
5515 /* We should never reach this. */
5519 static int runlevel_main(void) {
5520 int r, runlevel, previous;
5522 r = utmp_get_runlevel(&runlevel, &previous);
5529 previous <= 0 ? 'N' : previous,
5530 runlevel <= 0 ? 'N' : runlevel);
5535 int main(int argc, char*argv[]) {
5536 int r, retval = EXIT_FAILURE;
5537 DBusConnection *bus = NULL;
5538 DBusError _cleanup_dbus_error_free_ error;
5540 dbus_error_init(&error);
5542 setlocale(LC_ALL, "");
5543 log_parse_environment();
5546 r = parse_argv(argc, argv);
5550 retval = EXIT_SUCCESS;
5554 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5555 * let's shortcut this */
5556 if (arg_action == ACTION_RUNLEVEL) {
5557 r = runlevel_main();
5558 retval = r < 0 ? EXIT_FAILURE : r;
5562 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5563 log_info("Running in chroot, ignoring request.");
5569 if (arg_transport == TRANSPORT_NORMAL)
5570 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5571 else if (arg_transport == TRANSPORT_POLKIT) {
5572 bus_connect_system_polkit(&bus, &error);
5573 private_bus = false;
5574 } else if (arg_transport == TRANSPORT_SSH) {
5575 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5576 private_bus = false;
5578 assert_not_reached("Uh, invalid transport...");
5581 switch (arg_action) {
5583 case ACTION_SYSTEMCTL:
5584 r = systemctl_main(bus, argc, argv, &error);
5588 case ACTION_POWEROFF:
5594 case ACTION_RUNLEVEL2:
5595 case ACTION_RUNLEVEL3:
5596 case ACTION_RUNLEVEL4:
5597 case ACTION_RUNLEVEL5:
5599 case ACTION_EMERGENCY:
5600 case ACTION_DEFAULT:
5601 r = start_with_fallback(bus);
5606 r = reload_with_fallback(bus);
5609 case ACTION_CANCEL_SHUTDOWN: {
5613 m = strv_join(arg_wall, " ");
5615 retval = EXIT_FAILURE;
5619 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5621 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5626 case ACTION_INVALID:
5627 case ACTION_RUNLEVEL:
5629 assert_not_reached("Unknown action");
5632 retval = r < 0 ? EXIT_FAILURE : r;
5636 dbus_connection_flush(bus);
5637 dbus_connection_close(bus);
5638 dbus_connection_unref(bus);
5643 strv_free(arg_property);
5646 ask_password_agent_close();
5647 polkit_agent_close();