1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/reboot.h>
29 #include <sys/ioctl.h>
33 #include <sys/socket.h>
36 #include <sys/prctl.h>
37 #include <dbus/dbus.h>
39 #include <systemd/sd-daemon.h>
40 #include <systemd/sd-shutdown.h>
41 #include <systemd/sd-login.h>
47 #include "utmp-wtmp.h"
50 #include "path-util.h"
52 #include "dbus-common.h"
53 #include "cgroup-show.h"
54 #include "cgroup-util.h"
56 #include "path-lookup.h"
57 #include "conf-parser.h"
58 #include "exit-status.h"
59 #include "bus-errors.h"
61 #include "unit-name.h"
63 #include "spawn-ask-password-agent.h"
64 #include "spawn-polkit-agent.h"
66 #include "logs-show.h"
67 #include "path-util.h"
68 #include "socket-util.h"
71 static const char *arg_type = NULL;
72 static const char *arg_load_state = NULL;
73 static char **arg_property = NULL;
74 static bool arg_all = false;
75 static const char *arg_job_mode = "replace";
76 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
77 static bool arg_no_block = false;
78 static bool arg_no_legend = false;
79 static bool arg_no_pager = false;
80 static bool arg_no_wtmp = false;
81 static bool arg_no_wall = false;
82 static bool arg_no_reload = false;
83 static bool arg_ignore_inhibitors = false;
84 static bool arg_dry = false;
85 static bool arg_quiet = false;
86 static bool arg_full = false;
87 static int arg_force = 0;
88 static bool arg_ask_password = true;
89 static bool arg_failed = false;
90 static bool arg_runtime = false;
91 static char **arg_wall = NULL;
92 static const char *arg_kill_who = NULL;
93 static int arg_signal = SIGTERM;
94 static const char *arg_root = NULL;
95 static usec_t arg_when = 0;
117 ACTION_CANCEL_SHUTDOWN,
119 } arg_action = ACTION_SYSTEMCTL;
120 static enum transport {
124 } arg_transport = TRANSPORT_NORMAL;
125 static const char *arg_host = NULL;
126 static unsigned arg_lines = 10;
127 static OutputMode arg_output = OUTPUT_SHORT;
129 static bool private_bus = false;
131 static int daemon_reload(DBusConnection *bus, char **args);
132 static void halt_now(enum action a);
134 static void pager_open_if_enabled(void) {
142 static void ask_password_agent_open_if_enabled(void) {
144 /* Open the password agent as a child process if necessary */
146 if (!arg_ask_password)
149 if (arg_scope != UNIT_FILE_SYSTEM)
152 ask_password_agent_open();
156 static void polkit_agent_open_if_enabled(void) {
158 /* Open the polkit agent as a child process if necessary */
160 if (!arg_ask_password)
163 if (arg_scope != UNIT_FILE_SYSTEM)
170 static const char *ansi_highlight(bool b) {
175 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
178 static const char *ansi_highlight_red(bool b) {
183 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
186 static const char *ansi_highlight_green(bool b) {
191 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
194 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
197 if (!dbus_error_is_set(error))
200 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
201 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
202 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
203 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
204 return EXIT_NOPERMISSION;
206 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
207 return EXIT_NOTINSTALLED;
209 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
210 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
211 return EXIT_NOTIMPLEMENTED;
213 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
214 return EXIT_NOTCONFIGURED;
222 static void warn_wall(enum action a) {
223 static const char *table[_ACTION_MAX] = {
224 [ACTION_HALT] = "The system is going down for system halt NOW!",
225 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
226 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
227 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
228 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
229 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
230 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
237 _cleanup_free_ char *p;
239 p = strv_join(arg_wall, " ");
254 utmp_wall(table[a], NULL);
257 static bool avoid_bus(void) {
259 if (running_in_chroot() > 0)
262 if (sd_booted() <= 0)
265 if (!isempty(arg_root))
268 if (arg_scope == UNIT_FILE_GLOBAL)
274 static int compare_unit_info(const void *a, const void *b) {
276 const struct unit_info *u = a, *v = b;
278 d1 = strrchr(u->id, '.');
279 d2 = strrchr(v->id, '.');
284 r = strcasecmp(d1, d2);
289 return strcasecmp(u->id, v->id);
292 static bool output_show_unit(const struct unit_info *u) {
296 return streq(u->active_state, "failed");
298 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
299 streq(dot+1, arg_type))) &&
300 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
301 (arg_all || !(streq(u->active_state, "inactive")
302 || u->following[0]) || u->job_id > 0);
305 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
306 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
307 const struct unit_info *u;
310 max_id_len = sizeof("UNIT")-1;
311 active_len = sizeof("ACTIVE")-1;
312 sub_len = sizeof("SUB")-1;
313 job_len = sizeof("JOB")-1;
316 for (u = unit_infos; u < unit_infos + c; u++) {
317 if (!output_show_unit(u))
320 max_id_len = MAX(max_id_len, strlen(u->id));
321 active_len = MAX(active_len, strlen(u->active_state));
322 sub_len = MAX(sub_len, strlen(u->sub_state));
323 if (u->job_id != 0) {
324 job_len = MAX(job_len, strlen(u->job_type));
331 id_len = MIN(max_id_len, 25);
332 basic_len = 5 + id_len + 5 + active_len + sub_len;
334 basic_len += job_len + 1;
335 if (basic_len < (unsigned) columns()) {
336 unsigned extra_len, incr;
337 extra_len = columns() - basic_len;
338 /* Either UNIT already got 25, or is fully satisfied.
339 * Grant up to 25 to DESC now. */
340 incr = MIN(extra_len, 25);
343 /* split the remaining space between UNIT and DESC,
344 * but do not give UNIT more than it needs. */
346 incr = MIN(extra_len / 2, max_id_len - id_len);
348 desc_len += extra_len - incr;
354 for (u = unit_infos; u < unit_infos + c; u++) {
355 char _cleanup_free_ *e = NULL;
356 const char *on_loaded, *off_loaded;
357 const char *on_active, *off_active;
359 if (!output_show_unit(u))
362 if (!n_shown && !arg_no_legend) {
363 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
364 active_len, "ACTIVE", sub_len, "SUB");
366 printf("%-*s ", job_len, "JOB");
367 if (!arg_full && arg_no_pager)
368 printf("%.*s\n", desc_len, "DESCRIPTION");
370 printf("%s\n", "DESCRIPTION");
375 if (streq(u->load_state, "error")) {
376 on_loaded = ansi_highlight_red(true);
377 off_loaded = ansi_highlight_red(false);
379 on_loaded = off_loaded = "";
381 if (streq(u->active_state, "failed")) {
382 on_active = ansi_highlight_red(true);
383 off_active = ansi_highlight_red(false);
385 on_active = off_active = "";
387 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
389 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s",
390 id_len, e ? e : u->id,
391 on_loaded, u->load_state, off_loaded,
392 on_active, active_len, u->active_state,
393 sub_len, u->sub_state, off_active,
394 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
395 if (!arg_full && arg_no_pager)
396 printf("%.*s\n", desc_len, u->description);
398 printf("%s\n", u->description);
401 if (!arg_no_legend) {
402 const char *on, *off;
405 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
406 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
407 "SUB = The low-level unit activation state, values depend on unit type.\n");
409 printf("JOB = Pending job for the unit.\n");
411 on = ansi_highlight(true);
412 off = ansi_highlight(false);
414 on = ansi_highlight_red(true);
415 off = ansi_highlight_red(false);
419 printf("%s%u loaded units listed.%s\n"
420 "To show all installed unit files use 'systemctl list-unit-files'.\n",
423 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
424 "To show all installed unit files use 'systemctl list-unit-files'.\n",
429 static int 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, 16);
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, 25);
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, 16);
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(),20);
699 for (i = level - 1; i >= 0; i--) {
701 if(len > max_len - 3 && !arg_full) {
702 printf("%s...\n",max_len % 2 ? "" : " ");
705 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
708 if(len > max_len - 3 && !arg_full) {
709 printf("%s...\n",max_len % 2 ? "" : " ");
712 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
715 printf("%s\n", name);
719 n = ellipsize(name, max_len-len, 100);
727 static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
728 static const char dependencies[] =
730 "RequiresOverridable\0"
732 "RequisiteOverridable\0"
735 _cleanup_free_ char *path;
736 const char *interface = "org.freedesktop.systemd1.Unit";
738 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
739 DBusMessageIter iter, sub, sub2, sub3;
748 path = unit_dbus_path_from_name(name);
754 r = bus_method_call_with_reply(
756 "org.freedesktop.systemd1",
758 "org.freedesktop.DBus.Properties",
762 DBUS_TYPE_STRING, &interface,
767 if (!dbus_message_iter_init(reply, &iter) ||
768 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
769 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
770 log_error("Failed to parse reply.");
775 dbus_message_iter_recurse(&iter, &sub);
777 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
780 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
781 dbus_message_iter_recurse(&sub, &sub2);
783 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
784 log_error("Failed to parse reply.");
789 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
790 log_error("Failed to parse reply.");
795 dbus_message_iter_recurse(&sub2, &sub3);
796 dbus_message_iter_next(&sub);
798 if (!nulstr_contains(dependencies, prop))
801 if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
802 if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
803 DBusMessageIter sub4;
804 dbus_message_iter_recurse(&sub3, &sub4);
806 while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
809 assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
810 dbus_message_iter_get_basic(&sub4, &s);
812 r = strv_extend(&ret, s);
818 dbus_message_iter_next(&sub4);
831 static int list_dependencies_compare(const void *_a, const void *_b) {
832 const char **a = (const char**) _a, **b = (const char**) _b;
833 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
835 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
837 return strcasecmp(*a, *b);
840 static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char **units, unsigned int branches) {
841 char _cleanup_strv_free_ **deps = NULL, **u;
845 u = strv_append(units, name);
849 r = list_dependencies_get_dependencies(bus, name, &deps);
853 qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
855 STRV_FOREACH(c, deps) {
856 if (strv_contains(u, *c)) {
857 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
863 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
867 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
868 r = list_dependencies_one(bus, *c, level + 1, u, (branches << 1) | (c[1] == NULL ? 0 : 1));
877 static int list_dependencies(DBusConnection *bus, char **args) {
878 _cleanup_free_ char *unit = NULL;
884 unit = unit_name_mangle(args[1]);
889 u = SPECIAL_DEFAULT_TARGET;
891 pager_open_if_enabled();
895 return list_dependencies_one(bus, u, 0, NULL, 0);
898 static int list_jobs(DBusConnection *bus, char **args) {
899 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
900 DBusMessageIter iter, sub, sub2;
904 pager_open_if_enabled();
906 r = bus_method_call_with_reply(
908 "org.freedesktop.systemd1",
909 "/org/freedesktop/systemd1",
910 "org.freedesktop.systemd1.Manager",
918 if (!dbus_message_iter_init(reply, &iter) ||
919 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
920 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
921 log_error("Failed to parse reply.");
925 dbus_message_iter_recurse(&iter, &sub);
928 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
930 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
931 const char *name, *type, *state, *job_path, *unit_path;
933 char _cleanup_free_ *e = NULL;
935 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
936 log_error("Failed to parse reply.");
940 dbus_message_iter_recurse(&sub, &sub2);
942 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
943 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
944 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
945 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
946 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
947 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
948 log_error("Failed to parse reply.");
952 e = arg_full ? NULL : ellipsize(name, 25, 33);
953 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
957 dbus_message_iter_next(&sub);
961 printf("\n%u jobs listed.\n", k);
966 static int load_unit(DBusConnection *bus, char **args) {
971 STRV_FOREACH(name, args+1) {
972 _cleanup_free_ char *n = NULL;
975 n = unit_name_mangle(*name);
979 r = bus_method_call_with_reply(
981 "org.freedesktop.systemd1",
982 "/org/freedesktop/systemd1",
983 "org.freedesktop.systemd1.Manager",
987 DBUS_TYPE_STRING, &n,
996 static int cancel_job(DBusConnection *bus, char **args) {
1001 if (strv_length(args) <= 1)
1002 return daemon_reload(bus, args);
1004 STRV_FOREACH(name, args+1) {
1008 r = safe_atou32(*name, &id);
1010 log_error("Failed to parse job id: %s", strerror(-r));
1014 r = bus_method_call_with_reply(
1016 "org.freedesktop.systemd1",
1017 "/org/freedesktop/systemd1",
1018 "org.freedesktop.systemd1.Manager",
1022 DBUS_TYPE_UINT32, &id,
1031 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1032 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1033 dbus_bool_t b = FALSE;
1034 DBusMessageIter iter, sub;
1036 *interface = "org.freedesktop.systemd1.Unit",
1037 *property = "NeedDaemonReload",
1039 _cleanup_free_ char *n = NULL;
1042 /* We ignore all errors here, since this is used to show a warning only */
1044 n = unit_name_mangle(unit);
1048 r = bus_method_call_with_reply(
1050 "org.freedesktop.systemd1",
1051 "/org/freedesktop/systemd1",
1052 "org.freedesktop.systemd1.Manager",
1056 DBUS_TYPE_STRING, &n,
1061 if (!dbus_message_get_args(reply, NULL,
1062 DBUS_TYPE_OBJECT_PATH, &path,
1066 dbus_message_unref(reply);
1069 r = bus_method_call_with_reply(
1071 "org.freedesktop.systemd1",
1073 "org.freedesktop.DBus.Properties",
1077 DBUS_TYPE_STRING, &interface,
1078 DBUS_TYPE_STRING, &property,
1083 if (!dbus_message_iter_init(reply, &iter) ||
1084 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1087 dbus_message_iter_recurse(&iter, &sub);
1088 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1091 dbus_message_iter_get_basic(&sub, &b);
1095 typedef struct WaitData {
1102 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1103 DBusError _cleanup_dbus_error_free_ error;
1106 dbus_error_init(&error);
1112 log_debug("Got D-Bus request: %s.%s() on %s",
1113 dbus_message_get_interface(message),
1114 dbus_message_get_member(message),
1115 dbus_message_get_path(message));
1117 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1118 log_error("Warning! D-Bus connection terminated.");
1119 dbus_connection_close(connection);
1121 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1123 const char *path, *result, *unit;
1125 if (dbus_message_get_args(message, &error,
1126 DBUS_TYPE_UINT32, &id,
1127 DBUS_TYPE_OBJECT_PATH, &path,
1128 DBUS_TYPE_STRING, &unit,
1129 DBUS_TYPE_STRING, &result,
1130 DBUS_TYPE_INVALID)) {
1132 free(set_remove(d->set, (char*) path));
1134 if (!isempty(result))
1135 d->result = strdup(result);
1138 d->name = strdup(unit);
1140 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1143 dbus_error_free(&error);
1144 if (dbus_message_get_args(message, &error,
1145 DBUS_TYPE_UINT32, &id,
1146 DBUS_TYPE_OBJECT_PATH, &path,
1147 DBUS_TYPE_STRING, &result,
1148 DBUS_TYPE_INVALID)) {
1149 /* Compatibility with older systemd versions <
1150 * 183 during upgrades. This should be dropped
1152 free(set_remove(d->set, (char*) path));
1155 d->result = strdup(result);
1157 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1161 log_error("Failed to parse message: %s", bus_error_message(&error));
1164 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1167 static int enable_wait_for_jobs(DBusConnection *bus) {
1175 dbus_error_init(&error);
1176 dbus_bus_add_match(bus,
1178 "sender='org.freedesktop.systemd1',"
1179 "interface='org.freedesktop.systemd1.Manager',"
1180 "member='JobRemoved',"
1181 "path='/org/freedesktop/systemd1'",
1184 if (dbus_error_is_set(&error)) {
1185 log_error("Failed to add match: %s", bus_error_message(&error));
1186 dbus_error_free(&error);
1190 /* This is slightly dirty, since we don't undo the match registrations. */
1194 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1204 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1207 while (!set_isempty(s)) {
1209 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1210 log_error("Disconnected from bus.");
1211 return -ECONNREFUSED;
1218 if (streq(d.result, "timeout"))
1219 log_error("Job for %s timed out.", strna(d.name));
1220 else if (streq(d.result, "canceled"))
1221 log_error("Job for %s canceled.", strna(d.name));
1222 else if (streq(d.result, "dependency"))
1223 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1224 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1225 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1228 if (streq_ptr(d.result, "timeout"))
1230 else if (streq_ptr(d.result, "canceled"))
1232 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1243 dbus_connection_remove_filter(bus, wait_filter, &d);
1247 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1248 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1249 _cleanup_free_ char *n = NULL;
1250 DBusMessageIter iter, sub;
1252 *interface = "org.freedesktop.systemd1.Unit",
1253 *property = "ActiveState";
1254 const char *state, *path;
1260 dbus_error_init(&error);
1262 n = unit_name_mangle(name);
1266 r = bus_method_call_with_reply (
1268 "org.freedesktop.systemd1",
1269 "/org/freedesktop/systemd1",
1270 "org.freedesktop.systemd1.Manager",
1274 DBUS_TYPE_STRING, &n,
1277 dbus_error_free(&error);
1284 if (!dbus_message_get_args(reply, NULL,
1285 DBUS_TYPE_OBJECT_PATH, &path,
1286 DBUS_TYPE_INVALID)) {
1287 log_error("Failed to parse reply.");
1291 dbus_message_unref(reply);
1294 r = bus_method_call_with_reply(
1296 "org.freedesktop.systemd1",
1298 "org.freedesktop.DBus.Properties",
1302 DBUS_TYPE_STRING, &interface,
1303 DBUS_TYPE_STRING, &property,
1311 if (!dbus_message_iter_init(reply, &iter) ||
1312 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1313 log_error("Failed to parse reply.");
1317 dbus_message_iter_recurse(&iter, &sub);
1319 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1320 log_error("Failed to parse reply.");
1324 dbus_message_iter_get_basic(&sub, &state);
1329 return strv_find(check_states, state) ? 1 : 0;
1332 static void check_triggering_units(
1333 DBusConnection *bus,
1334 const char *unit_name) {
1336 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1337 DBusMessageIter iter, sub;
1338 const char *interface = "org.freedesktop.systemd1.Unit",
1339 *load_state_property = "LoadState",
1340 *triggered_by_property = "TriggeredBy",
1342 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1343 bool print_warning_label = true;
1346 n = unit_name_mangle(unit_name);
1352 unit_path = unit_dbus_path_from_name(n);
1358 r = bus_method_call_with_reply(
1360 "org.freedesktop.systemd1",
1362 "org.freedesktop.DBus.Properties",
1366 DBUS_TYPE_STRING, &interface,
1367 DBUS_TYPE_STRING, &load_state_property,
1372 if (!dbus_message_iter_init(reply, &iter) ||
1373 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1374 log_error("Failed to parse reply.");
1378 dbus_message_iter_recurse(&iter, &sub);
1380 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1381 log_error("Failed to parse reply.");
1385 dbus_message_iter_get_basic(&sub, &state);
1387 if (streq(state, "masked"))
1390 dbus_message_unref(reply);
1393 r = bus_method_call_with_reply(
1395 "org.freedesktop.systemd1",
1397 "org.freedesktop.DBus.Properties",
1401 DBUS_TYPE_STRING, &interface,
1402 DBUS_TYPE_STRING, &triggered_by_property,
1407 if (!dbus_message_iter_init(reply, &iter) ||
1408 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1409 log_error("Failed to parse reply.");
1413 dbus_message_iter_recurse(&iter, &sub);
1414 dbus_message_iter_recurse(&sub, &iter);
1417 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1418 const char * const check_states[] = {
1423 const char *service_trigger;
1425 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1426 log_error("Failed to parse reply.");
1430 dbus_message_iter_get_basic(&sub, &service_trigger);
1432 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1436 if (print_warning_label) {
1437 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1438 print_warning_label = false;
1441 log_warning(" %s", service_trigger);
1444 dbus_message_iter_next(&sub);
1448 static int start_unit_one(
1449 DBusConnection *bus,
1456 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1457 _cleanup_free_ char *n;
1466 n = unit_name_mangle(name);
1470 r = bus_method_call_with_reply(
1472 "org.freedesktop.systemd1",
1473 "/org/freedesktop/systemd1",
1474 "org.freedesktop.systemd1.Manager",
1478 DBUS_TYPE_STRING, &n,
1479 DBUS_TYPE_STRING, &mode,
1482 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1483 /* There's always a fallback possible for
1484 * legacy actions. */
1487 log_error("Failed to issue method call: %s", bus_error_message(error));
1492 if (!dbus_message_get_args(reply, error,
1493 DBUS_TYPE_OBJECT_PATH, &path,
1494 DBUS_TYPE_INVALID)) {
1495 log_error("Failed to parse reply: %s", bus_error_message(error));
1499 if (need_daemon_reload(bus, n))
1500 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1501 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1513 log_error("Failed to add path to set.");
1521 static const struct {
1525 } action_table[_ACTION_MAX] = {
1526 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
1527 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
1528 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
1529 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
1530 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
1531 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
1532 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
1533 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
1534 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
1535 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
1536 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
1537 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
1538 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
1539 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
1540 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1543 static enum action verb_to_action(const char *verb) {
1546 for (i = ACTION_INVALID; i < _ACTION_MAX; i++)
1547 if (action_table[i].verb && streq(verb, action_table[i].verb))
1549 return ACTION_INVALID;
1552 static int start_unit(DBusConnection *bus, char **args) {
1555 const char *method, *mode, *one_name;
1556 Set _cleanup_set_free_free_ *s = NULL;
1557 DBusError _cleanup_dbus_error_free_ error;
1560 dbus_error_init(&error);
1564 ask_password_agent_open_if_enabled();
1566 if (arg_action == ACTION_SYSTEMCTL) {
1569 streq(args[0], "stop") ||
1570 streq(args[0], "condstop") ? "StopUnit" :
1571 streq(args[0], "reload") ? "ReloadUnit" :
1572 streq(args[0], "restart") ? "RestartUnit" :
1574 streq(args[0], "try-restart") ||
1575 streq(args[0], "condrestart") ? "TryRestartUnit" :
1577 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1579 streq(args[0], "reload-or-try-restart") ||
1580 streq(args[0], "condreload") ||
1582 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1584 action = verb_to_action(args[0]);
1586 mode = streq(args[0], "isolate") ? "isolate" :
1587 action_table[action].mode ?: arg_job_mode;
1589 one_name = action_table[action].target;
1592 assert(arg_action < ELEMENTSOF(action_table));
1593 assert(action_table[arg_action].target);
1595 method = "StartUnit";
1597 mode = action_table[arg_action].mode;
1598 one_name = action_table[arg_action].target;
1601 if (!arg_no_block) {
1602 ret = enable_wait_for_jobs(bus);
1604 log_error("Could not watch jobs: %s", strerror(-ret));
1608 s = set_new(string_hash_func, string_compare_func);
1614 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1616 ret = translate_bus_error_to_exit_status(ret, &error);
1618 STRV_FOREACH(name, args+1) {
1619 r = start_unit_one(bus, method, *name, mode, &error, s);
1621 ret = translate_bus_error_to_exit_status(r, &error);
1622 dbus_error_free(&error);
1627 if (!arg_no_block) {
1628 r = wait_for_jobs(bus, s);
1632 /* When stopping units, warn if they can still be triggered by
1633 * another active unit (socket, path, timer) */
1634 if (!arg_quiet && streq(method, "StopUnit")) {
1636 check_triggering_units(bus, one_name);
1638 STRV_FOREACH(name, args+1)
1639 check_triggering_units(bus, *name);
1646 /* Ask systemd-logind, which might grant access to unprivileged users
1647 * through PolicyKit */
1648 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1651 dbus_bool_t interactive = true;
1656 polkit_agent_open_if_enabled();
1664 case ACTION_POWEROFF:
1665 method = "PowerOff";
1668 case ACTION_SUSPEND:
1672 case ACTION_HIBERNATE:
1673 method = "Hibernate";
1676 case ACTION_HYBRID_SLEEP:
1677 method = "HybridSleep";
1684 return bus_method_call_with_reply(
1686 "org.freedesktop.login1",
1687 "/org/freedesktop/login1",
1688 "org.freedesktop.login1.Manager",
1692 DBUS_TYPE_BOOLEAN, &interactive,
1699 static int check_inhibitors(DBusConnection *bus, enum action a) {
1701 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1702 DBusMessageIter iter, sub, sub2;
1705 _cleanup_strv_free_ char **sessions = NULL;
1711 if (arg_ignore_inhibitors || arg_force > 0)
1723 r = bus_method_call_with_reply(
1725 "org.freedesktop.login1",
1726 "/org/freedesktop/login1",
1727 "org.freedesktop.login1.Manager",
1733 /* If logind is not around, then there are no inhibitors... */
1736 if (!dbus_message_iter_init(reply, &iter) ||
1737 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1738 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1739 log_error("Failed to parse reply.");
1743 dbus_message_iter_recurse(&iter, &sub);
1744 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1745 const char *what, *who, *why, *mode;
1747 _cleanup_strv_free_ char **sv = NULL;
1748 _cleanup_free_ char *comm = NULL, *user = NULL;
1750 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1751 log_error("Failed to parse reply.");
1755 dbus_message_iter_recurse(&sub, &sub2);
1757 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
1758 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
1759 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
1760 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
1761 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
1762 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
1763 log_error("Failed to parse reply.");
1767 if (!streq(mode, "block"))
1770 sv = strv_split(what, ":");
1774 if (!strv_contains(sv,
1776 a == ACTION_POWEROFF ||
1777 a == ACTION_REBOOT ||
1778 a == ACTION_KEXEC ? "shutdown" : "sleep"))
1781 get_process_comm(pid, &comm);
1782 user = uid_to_name(uid);
1783 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
1784 who, (unsigned long) pid, strna(comm), strna(user), why);
1788 dbus_message_iter_next(&sub);
1791 dbus_message_iter_recurse(&iter, &sub);
1793 /* Check for current sessions */
1794 sd_get_sessions(&sessions);
1795 STRV_FOREACH(s, sessions) {
1797 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
1799 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
1802 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
1805 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
1808 sd_session_get_tty(*s, &tty);
1809 sd_session_get_seat(*s, &seat);
1810 sd_session_get_service(*s, &service);
1811 user = uid_to_name(uid);
1813 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
1820 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
1821 action_table[a].verb);
1829 static int start_special(DBusConnection *bus, char **args) {
1835 a = verb_to_action(args[0]);
1837 r = check_inhibitors(bus, a);
1841 if (arg_force >= 2 && geteuid() != 0) {
1842 log_error("Must be root.");
1846 if (arg_force >= 2 &&
1847 (a == ACTION_HALT ||
1848 a == ACTION_POWEROFF ||
1849 a == ACTION_REBOOT))
1852 if (arg_force >= 1 &&
1853 (a == ACTION_HALT ||
1854 a == ACTION_POWEROFF ||
1855 a == ACTION_REBOOT ||
1856 a == ACTION_KEXEC ||
1858 return daemon_reload(bus, args);
1860 /* first try logind, to allow authentication with polkit */
1861 if (geteuid() != 0 &&
1862 (a == ACTION_POWEROFF ||
1863 a == ACTION_REBOOT ||
1864 a == ACTION_SUSPEND ||
1865 a == ACTION_HIBERNATE ||
1866 a == ACTION_HYBRID_SLEEP)) {
1867 r = reboot_with_logind(bus, a);
1872 r = start_unit(bus, args);
1873 if (r == EXIT_SUCCESS)
1879 static int check_unit_active(DBusConnection *bus, char **args) {
1880 const char * const check_states[] = {
1887 int r = 3; /* According to LSB: "program is not running" */
1892 STRV_FOREACH(name, args+1) {
1895 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1905 static int check_unit_failed(DBusConnection *bus, char **args) {
1906 const char * const check_states[] = {
1917 STRV_FOREACH(name, args+1) {
1920 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1930 static int kill_unit(DBusConnection *bus, char **args) {
1938 arg_kill_who = "all";
1940 STRV_FOREACH(name, args+1) {
1941 _cleanup_free_ char *n = NULL;
1943 n = unit_name_mangle(*name);
1947 r = bus_method_call_with_reply(
1949 "org.freedesktop.systemd1",
1950 "/org/freedesktop/systemd1",
1951 "org.freedesktop.systemd1.Manager",
1955 DBUS_TYPE_STRING, &n,
1956 DBUS_TYPE_STRING, &arg_kill_who,
1957 DBUS_TYPE_INT32, &arg_signal,
1965 static int set_cgroup(DBusConnection *bus, char **args) {
1966 _cleanup_free_ char *n = NULL;
1967 const char *method, *runtime;
1975 streq(args[0], "set-cgroup") ? "SetUnitControlGroup" :
1976 streq(args[0], "unset-cgroup") ? "UnsetUnitControlGroup"
1977 : "UnsetUnitControlGroupAttribute";
1979 runtime = arg_runtime ? "runtime" : "persistent";
1981 n = unit_name_mangle(args[1]);
1985 STRV_FOREACH(argument, args + 2) {
1987 r = bus_method_call_with_reply(
1989 "org.freedesktop.systemd1",
1990 "/org/freedesktop/systemd1",
1991 "org.freedesktop.systemd1.Manager",
1995 DBUS_TYPE_STRING, &n,
1996 DBUS_TYPE_STRING, argument,
1997 DBUS_TYPE_STRING, &runtime,
2006 static int set_cgroup_attr(DBusConnection *bus, char **args) {
2007 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2009 DBusMessageIter iter;
2010 _cleanup_free_ char *n = NULL;
2011 const char *runtime;
2017 dbus_error_init(&error);
2019 runtime = arg_runtime ? "runtime" : "persistent";
2021 n = unit_name_mangle(args[1]);
2025 m = dbus_message_new_method_call(
2026 "org.freedesktop.systemd1",
2027 "/org/freedesktop/systemd1",
2028 "org.freedesktop.systemd1.Manager",
2029 "SetUnitControlGroupAttribute");
2033 dbus_message_iter_init_append(m, &iter);
2034 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2035 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[2]))
2038 r = bus_append_strv_iter(&iter, args + 3);
2042 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2045 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2047 log_error("Failed to issue method call: %s", bus_error_message(&error));
2048 dbus_error_free(&error);
2055 static int get_cgroup_attr(DBusConnection *bus, char **args) {
2056 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2057 _cleanup_free_ char *n = NULL;
2064 n = unit_name_mangle(args[1]);
2068 STRV_FOREACH(argument, args + 2) {
2069 _cleanup_strv_free_ char **list = NULL;
2070 DBusMessageIter iter;
2073 r = bus_method_call_with_reply(
2075 "org.freedesktop.systemd1",
2076 "/org/freedesktop/systemd1",
2077 "org.freedesktop.systemd1.Manager",
2078 "GetUnitControlGroupAttribute",
2081 DBUS_TYPE_STRING, &n,
2082 DBUS_TYPE_STRING, argument,
2087 dbus_message_iter_init(reply, &iter);
2088 r = bus_parse_strv_iter(&iter, &list);
2090 log_error("Failed to parse value list.");
2094 STRV_FOREACH(a, list) {
2095 if (endswith(*a, "\n"))
2105 typedef struct ExecStatusInfo {
2113 usec_t start_timestamp;
2114 usec_t exit_timestamp;
2119 LIST_FIELDS(struct ExecStatusInfo, exec);
2122 static void exec_status_info_free(ExecStatusInfo *i) {
2131 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2132 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2133 DBusMessageIter sub2, sub3;
2137 int32_t code, status;
2143 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2146 dbus_message_iter_recurse(sub, &sub2);
2148 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2151 i->path = strdup(path);
2155 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2156 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2160 dbus_message_iter_recurse(&sub2, &sub3);
2161 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2162 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2163 dbus_message_iter_next(&sub3);
2167 i->argv = new0(char*, n+1);
2172 dbus_message_iter_recurse(&sub2, &sub3);
2173 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2176 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2177 dbus_message_iter_get_basic(&sub3, &s);
2178 dbus_message_iter_next(&sub3);
2180 i->argv[n] = strdup(s);
2187 if (!dbus_message_iter_next(&sub2) ||
2188 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2189 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2190 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2191 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2192 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2193 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2194 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2195 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2199 i->start_timestamp = (usec_t) start_timestamp;
2200 i->exit_timestamp = (usec_t) exit_timestamp;
2201 i->pid = (pid_t) pid;
2208 typedef struct UnitStatusInfo {
2210 const char *load_state;
2211 const char *active_state;
2212 const char *sub_state;
2213 const char *unit_file_state;
2215 const char *description;
2216 const char *following;
2218 char **documentation;
2220 const char *fragment_path;
2221 const char *source_path;
2222 const char *default_control_group;
2224 const char *load_error;
2227 usec_t inactive_exit_timestamp;
2228 usec_t inactive_exit_timestamp_monotonic;
2229 usec_t active_enter_timestamp;
2230 usec_t active_exit_timestamp;
2231 usec_t inactive_enter_timestamp;
2233 bool need_daemon_reload;
2238 const char *status_text;
2241 usec_t start_timestamp;
2242 usec_t exit_timestamp;
2244 int exit_code, exit_status;
2246 usec_t condition_timestamp;
2247 bool condition_result;
2250 unsigned n_accepted;
2251 unsigned n_connections;
2255 const char *sysfs_path;
2257 /* Mount, Automount */
2263 LIST_HEAD(ExecStatusInfo, exec);
2266 static void print_status_info(UnitStatusInfo *i) {
2268 const char *on, *off, *ss;
2270 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2271 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2274 arg_all * OUTPUT_SHOW_ALL |
2275 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2276 on_tty() * OUTPUT_COLOR |
2277 !arg_quiet * OUTPUT_WARN_CUTOFF |
2278 arg_full * OUTPUT_FULL_WIDTH;
2282 /* This shows pretty information about a unit. See
2283 * print_property() for a low-level property printer */
2285 printf("%s", strna(i->id));
2287 if (i->description && !streq_ptr(i->id, i->description))
2288 printf(" - %s", i->description);
2293 printf("\t Follow: unit currently follows state of %s\n", i->following);
2295 if (streq_ptr(i->load_state, "error")) {
2296 on = ansi_highlight_red(true);
2297 off = ansi_highlight_red(false);
2301 path = i->source_path ? i->source_path : i->fragment_path;
2304 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2305 else if (path && i->unit_file_state)
2306 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2308 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2310 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2312 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2314 if (streq_ptr(i->active_state, "failed")) {
2315 on = ansi_highlight_red(true);
2316 off = ansi_highlight_red(false);
2317 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2318 on = ansi_highlight_green(true);
2319 off = ansi_highlight_green(false);
2324 printf("\t Active: %s%s (%s)%s",
2326 strna(i->active_state),
2330 printf("\t Active: %s%s%s",
2332 strna(i->active_state),
2335 if (!isempty(i->result) && !streq(i->result, "success"))
2336 printf(" (Result: %s)", i->result);
2338 timestamp = (streq_ptr(i->active_state, "active") ||
2339 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2340 (streq_ptr(i->active_state, "inactive") ||
2341 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2342 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2343 i->active_exit_timestamp;
2345 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2346 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2349 printf(" since %s; %s\n", s2, s1);
2351 printf(" since %s\n", s2);
2355 if (!i->condition_result && i->condition_timestamp > 0) {
2356 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2357 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2360 printf("\t start condition failed at %s; %s\n", s2, s1);
2362 printf("\t start condition failed at %s\n", s2);
2366 printf("\t Device: %s\n", i->sysfs_path);
2368 printf("\t Where: %s\n", i->where);
2370 printf("\t What: %s\n", i->what);
2372 if (!strv_isempty(i->documentation)) {
2376 STRV_FOREACH(t, i->documentation) {
2378 printf("\t Docs: %s\n", *t);
2381 printf("\t %s\n", *t);
2386 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2388 LIST_FOREACH(exec, p, i->exec) {
2389 _cleanup_free_ char *t = NULL;
2392 /* Only show exited processes here */
2396 t = strv_join(p->argv, " ");
2397 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2399 good = is_clean_exit_lsb(p->code, p->status, NULL);
2401 on = ansi_highlight_red(true);
2402 off = ansi_highlight_red(false);
2406 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2408 if (p->code == CLD_EXITED) {
2411 printf("status=%i", p->status);
2413 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2418 printf("signal=%s", signal_to_string(p->status));
2420 printf(")%s\n", off);
2422 if (i->main_pid == p->pid &&
2423 i->start_timestamp == p->start_timestamp &&
2424 i->exit_timestamp == p->start_timestamp)
2425 /* Let's not show this twice */
2428 if (p->pid == i->control_pid)
2432 if (i->main_pid > 0 || i->control_pid > 0) {
2435 if (i->main_pid > 0) {
2436 printf("Main PID: %u", (unsigned) i->main_pid);
2439 _cleanup_free_ char *t = NULL;
2440 get_process_comm(i->main_pid, &t);
2443 } else if (i->exit_code > 0) {
2444 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2446 if (i->exit_code == CLD_EXITED) {
2449 printf("status=%i", i->exit_status);
2451 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2456 printf("signal=%s", signal_to_string(i->exit_status));
2461 if (i->main_pid > 0 && i->control_pid > 0)
2464 if (i->control_pid > 0) {
2465 _cleanup_free_ char *t = NULL;
2467 printf(" Control: %u", (unsigned) i->control_pid);
2469 get_process_comm(i->control_pid, &t);
2478 printf("\t Status: \"%s\"\n", i->status_text);
2480 if (i->default_control_group &&
2481 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2484 printf("\t CGroup: %s\n", i->default_control_group);
2486 if (arg_transport != TRANSPORT_SSH) {
2496 if (i->main_pid > 0)
2497 extra[k++] = i->main_pid;
2499 if (i->control_pid > 0)
2500 extra[k++] = i->control_pid;
2502 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, extra, k, flags);
2506 if (i->id && arg_transport != TRANSPORT_SSH) {
2508 if(arg_scope == UNIT_FILE_SYSTEM)
2509 show_journal_by_unit(stdout,
2513 i->inactive_exit_timestamp_monotonic,
2517 show_journal_by_user_unit(stdout,
2521 i->inactive_exit_timestamp_monotonic,
2527 if (i->need_daemon_reload)
2528 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2529 ansi_highlight_red(true),
2530 ansi_highlight_red(false),
2531 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2534 static void show_unit_help(UnitStatusInfo *i) {
2539 if (!i->documentation) {
2540 log_info("Documentation for %s not known.", i->id);
2544 STRV_FOREACH(p, i->documentation) {
2546 if (startswith(*p, "man:")) {
2549 char _cleanup_free_ *page = NULL, *section = NULL;
2550 const char *args[4] = { "man", NULL, NULL, NULL };
2555 if ((*p)[k-1] == ')')
2556 e = strrchr(*p, '(');
2559 page = strndup((*p) + 4, e - *p - 4);
2560 section = strndup(e + 1, *p + k - e - 2);
2561 if (!page || !section) {
2573 log_error("Failed to fork: %m");
2579 execvp(args[0], (char**) args);
2580 log_error("Failed to execute man: %m");
2581 _exit(EXIT_FAILURE);
2584 wait_for_terminate(pid, NULL);
2586 log_info("Can't show: %s", *p);
2590 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2596 switch (dbus_message_iter_get_arg_type(iter)) {
2598 case DBUS_TYPE_STRING: {
2601 dbus_message_iter_get_basic(iter, &s);
2604 if (streq(name, "Id"))
2606 else if (streq(name, "LoadState"))
2608 else if (streq(name, "ActiveState"))
2609 i->active_state = s;
2610 else if (streq(name, "SubState"))
2612 else if (streq(name, "Description"))
2614 else if (streq(name, "FragmentPath"))
2615 i->fragment_path = s;
2616 else if (streq(name, "SourcePath"))
2618 else if (streq(name, "DefaultControlGroup"))
2619 i->default_control_group = s;
2620 else if (streq(name, "StatusText"))
2622 else if (streq(name, "SysFSPath"))
2624 else if (streq(name, "Where"))
2626 else if (streq(name, "What"))
2628 else if (streq(name, "Following"))
2630 else if (streq(name, "UnitFileState"))
2631 i->unit_file_state = s;
2632 else if (streq(name, "Result"))
2639 case DBUS_TYPE_BOOLEAN: {
2642 dbus_message_iter_get_basic(iter, &b);
2644 if (streq(name, "Accept"))
2646 else if (streq(name, "NeedDaemonReload"))
2647 i->need_daemon_reload = b;
2648 else if (streq(name, "ConditionResult"))
2649 i->condition_result = b;
2654 case DBUS_TYPE_UINT32: {
2657 dbus_message_iter_get_basic(iter, &u);
2659 if (streq(name, "MainPID")) {
2661 i->main_pid = (pid_t) u;
2664 } else if (streq(name, "ControlPID"))
2665 i->control_pid = (pid_t) u;
2666 else if (streq(name, "ExecMainPID")) {
2668 i->main_pid = (pid_t) u;
2669 } else if (streq(name, "NAccepted"))
2671 else if (streq(name, "NConnections"))
2672 i->n_connections = u;
2677 case DBUS_TYPE_INT32: {
2680 dbus_message_iter_get_basic(iter, &j);
2682 if (streq(name, "ExecMainCode"))
2683 i->exit_code = (int) j;
2684 else if (streq(name, "ExecMainStatus"))
2685 i->exit_status = (int) j;
2690 case DBUS_TYPE_UINT64: {
2693 dbus_message_iter_get_basic(iter, &u);
2695 if (streq(name, "ExecMainStartTimestamp"))
2696 i->start_timestamp = (usec_t) u;
2697 else if (streq(name, "ExecMainExitTimestamp"))
2698 i->exit_timestamp = (usec_t) u;
2699 else if (streq(name, "ActiveEnterTimestamp"))
2700 i->active_enter_timestamp = (usec_t) u;
2701 else if (streq(name, "InactiveEnterTimestamp"))
2702 i->inactive_enter_timestamp = (usec_t) u;
2703 else if (streq(name, "InactiveExitTimestamp"))
2704 i->inactive_exit_timestamp = (usec_t) u;
2705 else if (streq(name, "InactiveExitTimestampMonotonic"))
2706 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2707 else if (streq(name, "ActiveExitTimestamp"))
2708 i->active_exit_timestamp = (usec_t) u;
2709 else if (streq(name, "ConditionTimestamp"))
2710 i->condition_timestamp = (usec_t) u;
2715 case DBUS_TYPE_ARRAY: {
2717 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2718 startswith(name, "Exec")) {
2719 DBusMessageIter sub;
2721 dbus_message_iter_recurse(iter, &sub);
2722 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2723 ExecStatusInfo *info;
2726 if (!(info = new0(ExecStatusInfo, 1)))
2729 if (!(info->name = strdup(name))) {
2734 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2739 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2741 dbus_message_iter_next(&sub);
2743 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2744 streq(name, "Documentation")) {
2746 DBusMessageIter sub;
2748 dbus_message_iter_recurse(iter, &sub);
2749 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2753 dbus_message_iter_get_basic(&sub, &s);
2755 l = strv_append(i->documentation, s);
2759 strv_free(i->documentation);
2760 i->documentation = l;
2762 dbus_message_iter_next(&sub);
2769 case DBUS_TYPE_STRUCT: {
2771 if (streq(name, "LoadError")) {
2772 DBusMessageIter sub;
2773 const char *n, *message;
2776 dbus_message_iter_recurse(iter, &sub);
2778 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2782 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2786 if (!isempty(message))
2787 i->load_error = message;
2797 static int print_property(const char *name, DBusMessageIter *iter) {
2801 /* This is a low-level property printer, see
2802 * print_status_info() for the nicer output */
2804 if (arg_property && !strv_find(arg_property, name))
2807 switch (dbus_message_iter_get_arg_type(iter)) {
2809 case DBUS_TYPE_STRUCT: {
2810 DBusMessageIter sub;
2811 dbus_message_iter_recurse(iter, &sub);
2813 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2816 dbus_message_iter_get_basic(&sub, &u);
2819 printf("%s=%u\n", name, (unsigned) u);
2821 printf("%s=\n", name);
2824 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2827 dbus_message_iter_get_basic(&sub, &s);
2829 if (arg_all || s[0])
2830 printf("%s=%s\n", name, s);
2833 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2834 const char *a = NULL, *b = NULL;
2836 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2837 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2839 if (arg_all || !isempty(a) || !isempty(b))
2840 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2848 case DBUS_TYPE_ARRAY:
2850 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2851 DBusMessageIter sub, sub2;
2853 dbus_message_iter_recurse(iter, &sub);
2854 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2858 dbus_message_iter_recurse(&sub, &sub2);
2860 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2861 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2862 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2864 dbus_message_iter_next(&sub);
2869 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2870 DBusMessageIter sub, sub2;
2872 dbus_message_iter_recurse(iter, &sub);
2873 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2874 const char *type, *path;
2876 dbus_message_iter_recurse(&sub, &sub2);
2878 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2879 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2880 printf("%s=%s\n", type, path);
2882 dbus_message_iter_next(&sub);
2887 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2888 DBusMessageIter sub, sub2;
2890 dbus_message_iter_recurse(iter, &sub);
2891 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2893 uint64_t value, next_elapse;
2895 dbus_message_iter_recurse(&sub, &sub2);
2897 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2898 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2899 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2900 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2902 printf("%s={ value=%s ; next_elapse=%s }\n",
2904 format_timespan(timespan1, sizeof(timespan1), value),
2905 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2908 dbus_message_iter_next(&sub);
2913 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2914 DBusMessageIter sub, sub2;
2916 dbus_message_iter_recurse(iter, &sub);
2917 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2918 const char *controller, *attr, *value;
2920 dbus_message_iter_recurse(&sub, &sub2);
2922 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2923 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2924 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2926 printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2932 dbus_message_iter_next(&sub);
2937 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2938 DBusMessageIter sub;
2940 dbus_message_iter_recurse(iter, &sub);
2941 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2942 ExecStatusInfo info;
2945 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2946 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2947 char _cleanup_free_ *t;
2949 t = strv_join(info.argv, " ");
2951 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2955 yes_no(info.ignore),
2956 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2957 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2958 (unsigned) info. pid,
2959 sigchld_code_to_string(info.code),
2961 info.code == CLD_EXITED ? "" : "/",
2962 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2966 strv_free(info.argv);
2968 dbus_message_iter_next(&sub);
2977 if (generic_print_property(name, iter, arg_all) > 0)
2981 printf("%s=[unprintable]\n", name);
2986 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2987 _cleanup_free_ DBusMessage *reply = NULL;
2988 const char *interface = "";
2990 DBusMessageIter iter, sub, sub2, sub3;
2991 UnitStatusInfo info;
2999 r = bus_method_call_with_reply(
3001 "org.freedesktop.systemd1",
3003 "org.freedesktop.DBus.Properties",
3007 DBUS_TYPE_STRING, &interface,
3012 if (!dbus_message_iter_init(reply, &iter) ||
3013 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3014 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3015 log_error("Failed to parse reply.");
3019 dbus_message_iter_recurse(&iter, &sub);
3026 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3029 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3030 dbus_message_iter_recurse(&sub, &sub2);
3032 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3033 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3034 log_error("Failed to parse reply.");
3038 dbus_message_iter_recurse(&sub2, &sub3);
3040 if (show_properties)
3041 r = print_property(name, &sub3);
3043 r = status_property(name, &sub3, &info);
3045 log_error("Failed to parse reply.");
3049 dbus_message_iter_next(&sub);
3054 if (!show_properties) {
3055 if (streq(verb, "help"))
3056 show_unit_help(&info);
3058 print_status_info(&info);
3061 strv_free(info.documentation);
3063 if (!streq_ptr(info.active_state, "active") &&
3064 !streq_ptr(info.active_state, "reloading") &&
3065 streq(verb, "status"))
3066 /* According to LSB: "program not running" */
3069 while ((p = info.exec)) {
3070 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3071 exec_status_info_free(p);
3077 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3078 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3079 const char *path = NULL;
3080 DBusError _cleanup_dbus_error_free_ error;
3083 dbus_error_init(&error);
3085 r = bus_method_call_with_reply(
3087 "org.freedesktop.systemd1",
3088 "/org/freedesktop/systemd1",
3089 "org.freedesktop.systemd1.Manager",
3093 DBUS_TYPE_UINT32, &pid,
3098 if (!dbus_message_get_args(reply, &error,
3099 DBUS_TYPE_OBJECT_PATH, &path,
3100 DBUS_TYPE_INVALID)) {
3101 log_error("Failed to parse reply: %s", bus_error_message(&error));
3105 r = show_one(verb, bus, path, false, new_line);
3109 static int show_all(const char* verb, DBusConnection *bus, bool show_properties, bool *new_line) {
3110 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3111 _cleanup_free_ struct unit_info *unit_infos = NULL;
3113 const struct unit_info *u;
3116 r = get_unit_list(bus, &reply, &unit_infos, &c);
3120 for (u = unit_infos; u < unit_infos + c; u++) {
3121 char _cleanup_free_ *p = NULL;
3123 if (!output_show_unit(u))
3126 p = unit_dbus_path_from_name(u->id);
3130 printf("%s -> '%s'\n", u->id, p);
3132 r = show_one(verb, bus, p, show_properties, new_line);
3140 static int show(DBusConnection *bus, char **args) {
3142 bool show_properties, show_status, new_line = false;
3148 show_properties = streq(args[0], "show");
3149 show_status = streq(args[0], "status");
3151 if (show_properties)
3152 pager_open_if_enabled();
3154 /* If no argument is specified inspect the manager itself */
3156 if (show_properties && strv_length(args) <= 1)
3157 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3159 if (show_status && strv_length(args) <= 1)
3160 return show_all(args[0], bus, false, &new_line);
3162 STRV_FOREACH(name, args+1) {
3165 if (safe_atou32(*name, &id) < 0) {
3166 _cleanup_free_ char *p = NULL, *n = NULL;
3167 /* Interpret as unit name */
3169 n = unit_name_mangle(*name);
3173 p = unit_dbus_path_from_name(n);
3177 r = show_one(args[0], bus, p, show_properties, &new_line);
3181 } else if (show_properties) {
3182 _cleanup_free_ char *p = NULL;
3184 /* Interpret as job id */
3185 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3188 r = show_one(args[0], bus, p, show_properties, &new_line);
3193 /* Interpret as PID */
3194 r = show_one_by_pid(args[0], bus, id, &new_line);
3203 static int dump(DBusConnection *bus, char **args) {
3204 _cleanup_free_ DBusMessage *reply = NULL;
3209 dbus_error_init(&error);
3211 pager_open_if_enabled();
3213 r = bus_method_call_with_reply(
3215 "org.freedesktop.systemd1",
3216 "/org/freedesktop/systemd1",
3217 "org.freedesktop.systemd1.Manager",
3225 if (!dbus_message_get_args(reply, &error,
3226 DBUS_TYPE_STRING, &text,
3227 DBUS_TYPE_INVALID)) {
3228 log_error("Failed to parse reply: %s", bus_error_message(&error));
3229 dbus_error_free(&error);
3233 fputs(text, stdout);
3237 static int snapshot(DBusConnection *bus, char **args) {
3238 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3241 dbus_bool_t cleanup = FALSE;
3242 DBusMessageIter iter, sub;
3245 *interface = "org.freedesktop.systemd1.Unit",
3247 _cleanup_free_ char *n = NULL;
3249 dbus_error_init(&error);
3251 if (strv_length(args) > 1)
3252 n = snapshot_name_mangle(args[1]);
3258 r = bus_method_call_with_reply (
3260 "org.freedesktop.systemd1",
3261 "/org/freedesktop/systemd1",
3262 "org.freedesktop.systemd1.Manager",
3266 DBUS_TYPE_STRING, &n,
3267 DBUS_TYPE_BOOLEAN, &cleanup,
3272 if (!dbus_message_get_args(reply, &error,
3273 DBUS_TYPE_OBJECT_PATH, &path,
3274 DBUS_TYPE_INVALID)) {
3275 log_error("Failed to parse reply: %s", bus_error_message(&error));
3276 dbus_error_free(&error);
3280 dbus_message_unref(reply);
3283 r = bus_method_call_with_reply (
3285 "org.freedesktop.systemd1",
3287 "org.freedesktop.DBus.Properties",
3291 DBUS_TYPE_STRING, &interface,
3292 DBUS_TYPE_STRING, &property,
3297 if (!dbus_message_iter_init(reply, &iter) ||
3298 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3299 log_error("Failed to parse reply.");
3303 dbus_message_iter_recurse(&iter, &sub);
3305 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3306 log_error("Failed to parse reply.");
3310 dbus_message_iter_get_basic(&sub, &id);
3318 static int delete_snapshot(DBusConnection *bus, char **args) {
3323 STRV_FOREACH(name, args+1) {
3324 _cleanup_free_ char *n = NULL;
3327 n = snapshot_name_mangle(*name);
3331 r = bus_method_call_with_reply(
3333 "org.freedesktop.systemd1",
3334 "/org/freedesktop/systemd1",
3335 "org.freedesktop.systemd1.Manager",
3339 DBUS_TYPE_STRING, &n,
3348 static int daemon_reload(DBusConnection *bus, char **args) {
3353 if (arg_action == ACTION_RELOAD)
3355 else if (arg_action == ACTION_REEXEC)
3356 method = "Reexecute";
3358 assert(arg_action == ACTION_SYSTEMCTL);
3361 streq(args[0], "clear-jobs") ||
3362 streq(args[0], "cancel") ? "ClearJobs" :
3363 streq(args[0], "daemon-reexec") ? "Reexecute" :
3364 streq(args[0], "reset-failed") ? "ResetFailed" :
3365 streq(args[0], "halt") ? "Halt" :
3366 streq(args[0], "poweroff") ? "PowerOff" :
3367 streq(args[0], "reboot") ? "Reboot" :
3368 streq(args[0], "kexec") ? "KExec" :
3369 streq(args[0], "exit") ? "Exit" :
3370 /* "daemon-reload" */ "Reload";
3373 r = bus_method_call_with_reply(
3375 "org.freedesktop.systemd1",
3376 "/org/freedesktop/systemd1",
3377 "org.freedesktop.systemd1.Manager",
3383 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3384 /* There's always a fallback possible for
3385 * legacy actions. */
3387 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3388 /* On reexecution, we expect a disconnect, not
3392 log_error("Failed to issue method call: %s", bus_error_message(&error));
3394 dbus_error_free(&error);
3398 static int reset_failed(DBusConnection *bus, char **args) {
3402 if (strv_length(args) <= 1)
3403 return daemon_reload(bus, args);
3405 STRV_FOREACH(name, args+1) {
3406 _cleanup_free_ char *n;
3408 n = unit_name_mangle(*name);
3412 r = bus_method_call_with_reply(
3414 "org.freedesktop.systemd1",
3415 "/org/freedesktop/systemd1",
3416 "org.freedesktop.systemd1.Manager",
3420 DBUS_TYPE_STRING, &n,
3429 static int show_enviroment(DBusConnection *bus, char **args) {
3430 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3431 DBusMessageIter iter, sub, sub2;
3434 *interface = "org.freedesktop.systemd1.Manager",
3435 *property = "Environment";
3437 pager_open_if_enabled();
3439 r = bus_method_call_with_reply(
3441 "org.freedesktop.systemd1",
3442 "/org/freedesktop/systemd1",
3443 "org.freedesktop.DBus.Properties",
3447 DBUS_TYPE_STRING, &interface,
3448 DBUS_TYPE_STRING, &property,
3453 if (!dbus_message_iter_init(reply, &iter) ||
3454 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3455 log_error("Failed to parse reply.");
3459 dbus_message_iter_recurse(&iter, &sub);
3461 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3462 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3463 log_error("Failed to parse reply.");
3467 dbus_message_iter_recurse(&sub, &sub2);
3469 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3472 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3473 log_error("Failed to parse reply.");
3477 dbus_message_iter_get_basic(&sub2, &text);
3480 dbus_message_iter_next(&sub2);
3486 static int switch_root(DBusConnection *bus, char **args) {
3489 _cleanup_free_ char *init = NULL;
3491 l = strv_length(args);
3492 if (l < 2 || l > 3) {
3493 log_error("Wrong number of arguments.");
3500 init = strdup(args[2]);
3502 parse_env_file("/proc/cmdline", WHITESPACE,
3512 log_debug("switching root - root: %s; init: %s", root, init);
3514 return bus_method_call_with_reply(
3516 "org.freedesktop.systemd1",
3517 "/org/freedesktop/systemd1",
3518 "org.freedesktop.systemd1.Manager",
3522 DBUS_TYPE_STRING, &root,
3523 DBUS_TYPE_STRING, &init,
3527 static int set_environment(DBusConnection *bus, char **args) {
3528 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3531 DBusMessageIter iter;
3537 dbus_error_init(&error);
3539 method = streq(args[0], "set-environment")
3541 : "UnsetEnvironment";
3543 m = dbus_message_new_method_call(
3544 "org.freedesktop.systemd1",
3545 "/org/freedesktop/systemd1",
3546 "org.freedesktop.systemd1.Manager",
3551 dbus_message_iter_init_append(m, &iter);
3553 r = bus_append_strv_iter(&iter, args + 1);
3557 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3559 log_error("Failed to issue method call: %s", bus_error_message(&error));
3560 dbus_error_free(&error);
3567 static int enable_sysv_units(char **args) {
3570 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3571 const char *verb = args[0];
3572 unsigned f = 1, t = 1;
3575 if (arg_scope != UNIT_FILE_SYSTEM)
3578 if (!streq(verb, "enable") &&
3579 !streq(verb, "disable") &&
3580 !streq(verb, "is-enabled"))
3583 /* Processes all SysV units, and reshuffles the array so that
3584 * afterwards only the native units remain */
3587 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3592 for (f = 1; args[f]; f++) {
3595 bool found_native = false, found_sysv;
3597 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3598 char **k, *l, *q = NULL;
3605 if (!endswith(name, ".service"))
3608 if (path_is_absolute(name))
3611 STRV_FOREACH(k, paths.unit_path) {
3614 if (!isempty(arg_root))
3615 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3617 asprintf(&p, "%s/%s", *k, name);
3624 found_native = access(p, F_OK) >= 0;
3635 if (!isempty(arg_root))
3636 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3638 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3644 p[strlen(p) - sizeof(".service") + 1] = 0;
3645 found_sysv = access(p, F_OK) >= 0;
3652 /* Mark this entry, so that we don't try enabling it as native unit */
3653 args[f] = (char*) "";
3655 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3657 if (!isempty(arg_root))
3658 argv[c++] = q = strappend("--root=", arg_root);
3660 argv[c++] = path_get_file_name(p);
3662 streq(verb, "enable") ? "on" :
3663 streq(verb, "disable") ? "off" : "--level=5";
3666 l = strv_join((char**)argv, " ");
3674 log_info("Executing %s", l);
3679 log_error("Failed to fork: %m");
3684 } else if (pid == 0) {
3687 execv(argv[0], (char**) argv);
3688 _exit(EXIT_FAILURE);
3694 j = wait_for_terminate(pid, &status);
3696 log_error("Failed to wait for child: %s", strerror(-r));
3701 if (status.si_code == CLD_EXITED) {
3702 if (streq(verb, "is-enabled")) {
3703 if (status.si_status == 0) {
3712 } else if (status.si_status != 0) {
3723 lookup_paths_free(&paths);
3725 /* Drop all SysV units */
3726 for (f = 1, t = 1; args[f]; f++) {
3728 if (isempty(args[f]))
3731 args[t++] = args[f];
3740 static int mangle_names(char **original_names, char ***mangled_names) {
3741 char **i, **l, **name;
3743 l = new(char*, strv_length(original_names) + 1);
3748 STRV_FOREACH(name, original_names) {
3750 /* When enabling units qualified path names are OK,
3751 * too, hence allow them explicitly. */
3756 *i = unit_name_mangle(*name);
3772 static int enable_unit(DBusConnection *bus, char **args) {
3773 const char *verb = args[0];
3774 UnitFileChange *changes = NULL;
3775 unsigned n_changes = 0, i;
3776 int carries_install_info = -1;
3777 DBusMessage _cleanup_dbus_message_unref_ *m = NULL, *reply = NULL;
3779 DBusError _cleanup_dbus_error_free_ error;
3780 char _cleanup_strv_free_ **mangled_names = NULL;
3782 dbus_error_init(&error);
3784 r = enable_sysv_units(args);
3791 if (!bus || avoid_bus()) {
3792 if (streq(verb, "enable")) {
3793 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3794 carries_install_info = r;
3795 } else if (streq(verb, "disable"))
3796 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3797 else if (streq(verb, "reenable")) {
3798 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3799 carries_install_info = r;
3800 } else if (streq(verb, "link"))
3801 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3802 else if (streq(verb, "preset")) {
3803 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3804 carries_install_info = r;
3805 } else if (streq(verb, "mask"))
3806 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3807 else if (streq(verb, "unmask"))
3808 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3810 assert_not_reached("Unknown verb");
3813 log_error("Operation failed: %s", strerror(-r));
3818 for (i = 0; i < n_changes; i++) {
3819 if (changes[i].type == UNIT_FILE_SYMLINK)
3820 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3822 log_info("rm '%s'", changes[i].path);
3829 bool send_force = true, expect_carries_install_info = false;
3831 DBusMessageIter iter, sub, sub2;
3833 if (streq(verb, "enable")) {
3834 method = "EnableUnitFiles";
3835 expect_carries_install_info = true;
3836 } else if (streq(verb, "disable")) {
3837 method = "DisableUnitFiles";
3839 } else if (streq(verb, "reenable")) {
3840 method = "ReenableUnitFiles";
3841 expect_carries_install_info = true;
3842 } else if (streq(verb, "link"))
3843 method = "LinkUnitFiles";
3844 else if (streq(verb, "preset")) {
3845 method = "PresetUnitFiles";
3846 expect_carries_install_info = true;
3847 } else if (streq(verb, "mask"))
3848 method = "MaskUnitFiles";
3849 else if (streq(verb, "unmask")) {
3850 method = "UnmaskUnitFiles";
3853 assert_not_reached("Unknown verb");
3855 m = dbus_message_new_method_call(
3856 "org.freedesktop.systemd1",
3857 "/org/freedesktop/systemd1",
3858 "org.freedesktop.systemd1.Manager",
3865 dbus_message_iter_init_append(m, &iter);
3867 r = mangle_names(args+1, &mangled_names);
3871 r = bus_append_strv_iter(&iter, mangled_names);
3873 log_error("Failed to append unit files.");
3878 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3879 log_error("Failed to append runtime boolean.");
3887 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3888 log_error("Failed to append force boolean.");
3894 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3896 log_error("Failed to issue method call: %s", bus_error_message(&error));
3901 if (!dbus_message_iter_init(reply, &iter)) {
3902 log_error("Failed to initialize iterator.");
3906 if (expect_carries_install_info) {
3907 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3909 log_error("Failed to parse reply.");
3913 carries_install_info = b;
3916 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3917 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3918 log_error("Failed to parse reply.");
3923 dbus_message_iter_recurse(&iter, &sub);
3924 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3925 const char *type, *path, *source;
3927 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3928 log_error("Failed to parse reply.");
3933 dbus_message_iter_recurse(&sub, &sub2);
3935 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3936 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3937 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3938 log_error("Failed to parse reply.");
3944 if (streq(type, "symlink"))
3945 log_info("ln -s '%s' '%s'", source, path);
3947 log_info("rm '%s'", path);
3950 dbus_message_iter_next(&sub);
3953 /* Try to reload if enabeld */
3955 r = daemon_reload(bus, args);
3958 if (carries_install_info == 0)
3959 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
3960 "using systemctl.\n"
3961 "Possible reasons for having this kind of units are:\n"
3962 "1) A unit may be statically enabled by being symlinked from another unit's\n"
3963 " .wants/ or .requires/ directory.\n"
3964 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
3965 " a requirement dependency on it.\n"
3966 "3) A unit may be started when needed via activation (socket, path, timer,\n"
3967 " D-Bus, udev, scripted systemctl call, ...).\n");
3970 unit_file_changes_free(changes, n_changes);
3975 static int unit_is_enabled(DBusConnection *bus, char **args) {
3976 DBusError _cleanup_dbus_error_free_ error;
3978 DBusMessage _cleanup_dbus_message_unref_ *reply = NULL;
3982 dbus_error_init(&error);
3984 r = enable_sysv_units(args);
3990 if (!bus || avoid_bus()) {
3992 STRV_FOREACH(name, args+1) {
3993 UnitFileState state;
3995 state = unit_file_get_state(arg_scope, arg_root, *name);
3999 if (state == UNIT_FILE_ENABLED ||
4000 state == UNIT_FILE_ENABLED_RUNTIME ||
4001 state == UNIT_FILE_STATIC)
4005 puts(unit_file_state_to_string(state));
4009 STRV_FOREACH(name, args+1) {
4012 r = bus_method_call_with_reply (
4014 "org.freedesktop.systemd1",
4015 "/org/freedesktop/systemd1",
4016 "org.freedesktop.systemd1.Manager",
4020 DBUS_TYPE_STRING, name,
4025 if (!dbus_message_get_args(reply, &error,
4026 DBUS_TYPE_STRING, &s,
4027 DBUS_TYPE_INVALID)) {
4028 log_error("Failed to parse reply: %s", bus_error_message(&error));
4032 dbus_message_unref(reply);
4035 if (streq(s, "enabled") ||
4036 streq(s, "enabled-runtime") ||
4045 return enabled ? 0 : 1;
4048 static int systemctl_help(void) {
4050 pager_open_if_enabled();
4052 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4053 "Query or send control commands to the systemd manager.\n\n"
4054 " -h --help Show this help\n"
4055 " --version Show package version\n"
4056 " -t --type=TYPE List only units of a particular type\n"
4057 " -p --property=NAME Show only properties by this name\n"
4058 " -a --all Show all units/properties, including dead/empty ones\n"
4059 " --failed Show only failed units\n"
4060 " --full Don't ellipsize unit names on output\n"
4061 " --fail When queueing a new job, fail if conflicting jobs are\n"
4063 " --ignore-dependencies\n"
4064 " When queueing a new job, ignore all its dependencies\n"
4065 " -i --ignore-inhibitors\n"
4066 " When shutting down or sleeping, ignore inhibitors\n"
4067 " --kill-who=WHO Who to send signal to\n"
4068 " -s --signal=SIGNAL Which signal to send\n"
4069 " -H --host=[USER@]HOST\n"
4070 " Show information for remote host\n"
4071 " -P --privileged Acquire privileges before execution\n"
4072 " -q --quiet Suppress output\n"
4073 " --no-block Do not wait until operation finished\n"
4074 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4075 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4077 " --no-legend Do not print a legend (column headers and hints)\n"
4078 " --no-pager Do not pipe output into a pager\n"
4079 " --no-ask-password\n"
4080 " Do not ask for system passwords\n"
4081 " --system Connect to system manager\n"
4082 " --user Connect to user service manager\n"
4083 " --global Enable/disable unit files globally\n"
4084 " -f --force When enabling unit files, override existing symlinks\n"
4085 " When shutting down, execute action immediately\n"
4086 " --root=PATH Enable unit files in the specified root directory\n"
4087 " --runtime Enable unit files only temporarily until next reboot\n"
4088 " -n --lines=INTEGER Journal entries to show\n"
4089 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4090 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4092 " list-units List loaded units\n"
4093 " start [NAME...] Start (activate) one or more units\n"
4094 " stop [NAME...] Stop (deactivate) one or more units\n"
4095 " reload [NAME...] Reload one or more units\n"
4096 " restart [NAME...] Start or restart one or more units\n"
4097 " try-restart [NAME...] Restart one or more units if active\n"
4098 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4099 " otherwise start or restart\n"
4100 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4101 " otherwise restart if active\n"
4102 " isolate [NAME] Start one unit and stop all others\n"
4103 " kill [NAME...] Send signal to processes of a unit\n"
4104 " is-active [NAME...] Check whether units are active\n"
4105 " is-failed [NAME...] Check whether units are failed\n"
4106 " status [NAME...|PID...] Show runtime status of one or more units\n"
4107 " show [NAME...|JOB...] Show properties of one or more\n"
4108 " units/jobs or the manager\n"
4109 " help [NAME...|PID...] Show manual for one or more units\n"
4110 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4112 " get-cgroup-attr [NAME] [ATTR] ...\n"
4113 " Get control group attrubute\n"
4114 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4115 " Set control group attribute\n"
4116 " unset-cgroup-attr [NAME] [ATTR...]\n"
4117 " Unset control group attribute\n"
4118 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4119 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4120 " load [NAME...] Load one or more units\n"
4121 " list-dependencies [NAME] Recursively show units which are required\n"
4122 " or wanted by this unit\n\n"
4123 "Unit File Commands:\n"
4124 " list-unit-files List installed unit files\n"
4125 " enable [NAME...] Enable one or more unit files\n"
4126 " disable [NAME...] Disable one or more unit files\n"
4127 " reenable [NAME...] Reenable one or more unit files\n"
4128 " preset [NAME...] Enable/disable one or more unit files\n"
4129 " based on preset configuration\n"
4130 " mask [NAME...] Mask one or more units\n"
4131 " unmask [NAME...] Unmask one or more units\n"
4132 " link [PATH...] Link one or more units files into\n"
4133 " the search path\n"
4134 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4136 " list-jobs List jobs\n"
4137 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4138 "Status Commands:\n"
4139 " dump Dump server status\n"
4140 "Snapshot Commands:\n"
4141 " snapshot [NAME] Create a snapshot\n"
4142 " delete [NAME...] Remove one or more snapshots\n\n"
4143 "Environment Commands:\n"
4144 " show-environment Dump environment\n"
4145 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4146 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4147 "Manager Lifecycle Commands:\n"
4148 " daemon-reload Reload systemd manager configuration\n"
4149 " daemon-reexec Reexecute systemd manager\n\n"
4150 "System Commands:\n"
4151 " default Enter system default mode\n"
4152 " rescue Enter system rescue mode\n"
4153 " emergency Enter system emergency mode\n"
4154 " halt Shut down and halt the system\n"
4155 " poweroff Shut down and power-off the system\n"
4156 " reboot Shut down and reboot the system\n"
4157 " kexec Shut down and reboot the system with kexec\n"
4158 " exit Request user instance exit\n"
4159 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4160 " suspend Suspend the system\n"
4161 " hibernate Hibernate the system\n"
4162 " hybrid-sleep Hibernate and suspend the system\n",
4163 program_invocation_short_name);
4168 static int halt_help(void) {
4170 printf("%s [OPTIONS...]\n\n"
4171 "%s the system.\n\n"
4172 " --help Show this help\n"
4173 " --halt Halt the machine\n"
4174 " -p --poweroff Switch off the machine\n"
4175 " --reboot Reboot the machine\n"
4176 " -f --force Force immediate halt/power-off/reboot\n"
4177 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4178 " -d --no-wtmp Don't write wtmp record\n"
4179 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4180 program_invocation_short_name,
4181 arg_action == ACTION_REBOOT ? "Reboot" :
4182 arg_action == ACTION_POWEROFF ? "Power off" :
4188 static int shutdown_help(void) {
4190 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4191 "Shut down the system.\n\n"
4192 " --help Show this help\n"
4193 " -H --halt Halt the machine\n"
4194 " -P --poweroff Power-off the machine\n"
4195 " -r --reboot Reboot the machine\n"
4196 " -h Equivalent to --poweroff, overridden by --halt\n"
4197 " -k Don't halt/power-off/reboot, just send warnings\n"
4198 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4199 " -c Cancel a pending shutdown\n",
4200 program_invocation_short_name);
4205 static int telinit_help(void) {
4207 printf("%s [OPTIONS...] {COMMAND}\n\n"
4208 "Send control commands to the init daemon.\n\n"
4209 " --help Show this help\n"
4210 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4212 " 0 Power-off the machine\n"
4213 " 6 Reboot the machine\n"
4214 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4215 " 1, s, S Enter rescue mode\n"
4216 " q, Q Reload init daemon configuration\n"
4217 " u, U Reexecute init daemon\n",
4218 program_invocation_short_name);
4223 static int runlevel_help(void) {
4225 printf("%s [OPTIONS...]\n\n"
4226 "Prints the previous and current runlevel of the init system.\n\n"
4227 " --help Show this help\n",
4228 program_invocation_short_name);
4233 static int help_types(void) {
4236 puts("Available unit types:");
4237 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4238 if (unit_type_table[i])
4239 puts(unit_type_table[i]);
4241 puts("\nAvailable unit load states: ");
4242 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4243 if (unit_type_table[i])
4244 puts(unit_load_state_table[i]);
4249 static int systemctl_parse_argv(int argc, char *argv[]) {
4254 ARG_IGNORE_DEPENDENCIES,
4267 ARG_NO_ASK_PASSWORD,
4273 static const struct option options[] = {
4274 { "help", no_argument, NULL, 'h' },
4275 { "version", no_argument, NULL, ARG_VERSION },
4276 { "type", required_argument, NULL, 't' },
4277 { "property", required_argument, NULL, 'p' },
4278 { "all", no_argument, NULL, 'a' },
4279 { "failed", no_argument, NULL, ARG_FAILED },
4280 { "full", no_argument, NULL, ARG_FULL },
4281 { "fail", no_argument, NULL, ARG_FAIL },
4282 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4283 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4284 { "ignore-inhibitors", no_argument, NULL, 'i' },
4285 { "user", no_argument, NULL, ARG_USER },
4286 { "system", no_argument, NULL, ARG_SYSTEM },
4287 { "global", no_argument, NULL, ARG_GLOBAL },
4288 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4289 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4290 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4291 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4292 { "quiet", no_argument, NULL, 'q' },
4293 { "root", required_argument, NULL, ARG_ROOT },
4294 { "force", no_argument, NULL, ARG_FORCE },
4295 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4296 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4297 { "signal", required_argument, NULL, 's' },
4298 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4299 { "host", required_argument, NULL, 'H' },
4300 { "privileged",no_argument, NULL, 'P' },
4301 { "runtime", no_argument, NULL, ARG_RUNTIME },
4302 { "lines", required_argument, NULL, 'n' },
4303 { "output", required_argument, NULL, 'o' },
4304 { NULL, 0, NULL, 0 }
4312 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4321 puts(PACKAGE_STRING);
4322 puts(SYSTEMD_FEATURES);
4326 if (streq(optarg, "help")) {
4331 if (unit_type_from_string(optarg) >= 0) {
4335 if (unit_load_state_from_string(optarg) >= 0) {
4336 arg_load_state = optarg;
4339 log_error("Unkown unit type or load state '%s'.",
4341 log_info("Use -t help to see a list of allowed values.");
4346 /* Make sure that if the empty property list
4347 was specified, we won't show any properties. */
4348 const char *source = isempty(optarg) ? " " : optarg;
4350 FOREACH_WORD_SEPARATOR(word, size, source, ",", state) {
4351 char _cleanup_free_ *prop;
4354 prop = strndup(word, size);
4358 tmp = strv_append(arg_property, prop);
4362 strv_free(arg_property);
4366 /* If the user asked for a particular
4367 * property, show it to him, even if it is
4379 arg_job_mode = "fail";
4382 case ARG_IRREVERSIBLE:
4383 arg_job_mode = "replace-irreversibly";
4386 case ARG_IGNORE_DEPENDENCIES:
4387 arg_job_mode = "ignore-dependencies";
4391 arg_scope = UNIT_FILE_USER;
4395 arg_scope = UNIT_FILE_SYSTEM;
4399 arg_scope = UNIT_FILE_GLOBAL;
4403 arg_no_block = true;
4407 arg_no_legend = true;
4411 arg_no_pager = true;
4443 arg_no_reload = true;
4447 arg_kill_who = optarg;
4451 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4452 log_error("Failed to parse signal string %s.", optarg);
4457 case ARG_NO_ASK_PASSWORD:
4458 arg_ask_password = false;
4462 arg_transport = TRANSPORT_POLKIT;
4466 arg_transport = TRANSPORT_SSH;
4475 if (safe_atou(optarg, &arg_lines) < 0) {
4476 log_error("Failed to parse lines '%s'", optarg);
4482 arg_output = output_mode_from_string(optarg);
4483 if (arg_output < 0) {
4484 log_error("Unknown output '%s'.", optarg);
4490 arg_ignore_inhibitors = true;
4497 log_error("Unknown option code '%c'.", c);
4502 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4503 log_error("Cannot access user instance remotely.");
4510 static int halt_parse_argv(int argc, char *argv[]) {
4519 static const struct option options[] = {
4520 { "help", no_argument, NULL, ARG_HELP },
4521 { "halt", no_argument, NULL, ARG_HALT },
4522 { "poweroff", no_argument, NULL, 'p' },
4523 { "reboot", no_argument, NULL, ARG_REBOOT },
4524 { "force", no_argument, NULL, 'f' },
4525 { "wtmp-only", no_argument, NULL, 'w' },
4526 { "no-wtmp", no_argument, NULL, 'd' },
4527 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4528 { NULL, 0, NULL, 0 }
4536 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4537 if (runlevel == '0' || runlevel == '6')
4540 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4548 arg_action = ACTION_HALT;
4552 if (arg_action != ACTION_REBOOT)
4553 arg_action = ACTION_POWEROFF;
4557 arg_action = ACTION_REBOOT;
4579 /* Compatibility nops */
4586 log_error("Unknown option code '%c'.", c);
4591 if (optind < argc) {
4592 log_error("Too many arguments.");
4599 static int parse_time_spec(const char *t, usec_t *_u) {
4603 if (streq(t, "now"))
4605 else if (!strchr(t, ':')) {
4608 if (safe_atou64(t, &u) < 0)
4611 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4620 hour = strtol(t, &e, 10);
4621 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4624 minute = strtol(e+1, &e, 10);
4625 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4628 n = now(CLOCK_REALTIME);
4629 s = (time_t) (n / USEC_PER_SEC);
4632 assert_se(localtime_r(&s, &tm));
4634 tm.tm_hour = (int) hour;
4635 tm.tm_min = (int) minute;
4638 assert_se(s = mktime(&tm));
4640 *_u = (usec_t) s * USEC_PER_SEC;
4643 *_u += USEC_PER_DAY;
4649 static int shutdown_parse_argv(int argc, char *argv[]) {
4656 static const struct option options[] = {
4657 { "help", no_argument, NULL, ARG_HELP },
4658 { "halt", no_argument, NULL, 'H' },
4659 { "poweroff", no_argument, NULL, 'P' },
4660 { "reboot", no_argument, NULL, 'r' },
4661 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4662 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4663 { NULL, 0, NULL, 0 }
4671 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4679 arg_action = ACTION_HALT;
4683 arg_action = ACTION_POWEROFF;
4688 arg_action = ACTION_KEXEC;
4690 arg_action = ACTION_REBOOT;
4694 arg_action = ACTION_KEXEC;
4698 if (arg_action != ACTION_HALT)
4699 arg_action = ACTION_POWEROFF;
4712 /* Compatibility nops */
4716 arg_action = ACTION_CANCEL_SHUTDOWN;
4723 log_error("Unknown option code '%c'.", c);
4728 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4729 r = parse_time_spec(argv[optind], &arg_when);
4731 log_error("Failed to parse time specification: %s", argv[optind]);
4735 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4737 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4738 /* No time argument for shutdown cancel */
4739 arg_wall = argv + optind;
4740 else if (argc > optind + 1)
4741 /* We skip the time argument */
4742 arg_wall = argv + optind + 1;
4749 static int telinit_parse_argv(int argc, char *argv[]) {
4756 static const struct option options[] = {
4757 { "help", no_argument, NULL, ARG_HELP },
4758 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4759 { NULL, 0, NULL, 0 }
4762 static const struct {
4766 { '0', ACTION_POWEROFF },
4767 { '6', ACTION_REBOOT },
4768 { '1', ACTION_RESCUE },
4769 { '2', ACTION_RUNLEVEL2 },
4770 { '3', ACTION_RUNLEVEL3 },
4771 { '4', ACTION_RUNLEVEL4 },
4772 { '5', ACTION_RUNLEVEL5 },
4773 { 's', ACTION_RESCUE },
4774 { 'S', ACTION_RESCUE },
4775 { 'q', ACTION_RELOAD },
4776 { 'Q', ACTION_RELOAD },
4777 { 'u', ACTION_REEXEC },
4778 { 'U', ACTION_REEXEC }
4787 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4802 log_error("Unknown option code '%c'.", c);
4807 if (optind >= argc) {
4812 if (optind + 1 < argc) {
4813 log_error("Too many arguments.");
4817 if (strlen(argv[optind]) != 1) {
4818 log_error("Expected single character argument.");
4822 for (i = 0; i < ELEMENTSOF(table); i++)
4823 if (table[i].from == argv[optind][0])
4826 if (i >= ELEMENTSOF(table)) {
4827 log_error("Unknown command '%s'.", argv[optind]);
4831 arg_action = table[i].to;
4838 static int runlevel_parse_argv(int argc, char *argv[]) {
4844 static const struct option options[] = {
4845 { "help", no_argument, NULL, ARG_HELP },
4846 { NULL, 0, NULL, 0 }
4854 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4865 log_error("Unknown option code '%c'.", c);
4870 if (optind < argc) {
4871 log_error("Too many arguments.");
4878 static int parse_argv(int argc, char *argv[]) {
4882 if (program_invocation_short_name) {
4884 if (strstr(program_invocation_short_name, "halt")) {
4885 arg_action = ACTION_HALT;
4886 return halt_parse_argv(argc, argv);
4887 } else if (strstr(program_invocation_short_name, "poweroff")) {
4888 arg_action = ACTION_POWEROFF;
4889 return halt_parse_argv(argc, argv);
4890 } else if (strstr(program_invocation_short_name, "reboot")) {
4892 arg_action = ACTION_KEXEC;
4894 arg_action = ACTION_REBOOT;
4895 return halt_parse_argv(argc, argv);
4896 } else if (strstr(program_invocation_short_name, "shutdown")) {
4897 arg_action = ACTION_POWEROFF;
4898 return shutdown_parse_argv(argc, argv);
4899 } else if (strstr(program_invocation_short_name, "init")) {
4901 if (sd_booted() > 0) {
4902 arg_action = ACTION_INVALID;
4903 return telinit_parse_argv(argc, argv);
4905 /* Hmm, so some other init system is
4906 * running, we need to forward this
4907 * request to it. For now we simply
4908 * guess that it is Upstart. */
4910 execv("/lib/upstart/telinit", argv);
4912 log_error("Couldn't find an alternative telinit implementation to spawn.");
4916 } else if (strstr(program_invocation_short_name, "runlevel")) {
4917 arg_action = ACTION_RUNLEVEL;
4918 return runlevel_parse_argv(argc, argv);
4922 arg_action = ACTION_SYSTEMCTL;
4923 return systemctl_parse_argv(argc, argv);
4926 static int action_to_runlevel(void) {
4928 static const char table[_ACTION_MAX] = {
4929 [ACTION_HALT] = '0',
4930 [ACTION_POWEROFF] = '0',
4931 [ACTION_REBOOT] = '6',
4932 [ACTION_RUNLEVEL2] = '2',
4933 [ACTION_RUNLEVEL3] = '3',
4934 [ACTION_RUNLEVEL4] = '4',
4935 [ACTION_RUNLEVEL5] = '5',
4936 [ACTION_RESCUE] = '1'
4939 assert(arg_action < _ACTION_MAX);
4941 return table[arg_action];
4944 static int talk_upstart(void) {
4945 DBusMessage _cleanup_dbus_message_unref_ *m = NULL, *reply = NULL;
4946 DBusError _cleanup_dbus_error_free_ error;
4947 int previous, rl, r;
4949 env1_buf[] = "RUNLEVEL=X",
4950 env2_buf[] = "PREVLEVEL=X";
4951 char *env1 = env1_buf, *env2 = env2_buf;
4952 const char *emit = "runlevel";
4953 dbus_bool_t b_false = FALSE;
4954 DBusMessageIter iter, sub;
4955 DBusConnection *bus;
4957 dbus_error_init(&error);
4959 if (!(rl = action_to_runlevel()))
4962 if (utmp_get_runlevel(&previous, NULL) < 0)
4965 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4966 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4971 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4976 if ((r = bus_check_peercred(bus)) < 0) {
4977 log_error("Failed to verify owner of bus.");
4981 if (!(m = dbus_message_new_method_call(
4982 "com.ubuntu.Upstart",
4983 "/com/ubuntu/Upstart",
4984 "com.ubuntu.Upstart0_6",
4987 log_error("Could not allocate message.");
4992 dbus_message_iter_init_append(m, &iter);
4994 env1_buf[sizeof(env1_buf)-2] = rl;
4995 env2_buf[sizeof(env2_buf)-2] = previous;
4997 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4998 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4999 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5000 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5001 !dbus_message_iter_close_container(&iter, &sub) ||
5002 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5003 log_error("Could not append arguments to message.");
5008 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5010 if (bus_error_is_no_service(&error)) {
5015 log_error("Failed to issue method call: %s", bus_error_message(&error));
5024 dbus_connection_flush(bus);
5025 dbus_connection_close(bus);
5026 dbus_connection_unref(bus);
5032 static int talk_initctl(void) {
5033 struct init_request request;
5037 if (!(rl = action_to_runlevel()))
5041 request.magic = INIT_MAGIC;
5042 request.sleeptime = 0;
5043 request.cmd = INIT_CMD_RUNLVL;
5044 request.runlevel = rl;
5046 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5048 if (errno == ENOENT)
5051 log_error("Failed to open "INIT_FIFO": %m");
5056 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5057 close_nointr_nofail(fd);
5060 log_error("Failed to write to "INIT_FIFO": %m");
5061 return errno ? -errno : -EIO;
5067 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5069 static const struct {
5077 int (* const dispatch)(DBusConnection *bus, char **args);
5079 { "list-units", LESS, 1, list_units },
5080 { "list-unit-files", EQUAL, 1, list_unit_files },
5081 { "list-jobs", EQUAL, 1, list_jobs },
5082 { "clear-jobs", EQUAL, 1, daemon_reload },
5083 { "load", MORE, 2, load_unit },
5084 { "cancel", MORE, 2, cancel_job },
5085 { "start", MORE, 2, start_unit },
5086 { "stop", MORE, 2, start_unit },
5087 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5088 { "reload", MORE, 2, start_unit },
5089 { "restart", MORE, 2, start_unit },
5090 { "try-restart", MORE, 2, start_unit },
5091 { "reload-or-restart", MORE, 2, start_unit },
5092 { "reload-or-try-restart", MORE, 2, start_unit },
5093 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5094 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5095 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5096 { "isolate", EQUAL, 2, start_unit },
5097 { "set-cgroup", MORE, 3, set_cgroup },
5098 { "unset-cgroup", MORE, 3, set_cgroup },
5099 { "get-cgroup-attr", MORE, 3, get_cgroup_attr },
5100 { "set-cgroup-attr", MORE, 4, set_cgroup_attr },
5101 { "unset-cgroup-attr", MORE, 3, set_cgroup },
5102 { "kill", MORE, 2, kill_unit },
5103 { "is-active", MORE, 2, check_unit_active },
5104 { "check", MORE, 2, check_unit_active },
5105 { "is-failed", MORE, 2, check_unit_failed },
5106 { "show", MORE, 1, show },
5107 { "status", MORE, 1, show },
5108 { "help", MORE, 2, show },
5109 { "dump", EQUAL, 1, dump },
5110 { "snapshot", LESS, 2, snapshot },
5111 { "delete", MORE, 2, delete_snapshot },
5112 { "daemon-reload", EQUAL, 1, daemon_reload },
5113 { "daemon-reexec", EQUAL, 1, daemon_reload },
5114 { "show-environment", EQUAL, 1, show_enviroment },
5115 { "set-environment", MORE, 2, set_environment },
5116 { "unset-environment", MORE, 2, set_environment },
5117 { "halt", EQUAL, 1, start_special },
5118 { "poweroff", EQUAL, 1, start_special },
5119 { "reboot", EQUAL, 1, start_special },
5120 { "kexec", EQUAL, 1, start_special },
5121 { "suspend", EQUAL, 1, start_special },
5122 { "hibernate", EQUAL, 1, start_special },
5123 { "hybrid-sleep", EQUAL, 1, start_special },
5124 { "default", EQUAL, 1, start_special },
5125 { "rescue", EQUAL, 1, start_special },
5126 { "emergency", EQUAL, 1, start_special },
5127 { "exit", EQUAL, 1, start_special },
5128 { "reset-failed", MORE, 1, reset_failed },
5129 { "enable", MORE, 2, enable_unit },
5130 { "disable", MORE, 2, enable_unit },
5131 { "is-enabled", MORE, 2, unit_is_enabled },
5132 { "reenable", MORE, 2, enable_unit },
5133 { "preset", MORE, 2, enable_unit },
5134 { "mask", MORE, 2, enable_unit },
5135 { "unmask", MORE, 2, enable_unit },
5136 { "link", MORE, 2, enable_unit },
5137 { "switch-root", MORE, 2, switch_root },
5138 { "list-dependencies", LESS, 2, list_dependencies },
5148 left = argc - optind;
5151 /* Special rule: no arguments means "list-units" */
5154 if (streq(argv[optind], "help") && !argv[optind+1]) {
5155 log_error("This command expects one or more "
5156 "unit names. Did you mean --help?");
5160 for (i = 0; i < ELEMENTSOF(verbs); i++)
5161 if (streq(argv[optind], verbs[i].verb))
5164 if (i >= ELEMENTSOF(verbs)) {
5165 log_error("Unknown operation '%s'.", argv[optind]);
5170 switch (verbs[i].argc_cmp) {
5173 if (left != verbs[i].argc) {
5174 log_error("Invalid number of arguments.");
5181 if (left < verbs[i].argc) {
5182 log_error("Too few arguments.");
5189 if (left > verbs[i].argc) {
5190 log_error("Too many arguments.");
5197 assert_not_reached("Unknown comparison operator.");
5200 /* Require a bus connection for all operations but
5202 if (!streq(verbs[i].verb, "enable") &&
5203 !streq(verbs[i].verb, "disable") &&
5204 !streq(verbs[i].verb, "is-enabled") &&
5205 !streq(verbs[i].verb, "list-unit-files") &&
5206 !streq(verbs[i].verb, "reenable") &&
5207 !streq(verbs[i].verb, "preset") &&
5208 !streq(verbs[i].verb, "mask") &&
5209 !streq(verbs[i].verb, "unmask") &&
5210 !streq(verbs[i].verb, "link")) {
5212 if (running_in_chroot() > 0) {
5213 log_info("Running in chroot, ignoring request.");
5217 if (((!streq(verbs[i].verb, "reboot") &&
5218 !streq(verbs[i].verb, "halt") &&
5219 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5220 log_error("Failed to get D-Bus connection: %s",
5221 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5227 if (!bus && !avoid_bus()) {
5228 log_error("Failed to get D-Bus connection: %s",
5229 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5234 return verbs[i].dispatch(bus, argv + optind);
5237 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5238 int _cleanup_close_ fd;
5239 struct msghdr msghdr;
5240 struct iovec iovec[2];
5241 union sockaddr_union sockaddr;
5242 struct sd_shutdown_command c;
5244 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5251 c.dry_run = dry_run;
5255 sockaddr.sa.sa_family = AF_UNIX;
5256 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5259 msghdr.msg_name = &sockaddr;
5260 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5263 iovec[0].iov_base = (char*) &c;
5264 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5266 if (isempty(message))
5267 msghdr.msg_iovlen = 1;
5269 iovec[1].iov_base = (char*) message;
5270 iovec[1].iov_len = strlen(message);
5271 msghdr.msg_iovlen = 2;
5273 msghdr.msg_iov = iovec;
5275 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5281 static int reload_with_fallback(DBusConnection *bus) {
5284 /* First, try systemd via D-Bus. */
5285 if (daemon_reload(bus, NULL) >= 0)
5289 /* Nothing else worked, so let's try signals */
5290 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5292 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5293 log_error("kill() failed: %m");
5300 static int start_with_fallback(DBusConnection *bus) {
5303 /* First, try systemd via D-Bus. */
5304 if (start_unit(bus, NULL) >= 0)
5308 /* Hmm, talking to systemd via D-Bus didn't work. Then
5309 * let's try to talk to Upstart via D-Bus. */
5310 if (talk_upstart() > 0)
5313 /* Nothing else worked, so let's try
5315 if (talk_initctl() > 0)
5318 log_error("Failed to talk to init daemon.");
5322 warn_wall(arg_action);
5326 static _noreturn_ void halt_now(enum action a) {
5328 /* Make sure C-A-D is handled by the kernel from this
5330 reboot(RB_ENABLE_CAD);
5335 log_info("Halting.");
5336 reboot(RB_HALT_SYSTEM);
5339 case ACTION_POWEROFF:
5340 log_info("Powering off.");
5341 reboot(RB_POWER_OFF);
5345 log_info("Rebooting.");
5346 reboot(RB_AUTOBOOT);
5350 assert_not_reached("Unknown halt action.");
5353 assert_not_reached("Uh? This shouldn't happen.");
5356 static int halt_main(DBusConnection *bus) {
5359 r = check_inhibitors(bus, arg_action);
5363 if (geteuid() != 0) {
5364 /* Try logind if we are a normal user and no special
5365 * mode applies. Maybe PolicyKit allows us to shutdown
5368 if (arg_when <= 0 &&
5371 (arg_action == ACTION_POWEROFF ||
5372 arg_action == ACTION_REBOOT)) {
5373 r = reboot_with_logind(bus, arg_action);
5378 log_error("Must be root.");
5383 char _cleanup_free_ *m;
5385 m = strv_join(arg_wall, " ");
5386 r = send_shutdownd(arg_when,
5387 arg_action == ACTION_HALT ? 'H' :
5388 arg_action == ACTION_POWEROFF ? 'P' :
5389 arg_action == ACTION_KEXEC ? 'K' :
5396 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5398 char date[FORMAT_TIMESTAMP_MAX];
5400 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5401 format_timestamp(date, sizeof(date), arg_when));
5406 if (!arg_dry && !arg_force)
5407 return start_with_fallback(bus);
5410 if (sd_booted() > 0)
5411 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5413 r = utmp_put_shutdown();
5415 log_warning("Failed to write utmp record: %s", strerror(-r));
5422 halt_now(arg_action);
5423 /* We should never reach this. */
5427 static int runlevel_main(void) {
5428 int r, runlevel, previous;
5430 r = utmp_get_runlevel(&runlevel, &previous);
5437 previous <= 0 ? 'N' : previous,
5438 runlevel <= 0 ? 'N' : runlevel);
5443 int main(int argc, char*argv[]) {
5444 int r, retval = EXIT_FAILURE;
5445 DBusConnection *bus = NULL;
5446 DBusError _cleanup_dbus_error_free_ error;
5448 dbus_error_init(&error);
5450 setlocale(LC_ALL, "");
5451 log_parse_environment();
5454 r = parse_argv(argc, argv);
5458 retval = EXIT_SUCCESS;
5462 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5463 * let's shortcut this */
5464 if (arg_action == ACTION_RUNLEVEL) {
5465 r = runlevel_main();
5466 retval = r < 0 ? EXIT_FAILURE : r;
5470 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5471 log_info("Running in chroot, ignoring request.");
5477 if (arg_transport == TRANSPORT_NORMAL)
5478 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5479 else if (arg_transport == TRANSPORT_POLKIT) {
5480 bus_connect_system_polkit(&bus, &error);
5481 private_bus = false;
5482 } else if (arg_transport == TRANSPORT_SSH) {
5483 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5484 private_bus = false;
5486 assert_not_reached("Uh, invalid transport...");
5489 switch (arg_action) {
5491 case ACTION_SYSTEMCTL:
5492 r = systemctl_main(bus, argc, argv, &error);
5496 case ACTION_POWEROFF:
5502 case ACTION_RUNLEVEL2:
5503 case ACTION_RUNLEVEL3:
5504 case ACTION_RUNLEVEL4:
5505 case ACTION_RUNLEVEL5:
5507 case ACTION_EMERGENCY:
5508 case ACTION_DEFAULT:
5509 r = start_with_fallback(bus);
5514 r = reload_with_fallback(bus);
5517 case ACTION_CANCEL_SHUTDOWN: {
5521 m = strv_join(arg_wall, " ");
5523 retval = EXIT_FAILURE;
5527 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5529 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5534 case ACTION_INVALID:
5535 case ACTION_RUNLEVEL:
5537 assert_not_reached("Unknown action");
5540 retval = r < 0 ? EXIT_FAILURE : r;
5544 dbus_connection_flush(bus);
5545 dbus_connection_close(bus);
5546 dbus_connection_unref(bus);
5551 strv_free(arg_property);
5554 ask_password_agent_close();
5555 polkit_agent_close();