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 if (!dbus_message_iter_init(reply, &iter)) {
2088 log_error("Failed to initialize iterator.");
2092 r = bus_parse_strv_iter(&iter, &list);
2094 log_error("Failed to parse value list.");
2098 STRV_FOREACH(a, list) {
2099 if (endswith(*a, "\n"))
2109 typedef struct ExecStatusInfo {
2117 usec_t start_timestamp;
2118 usec_t exit_timestamp;
2123 LIST_FIELDS(struct ExecStatusInfo, exec);
2126 static void exec_status_info_free(ExecStatusInfo *i) {
2135 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2136 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2137 DBusMessageIter sub2, sub3;
2141 int32_t code, status;
2147 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2150 dbus_message_iter_recurse(sub, &sub2);
2152 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2155 i->path = strdup(path);
2159 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2160 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2164 dbus_message_iter_recurse(&sub2, &sub3);
2165 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2166 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2167 dbus_message_iter_next(&sub3);
2171 i->argv = new0(char*, n+1);
2176 dbus_message_iter_recurse(&sub2, &sub3);
2177 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2180 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2181 dbus_message_iter_get_basic(&sub3, &s);
2182 dbus_message_iter_next(&sub3);
2184 i->argv[n] = strdup(s);
2191 if (!dbus_message_iter_next(&sub2) ||
2192 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2193 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2194 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2195 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2196 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2197 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2198 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2199 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2203 i->start_timestamp = (usec_t) start_timestamp;
2204 i->exit_timestamp = (usec_t) exit_timestamp;
2205 i->pid = (pid_t) pid;
2212 typedef struct UnitStatusInfo {
2214 const char *load_state;
2215 const char *active_state;
2216 const char *sub_state;
2217 const char *unit_file_state;
2219 const char *description;
2220 const char *following;
2222 char **documentation;
2224 const char *fragment_path;
2225 const char *source_path;
2226 const char *default_control_group;
2228 const char *load_error;
2231 usec_t inactive_exit_timestamp;
2232 usec_t inactive_exit_timestamp_monotonic;
2233 usec_t active_enter_timestamp;
2234 usec_t active_exit_timestamp;
2235 usec_t inactive_enter_timestamp;
2237 bool need_daemon_reload;
2242 const char *status_text;
2245 usec_t start_timestamp;
2246 usec_t exit_timestamp;
2248 int exit_code, exit_status;
2250 usec_t condition_timestamp;
2251 bool condition_result;
2254 unsigned n_accepted;
2255 unsigned n_connections;
2259 const char *sysfs_path;
2261 /* Mount, Automount */
2267 LIST_HEAD(ExecStatusInfo, exec);
2270 static void print_status_info(UnitStatusInfo *i) {
2272 const char *on, *off, *ss;
2274 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2275 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2278 arg_all * OUTPUT_SHOW_ALL |
2279 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2280 on_tty() * OUTPUT_COLOR |
2281 !arg_quiet * OUTPUT_WARN_CUTOFF |
2282 arg_full * OUTPUT_FULL_WIDTH;
2286 /* This shows pretty information about a unit. See
2287 * print_property() for a low-level property printer */
2289 printf("%s", strna(i->id));
2291 if (i->description && !streq_ptr(i->id, i->description))
2292 printf(" - %s", i->description);
2297 printf("\t Follow: unit currently follows state of %s\n", i->following);
2299 if (streq_ptr(i->load_state, "error")) {
2300 on = ansi_highlight_red(true);
2301 off = ansi_highlight_red(false);
2305 path = i->source_path ? i->source_path : i->fragment_path;
2308 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2309 else if (path && i->unit_file_state)
2310 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2312 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2314 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2316 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2318 if (streq_ptr(i->active_state, "failed")) {
2319 on = ansi_highlight_red(true);
2320 off = ansi_highlight_red(false);
2321 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2322 on = ansi_highlight_green(true);
2323 off = ansi_highlight_green(false);
2328 printf("\t Active: %s%s (%s)%s",
2330 strna(i->active_state),
2334 printf("\t Active: %s%s%s",
2336 strna(i->active_state),
2339 if (!isempty(i->result) && !streq(i->result, "success"))
2340 printf(" (Result: %s)", i->result);
2342 timestamp = (streq_ptr(i->active_state, "active") ||
2343 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2344 (streq_ptr(i->active_state, "inactive") ||
2345 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2346 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2347 i->active_exit_timestamp;
2349 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2350 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2353 printf(" since %s; %s\n", s2, s1);
2355 printf(" since %s\n", s2);
2359 if (!i->condition_result && i->condition_timestamp > 0) {
2360 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2361 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2364 printf("\t start condition failed at %s; %s\n", s2, s1);
2366 printf("\t start condition failed at %s\n", s2);
2370 printf("\t Device: %s\n", i->sysfs_path);
2372 printf("\t Where: %s\n", i->where);
2374 printf("\t What: %s\n", i->what);
2376 if (!strv_isempty(i->documentation)) {
2380 STRV_FOREACH(t, i->documentation) {
2382 printf("\t Docs: %s\n", *t);
2385 printf("\t %s\n", *t);
2390 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2392 LIST_FOREACH(exec, p, i->exec) {
2393 _cleanup_free_ char *t = NULL;
2396 /* Only show exited processes here */
2400 t = strv_join(p->argv, " ");
2401 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2403 good = is_clean_exit_lsb(p->code, p->status, NULL);
2405 on = ansi_highlight_red(true);
2406 off = ansi_highlight_red(false);
2410 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2412 if (p->code == CLD_EXITED) {
2415 printf("status=%i", p->status);
2417 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2422 printf("signal=%s", signal_to_string(p->status));
2424 printf(")%s\n", off);
2426 if (i->main_pid == p->pid &&
2427 i->start_timestamp == p->start_timestamp &&
2428 i->exit_timestamp == p->start_timestamp)
2429 /* Let's not show this twice */
2432 if (p->pid == i->control_pid)
2436 if (i->main_pid > 0 || i->control_pid > 0) {
2439 if (i->main_pid > 0) {
2440 printf("Main PID: %u", (unsigned) i->main_pid);
2443 _cleanup_free_ char *t = NULL;
2444 get_process_comm(i->main_pid, &t);
2447 } else if (i->exit_code > 0) {
2448 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2450 if (i->exit_code == CLD_EXITED) {
2453 printf("status=%i", i->exit_status);
2455 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2460 printf("signal=%s", signal_to_string(i->exit_status));
2465 if (i->main_pid > 0 && i->control_pid > 0)
2468 if (i->control_pid > 0) {
2469 _cleanup_free_ char *t = NULL;
2471 printf(" Control: %u", (unsigned) i->control_pid);
2473 get_process_comm(i->control_pid, &t);
2482 printf("\t Status: \"%s\"\n", i->status_text);
2484 if (i->default_control_group &&
2485 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2488 printf("\t CGroup: %s\n", i->default_control_group);
2490 if (arg_transport != TRANSPORT_SSH) {
2500 if (i->main_pid > 0)
2501 extra[k++] = i->main_pid;
2503 if (i->control_pid > 0)
2504 extra[k++] = i->control_pid;
2506 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, extra, k, flags);
2510 if (i->id && arg_transport != TRANSPORT_SSH) {
2512 if(arg_scope == UNIT_FILE_SYSTEM)
2513 show_journal_by_unit(stdout,
2517 i->inactive_exit_timestamp_monotonic,
2521 show_journal_by_user_unit(stdout,
2525 i->inactive_exit_timestamp_monotonic,
2531 if (i->need_daemon_reload)
2532 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2533 ansi_highlight_red(true),
2534 ansi_highlight_red(false),
2535 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2538 static void show_unit_help(UnitStatusInfo *i) {
2543 if (!i->documentation) {
2544 log_info("Documentation for %s not known.", i->id);
2548 STRV_FOREACH(p, i->documentation) {
2550 if (startswith(*p, "man:")) {
2553 char _cleanup_free_ *page = NULL, *section = NULL;
2554 const char *args[4] = { "man", NULL, NULL, NULL };
2559 if ((*p)[k-1] == ')')
2560 e = strrchr(*p, '(');
2563 page = strndup((*p) + 4, e - *p - 4);
2564 section = strndup(e + 1, *p + k - e - 2);
2565 if (!page || !section) {
2577 log_error("Failed to fork: %m");
2583 execvp(args[0], (char**) args);
2584 log_error("Failed to execute man: %m");
2585 _exit(EXIT_FAILURE);
2588 wait_for_terminate(pid, NULL);
2590 log_info("Can't show: %s", *p);
2594 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2600 switch (dbus_message_iter_get_arg_type(iter)) {
2602 case DBUS_TYPE_STRING: {
2605 dbus_message_iter_get_basic(iter, &s);
2608 if (streq(name, "Id"))
2610 else if (streq(name, "LoadState"))
2612 else if (streq(name, "ActiveState"))
2613 i->active_state = s;
2614 else if (streq(name, "SubState"))
2616 else if (streq(name, "Description"))
2618 else if (streq(name, "FragmentPath"))
2619 i->fragment_path = s;
2620 else if (streq(name, "SourcePath"))
2622 else if (streq(name, "DefaultControlGroup"))
2623 i->default_control_group = s;
2624 else if (streq(name, "StatusText"))
2626 else if (streq(name, "SysFSPath"))
2628 else if (streq(name, "Where"))
2630 else if (streq(name, "What"))
2632 else if (streq(name, "Following"))
2634 else if (streq(name, "UnitFileState"))
2635 i->unit_file_state = s;
2636 else if (streq(name, "Result"))
2643 case DBUS_TYPE_BOOLEAN: {
2646 dbus_message_iter_get_basic(iter, &b);
2648 if (streq(name, "Accept"))
2650 else if (streq(name, "NeedDaemonReload"))
2651 i->need_daemon_reload = b;
2652 else if (streq(name, "ConditionResult"))
2653 i->condition_result = b;
2658 case DBUS_TYPE_UINT32: {
2661 dbus_message_iter_get_basic(iter, &u);
2663 if (streq(name, "MainPID")) {
2665 i->main_pid = (pid_t) u;
2668 } else if (streq(name, "ControlPID"))
2669 i->control_pid = (pid_t) u;
2670 else if (streq(name, "ExecMainPID")) {
2672 i->main_pid = (pid_t) u;
2673 } else if (streq(name, "NAccepted"))
2675 else if (streq(name, "NConnections"))
2676 i->n_connections = u;
2681 case DBUS_TYPE_INT32: {
2684 dbus_message_iter_get_basic(iter, &j);
2686 if (streq(name, "ExecMainCode"))
2687 i->exit_code = (int) j;
2688 else if (streq(name, "ExecMainStatus"))
2689 i->exit_status = (int) j;
2694 case DBUS_TYPE_UINT64: {
2697 dbus_message_iter_get_basic(iter, &u);
2699 if (streq(name, "ExecMainStartTimestamp"))
2700 i->start_timestamp = (usec_t) u;
2701 else if (streq(name, "ExecMainExitTimestamp"))
2702 i->exit_timestamp = (usec_t) u;
2703 else if (streq(name, "ActiveEnterTimestamp"))
2704 i->active_enter_timestamp = (usec_t) u;
2705 else if (streq(name, "InactiveEnterTimestamp"))
2706 i->inactive_enter_timestamp = (usec_t) u;
2707 else if (streq(name, "InactiveExitTimestamp"))
2708 i->inactive_exit_timestamp = (usec_t) u;
2709 else if (streq(name, "InactiveExitTimestampMonotonic"))
2710 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2711 else if (streq(name, "ActiveExitTimestamp"))
2712 i->active_exit_timestamp = (usec_t) u;
2713 else if (streq(name, "ConditionTimestamp"))
2714 i->condition_timestamp = (usec_t) u;
2719 case DBUS_TYPE_ARRAY: {
2721 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2722 startswith(name, "Exec")) {
2723 DBusMessageIter sub;
2725 dbus_message_iter_recurse(iter, &sub);
2726 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2727 ExecStatusInfo *info;
2730 if (!(info = new0(ExecStatusInfo, 1)))
2733 if (!(info->name = strdup(name))) {
2738 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2743 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2745 dbus_message_iter_next(&sub);
2747 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2748 streq(name, "Documentation")) {
2750 DBusMessageIter sub;
2752 dbus_message_iter_recurse(iter, &sub);
2753 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2757 dbus_message_iter_get_basic(&sub, &s);
2759 l = strv_append(i->documentation, s);
2763 strv_free(i->documentation);
2764 i->documentation = l;
2766 dbus_message_iter_next(&sub);
2773 case DBUS_TYPE_STRUCT: {
2775 if (streq(name, "LoadError")) {
2776 DBusMessageIter sub;
2777 const char *n, *message;
2780 dbus_message_iter_recurse(iter, &sub);
2782 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2786 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2790 if (!isempty(message))
2791 i->load_error = message;
2801 static int print_property(const char *name, DBusMessageIter *iter) {
2805 /* This is a low-level property printer, see
2806 * print_status_info() for the nicer output */
2808 if (arg_property && !strv_find(arg_property, name))
2811 switch (dbus_message_iter_get_arg_type(iter)) {
2813 case DBUS_TYPE_STRUCT: {
2814 DBusMessageIter sub;
2815 dbus_message_iter_recurse(iter, &sub);
2817 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2820 dbus_message_iter_get_basic(&sub, &u);
2823 printf("%s=%u\n", name, (unsigned) u);
2825 printf("%s=\n", name);
2828 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2831 dbus_message_iter_get_basic(&sub, &s);
2833 if (arg_all || s[0])
2834 printf("%s=%s\n", name, s);
2837 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2838 const char *a = NULL, *b = NULL;
2840 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2841 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2843 if (arg_all || !isempty(a) || !isempty(b))
2844 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2852 case DBUS_TYPE_ARRAY:
2854 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2855 DBusMessageIter sub, sub2;
2857 dbus_message_iter_recurse(iter, &sub);
2858 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2862 dbus_message_iter_recurse(&sub, &sub2);
2864 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2865 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2866 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2868 dbus_message_iter_next(&sub);
2873 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2874 DBusMessageIter sub, sub2;
2876 dbus_message_iter_recurse(iter, &sub);
2877 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2878 const char *type, *path;
2880 dbus_message_iter_recurse(&sub, &sub2);
2882 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2883 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2884 printf("%s=%s\n", type, path);
2886 dbus_message_iter_next(&sub);
2891 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2892 DBusMessageIter sub, sub2;
2894 dbus_message_iter_recurse(iter, &sub);
2895 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2897 uint64_t value, next_elapse;
2899 dbus_message_iter_recurse(&sub, &sub2);
2901 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2902 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2903 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2904 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2906 printf("%s={ value=%s ; next_elapse=%s }\n",
2908 format_timespan(timespan1, sizeof(timespan1), value),
2909 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2912 dbus_message_iter_next(&sub);
2917 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2918 DBusMessageIter sub, sub2;
2920 dbus_message_iter_recurse(iter, &sub);
2921 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2922 const char *controller, *attr, *value;
2924 dbus_message_iter_recurse(&sub, &sub2);
2926 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2927 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2928 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2930 printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2936 dbus_message_iter_next(&sub);
2941 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2942 DBusMessageIter sub;
2944 dbus_message_iter_recurse(iter, &sub);
2945 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2946 ExecStatusInfo info;
2949 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2950 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2951 char _cleanup_free_ *t;
2953 t = strv_join(info.argv, " ");
2955 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2959 yes_no(info.ignore),
2960 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2961 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2962 (unsigned) info. pid,
2963 sigchld_code_to_string(info.code),
2965 info.code == CLD_EXITED ? "" : "/",
2966 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2970 strv_free(info.argv);
2972 dbus_message_iter_next(&sub);
2981 if (generic_print_property(name, iter, arg_all) > 0)
2985 printf("%s=[unprintable]\n", name);
2990 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2991 _cleanup_free_ DBusMessage *reply = NULL;
2992 const char *interface = "";
2994 DBusMessageIter iter, sub, sub2, sub3;
2995 UnitStatusInfo info;
3003 r = bus_method_call_with_reply(
3005 "org.freedesktop.systemd1",
3007 "org.freedesktop.DBus.Properties",
3011 DBUS_TYPE_STRING, &interface,
3016 if (!dbus_message_iter_init(reply, &iter) ||
3017 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3018 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3019 log_error("Failed to parse reply.");
3023 dbus_message_iter_recurse(&iter, &sub);
3030 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3033 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3034 dbus_message_iter_recurse(&sub, &sub2);
3036 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3037 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3038 log_error("Failed to parse reply.");
3042 dbus_message_iter_recurse(&sub2, &sub3);
3044 if (show_properties)
3045 r = print_property(name, &sub3);
3047 r = status_property(name, &sub3, &info);
3049 log_error("Failed to parse reply.");
3053 dbus_message_iter_next(&sub);
3058 if (!show_properties) {
3059 if (streq(verb, "help"))
3060 show_unit_help(&info);
3062 print_status_info(&info);
3065 strv_free(info.documentation);
3067 if (!streq_ptr(info.active_state, "active") &&
3068 !streq_ptr(info.active_state, "reloading") &&
3069 streq(verb, "status"))
3070 /* According to LSB: "program not running" */
3073 while ((p = info.exec)) {
3074 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3075 exec_status_info_free(p);
3081 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3082 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3083 const char *path = NULL;
3084 DBusError _cleanup_dbus_error_free_ error;
3087 dbus_error_init(&error);
3089 r = bus_method_call_with_reply(
3091 "org.freedesktop.systemd1",
3092 "/org/freedesktop/systemd1",
3093 "org.freedesktop.systemd1.Manager",
3097 DBUS_TYPE_UINT32, &pid,
3102 if (!dbus_message_get_args(reply, &error,
3103 DBUS_TYPE_OBJECT_PATH, &path,
3104 DBUS_TYPE_INVALID)) {
3105 log_error("Failed to parse reply: %s", bus_error_message(&error));
3109 r = show_one(verb, bus, path, false, new_line);
3113 static int show_all(const char* verb, DBusConnection *bus, bool show_properties, bool *new_line) {
3114 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3115 _cleanup_free_ struct unit_info *unit_infos = NULL;
3117 const struct unit_info *u;
3120 r = get_unit_list(bus, &reply, &unit_infos, &c);
3124 for (u = unit_infos; u < unit_infos + c; u++) {
3125 char _cleanup_free_ *p = NULL;
3127 if (!output_show_unit(u))
3130 p = unit_dbus_path_from_name(u->id);
3134 printf("%s -> '%s'\n", u->id, p);
3136 r = show_one(verb, bus, p, show_properties, new_line);
3144 static int show(DBusConnection *bus, char **args) {
3146 bool show_properties, show_status, new_line = false;
3152 show_properties = streq(args[0], "show");
3153 show_status = streq(args[0], "status");
3155 if (show_properties)
3156 pager_open_if_enabled();
3158 /* If no argument is specified inspect the manager itself */
3160 if (show_properties && strv_length(args) <= 1)
3161 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3163 if (show_status && strv_length(args) <= 1)
3164 return show_all(args[0], bus, false, &new_line);
3166 STRV_FOREACH(name, args+1) {
3169 if (safe_atou32(*name, &id) < 0) {
3170 _cleanup_free_ char *p = NULL, *n = NULL;
3171 /* Interpret as unit name */
3173 n = unit_name_mangle(*name);
3177 p = unit_dbus_path_from_name(n);
3181 r = show_one(args[0], bus, p, show_properties, &new_line);
3185 } else if (show_properties) {
3186 _cleanup_free_ char *p = NULL;
3188 /* Interpret as job id */
3189 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3192 r = show_one(args[0], bus, p, show_properties, &new_line);
3197 /* Interpret as PID */
3198 r = show_one_by_pid(args[0], bus, id, &new_line);
3207 static int dump(DBusConnection *bus, char **args) {
3208 _cleanup_free_ DBusMessage *reply = NULL;
3213 dbus_error_init(&error);
3215 pager_open_if_enabled();
3217 r = bus_method_call_with_reply(
3219 "org.freedesktop.systemd1",
3220 "/org/freedesktop/systemd1",
3221 "org.freedesktop.systemd1.Manager",
3229 if (!dbus_message_get_args(reply, &error,
3230 DBUS_TYPE_STRING, &text,
3231 DBUS_TYPE_INVALID)) {
3232 log_error("Failed to parse reply: %s", bus_error_message(&error));
3233 dbus_error_free(&error);
3237 fputs(text, stdout);
3241 static int snapshot(DBusConnection *bus, char **args) {
3242 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3245 dbus_bool_t cleanup = FALSE;
3246 DBusMessageIter iter, sub;
3249 *interface = "org.freedesktop.systemd1.Unit",
3251 _cleanup_free_ char *n = NULL;
3253 dbus_error_init(&error);
3255 if (strv_length(args) > 1)
3256 n = snapshot_name_mangle(args[1]);
3262 r = bus_method_call_with_reply (
3264 "org.freedesktop.systemd1",
3265 "/org/freedesktop/systemd1",
3266 "org.freedesktop.systemd1.Manager",
3270 DBUS_TYPE_STRING, &n,
3271 DBUS_TYPE_BOOLEAN, &cleanup,
3276 if (!dbus_message_get_args(reply, &error,
3277 DBUS_TYPE_OBJECT_PATH, &path,
3278 DBUS_TYPE_INVALID)) {
3279 log_error("Failed to parse reply: %s", bus_error_message(&error));
3280 dbus_error_free(&error);
3284 dbus_message_unref(reply);
3287 r = bus_method_call_with_reply (
3289 "org.freedesktop.systemd1",
3291 "org.freedesktop.DBus.Properties",
3295 DBUS_TYPE_STRING, &interface,
3296 DBUS_TYPE_STRING, &property,
3301 if (!dbus_message_iter_init(reply, &iter) ||
3302 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3303 log_error("Failed to parse reply.");
3307 dbus_message_iter_recurse(&iter, &sub);
3309 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3310 log_error("Failed to parse reply.");
3314 dbus_message_iter_get_basic(&sub, &id);
3322 static int delete_snapshot(DBusConnection *bus, char **args) {
3327 STRV_FOREACH(name, args+1) {
3328 _cleanup_free_ char *n = NULL;
3331 n = snapshot_name_mangle(*name);
3335 r = bus_method_call_with_reply(
3337 "org.freedesktop.systemd1",
3338 "/org/freedesktop/systemd1",
3339 "org.freedesktop.systemd1.Manager",
3343 DBUS_TYPE_STRING, &n,
3352 static int daemon_reload(DBusConnection *bus, char **args) {
3357 if (arg_action == ACTION_RELOAD)
3359 else if (arg_action == ACTION_REEXEC)
3360 method = "Reexecute";
3362 assert(arg_action == ACTION_SYSTEMCTL);
3365 streq(args[0], "clear-jobs") ||
3366 streq(args[0], "cancel") ? "ClearJobs" :
3367 streq(args[0], "daemon-reexec") ? "Reexecute" :
3368 streq(args[0], "reset-failed") ? "ResetFailed" :
3369 streq(args[0], "halt") ? "Halt" :
3370 streq(args[0], "poweroff") ? "PowerOff" :
3371 streq(args[0], "reboot") ? "Reboot" :
3372 streq(args[0], "kexec") ? "KExec" :
3373 streq(args[0], "exit") ? "Exit" :
3374 /* "daemon-reload" */ "Reload";
3377 r = bus_method_call_with_reply(
3379 "org.freedesktop.systemd1",
3380 "/org/freedesktop/systemd1",
3381 "org.freedesktop.systemd1.Manager",
3387 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3388 /* There's always a fallback possible for
3389 * legacy actions. */
3391 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3392 /* On reexecution, we expect a disconnect, not
3396 log_error("Failed to issue method call: %s", bus_error_message(&error));
3398 dbus_error_free(&error);
3402 static int reset_failed(DBusConnection *bus, char **args) {
3406 if (strv_length(args) <= 1)
3407 return daemon_reload(bus, args);
3409 STRV_FOREACH(name, args+1) {
3410 _cleanup_free_ char *n;
3412 n = unit_name_mangle(*name);
3416 r = bus_method_call_with_reply(
3418 "org.freedesktop.systemd1",
3419 "/org/freedesktop/systemd1",
3420 "org.freedesktop.systemd1.Manager",
3424 DBUS_TYPE_STRING, &n,
3433 static int show_enviroment(DBusConnection *bus, char **args) {
3434 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3435 DBusMessageIter iter, sub, sub2;
3438 *interface = "org.freedesktop.systemd1.Manager",
3439 *property = "Environment";
3441 pager_open_if_enabled();
3443 r = bus_method_call_with_reply(
3445 "org.freedesktop.systemd1",
3446 "/org/freedesktop/systemd1",
3447 "org.freedesktop.DBus.Properties",
3451 DBUS_TYPE_STRING, &interface,
3452 DBUS_TYPE_STRING, &property,
3457 if (!dbus_message_iter_init(reply, &iter) ||
3458 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3459 log_error("Failed to parse reply.");
3463 dbus_message_iter_recurse(&iter, &sub);
3465 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3466 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3467 log_error("Failed to parse reply.");
3471 dbus_message_iter_recurse(&sub, &sub2);
3473 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3476 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3477 log_error("Failed to parse reply.");
3481 dbus_message_iter_get_basic(&sub2, &text);
3484 dbus_message_iter_next(&sub2);
3490 static int switch_root(DBusConnection *bus, char **args) {
3493 _cleanup_free_ char *init = NULL;
3495 l = strv_length(args);
3496 if (l < 2 || l > 3) {
3497 log_error("Wrong number of arguments.");
3504 init = strdup(args[2]);
3506 parse_env_file("/proc/cmdline", WHITESPACE,
3516 log_debug("switching root - root: %s; init: %s", root, init);
3518 return bus_method_call_with_reply(
3520 "org.freedesktop.systemd1",
3521 "/org/freedesktop/systemd1",
3522 "org.freedesktop.systemd1.Manager",
3526 DBUS_TYPE_STRING, &root,
3527 DBUS_TYPE_STRING, &init,
3531 static int set_environment(DBusConnection *bus, char **args) {
3532 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3535 DBusMessageIter iter;
3541 dbus_error_init(&error);
3543 method = streq(args[0], "set-environment")
3545 : "UnsetEnvironment";
3547 m = dbus_message_new_method_call(
3548 "org.freedesktop.systemd1",
3549 "/org/freedesktop/systemd1",
3550 "org.freedesktop.systemd1.Manager",
3555 dbus_message_iter_init_append(m, &iter);
3557 r = bus_append_strv_iter(&iter, args + 1);
3561 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3563 log_error("Failed to issue method call: %s", bus_error_message(&error));
3564 dbus_error_free(&error);
3571 static int enable_sysv_units(char **args) {
3574 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3575 const char *verb = args[0];
3576 unsigned f = 1, t = 1;
3579 if (arg_scope != UNIT_FILE_SYSTEM)
3582 if (!streq(verb, "enable") &&
3583 !streq(verb, "disable") &&
3584 !streq(verb, "is-enabled"))
3587 /* Processes all SysV units, and reshuffles the array so that
3588 * afterwards only the native units remain */
3591 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3596 for (f = 1; args[f]; f++) {
3599 bool found_native = false, found_sysv;
3601 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3602 char **k, *l, *q = NULL;
3609 if (!endswith(name, ".service"))
3612 if (path_is_absolute(name))
3615 STRV_FOREACH(k, paths.unit_path) {
3618 if (!isempty(arg_root))
3619 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3621 asprintf(&p, "%s/%s", *k, name);
3628 found_native = access(p, F_OK) >= 0;
3639 if (!isempty(arg_root))
3640 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3642 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3648 p[strlen(p) - sizeof(".service") + 1] = 0;
3649 found_sysv = access(p, F_OK) >= 0;
3656 /* Mark this entry, so that we don't try enabling it as native unit */
3657 args[f] = (char*) "";
3659 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3661 if (!isempty(arg_root))
3662 argv[c++] = q = strappend("--root=", arg_root);
3664 argv[c++] = path_get_file_name(p);
3666 streq(verb, "enable") ? "on" :
3667 streq(verb, "disable") ? "off" : "--level=5";
3670 l = strv_join((char**)argv, " ");
3678 log_info("Executing %s", l);
3683 log_error("Failed to fork: %m");
3688 } else if (pid == 0) {
3691 execv(argv[0], (char**) argv);
3692 _exit(EXIT_FAILURE);
3698 j = wait_for_terminate(pid, &status);
3700 log_error("Failed to wait for child: %s", strerror(-r));
3705 if (status.si_code == CLD_EXITED) {
3706 if (streq(verb, "is-enabled")) {
3707 if (status.si_status == 0) {
3716 } else if (status.si_status != 0) {
3727 lookup_paths_free(&paths);
3729 /* Drop all SysV units */
3730 for (f = 1, t = 1; args[f]; f++) {
3732 if (isempty(args[f]))
3735 args[t++] = args[f];
3744 static int mangle_names(char **original_names, char ***mangled_names) {
3745 char **i, **l, **name;
3747 l = new(char*, strv_length(original_names) + 1);
3752 STRV_FOREACH(name, original_names) {
3754 /* When enabling units qualified path names are OK,
3755 * too, hence allow them explicitly. */
3760 *i = unit_name_mangle(*name);
3776 static int enable_unit(DBusConnection *bus, char **args) {
3777 const char *verb = args[0];
3778 UnitFileChange *changes = NULL;
3779 unsigned n_changes = 0, i;
3780 int carries_install_info = -1;
3781 DBusMessage _cleanup_dbus_message_unref_ *m = NULL, *reply = NULL;
3783 DBusError _cleanup_dbus_error_free_ error;
3784 char _cleanup_strv_free_ **mangled_names = NULL;
3786 dbus_error_init(&error);
3788 r = enable_sysv_units(args);
3795 if (!bus || avoid_bus()) {
3796 if (streq(verb, "enable")) {
3797 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3798 carries_install_info = r;
3799 } else if (streq(verb, "disable"))
3800 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3801 else if (streq(verb, "reenable")) {
3802 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3803 carries_install_info = r;
3804 } else if (streq(verb, "link"))
3805 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3806 else if (streq(verb, "preset")) {
3807 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3808 carries_install_info = r;
3809 } else if (streq(verb, "mask"))
3810 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3811 else if (streq(verb, "unmask"))
3812 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3814 assert_not_reached("Unknown verb");
3817 log_error("Operation failed: %s", strerror(-r));
3822 for (i = 0; i < n_changes; i++) {
3823 if (changes[i].type == UNIT_FILE_SYMLINK)
3824 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3826 log_info("rm '%s'", changes[i].path);
3833 bool send_force = true, expect_carries_install_info = false;
3835 DBusMessageIter iter, sub, sub2;
3837 if (streq(verb, "enable")) {
3838 method = "EnableUnitFiles";
3839 expect_carries_install_info = true;
3840 } else if (streq(verb, "disable")) {
3841 method = "DisableUnitFiles";
3843 } else if (streq(verb, "reenable")) {
3844 method = "ReenableUnitFiles";
3845 expect_carries_install_info = true;
3846 } else if (streq(verb, "link"))
3847 method = "LinkUnitFiles";
3848 else if (streq(verb, "preset")) {
3849 method = "PresetUnitFiles";
3850 expect_carries_install_info = true;
3851 } else if (streq(verb, "mask"))
3852 method = "MaskUnitFiles";
3853 else if (streq(verb, "unmask")) {
3854 method = "UnmaskUnitFiles";
3857 assert_not_reached("Unknown verb");
3859 m = dbus_message_new_method_call(
3860 "org.freedesktop.systemd1",
3861 "/org/freedesktop/systemd1",
3862 "org.freedesktop.systemd1.Manager",
3869 dbus_message_iter_init_append(m, &iter);
3871 r = mangle_names(args+1, &mangled_names);
3875 r = bus_append_strv_iter(&iter, mangled_names);
3877 log_error("Failed to append unit files.");
3882 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3883 log_error("Failed to append runtime boolean.");
3891 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3892 log_error("Failed to append force boolean.");
3898 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3900 log_error("Failed to issue method call: %s", bus_error_message(&error));
3905 if (!dbus_message_iter_init(reply, &iter)) {
3906 log_error("Failed to initialize iterator.");
3910 if (expect_carries_install_info) {
3911 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3913 log_error("Failed to parse reply.");
3917 carries_install_info = b;
3920 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3921 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3922 log_error("Failed to parse reply.");
3927 dbus_message_iter_recurse(&iter, &sub);
3928 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3929 const char *type, *path, *source;
3931 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3932 log_error("Failed to parse reply.");
3937 dbus_message_iter_recurse(&sub, &sub2);
3939 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3940 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3941 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3942 log_error("Failed to parse reply.");
3948 if (streq(type, "symlink"))
3949 log_info("ln -s '%s' '%s'", source, path);
3951 log_info("rm '%s'", path);
3954 dbus_message_iter_next(&sub);
3957 /* Try to reload if enabeld */
3959 r = daemon_reload(bus, args);
3962 if (carries_install_info == 0)
3963 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
3964 "using systemctl.\n"
3965 "Possible reasons for having this kind of units are:\n"
3966 "1) A unit may be statically enabled by being symlinked from another unit's\n"
3967 " .wants/ or .requires/ directory.\n"
3968 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
3969 " a requirement dependency on it.\n"
3970 "3) A unit may be started when needed via activation (socket, path, timer,\n"
3971 " D-Bus, udev, scripted systemctl call, ...).\n");
3974 unit_file_changes_free(changes, n_changes);
3979 static int unit_is_enabled(DBusConnection *bus, char **args) {
3980 DBusError _cleanup_dbus_error_free_ error;
3982 DBusMessage _cleanup_dbus_message_unref_ *reply = NULL;
3986 dbus_error_init(&error);
3988 r = enable_sysv_units(args);
3994 if (!bus || avoid_bus()) {
3996 STRV_FOREACH(name, args+1) {
3997 UnitFileState state;
3999 state = unit_file_get_state(arg_scope, arg_root, *name);
4003 if (state == UNIT_FILE_ENABLED ||
4004 state == UNIT_FILE_ENABLED_RUNTIME ||
4005 state == UNIT_FILE_STATIC)
4009 puts(unit_file_state_to_string(state));
4013 STRV_FOREACH(name, args+1) {
4016 r = bus_method_call_with_reply (
4018 "org.freedesktop.systemd1",
4019 "/org/freedesktop/systemd1",
4020 "org.freedesktop.systemd1.Manager",
4024 DBUS_TYPE_STRING, name,
4029 if (!dbus_message_get_args(reply, &error,
4030 DBUS_TYPE_STRING, &s,
4031 DBUS_TYPE_INVALID)) {
4032 log_error("Failed to parse reply: %s", bus_error_message(&error));
4036 dbus_message_unref(reply);
4039 if (streq(s, "enabled") ||
4040 streq(s, "enabled-runtime") ||
4049 return enabled ? 0 : 1;
4052 static int systemctl_help(void) {
4054 pager_open_if_enabled();
4056 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4057 "Query or send control commands to the systemd manager.\n\n"
4058 " -h --help Show this help\n"
4059 " --version Show package version\n"
4060 " -t --type=TYPE List only units of a particular type\n"
4061 " -p --property=NAME Show only properties by this name\n"
4062 " -a --all Show all units/properties, including dead/empty ones\n"
4063 " --failed Show only failed units\n"
4064 " --full Don't ellipsize unit names on output\n"
4065 " --fail When queueing a new job, fail if conflicting jobs are\n"
4067 " --ignore-dependencies\n"
4068 " When queueing a new job, ignore all its dependencies\n"
4069 " -i --ignore-inhibitors\n"
4070 " When shutting down or sleeping, ignore inhibitors\n"
4071 " --kill-who=WHO Who to send signal to\n"
4072 " -s --signal=SIGNAL Which signal to send\n"
4073 " -H --host=[USER@]HOST\n"
4074 " Show information for remote host\n"
4075 " -P --privileged Acquire privileges before execution\n"
4076 " -q --quiet Suppress output\n"
4077 " --no-block Do not wait until operation finished\n"
4078 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4079 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4081 " --no-legend Do not print a legend (column headers and hints)\n"
4082 " --no-pager Do not pipe output into a pager\n"
4083 " --no-ask-password\n"
4084 " Do not ask for system passwords\n"
4085 " --system Connect to system manager\n"
4086 " --user Connect to user service manager\n"
4087 " --global Enable/disable unit files globally\n"
4088 " -f --force When enabling unit files, override existing symlinks\n"
4089 " When shutting down, execute action immediately\n"
4090 " --root=PATH Enable unit files in the specified root directory\n"
4091 " --runtime Enable unit files only temporarily until next reboot\n"
4092 " -n --lines=INTEGER Journal entries to show\n"
4093 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4094 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4096 " list-units List loaded units\n"
4097 " start [NAME...] Start (activate) one or more units\n"
4098 " stop [NAME...] Stop (deactivate) one or more units\n"
4099 " reload [NAME...] Reload one or more units\n"
4100 " restart [NAME...] Start or restart one or more units\n"
4101 " try-restart [NAME...] Restart one or more units if active\n"
4102 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4103 " otherwise start or restart\n"
4104 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4105 " otherwise restart if active\n"
4106 " isolate [NAME] Start one unit and stop all others\n"
4107 " kill [NAME...] Send signal to processes of a unit\n"
4108 " is-active [NAME...] Check whether units are active\n"
4109 " is-failed [NAME...] Check whether units are failed\n"
4110 " status [NAME...|PID...] Show runtime status of one or more units\n"
4111 " show [NAME...|JOB...] Show properties of one or more\n"
4112 " units/jobs or the manager\n"
4113 " help [NAME...|PID...] Show manual for one or more units\n"
4114 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4116 " get-cgroup-attr [NAME] [ATTR] ...\n"
4117 " Get control group attrubute\n"
4118 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4119 " Set control group attribute\n"
4120 " unset-cgroup-attr [NAME] [ATTR...]\n"
4121 " Unset control group attribute\n"
4122 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4123 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4124 " load [NAME...] Load one or more units\n"
4125 " list-dependencies [NAME] Recursively show units which are required\n"
4126 " or wanted by this unit\n\n"
4127 "Unit File Commands:\n"
4128 " list-unit-files List installed unit files\n"
4129 " enable [NAME...] Enable one or more unit files\n"
4130 " disable [NAME...] Disable one or more unit files\n"
4131 " reenable [NAME...] Reenable one or more unit files\n"
4132 " preset [NAME...] Enable/disable one or more unit files\n"
4133 " based on preset configuration\n"
4134 " mask [NAME...] Mask one or more units\n"
4135 " unmask [NAME...] Unmask one or more units\n"
4136 " link [PATH...] Link one or more units files into\n"
4137 " the search path\n"
4138 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4140 " list-jobs List jobs\n"
4141 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4142 "Status Commands:\n"
4143 " dump Dump server status\n"
4144 "Snapshot Commands:\n"
4145 " snapshot [NAME] Create a snapshot\n"
4146 " delete [NAME...] Remove one or more snapshots\n\n"
4147 "Environment Commands:\n"
4148 " show-environment Dump environment\n"
4149 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4150 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4151 "Manager Lifecycle Commands:\n"
4152 " daemon-reload Reload systemd manager configuration\n"
4153 " daemon-reexec Reexecute systemd manager\n\n"
4154 "System Commands:\n"
4155 " default Enter system default mode\n"
4156 " rescue Enter system rescue mode\n"
4157 " emergency Enter system emergency mode\n"
4158 " halt Shut down and halt the system\n"
4159 " poweroff Shut down and power-off the system\n"
4160 " reboot Shut down and reboot the system\n"
4161 " kexec Shut down and reboot the system with kexec\n"
4162 " exit Request user instance exit\n"
4163 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4164 " suspend Suspend the system\n"
4165 " hibernate Hibernate the system\n"
4166 " hybrid-sleep Hibernate and suspend the system\n",
4167 program_invocation_short_name);
4172 static int halt_help(void) {
4174 printf("%s [OPTIONS...]\n\n"
4175 "%s the system.\n\n"
4176 " --help Show this help\n"
4177 " --halt Halt the machine\n"
4178 " -p --poweroff Switch off the machine\n"
4179 " --reboot Reboot the machine\n"
4180 " -f --force Force immediate halt/power-off/reboot\n"
4181 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4182 " -d --no-wtmp Don't write wtmp record\n"
4183 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4184 program_invocation_short_name,
4185 arg_action == ACTION_REBOOT ? "Reboot" :
4186 arg_action == ACTION_POWEROFF ? "Power off" :
4192 static int shutdown_help(void) {
4194 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4195 "Shut down the system.\n\n"
4196 " --help Show this help\n"
4197 " -H --halt Halt the machine\n"
4198 " -P --poweroff Power-off the machine\n"
4199 " -r --reboot Reboot the machine\n"
4200 " -h Equivalent to --poweroff, overridden by --halt\n"
4201 " -k Don't halt/power-off/reboot, just send warnings\n"
4202 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4203 " -c Cancel a pending shutdown\n",
4204 program_invocation_short_name);
4209 static int telinit_help(void) {
4211 printf("%s [OPTIONS...] {COMMAND}\n\n"
4212 "Send control commands to the init daemon.\n\n"
4213 " --help Show this help\n"
4214 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4216 " 0 Power-off the machine\n"
4217 " 6 Reboot the machine\n"
4218 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4219 " 1, s, S Enter rescue mode\n"
4220 " q, Q Reload init daemon configuration\n"
4221 " u, U Reexecute init daemon\n",
4222 program_invocation_short_name);
4227 static int runlevel_help(void) {
4229 printf("%s [OPTIONS...]\n\n"
4230 "Prints the previous and current runlevel of the init system.\n\n"
4231 " --help Show this help\n",
4232 program_invocation_short_name);
4237 static int help_types(void) {
4240 puts("Available unit types:");
4241 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4242 if (unit_type_table[i])
4243 puts(unit_type_table[i]);
4245 puts("\nAvailable unit load states: ");
4246 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4247 if (unit_type_table[i])
4248 puts(unit_load_state_table[i]);
4253 static int systemctl_parse_argv(int argc, char *argv[]) {
4258 ARG_IGNORE_DEPENDENCIES,
4271 ARG_NO_ASK_PASSWORD,
4277 static const struct option options[] = {
4278 { "help", no_argument, NULL, 'h' },
4279 { "version", no_argument, NULL, ARG_VERSION },
4280 { "type", required_argument, NULL, 't' },
4281 { "property", required_argument, NULL, 'p' },
4282 { "all", no_argument, NULL, 'a' },
4283 { "failed", no_argument, NULL, ARG_FAILED },
4284 { "full", no_argument, NULL, ARG_FULL },
4285 { "fail", no_argument, NULL, ARG_FAIL },
4286 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4287 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4288 { "ignore-inhibitors", no_argument, NULL, 'i' },
4289 { "user", no_argument, NULL, ARG_USER },
4290 { "system", no_argument, NULL, ARG_SYSTEM },
4291 { "global", no_argument, NULL, ARG_GLOBAL },
4292 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4293 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4294 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4295 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4296 { "quiet", no_argument, NULL, 'q' },
4297 { "root", required_argument, NULL, ARG_ROOT },
4298 { "force", no_argument, NULL, ARG_FORCE },
4299 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4300 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4301 { "signal", required_argument, NULL, 's' },
4302 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4303 { "host", required_argument, NULL, 'H' },
4304 { "privileged",no_argument, NULL, 'P' },
4305 { "runtime", no_argument, NULL, ARG_RUNTIME },
4306 { "lines", required_argument, NULL, 'n' },
4307 { "output", required_argument, NULL, 'o' },
4308 { NULL, 0, NULL, 0 }
4316 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4325 puts(PACKAGE_STRING);
4326 puts(SYSTEMD_FEATURES);
4330 if (streq(optarg, "help")) {
4335 if (unit_type_from_string(optarg) >= 0) {
4339 if (unit_load_state_from_string(optarg) >= 0) {
4340 arg_load_state = optarg;
4343 log_error("Unkown unit type or load state '%s'.",
4345 log_info("Use -t help to see a list of allowed values.");
4350 /* Make sure that if the empty property list
4351 was specified, we won't show any properties. */
4352 const char *source = isempty(optarg) ? " " : optarg;
4354 FOREACH_WORD_SEPARATOR(word, size, source, ",", state) {
4355 char _cleanup_free_ *prop;
4358 prop = strndup(word, size);
4362 tmp = strv_append(arg_property, prop);
4366 strv_free(arg_property);
4370 /* If the user asked for a particular
4371 * property, show it to him, even if it is
4383 arg_job_mode = "fail";
4386 case ARG_IRREVERSIBLE:
4387 arg_job_mode = "replace-irreversibly";
4390 case ARG_IGNORE_DEPENDENCIES:
4391 arg_job_mode = "ignore-dependencies";
4395 arg_scope = UNIT_FILE_USER;
4399 arg_scope = UNIT_FILE_SYSTEM;
4403 arg_scope = UNIT_FILE_GLOBAL;
4407 arg_no_block = true;
4411 arg_no_legend = true;
4415 arg_no_pager = true;
4447 arg_no_reload = true;
4451 arg_kill_who = optarg;
4455 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4456 log_error("Failed to parse signal string %s.", optarg);
4461 case ARG_NO_ASK_PASSWORD:
4462 arg_ask_password = false;
4466 arg_transport = TRANSPORT_POLKIT;
4470 arg_transport = TRANSPORT_SSH;
4479 if (safe_atou(optarg, &arg_lines) < 0) {
4480 log_error("Failed to parse lines '%s'", optarg);
4486 arg_output = output_mode_from_string(optarg);
4487 if (arg_output < 0) {
4488 log_error("Unknown output '%s'.", optarg);
4494 arg_ignore_inhibitors = true;
4501 log_error("Unknown option code '%c'.", c);
4506 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4507 log_error("Cannot access user instance remotely.");
4514 static int halt_parse_argv(int argc, char *argv[]) {
4523 static const struct option options[] = {
4524 { "help", no_argument, NULL, ARG_HELP },
4525 { "halt", no_argument, NULL, ARG_HALT },
4526 { "poweroff", no_argument, NULL, 'p' },
4527 { "reboot", no_argument, NULL, ARG_REBOOT },
4528 { "force", no_argument, NULL, 'f' },
4529 { "wtmp-only", no_argument, NULL, 'w' },
4530 { "no-wtmp", no_argument, NULL, 'd' },
4531 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4532 { NULL, 0, NULL, 0 }
4540 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4541 if (runlevel == '0' || runlevel == '6')
4544 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4552 arg_action = ACTION_HALT;
4556 if (arg_action != ACTION_REBOOT)
4557 arg_action = ACTION_POWEROFF;
4561 arg_action = ACTION_REBOOT;
4583 /* Compatibility nops */
4590 log_error("Unknown option code '%c'.", c);
4595 if (optind < argc) {
4596 log_error("Too many arguments.");
4603 static int parse_time_spec(const char *t, usec_t *_u) {
4607 if (streq(t, "now"))
4609 else if (!strchr(t, ':')) {
4612 if (safe_atou64(t, &u) < 0)
4615 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4624 hour = strtol(t, &e, 10);
4625 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4628 minute = strtol(e+1, &e, 10);
4629 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4632 n = now(CLOCK_REALTIME);
4633 s = (time_t) (n / USEC_PER_SEC);
4636 assert_se(localtime_r(&s, &tm));
4638 tm.tm_hour = (int) hour;
4639 tm.tm_min = (int) minute;
4642 assert_se(s = mktime(&tm));
4644 *_u = (usec_t) s * USEC_PER_SEC;
4647 *_u += USEC_PER_DAY;
4653 static int shutdown_parse_argv(int argc, char *argv[]) {
4660 static const struct option options[] = {
4661 { "help", no_argument, NULL, ARG_HELP },
4662 { "halt", no_argument, NULL, 'H' },
4663 { "poweroff", no_argument, NULL, 'P' },
4664 { "reboot", no_argument, NULL, 'r' },
4665 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4666 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4667 { NULL, 0, NULL, 0 }
4675 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4683 arg_action = ACTION_HALT;
4687 arg_action = ACTION_POWEROFF;
4692 arg_action = ACTION_KEXEC;
4694 arg_action = ACTION_REBOOT;
4698 arg_action = ACTION_KEXEC;
4702 if (arg_action != ACTION_HALT)
4703 arg_action = ACTION_POWEROFF;
4716 /* Compatibility nops */
4720 arg_action = ACTION_CANCEL_SHUTDOWN;
4727 log_error("Unknown option code '%c'.", c);
4732 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4733 r = parse_time_spec(argv[optind], &arg_when);
4735 log_error("Failed to parse time specification: %s", argv[optind]);
4739 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4741 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4742 /* No time argument for shutdown cancel */
4743 arg_wall = argv + optind;
4744 else if (argc > optind + 1)
4745 /* We skip the time argument */
4746 arg_wall = argv + optind + 1;
4753 static int telinit_parse_argv(int argc, char *argv[]) {
4760 static const struct option options[] = {
4761 { "help", no_argument, NULL, ARG_HELP },
4762 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4763 { NULL, 0, NULL, 0 }
4766 static const struct {
4770 { '0', ACTION_POWEROFF },
4771 { '6', ACTION_REBOOT },
4772 { '1', ACTION_RESCUE },
4773 { '2', ACTION_RUNLEVEL2 },
4774 { '3', ACTION_RUNLEVEL3 },
4775 { '4', ACTION_RUNLEVEL4 },
4776 { '5', ACTION_RUNLEVEL5 },
4777 { 's', ACTION_RESCUE },
4778 { 'S', ACTION_RESCUE },
4779 { 'q', ACTION_RELOAD },
4780 { 'Q', ACTION_RELOAD },
4781 { 'u', ACTION_REEXEC },
4782 { 'U', ACTION_REEXEC }
4791 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4806 log_error("Unknown option code '%c'.", c);
4811 if (optind >= argc) {
4816 if (optind + 1 < argc) {
4817 log_error("Too many arguments.");
4821 if (strlen(argv[optind]) != 1) {
4822 log_error("Expected single character argument.");
4826 for (i = 0; i < ELEMENTSOF(table); i++)
4827 if (table[i].from == argv[optind][0])
4830 if (i >= ELEMENTSOF(table)) {
4831 log_error("Unknown command '%s'.", argv[optind]);
4835 arg_action = table[i].to;
4842 static int runlevel_parse_argv(int argc, char *argv[]) {
4848 static const struct option options[] = {
4849 { "help", no_argument, NULL, ARG_HELP },
4850 { NULL, 0, NULL, 0 }
4858 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4869 log_error("Unknown option code '%c'.", c);
4874 if (optind < argc) {
4875 log_error("Too many arguments.");
4882 static int parse_argv(int argc, char *argv[]) {
4886 if (program_invocation_short_name) {
4888 if (strstr(program_invocation_short_name, "halt")) {
4889 arg_action = ACTION_HALT;
4890 return halt_parse_argv(argc, argv);
4891 } else if (strstr(program_invocation_short_name, "poweroff")) {
4892 arg_action = ACTION_POWEROFF;
4893 return halt_parse_argv(argc, argv);
4894 } else if (strstr(program_invocation_short_name, "reboot")) {
4896 arg_action = ACTION_KEXEC;
4898 arg_action = ACTION_REBOOT;
4899 return halt_parse_argv(argc, argv);
4900 } else if (strstr(program_invocation_short_name, "shutdown")) {
4901 arg_action = ACTION_POWEROFF;
4902 return shutdown_parse_argv(argc, argv);
4903 } else if (strstr(program_invocation_short_name, "init")) {
4905 if (sd_booted() > 0) {
4906 arg_action = ACTION_INVALID;
4907 return telinit_parse_argv(argc, argv);
4909 /* Hmm, so some other init system is
4910 * running, we need to forward this
4911 * request to it. For now we simply
4912 * guess that it is Upstart. */
4914 execv("/lib/upstart/telinit", argv);
4916 log_error("Couldn't find an alternative telinit implementation to spawn.");
4920 } else if (strstr(program_invocation_short_name, "runlevel")) {
4921 arg_action = ACTION_RUNLEVEL;
4922 return runlevel_parse_argv(argc, argv);
4926 arg_action = ACTION_SYSTEMCTL;
4927 return systemctl_parse_argv(argc, argv);
4930 static int action_to_runlevel(void) {
4932 static const char table[_ACTION_MAX] = {
4933 [ACTION_HALT] = '0',
4934 [ACTION_POWEROFF] = '0',
4935 [ACTION_REBOOT] = '6',
4936 [ACTION_RUNLEVEL2] = '2',
4937 [ACTION_RUNLEVEL3] = '3',
4938 [ACTION_RUNLEVEL4] = '4',
4939 [ACTION_RUNLEVEL5] = '5',
4940 [ACTION_RESCUE] = '1'
4943 assert(arg_action < _ACTION_MAX);
4945 return table[arg_action];
4948 static int talk_upstart(void) {
4949 DBusMessage _cleanup_dbus_message_unref_ *m = NULL, *reply = NULL;
4950 DBusError _cleanup_dbus_error_free_ error;
4951 int previous, rl, r;
4953 env1_buf[] = "RUNLEVEL=X",
4954 env2_buf[] = "PREVLEVEL=X";
4955 char *env1 = env1_buf, *env2 = env2_buf;
4956 const char *emit = "runlevel";
4957 dbus_bool_t b_false = FALSE;
4958 DBusMessageIter iter, sub;
4959 DBusConnection *bus;
4961 dbus_error_init(&error);
4963 if (!(rl = action_to_runlevel()))
4966 if (utmp_get_runlevel(&previous, NULL) < 0)
4969 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4970 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4975 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4980 if ((r = bus_check_peercred(bus)) < 0) {
4981 log_error("Failed to verify owner of bus.");
4985 if (!(m = dbus_message_new_method_call(
4986 "com.ubuntu.Upstart",
4987 "/com/ubuntu/Upstart",
4988 "com.ubuntu.Upstart0_6",
4991 log_error("Could not allocate message.");
4996 dbus_message_iter_init_append(m, &iter);
4998 env1_buf[sizeof(env1_buf)-2] = rl;
4999 env2_buf[sizeof(env2_buf)-2] = previous;
5001 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5002 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5003 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5004 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5005 !dbus_message_iter_close_container(&iter, &sub) ||
5006 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5007 log_error("Could not append arguments to message.");
5012 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5014 if (bus_error_is_no_service(&error)) {
5019 log_error("Failed to issue method call: %s", bus_error_message(&error));
5028 dbus_connection_flush(bus);
5029 dbus_connection_close(bus);
5030 dbus_connection_unref(bus);
5036 static int talk_initctl(void) {
5037 struct init_request request;
5041 if (!(rl = action_to_runlevel()))
5045 request.magic = INIT_MAGIC;
5046 request.sleeptime = 0;
5047 request.cmd = INIT_CMD_RUNLVL;
5048 request.runlevel = rl;
5050 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5052 if (errno == ENOENT)
5055 log_error("Failed to open "INIT_FIFO": %m");
5060 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5061 close_nointr_nofail(fd);
5064 log_error("Failed to write to "INIT_FIFO": %m");
5065 return errno ? -errno : -EIO;
5071 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5073 static const struct {
5081 int (* const dispatch)(DBusConnection *bus, char **args);
5083 { "list-units", LESS, 1, list_units },
5084 { "list-unit-files", EQUAL, 1, list_unit_files },
5085 { "list-jobs", EQUAL, 1, list_jobs },
5086 { "clear-jobs", EQUAL, 1, daemon_reload },
5087 { "load", MORE, 2, load_unit },
5088 { "cancel", MORE, 2, cancel_job },
5089 { "start", MORE, 2, start_unit },
5090 { "stop", MORE, 2, start_unit },
5091 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5092 { "reload", MORE, 2, start_unit },
5093 { "restart", MORE, 2, start_unit },
5094 { "try-restart", MORE, 2, start_unit },
5095 { "reload-or-restart", MORE, 2, start_unit },
5096 { "reload-or-try-restart", MORE, 2, start_unit },
5097 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5098 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5099 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5100 { "isolate", EQUAL, 2, start_unit },
5101 { "set-cgroup", MORE, 3, set_cgroup },
5102 { "unset-cgroup", MORE, 3, set_cgroup },
5103 { "get-cgroup-attr", MORE, 3, get_cgroup_attr },
5104 { "set-cgroup-attr", MORE, 4, set_cgroup_attr },
5105 { "unset-cgroup-attr", MORE, 3, set_cgroup },
5106 { "kill", MORE, 2, kill_unit },
5107 { "is-active", MORE, 2, check_unit_active },
5108 { "check", MORE, 2, check_unit_active },
5109 { "is-failed", MORE, 2, check_unit_failed },
5110 { "show", MORE, 1, show },
5111 { "status", MORE, 1, show },
5112 { "help", MORE, 2, show },
5113 { "dump", EQUAL, 1, dump },
5114 { "snapshot", LESS, 2, snapshot },
5115 { "delete", MORE, 2, delete_snapshot },
5116 { "daemon-reload", EQUAL, 1, daemon_reload },
5117 { "daemon-reexec", EQUAL, 1, daemon_reload },
5118 { "show-environment", EQUAL, 1, show_enviroment },
5119 { "set-environment", MORE, 2, set_environment },
5120 { "unset-environment", MORE, 2, set_environment },
5121 { "halt", EQUAL, 1, start_special },
5122 { "poweroff", EQUAL, 1, start_special },
5123 { "reboot", EQUAL, 1, start_special },
5124 { "kexec", EQUAL, 1, start_special },
5125 { "suspend", EQUAL, 1, start_special },
5126 { "hibernate", EQUAL, 1, start_special },
5127 { "hybrid-sleep", EQUAL, 1, start_special },
5128 { "default", EQUAL, 1, start_special },
5129 { "rescue", EQUAL, 1, start_special },
5130 { "emergency", EQUAL, 1, start_special },
5131 { "exit", EQUAL, 1, start_special },
5132 { "reset-failed", MORE, 1, reset_failed },
5133 { "enable", MORE, 2, enable_unit },
5134 { "disable", MORE, 2, enable_unit },
5135 { "is-enabled", MORE, 2, unit_is_enabled },
5136 { "reenable", MORE, 2, enable_unit },
5137 { "preset", MORE, 2, enable_unit },
5138 { "mask", MORE, 2, enable_unit },
5139 { "unmask", MORE, 2, enable_unit },
5140 { "link", MORE, 2, enable_unit },
5141 { "switch-root", MORE, 2, switch_root },
5142 { "list-dependencies", LESS, 2, list_dependencies },
5152 left = argc - optind;
5155 /* Special rule: no arguments means "list-units" */
5158 if (streq(argv[optind], "help") && !argv[optind+1]) {
5159 log_error("This command expects one or more "
5160 "unit names. Did you mean --help?");
5164 for (i = 0; i < ELEMENTSOF(verbs); i++)
5165 if (streq(argv[optind], verbs[i].verb))
5168 if (i >= ELEMENTSOF(verbs)) {
5169 log_error("Unknown operation '%s'.", argv[optind]);
5174 switch (verbs[i].argc_cmp) {
5177 if (left != verbs[i].argc) {
5178 log_error("Invalid number of arguments.");
5185 if (left < verbs[i].argc) {
5186 log_error("Too few arguments.");
5193 if (left > verbs[i].argc) {
5194 log_error("Too many arguments.");
5201 assert_not_reached("Unknown comparison operator.");
5204 /* Require a bus connection for all operations but
5206 if (!streq(verbs[i].verb, "enable") &&
5207 !streq(verbs[i].verb, "disable") &&
5208 !streq(verbs[i].verb, "is-enabled") &&
5209 !streq(verbs[i].verb, "list-unit-files") &&
5210 !streq(verbs[i].verb, "reenable") &&
5211 !streq(verbs[i].verb, "preset") &&
5212 !streq(verbs[i].verb, "mask") &&
5213 !streq(verbs[i].verb, "unmask") &&
5214 !streq(verbs[i].verb, "link")) {
5216 if (running_in_chroot() > 0) {
5217 log_info("Running in chroot, ignoring request.");
5221 if (((!streq(verbs[i].verb, "reboot") &&
5222 !streq(verbs[i].verb, "halt") &&
5223 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5224 log_error("Failed to get D-Bus connection: %s",
5225 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5231 if (!bus && !avoid_bus()) {
5232 log_error("Failed to get D-Bus connection: %s",
5233 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5238 return verbs[i].dispatch(bus, argv + optind);
5241 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5242 int _cleanup_close_ fd;
5243 struct msghdr msghdr;
5244 struct iovec iovec[2];
5245 union sockaddr_union sockaddr;
5246 struct sd_shutdown_command c;
5248 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5255 c.dry_run = dry_run;
5259 sockaddr.sa.sa_family = AF_UNIX;
5260 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5263 msghdr.msg_name = &sockaddr;
5264 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5267 iovec[0].iov_base = (char*) &c;
5268 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5270 if (isempty(message))
5271 msghdr.msg_iovlen = 1;
5273 iovec[1].iov_base = (char*) message;
5274 iovec[1].iov_len = strlen(message);
5275 msghdr.msg_iovlen = 2;
5277 msghdr.msg_iov = iovec;
5279 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5285 static int reload_with_fallback(DBusConnection *bus) {
5288 /* First, try systemd via D-Bus. */
5289 if (daemon_reload(bus, NULL) >= 0)
5293 /* Nothing else worked, so let's try signals */
5294 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5296 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5297 log_error("kill() failed: %m");
5304 static int start_with_fallback(DBusConnection *bus) {
5307 /* First, try systemd via D-Bus. */
5308 if (start_unit(bus, NULL) >= 0)
5312 /* Hmm, talking to systemd via D-Bus didn't work. Then
5313 * let's try to talk to Upstart via D-Bus. */
5314 if (talk_upstart() > 0)
5317 /* Nothing else worked, so let's try
5319 if (talk_initctl() > 0)
5322 log_error("Failed to talk to init daemon.");
5326 warn_wall(arg_action);
5330 static _noreturn_ void halt_now(enum action a) {
5332 /* Make sure C-A-D is handled by the kernel from this
5334 reboot(RB_ENABLE_CAD);
5339 log_info("Halting.");
5340 reboot(RB_HALT_SYSTEM);
5343 case ACTION_POWEROFF:
5344 log_info("Powering off.");
5345 reboot(RB_POWER_OFF);
5349 log_info("Rebooting.");
5350 reboot(RB_AUTOBOOT);
5354 assert_not_reached("Unknown halt action.");
5357 assert_not_reached("Uh? This shouldn't happen.");
5360 static int halt_main(DBusConnection *bus) {
5363 r = check_inhibitors(bus, arg_action);
5367 if (geteuid() != 0) {
5368 /* Try logind if we are a normal user and no special
5369 * mode applies. Maybe PolicyKit allows us to shutdown
5372 if (arg_when <= 0 &&
5375 (arg_action == ACTION_POWEROFF ||
5376 arg_action == ACTION_REBOOT)) {
5377 r = reboot_with_logind(bus, arg_action);
5382 log_error("Must be root.");
5387 char _cleanup_free_ *m;
5389 m = strv_join(arg_wall, " ");
5390 r = send_shutdownd(arg_when,
5391 arg_action == ACTION_HALT ? 'H' :
5392 arg_action == ACTION_POWEROFF ? 'P' :
5393 arg_action == ACTION_KEXEC ? 'K' :
5400 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5402 char date[FORMAT_TIMESTAMP_MAX];
5404 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5405 format_timestamp(date, sizeof(date), arg_when));
5410 if (!arg_dry && !arg_force)
5411 return start_with_fallback(bus);
5414 if (sd_booted() > 0)
5415 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5417 r = utmp_put_shutdown();
5419 log_warning("Failed to write utmp record: %s", strerror(-r));
5426 halt_now(arg_action);
5427 /* We should never reach this. */
5431 static int runlevel_main(void) {
5432 int r, runlevel, previous;
5434 r = utmp_get_runlevel(&runlevel, &previous);
5441 previous <= 0 ? 'N' : previous,
5442 runlevel <= 0 ? 'N' : runlevel);
5447 int main(int argc, char*argv[]) {
5448 int r, retval = EXIT_FAILURE;
5449 DBusConnection *bus = NULL;
5450 DBusError _cleanup_dbus_error_free_ error;
5452 dbus_error_init(&error);
5454 setlocale(LC_ALL, "");
5455 log_parse_environment();
5458 r = parse_argv(argc, argv);
5462 retval = EXIT_SUCCESS;
5466 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5467 * let's shortcut this */
5468 if (arg_action == ACTION_RUNLEVEL) {
5469 r = runlevel_main();
5470 retval = r < 0 ? EXIT_FAILURE : r;
5474 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5475 log_info("Running in chroot, ignoring request.");
5481 if (arg_transport == TRANSPORT_NORMAL)
5482 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5483 else if (arg_transport == TRANSPORT_POLKIT) {
5484 bus_connect_system_polkit(&bus, &error);
5485 private_bus = false;
5486 } else if (arg_transport == TRANSPORT_SSH) {
5487 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5488 private_bus = false;
5490 assert_not_reached("Uh, invalid transport...");
5493 switch (arg_action) {
5495 case ACTION_SYSTEMCTL:
5496 r = systemctl_main(bus, argc, argv, &error);
5500 case ACTION_POWEROFF:
5506 case ACTION_RUNLEVEL2:
5507 case ACTION_RUNLEVEL3:
5508 case ACTION_RUNLEVEL4:
5509 case ACTION_RUNLEVEL5:
5511 case ACTION_EMERGENCY:
5512 case ACTION_DEFAULT:
5513 r = start_with_fallback(bus);
5518 r = reload_with_fallback(bus);
5521 case ACTION_CANCEL_SHUTDOWN: {
5525 m = strv_join(arg_wall, " ");
5527 retval = EXIT_FAILURE;
5531 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5533 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5538 case ACTION_INVALID:
5539 case ACTION_RUNLEVEL:
5541 assert_not_reached("Unknown action");
5544 retval = r < 0 ? EXIT_FAILURE : r;
5548 dbus_connection_flush(bus);
5549 dbus_connection_close(bus);
5550 dbus_connection_unref(bus);
5555 strv_free(arg_property);
5558 ask_password_agent_close();
5559 polkit_agent_close();