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 enum action verb_to_action(const char *verb) {
1522 if (streq(verb, "halt"))
1524 else if (streq(verb, "poweroff"))
1525 return ACTION_POWEROFF;
1526 else if (streq(verb, "reboot"))
1527 return ACTION_REBOOT;
1528 else if (streq(verb, "kexec"))
1529 return ACTION_KEXEC;
1530 else if (streq(verb, "rescue"))
1531 return ACTION_RESCUE;
1532 else if (streq(verb, "emergency"))
1533 return ACTION_EMERGENCY;
1534 else if (streq(verb, "default"))
1535 return ACTION_DEFAULT;
1536 else if (streq(verb, "exit"))
1538 else if (streq(verb, "suspend"))
1539 return ACTION_SUSPEND;
1540 else if (streq(verb, "hibernate"))
1541 return ACTION_HIBERNATE;
1542 else if (streq(verb, "hybrid-sleep"))
1543 return ACTION_HYBRID_SLEEP;
1545 return ACTION_INVALID;
1548 static int start_unit(DBusConnection *bus, char **args) {
1550 static const char * const table[_ACTION_MAX] = {
1551 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1552 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1553 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1554 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1555 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1556 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1557 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1558 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1559 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1560 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1561 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1562 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1563 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1564 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
1565 [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
1569 const char *method, *mode, *one_name;
1570 Set _cleanup_set_free_free_ *s = NULL;
1571 DBusError _cleanup_dbus_error_free_ error;
1574 dbus_error_init(&error);
1578 ask_password_agent_open_if_enabled();
1580 if (arg_action == ACTION_SYSTEMCTL) {
1582 streq(args[0], "stop") ||
1583 streq(args[0], "condstop") ? "StopUnit" :
1584 streq(args[0], "reload") ? "ReloadUnit" :
1585 streq(args[0], "restart") ? "RestartUnit" :
1587 streq(args[0], "try-restart") ||
1588 streq(args[0], "condrestart") ? "TryRestartUnit" :
1590 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1592 streq(args[0], "reload-or-try-restart") ||
1593 streq(args[0], "condreload") ||
1595 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1598 if (streq(args[0], "isolate") ||
1599 streq(args[0], "rescue") ||
1600 streq(args[0], "emergency") ||
1601 streq(args[0], "default"))
1603 else if (streq(args[0], "halt") ||
1604 streq(args[0], "poweroff") ||
1605 streq(args[0], "reboot") ||
1606 streq(args[0], "kexec") ||
1607 streq(args[0], "exit") ||
1608 streq(args[0], "suspend") ||
1609 streq(args[0], "hibernate") ||
1610 streq(args[0], "hybrid-sleep"))
1611 mode = "replace-irreversibly";
1613 mode = arg_job_mode;
1615 one_name = table[verb_to_action(args[0])];
1618 assert(arg_action < ELEMENTSOF(table));
1619 assert(table[arg_action]);
1621 method = "StartUnit";
1623 mode = (arg_action == ACTION_EMERGENCY ||
1624 arg_action == ACTION_RESCUE ||
1625 arg_action == ACTION_RUNLEVEL2 ||
1626 arg_action == ACTION_RUNLEVEL3 ||
1627 arg_action == ACTION_RUNLEVEL4 ||
1628 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace-irreversibly";
1630 one_name = table[arg_action];
1633 if (!arg_no_block) {
1634 ret = enable_wait_for_jobs(bus);
1636 log_error("Could not watch jobs: %s", strerror(-ret));
1640 s = set_new(string_hash_func, string_compare_func);
1646 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1648 ret = translate_bus_error_to_exit_status(ret, &error);
1650 STRV_FOREACH(name, args+1) {
1651 r = start_unit_one(bus, method, *name, mode, &error, s);
1653 ret = translate_bus_error_to_exit_status(r, &error);
1654 dbus_error_free(&error);
1659 if (!arg_no_block) {
1660 r = wait_for_jobs(bus, s);
1664 /* When stopping units, warn if they can still be triggered by
1665 * another active unit (socket, path, timer) */
1666 if (!arg_quiet && streq(method, "StopUnit")) {
1668 check_triggering_units(bus, one_name);
1670 STRV_FOREACH(name, args+1)
1671 check_triggering_units(bus, *name);
1678 /* Ask systemd-logind, which might grant access to unprivileged users
1679 * through PolicyKit */
1680 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1683 dbus_bool_t interactive = true;
1688 polkit_agent_open_if_enabled();
1696 case ACTION_POWEROFF:
1697 method = "PowerOff";
1700 case ACTION_SUSPEND:
1704 case ACTION_HIBERNATE:
1705 method = "Hibernate";
1708 case ACTION_HYBRID_SLEEP:
1709 method = "HybridSleep";
1716 return bus_method_call_with_reply(
1718 "org.freedesktop.login1",
1719 "/org/freedesktop/login1",
1720 "org.freedesktop.login1.Manager",
1724 DBUS_TYPE_BOOLEAN, &interactive,
1731 static int check_inhibitors(DBusConnection *bus, enum action a) {
1733 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1734 DBusMessageIter iter, sub, sub2;
1737 _cleanup_strv_free_ char **sessions = NULL;
1743 if (arg_ignore_inhibitors || arg_force > 0)
1755 r = bus_method_call_with_reply(
1757 "org.freedesktop.login1",
1758 "/org/freedesktop/login1",
1759 "org.freedesktop.login1.Manager",
1765 /* If logind is not around, then there are no inhibitors... */
1768 if (!dbus_message_iter_init(reply, &iter) ||
1769 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1770 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1771 log_error("Failed to parse reply.");
1775 dbus_message_iter_recurse(&iter, &sub);
1776 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1777 const char *what, *who, *why, *mode;
1779 _cleanup_strv_free_ char **sv = NULL;
1780 _cleanup_free_ char *comm = NULL, *user = NULL;
1782 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1783 log_error("Failed to parse reply.");
1787 dbus_message_iter_recurse(&sub, &sub2);
1789 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
1790 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
1791 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
1792 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
1793 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
1794 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
1795 log_error("Failed to parse reply.");
1799 if (!streq(mode, "block"))
1802 sv = strv_split(what, ":");
1806 if (!strv_contains(sv,
1808 a == ACTION_POWEROFF ||
1809 a == ACTION_REBOOT ||
1810 a == ACTION_KEXEC ? "shutdown" : "sleep"))
1813 get_process_comm(pid, &comm);
1814 user = uid_to_name(uid);
1815 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
1816 who, (unsigned long) pid, strna(comm), strna(user), why);
1820 dbus_message_iter_next(&sub);
1823 dbus_message_iter_recurse(&iter, &sub);
1825 /* Check for current sessions */
1826 sd_get_sessions(&sessions);
1827 STRV_FOREACH(s, sessions) {
1829 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
1831 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
1834 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
1837 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
1840 sd_session_get_tty(*s, &tty);
1841 sd_session_get_seat(*s, &seat);
1842 sd_session_get_service(*s, &service);
1843 user = uid_to_name(uid);
1845 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
1852 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
1853 a == ACTION_HALT ? "halt" :
1854 a == ACTION_POWEROFF ? "poweroff" :
1855 a == ACTION_REBOOT ? "reboot" :
1856 a == ACTION_KEXEC ? "kexec" :
1857 a == ACTION_SUSPEND ? "suspend" :
1858 a == ACTION_HIBERNATE ? "hibernate" : "hybrid-sleep");
1866 static int start_special(DBusConnection *bus, char **args) {
1872 a = verb_to_action(args[0]);
1874 r = check_inhibitors(bus, a);
1878 if (arg_force >= 2 && geteuid() != 0) {
1879 log_error("Must be root.");
1883 if (arg_force >= 2 &&
1884 (a == ACTION_HALT ||
1885 a == ACTION_POWEROFF ||
1886 a == ACTION_REBOOT))
1889 if (arg_force >= 1 &&
1890 (a == ACTION_HALT ||
1891 a == ACTION_POWEROFF ||
1892 a == ACTION_REBOOT ||
1893 a == ACTION_KEXEC ||
1895 return daemon_reload(bus, args);
1897 /* first try logind, to allow authentication with polkit */
1898 if (geteuid() != 0 &&
1899 (a == ACTION_POWEROFF ||
1900 a == ACTION_REBOOT ||
1901 a == ACTION_SUSPEND ||
1902 a == ACTION_HIBERNATE ||
1903 a == ACTION_HYBRID_SLEEP)) {
1904 r = reboot_with_logind(bus, a);
1909 r = start_unit(bus, args);
1910 if (r == EXIT_SUCCESS)
1916 static int check_unit_active(DBusConnection *bus, char **args) {
1917 const char * const check_states[] = {
1924 int r = 3; /* According to LSB: "program is not running" */
1929 STRV_FOREACH(name, args+1) {
1932 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1942 static int check_unit_failed(DBusConnection *bus, char **args) {
1943 const char * const check_states[] = {
1954 STRV_FOREACH(name, args+1) {
1957 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1967 static int kill_unit(DBusConnection *bus, char **args) {
1975 arg_kill_who = "all";
1977 STRV_FOREACH(name, args+1) {
1978 _cleanup_free_ char *n = NULL;
1980 n = unit_name_mangle(*name);
1984 r = bus_method_call_with_reply(
1986 "org.freedesktop.systemd1",
1987 "/org/freedesktop/systemd1",
1988 "org.freedesktop.systemd1.Manager",
1992 DBUS_TYPE_STRING, &n,
1993 DBUS_TYPE_STRING, &arg_kill_who,
1994 DBUS_TYPE_INT32, &arg_signal,
2002 static int set_cgroup(DBusConnection *bus, char **args) {
2003 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2006 DBusMessageIter iter;
2008 _cleanup_free_ char *n = NULL;
2009 const char *runtime;
2014 dbus_error_init(&error);
2017 streq(args[0], "set-cgroup") ? "SetUnitControlGroups" :
2018 streq(args[0], "unset-group") ? "UnsetUnitControlGroups"
2019 : "UnsetUnitControlGroupAttributes";
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",
2033 dbus_message_iter_init_append(m, &iter);
2034 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
2037 r = bus_append_strv_iter(&iter, args + 2);
2041 runtime = arg_runtime ? "runtime" : "persistent";
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 set_cgroup_attr(DBusConnection *bus, char **args) {
2056 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2058 DBusMessageIter iter, sub, sub2;
2060 _cleanup_free_ char *n = NULL;
2061 const char *runtime;
2066 dbus_error_init(&error);
2068 if (strv_length(args) % 2 != 0) {
2069 log_error("Expecting an uneven number of arguments!");
2073 n = unit_name_mangle(args[1]);
2077 m = dbus_message_new_method_call(
2078 "org.freedesktop.systemd1",
2079 "/org/freedesktop/systemd1",
2080 "org.freedesktop.systemd1.Manager",
2081 "SetUnitControlGroupAttributes");
2085 dbus_message_iter_init_append(m, &iter);
2086 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2087 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub))
2090 STRV_FOREACH_PAIR(x, y, args + 2) {
2091 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
2092 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, x) ||
2093 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, y) ||
2094 !dbus_message_iter_close_container(&sub, &sub2))
2098 runtime = arg_runtime ? "runtime" : "persistent";
2099 if (!dbus_message_iter_close_container(&iter, &sub) ||
2100 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2103 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2105 log_error("Failed to issue method call: %s", bus_error_message(&error));
2106 dbus_error_free(&error);
2113 static int get_cgroup_attr(DBusConnection *bus, char **args) {
2114 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2116 DBusMessageIter iter;
2118 _cleanup_free_ char *n = NULL;
2119 _cleanup_strv_free_ char **list = NULL;
2125 dbus_error_init(&error);
2127 n = unit_name_mangle(args[1]);
2131 m = dbus_message_new_method_call(
2132 "org.freedesktop.systemd1",
2133 "/org/freedesktop/systemd1",
2134 "org.freedesktop.systemd1.Manager",
2135 "GetUnitControlGroupAttributes");
2139 dbus_message_iter_init_append(m, &iter);
2140 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
2143 r = bus_append_strv_iter(&iter, args + 2);
2147 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2149 log_error("Failed to issue method call: %s", bus_error_message(&error));
2150 dbus_error_free(&error);
2154 dbus_message_iter_init(reply, &iter);
2155 r = bus_parse_strv_iter(&iter, &list);
2157 log_error("Failed to parse value list.");
2161 STRV_FOREACH(a, list) {
2162 if (endswith(*a, "\n"))
2171 typedef struct ExecStatusInfo {
2179 usec_t start_timestamp;
2180 usec_t exit_timestamp;
2185 LIST_FIELDS(struct ExecStatusInfo, exec);
2188 static void exec_status_info_free(ExecStatusInfo *i) {
2197 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2198 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2199 DBusMessageIter sub2, sub3;
2203 int32_t code, status;
2209 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2212 dbus_message_iter_recurse(sub, &sub2);
2214 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2217 i->path = strdup(path);
2221 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2222 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2226 dbus_message_iter_recurse(&sub2, &sub3);
2227 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2228 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2229 dbus_message_iter_next(&sub3);
2233 i->argv = new0(char*, n+1);
2238 dbus_message_iter_recurse(&sub2, &sub3);
2239 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2242 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2243 dbus_message_iter_get_basic(&sub3, &s);
2244 dbus_message_iter_next(&sub3);
2246 i->argv[n] = strdup(s);
2253 if (!dbus_message_iter_next(&sub2) ||
2254 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2255 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2256 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2257 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2258 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2259 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2260 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2261 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2265 i->start_timestamp = (usec_t) start_timestamp;
2266 i->exit_timestamp = (usec_t) exit_timestamp;
2267 i->pid = (pid_t) pid;
2274 typedef struct UnitStatusInfo {
2276 const char *load_state;
2277 const char *active_state;
2278 const char *sub_state;
2279 const char *unit_file_state;
2281 const char *description;
2282 const char *following;
2284 char **documentation;
2286 const char *fragment_path;
2287 const char *source_path;
2288 const char *default_control_group;
2290 const char *load_error;
2293 usec_t inactive_exit_timestamp;
2294 usec_t inactive_exit_timestamp_monotonic;
2295 usec_t active_enter_timestamp;
2296 usec_t active_exit_timestamp;
2297 usec_t inactive_enter_timestamp;
2299 bool need_daemon_reload;
2304 const char *status_text;
2307 usec_t start_timestamp;
2308 usec_t exit_timestamp;
2310 int exit_code, exit_status;
2312 usec_t condition_timestamp;
2313 bool condition_result;
2316 unsigned n_accepted;
2317 unsigned n_connections;
2321 const char *sysfs_path;
2323 /* Mount, Automount */
2329 LIST_HEAD(ExecStatusInfo, exec);
2332 static void print_status_info(UnitStatusInfo *i) {
2334 const char *on, *off, *ss;
2336 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2337 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2340 arg_all * OUTPUT_SHOW_ALL |
2341 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2342 on_tty() * OUTPUT_COLOR |
2343 !arg_quiet * OUTPUT_WARN_CUTOFF |
2344 arg_full * OUTPUT_FULL_WIDTH;
2348 /* This shows pretty information about a unit. See
2349 * print_property() for a low-level property printer */
2351 printf("%s", strna(i->id));
2353 if (i->description && !streq_ptr(i->id, i->description))
2354 printf(" - %s", i->description);
2359 printf("\t Follow: unit currently follows state of %s\n", i->following);
2361 if (streq_ptr(i->load_state, "error")) {
2362 on = ansi_highlight_red(true);
2363 off = ansi_highlight_red(false);
2367 path = i->source_path ? i->source_path : i->fragment_path;
2370 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2371 else if (path && i->unit_file_state)
2372 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2374 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2376 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2378 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2380 if (streq_ptr(i->active_state, "failed")) {
2381 on = ansi_highlight_red(true);
2382 off = ansi_highlight_red(false);
2383 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2384 on = ansi_highlight_green(true);
2385 off = ansi_highlight_green(false);
2390 printf("\t Active: %s%s (%s)%s",
2392 strna(i->active_state),
2396 printf("\t Active: %s%s%s",
2398 strna(i->active_state),
2401 if (!isempty(i->result) && !streq(i->result, "success"))
2402 printf(" (Result: %s)", i->result);
2404 timestamp = (streq_ptr(i->active_state, "active") ||
2405 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2406 (streq_ptr(i->active_state, "inactive") ||
2407 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2408 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2409 i->active_exit_timestamp;
2411 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2412 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2415 printf(" since %s; %s\n", s2, s1);
2417 printf(" since %s\n", s2);
2421 if (!i->condition_result && i->condition_timestamp > 0) {
2422 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2423 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2426 printf("\t start condition failed at %s; %s\n", s2, s1);
2428 printf("\t start condition failed at %s\n", s2);
2432 printf("\t Device: %s\n", i->sysfs_path);
2434 printf("\t Where: %s\n", i->where);
2436 printf("\t What: %s\n", i->what);
2438 if (!strv_isempty(i->documentation)) {
2442 STRV_FOREACH(t, i->documentation) {
2444 printf("\t Docs: %s\n", *t);
2447 printf("\t %s\n", *t);
2452 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2454 LIST_FOREACH(exec, p, i->exec) {
2455 _cleanup_free_ char *t = NULL;
2458 /* Only show exited processes here */
2462 t = strv_join(p->argv, " ");
2463 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2465 good = is_clean_exit_lsb(p->code, p->status, NULL);
2467 on = ansi_highlight_red(true);
2468 off = ansi_highlight_red(false);
2472 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2474 if (p->code == CLD_EXITED) {
2477 printf("status=%i", p->status);
2479 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2484 printf("signal=%s", signal_to_string(p->status));
2486 printf(")%s\n", off);
2488 if (i->main_pid == p->pid &&
2489 i->start_timestamp == p->start_timestamp &&
2490 i->exit_timestamp == p->start_timestamp)
2491 /* Let's not show this twice */
2494 if (p->pid == i->control_pid)
2498 if (i->main_pid > 0 || i->control_pid > 0) {
2501 if (i->main_pid > 0) {
2502 printf("Main PID: %u", (unsigned) i->main_pid);
2505 _cleanup_free_ char *t = NULL;
2506 get_process_comm(i->main_pid, &t);
2509 } else if (i->exit_code > 0) {
2510 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2512 if (i->exit_code == CLD_EXITED) {
2515 printf("status=%i", i->exit_status);
2517 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2522 printf("signal=%s", signal_to_string(i->exit_status));
2527 if (i->main_pid > 0 && i->control_pid > 0)
2530 if (i->control_pid > 0) {
2531 _cleanup_free_ char *t = NULL;
2533 printf(" Control: %u", (unsigned) i->control_pid);
2535 get_process_comm(i->control_pid, &t);
2544 printf("\t Status: \"%s\"\n", i->status_text);
2546 if (i->default_control_group &&
2547 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2550 printf("\t CGroup: %s\n", i->default_control_group);
2552 if (arg_transport != TRANSPORT_SSH) {
2562 if (i->main_pid > 0)
2563 extra[k++] = i->main_pid;
2565 if (i->control_pid > 0)
2566 extra[k++] = i->control_pid;
2568 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, extra, k, flags);
2572 if (i->id && arg_transport != TRANSPORT_SSH) {
2574 if(arg_scope == UNIT_FILE_SYSTEM)
2575 show_journal_by_unit(stdout,
2579 i->inactive_exit_timestamp_monotonic,
2583 show_journal_by_user_unit(stdout,
2587 i->inactive_exit_timestamp_monotonic,
2593 if (i->need_daemon_reload)
2594 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2595 ansi_highlight_red(true),
2596 ansi_highlight_red(false),
2597 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2600 static void show_unit_help(UnitStatusInfo *i) {
2605 if (!i->documentation) {
2606 log_info("Documentation for %s not known.", i->id);
2610 STRV_FOREACH(p, i->documentation) {
2612 if (startswith(*p, "man:")) {
2615 char _cleanup_free_ *page = NULL, *section = NULL;
2616 const char *args[4] = { "man", NULL, NULL, NULL };
2621 if ((*p)[k-1] == ')')
2622 e = strrchr(*p, '(');
2625 page = strndup((*p) + 4, e - *p - 4);
2626 section = strndup(e + 1, *p + k - e - 2);
2627 if (!page || !section) {
2639 log_error("Failed to fork: %m");
2645 execvp(args[0], (char**) args);
2646 log_error("Failed to execute man: %m");
2647 _exit(EXIT_FAILURE);
2650 wait_for_terminate(pid, NULL);
2652 log_info("Can't show: %s", *p);
2656 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2662 switch (dbus_message_iter_get_arg_type(iter)) {
2664 case DBUS_TYPE_STRING: {
2667 dbus_message_iter_get_basic(iter, &s);
2670 if (streq(name, "Id"))
2672 else if (streq(name, "LoadState"))
2674 else if (streq(name, "ActiveState"))
2675 i->active_state = s;
2676 else if (streq(name, "SubState"))
2678 else if (streq(name, "Description"))
2680 else if (streq(name, "FragmentPath"))
2681 i->fragment_path = s;
2682 else if (streq(name, "SourcePath"))
2684 else if (streq(name, "DefaultControlGroup"))
2685 i->default_control_group = s;
2686 else if (streq(name, "StatusText"))
2688 else if (streq(name, "SysFSPath"))
2690 else if (streq(name, "Where"))
2692 else if (streq(name, "What"))
2694 else if (streq(name, "Following"))
2696 else if (streq(name, "UnitFileState"))
2697 i->unit_file_state = s;
2698 else if (streq(name, "Result"))
2705 case DBUS_TYPE_BOOLEAN: {
2708 dbus_message_iter_get_basic(iter, &b);
2710 if (streq(name, "Accept"))
2712 else if (streq(name, "NeedDaemonReload"))
2713 i->need_daemon_reload = b;
2714 else if (streq(name, "ConditionResult"))
2715 i->condition_result = b;
2720 case DBUS_TYPE_UINT32: {
2723 dbus_message_iter_get_basic(iter, &u);
2725 if (streq(name, "MainPID")) {
2727 i->main_pid = (pid_t) u;
2730 } else if (streq(name, "ControlPID"))
2731 i->control_pid = (pid_t) u;
2732 else if (streq(name, "ExecMainPID")) {
2734 i->main_pid = (pid_t) u;
2735 } else if (streq(name, "NAccepted"))
2737 else if (streq(name, "NConnections"))
2738 i->n_connections = u;
2743 case DBUS_TYPE_INT32: {
2746 dbus_message_iter_get_basic(iter, &j);
2748 if (streq(name, "ExecMainCode"))
2749 i->exit_code = (int) j;
2750 else if (streq(name, "ExecMainStatus"))
2751 i->exit_status = (int) j;
2756 case DBUS_TYPE_UINT64: {
2759 dbus_message_iter_get_basic(iter, &u);
2761 if (streq(name, "ExecMainStartTimestamp"))
2762 i->start_timestamp = (usec_t) u;
2763 else if (streq(name, "ExecMainExitTimestamp"))
2764 i->exit_timestamp = (usec_t) u;
2765 else if (streq(name, "ActiveEnterTimestamp"))
2766 i->active_enter_timestamp = (usec_t) u;
2767 else if (streq(name, "InactiveEnterTimestamp"))
2768 i->inactive_enter_timestamp = (usec_t) u;
2769 else if (streq(name, "InactiveExitTimestamp"))
2770 i->inactive_exit_timestamp = (usec_t) u;
2771 else if (streq(name, "InactiveExitTimestampMonotonic"))
2772 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2773 else if (streq(name, "ActiveExitTimestamp"))
2774 i->active_exit_timestamp = (usec_t) u;
2775 else if (streq(name, "ConditionTimestamp"))
2776 i->condition_timestamp = (usec_t) u;
2781 case DBUS_TYPE_ARRAY: {
2783 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2784 startswith(name, "Exec")) {
2785 DBusMessageIter sub;
2787 dbus_message_iter_recurse(iter, &sub);
2788 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2789 ExecStatusInfo *info;
2792 if (!(info = new0(ExecStatusInfo, 1)))
2795 if (!(info->name = strdup(name))) {
2800 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2805 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2807 dbus_message_iter_next(&sub);
2809 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2810 streq(name, "Documentation")) {
2812 DBusMessageIter sub;
2814 dbus_message_iter_recurse(iter, &sub);
2815 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2819 dbus_message_iter_get_basic(&sub, &s);
2821 l = strv_append(i->documentation, s);
2825 strv_free(i->documentation);
2826 i->documentation = l;
2828 dbus_message_iter_next(&sub);
2835 case DBUS_TYPE_STRUCT: {
2837 if (streq(name, "LoadError")) {
2838 DBusMessageIter sub;
2839 const char *n, *message;
2842 dbus_message_iter_recurse(iter, &sub);
2844 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2848 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2852 if (!isempty(message))
2853 i->load_error = message;
2863 static int print_property(const char *name, DBusMessageIter *iter) {
2867 /* This is a low-level property printer, see
2868 * print_status_info() for the nicer output */
2870 if (arg_property && !strv_find(arg_property, name))
2873 switch (dbus_message_iter_get_arg_type(iter)) {
2875 case DBUS_TYPE_STRUCT: {
2876 DBusMessageIter sub;
2877 dbus_message_iter_recurse(iter, &sub);
2879 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2882 dbus_message_iter_get_basic(&sub, &u);
2885 printf("%s=%u\n", name, (unsigned) u);
2887 printf("%s=\n", name);
2890 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2893 dbus_message_iter_get_basic(&sub, &s);
2895 if (arg_all || s[0])
2896 printf("%s=%s\n", name, s);
2899 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2900 const char *a = NULL, *b = NULL;
2902 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2903 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2905 if (arg_all || !isempty(a) || !isempty(b))
2906 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2914 case DBUS_TYPE_ARRAY:
2916 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2917 DBusMessageIter sub, sub2;
2919 dbus_message_iter_recurse(iter, &sub);
2920 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2924 dbus_message_iter_recurse(&sub, &sub2);
2926 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2927 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2928 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2930 dbus_message_iter_next(&sub);
2935 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2936 DBusMessageIter sub, sub2;
2938 dbus_message_iter_recurse(iter, &sub);
2939 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2940 const char *type, *path;
2942 dbus_message_iter_recurse(&sub, &sub2);
2944 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2945 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2946 printf("%s=%s\n", type, path);
2948 dbus_message_iter_next(&sub);
2953 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2954 DBusMessageIter sub, sub2;
2956 dbus_message_iter_recurse(iter, &sub);
2957 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2959 uint64_t value, next_elapse;
2961 dbus_message_iter_recurse(&sub, &sub2);
2963 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2964 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2965 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2966 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2968 printf("%s={ value=%s ; next_elapse=%s }\n",
2970 format_timespan(timespan1, sizeof(timespan1), value),
2971 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2974 dbus_message_iter_next(&sub);
2979 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2980 DBusMessageIter sub, sub2;
2982 dbus_message_iter_recurse(iter, &sub);
2983 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2984 const char *controller, *attr, *value;
2986 dbus_message_iter_recurse(&sub, &sub2);
2988 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2989 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2990 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2992 printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2998 dbus_message_iter_next(&sub);
3003 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3004 DBusMessageIter sub;
3006 dbus_message_iter_recurse(iter, &sub);
3007 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3008 ExecStatusInfo info;
3011 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3012 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3013 char _cleanup_free_ *t;
3015 t = strv_join(info.argv, " ");
3017 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3021 yes_no(info.ignore),
3022 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3023 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3024 (unsigned) info. pid,
3025 sigchld_code_to_string(info.code),
3027 info.code == CLD_EXITED ? "" : "/",
3028 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3032 strv_free(info.argv);
3034 dbus_message_iter_next(&sub);
3043 if (generic_print_property(name, iter, arg_all) > 0)
3047 printf("%s=[unprintable]\n", name);
3052 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3053 _cleanup_free_ DBusMessage *reply = NULL;
3054 const char *interface = "";
3056 DBusMessageIter iter, sub, sub2, sub3;
3057 UnitStatusInfo info;
3065 r = bus_method_call_with_reply(
3067 "org.freedesktop.systemd1",
3069 "org.freedesktop.DBus.Properties",
3073 DBUS_TYPE_STRING, &interface,
3078 if (!dbus_message_iter_init(reply, &iter) ||
3079 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3080 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3081 log_error("Failed to parse reply.");
3085 dbus_message_iter_recurse(&iter, &sub);
3092 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3095 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3096 dbus_message_iter_recurse(&sub, &sub2);
3098 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3099 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3100 log_error("Failed to parse reply.");
3104 dbus_message_iter_recurse(&sub2, &sub3);
3106 if (show_properties)
3107 r = print_property(name, &sub3);
3109 r = status_property(name, &sub3, &info);
3111 log_error("Failed to parse reply.");
3115 dbus_message_iter_next(&sub);
3120 if (!show_properties) {
3121 if (streq(verb, "help"))
3122 show_unit_help(&info);
3124 print_status_info(&info);
3127 strv_free(info.documentation);
3129 if (!streq_ptr(info.active_state, "active") &&
3130 !streq_ptr(info.active_state, "reloading") &&
3131 streq(verb, "status"))
3132 /* According to LSB: "program not running" */
3135 while ((p = info.exec)) {
3136 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3137 exec_status_info_free(p);
3143 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3144 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3145 const char *path = NULL;
3146 DBusError _cleanup_dbus_error_free_ error;
3149 dbus_error_init(&error);
3151 r = bus_method_call_with_reply(
3153 "org.freedesktop.systemd1",
3154 "/org/freedesktop/systemd1",
3155 "org.freedesktop.systemd1.Manager",
3159 DBUS_TYPE_UINT32, &pid,
3164 if (!dbus_message_get_args(reply, &error,
3165 DBUS_TYPE_OBJECT_PATH, &path,
3166 DBUS_TYPE_INVALID)) {
3167 log_error("Failed to parse reply: %s", bus_error_message(&error));
3171 r = show_one(verb, bus, path, false, new_line);
3175 static int show_all(const char* verb, DBusConnection *bus, bool show_properties, bool *new_line) {
3176 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3177 _cleanup_free_ struct unit_info *unit_infos = NULL;
3179 const struct unit_info *u;
3182 r = get_unit_list(bus, &reply, &unit_infos, &c);
3186 for (u = unit_infos; u < unit_infos + c; u++) {
3187 char _cleanup_free_ *p = NULL;
3189 if (!output_show_unit(u))
3192 p = unit_dbus_path_from_name(u->id);
3196 printf("%s -> '%s'\n", u->id, p);
3198 r = show_one(verb, bus, p, show_properties, new_line);
3206 static int show(DBusConnection *bus, char **args) {
3208 bool show_properties, show_status, new_line = false;
3214 show_properties = streq(args[0], "show");
3215 show_status = streq(args[0], "status");
3217 if (show_properties)
3218 pager_open_if_enabled();
3220 /* If no argument is specified inspect the manager itself */
3222 if (show_properties && strv_length(args) <= 1)
3223 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3225 if (show_status && strv_length(args) <= 1)
3226 return show_all(args[0], bus, false, &new_line);
3228 STRV_FOREACH(name, args+1) {
3231 if (safe_atou32(*name, &id) < 0) {
3232 _cleanup_free_ char *p = NULL, *n = NULL;
3233 /* Interpret as unit name */
3235 n = unit_name_mangle(*name);
3239 p = unit_dbus_path_from_name(n);
3243 r = show_one(args[0], bus, p, show_properties, &new_line);
3247 } else if (show_properties) {
3248 _cleanup_free_ char *p = NULL;
3250 /* Interpret as job id */
3251 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3254 r = show_one(args[0], bus, p, show_properties, &new_line);
3259 /* Interpret as PID */
3260 r = show_one_by_pid(args[0], bus, id, &new_line);
3269 static int dump(DBusConnection *bus, char **args) {
3270 _cleanup_free_ DBusMessage *reply = NULL;
3275 dbus_error_init(&error);
3277 pager_open_if_enabled();
3279 r = bus_method_call_with_reply(
3281 "org.freedesktop.systemd1",
3282 "/org/freedesktop/systemd1",
3283 "org.freedesktop.systemd1.Manager",
3291 if (!dbus_message_get_args(reply, &error,
3292 DBUS_TYPE_STRING, &text,
3293 DBUS_TYPE_INVALID)) {
3294 log_error("Failed to parse reply: %s", bus_error_message(&error));
3295 dbus_error_free(&error);
3299 fputs(text, stdout);
3303 static int snapshot(DBusConnection *bus, char **args) {
3304 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3307 dbus_bool_t cleanup = FALSE;
3308 DBusMessageIter iter, sub;
3311 *interface = "org.freedesktop.systemd1.Unit",
3313 _cleanup_free_ char *n = NULL;
3315 dbus_error_init(&error);
3317 if (strv_length(args) > 1)
3318 n = snapshot_name_mangle(args[1]);
3324 r = bus_method_call_with_reply (
3326 "org.freedesktop.systemd1",
3327 "/org/freedesktop/systemd1",
3328 "org.freedesktop.systemd1.Manager",
3332 DBUS_TYPE_STRING, &n,
3333 DBUS_TYPE_BOOLEAN, &cleanup,
3338 if (!dbus_message_get_args(reply, &error,
3339 DBUS_TYPE_OBJECT_PATH, &path,
3340 DBUS_TYPE_INVALID)) {
3341 log_error("Failed to parse reply: %s", bus_error_message(&error));
3342 dbus_error_free(&error);
3346 dbus_message_unref(reply);
3349 r = bus_method_call_with_reply (
3351 "org.freedesktop.systemd1",
3353 "org.freedesktop.DBus.Properties",
3357 DBUS_TYPE_STRING, &interface,
3358 DBUS_TYPE_STRING, &property,
3363 if (!dbus_message_iter_init(reply, &iter) ||
3364 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3365 log_error("Failed to parse reply.");
3369 dbus_message_iter_recurse(&iter, &sub);
3371 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3372 log_error("Failed to parse reply.");
3376 dbus_message_iter_get_basic(&sub, &id);
3384 static int delete_snapshot(DBusConnection *bus, char **args) {
3389 STRV_FOREACH(name, args+1) {
3390 _cleanup_free_ char *n = NULL;
3393 n = snapshot_name_mangle(*name);
3397 r = bus_method_call_with_reply(
3399 "org.freedesktop.systemd1",
3400 "/org/freedesktop/systemd1",
3401 "org.freedesktop.systemd1.Manager",
3405 DBUS_TYPE_STRING, &n,
3414 static int daemon_reload(DBusConnection *bus, char **args) {
3419 if (arg_action == ACTION_RELOAD)
3421 else if (arg_action == ACTION_REEXEC)
3422 method = "Reexecute";
3424 assert(arg_action == ACTION_SYSTEMCTL);
3427 streq(args[0], "clear-jobs") ||
3428 streq(args[0], "cancel") ? "ClearJobs" :
3429 streq(args[0], "daemon-reexec") ? "Reexecute" :
3430 streq(args[0], "reset-failed") ? "ResetFailed" :
3431 streq(args[0], "halt") ? "Halt" :
3432 streq(args[0], "poweroff") ? "PowerOff" :
3433 streq(args[0], "reboot") ? "Reboot" :
3434 streq(args[0], "kexec") ? "KExec" :
3435 streq(args[0], "exit") ? "Exit" :
3436 /* "daemon-reload" */ "Reload";
3439 r = bus_method_call_with_reply(
3441 "org.freedesktop.systemd1",
3442 "/org/freedesktop/systemd1",
3443 "org.freedesktop.systemd1.Manager",
3449 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3450 /* There's always a fallback possible for
3451 * legacy actions. */
3453 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3454 /* On reexecution, we expect a disconnect, not
3458 log_error("Failed to issue method call: %s", bus_error_message(&error));
3460 dbus_error_free(&error);
3464 static int reset_failed(DBusConnection *bus, char **args) {
3468 if (strv_length(args) <= 1)
3469 return daemon_reload(bus, args);
3471 STRV_FOREACH(name, args+1) {
3472 _cleanup_free_ char *n;
3474 n = unit_name_mangle(*name);
3478 r = bus_method_call_with_reply(
3480 "org.freedesktop.systemd1",
3481 "/org/freedesktop/systemd1",
3482 "org.freedesktop.systemd1.Manager",
3486 DBUS_TYPE_STRING, &n,
3495 static int show_enviroment(DBusConnection *bus, char **args) {
3496 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3497 DBusMessageIter iter, sub, sub2;
3500 *interface = "org.freedesktop.systemd1.Manager",
3501 *property = "Environment";
3503 pager_open_if_enabled();
3505 r = bus_method_call_with_reply(
3507 "org.freedesktop.systemd1",
3508 "/org/freedesktop/systemd1",
3509 "org.freedesktop.DBus.Properties",
3513 DBUS_TYPE_STRING, &interface,
3514 DBUS_TYPE_STRING, &property,
3519 if (!dbus_message_iter_init(reply, &iter) ||
3520 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3521 log_error("Failed to parse reply.");
3525 dbus_message_iter_recurse(&iter, &sub);
3527 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3528 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3529 log_error("Failed to parse reply.");
3533 dbus_message_iter_recurse(&sub, &sub2);
3535 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3538 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3539 log_error("Failed to parse reply.");
3543 dbus_message_iter_get_basic(&sub2, &text);
3546 dbus_message_iter_next(&sub2);
3552 static int switch_root(DBusConnection *bus, char **args) {
3555 _cleanup_free_ char *init = NULL;
3557 l = strv_length(args);
3558 if (l < 2 || l > 3) {
3559 log_error("Wrong number of arguments.");
3566 init = strdup(args[2]);
3568 parse_env_file("/proc/cmdline", WHITESPACE,
3578 log_debug("switching root - root: %s; init: %s", root, init);
3580 return bus_method_call_with_reply(
3582 "org.freedesktop.systemd1",
3583 "/org/freedesktop/systemd1",
3584 "org.freedesktop.systemd1.Manager",
3588 DBUS_TYPE_STRING, &root,
3589 DBUS_TYPE_STRING, &init,
3593 static int set_environment(DBusConnection *bus, char **args) {
3594 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3597 DBusMessageIter iter;
3603 dbus_error_init(&error);
3605 method = streq(args[0], "set-environment")
3607 : "UnsetEnvironment";
3609 m = dbus_message_new_method_call(
3610 "org.freedesktop.systemd1",
3611 "/org/freedesktop/systemd1",
3612 "org.freedesktop.systemd1.Manager",
3617 dbus_message_iter_init_append(m, &iter);
3619 r = bus_append_strv_iter(&iter, args + 1);
3623 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3625 log_error("Failed to issue method call: %s", bus_error_message(&error));
3626 dbus_error_free(&error);
3633 static int enable_sysv_units(char **args) {
3636 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3637 const char *verb = args[0];
3638 unsigned f = 1, t = 1;
3641 if (arg_scope != UNIT_FILE_SYSTEM)
3644 if (!streq(verb, "enable") &&
3645 !streq(verb, "disable") &&
3646 !streq(verb, "is-enabled"))
3649 /* Processes all SysV units, and reshuffles the array so that
3650 * afterwards only the native units remain */
3653 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3658 for (f = 1; args[f]; f++) {
3661 bool found_native = false, found_sysv;
3663 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3664 char **k, *l, *q = NULL;
3671 if (!endswith(name, ".service"))
3674 if (path_is_absolute(name))
3677 STRV_FOREACH(k, paths.unit_path) {
3680 if (!isempty(arg_root))
3681 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3683 asprintf(&p, "%s/%s", *k, name);
3690 found_native = access(p, F_OK) >= 0;
3701 if (!isempty(arg_root))
3702 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3704 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3710 p[strlen(p) - sizeof(".service") + 1] = 0;
3711 found_sysv = access(p, F_OK) >= 0;
3718 /* Mark this entry, so that we don't try enabling it as native unit */
3719 args[f] = (char*) "";
3721 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3723 if (!isempty(arg_root))
3724 argv[c++] = q = strappend("--root=", arg_root);
3726 argv[c++] = path_get_file_name(p);
3728 streq(verb, "enable") ? "on" :
3729 streq(verb, "disable") ? "off" : "--level=5";
3732 l = strv_join((char**)argv, " ");
3740 log_info("Executing %s", l);
3745 log_error("Failed to fork: %m");
3750 } else if (pid == 0) {
3753 execv(argv[0], (char**) argv);
3754 _exit(EXIT_FAILURE);
3760 j = wait_for_terminate(pid, &status);
3762 log_error("Failed to wait for child: %s", strerror(-r));
3767 if (status.si_code == CLD_EXITED) {
3768 if (streq(verb, "is-enabled")) {
3769 if (status.si_status == 0) {
3778 } else if (status.si_status != 0) {
3789 lookup_paths_free(&paths);
3791 /* Drop all SysV units */
3792 for (f = 1, t = 1; args[f]; f++) {
3794 if (isempty(args[f]))
3797 args[t++] = args[f];
3806 static int mangle_names(char **original_names, char ***mangled_names) {
3807 char **i, **l, **name;
3809 l = new(char*, strv_length(original_names) + 1);
3814 STRV_FOREACH(name, original_names) {
3816 /* When enabling units qualified path names are OK,
3817 * too, hence allow them explicitly. */
3822 *i = unit_name_mangle(*name);
3838 static int enable_unit(DBusConnection *bus, char **args) {
3839 const char *verb = args[0];
3840 UnitFileChange *changes = NULL;
3841 unsigned n_changes = 0, i;
3842 int carries_install_info = -1;
3843 DBusMessage _cleanup_dbus_message_unref_ *m = NULL, *reply = NULL;
3845 DBusError _cleanup_dbus_error_free_ error;
3846 char _cleanup_strv_free_ **mangled_names = NULL;
3848 dbus_error_init(&error);
3850 r = enable_sysv_units(args);
3857 if (!bus || avoid_bus()) {
3858 if (streq(verb, "enable")) {
3859 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3860 carries_install_info = r;
3861 } else if (streq(verb, "disable"))
3862 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3863 else if (streq(verb, "reenable")) {
3864 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3865 carries_install_info = r;
3866 } else if (streq(verb, "link"))
3867 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3868 else if (streq(verb, "preset")) {
3869 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3870 carries_install_info = r;
3871 } else if (streq(verb, "mask"))
3872 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3873 else if (streq(verb, "unmask"))
3874 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3876 assert_not_reached("Unknown verb");
3879 log_error("Operation failed: %s", strerror(-r));
3884 for (i = 0; i < n_changes; i++) {
3885 if (changes[i].type == UNIT_FILE_SYMLINK)
3886 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3888 log_info("rm '%s'", changes[i].path);
3895 bool send_force = true, expect_carries_install_info = false;
3897 DBusMessageIter iter, sub, sub2;
3899 if (streq(verb, "enable")) {
3900 method = "EnableUnitFiles";
3901 expect_carries_install_info = true;
3902 } else if (streq(verb, "disable")) {
3903 method = "DisableUnitFiles";
3905 } else if (streq(verb, "reenable")) {
3906 method = "ReenableUnitFiles";
3907 expect_carries_install_info = true;
3908 } else if (streq(verb, "link"))
3909 method = "LinkUnitFiles";
3910 else if (streq(verb, "preset")) {
3911 method = "PresetUnitFiles";
3912 expect_carries_install_info = true;
3913 } else if (streq(verb, "mask"))
3914 method = "MaskUnitFiles";
3915 else if (streq(verb, "unmask")) {
3916 method = "UnmaskUnitFiles";
3919 assert_not_reached("Unknown verb");
3921 m = dbus_message_new_method_call(
3922 "org.freedesktop.systemd1",
3923 "/org/freedesktop/systemd1",
3924 "org.freedesktop.systemd1.Manager",
3931 dbus_message_iter_init_append(m, &iter);
3933 r = mangle_names(args+1, &mangled_names);
3937 r = bus_append_strv_iter(&iter, mangled_names);
3939 log_error("Failed to append unit files.");
3944 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3945 log_error("Failed to append runtime boolean.");
3953 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3954 log_error("Failed to append force boolean.");
3960 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3962 log_error("Failed to issue method call: %s", bus_error_message(&error));
3967 if (!dbus_message_iter_init(reply, &iter)) {
3968 log_error("Failed to initialize iterator.");
3972 if (expect_carries_install_info) {
3973 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3975 log_error("Failed to parse reply.");
3979 carries_install_info = b;
3982 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3983 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3984 log_error("Failed to parse reply.");
3989 dbus_message_iter_recurse(&iter, &sub);
3990 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3991 const char *type, *path, *source;
3993 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3994 log_error("Failed to parse reply.");
3999 dbus_message_iter_recurse(&sub, &sub2);
4001 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4002 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4003 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4004 log_error("Failed to parse reply.");
4010 if (streq(type, "symlink"))
4011 log_info("ln -s '%s' '%s'", source, path);
4013 log_info("rm '%s'", path);
4016 dbus_message_iter_next(&sub);
4019 /* Try to reload if enabeld */
4021 r = daemon_reload(bus, args);
4024 if (carries_install_info == 0)
4026 "The unit files have no [Install] section. They are not meant to be enabled\n"
4027 "using systemctl.\n"
4028 "Possible reasons for having this kind of units are:\n"
4029 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4030 " .wants/ or .requires/ directory.\n"
4031 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4032 " a requirement dependency on it.\n"
4033 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4034 " D-Bus, udev, scripted systemctl call, ...).\n");
4037 unit_file_changes_free(changes, n_changes);
4042 static int unit_is_enabled(DBusConnection *bus, char **args) {
4043 DBusError _cleanup_dbus_error_free_ error;
4045 DBusMessage _cleanup_dbus_message_unref_ *reply = NULL;
4049 dbus_error_init(&error);
4051 r = enable_sysv_units(args);
4057 if (!bus || avoid_bus()) {
4059 STRV_FOREACH(name, args+1) {
4060 UnitFileState state;
4062 state = unit_file_get_state(arg_scope, arg_root, *name);
4066 if (state == UNIT_FILE_ENABLED ||
4067 state == UNIT_FILE_ENABLED_RUNTIME ||
4068 state == UNIT_FILE_STATIC)
4072 puts(unit_file_state_to_string(state));
4076 STRV_FOREACH(name, args+1) {
4079 r = bus_method_call_with_reply (
4081 "org.freedesktop.systemd1",
4082 "/org/freedesktop/systemd1",
4083 "org.freedesktop.systemd1.Manager",
4087 DBUS_TYPE_STRING, name,
4092 if (!dbus_message_get_args(reply, &error,
4093 DBUS_TYPE_STRING, &s,
4094 DBUS_TYPE_INVALID)) {
4095 log_error("Failed to parse reply: %s", bus_error_message(&error));
4099 dbus_message_unref(reply);
4102 if (streq(s, "enabled") ||
4103 streq(s, "enabled-runtime") ||
4112 return enabled ? 0 : 1;
4115 static int systemctl_help(void) {
4117 pager_open_if_enabled();
4119 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4120 "Query or send control commands to the systemd manager.\n\n"
4121 " -h --help Show this help\n"
4122 " --version Show package version\n"
4123 " -t --type=TYPE List only units of a particular type\n"
4124 " -p --property=NAME Show only properties by this name\n"
4125 " -a --all Show all units/properties, including dead/empty ones\n"
4126 " --failed Show only failed units\n"
4127 " --full Don't ellipsize unit names on output\n"
4128 " --fail When queueing a new job, fail if conflicting jobs are\n"
4130 " --ignore-dependencies\n"
4131 " When queueing a new job, ignore all its dependencies\n"
4132 " -i --ignore-inhibitors\n"
4133 " When shutting down or sleeping, ignore inhibitors\n"
4134 " --kill-who=WHO Who to send signal to\n"
4135 " -s --signal=SIGNAL Which signal to send\n"
4136 " -H --host=[USER@]HOST\n"
4137 " Show information for remote host\n"
4138 " -P --privileged Acquire privileges before execution\n"
4139 " -q --quiet Suppress output\n"
4140 " --no-block Do not wait until operation finished\n"
4141 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4142 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4144 " --no-legend Do not print a legend (column headers and hints)\n"
4145 " --no-pager Do not pipe output into a pager\n"
4146 " --no-ask-password\n"
4147 " Do not ask for system passwords\n"
4148 " --system Connect to system manager\n"
4149 " --user Connect to user service manager\n"
4150 " --global Enable/disable unit files globally\n"
4151 " -f --force When enabling unit files, override existing symlinks\n"
4152 " When shutting down, execute action immediately\n"
4153 " --root=PATH Enable unit files in the specified root directory\n"
4154 " --runtime Enable unit files only temporarily until next reboot\n"
4155 " -n --lines=INTEGER Journal entries to show\n"
4156 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4157 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4159 " list-units List loaded units\n"
4160 " start [NAME...] Start (activate) one or more units\n"
4161 " stop [NAME...] Stop (deactivate) one or more units\n"
4162 " reload [NAME...] Reload one or more units\n"
4163 " restart [NAME...] Start or restart one or more units\n"
4164 " try-restart [NAME...] Restart one or more units if active\n"
4165 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4166 " otherwise start or restart\n"
4167 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4168 " otherwise restart if active\n"
4169 " isolate [NAME] Start one unit and stop all others\n"
4170 " kill [NAME...] Send signal to processes of a unit\n"
4171 " is-active [NAME...] Check whether units are active\n"
4172 " is-failed [NAME...] Check whether units are failed\n"
4173 " status [NAME...|PID...] Show runtime status of one or more units\n"
4174 " show [NAME...|JOB...] Show properties of one or more\n"
4175 " units/jobs or the manager\n"
4176 " help [NAME...|PID...] Show manual for one or more units\n"
4177 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4179 " get-cgroup-attr [NAME] [ATTR] ...\n"
4180 " Get control group attrubute\n"
4181 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4182 " Set control group attribute\n"
4183 " unset-cgroup-attr [NAME] [ATTR...]\n"
4184 " Unset control group attribute\n"
4185 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4186 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4187 " load [NAME...] Load one or more units\n"
4188 " list-dependencies [NAME] Recursively show units which are required\n"
4189 " or wanted by this unit\n\n"
4190 "Unit File Commands:\n"
4191 " list-unit-files List installed unit files\n"
4192 " enable [NAME...] Enable one or more unit files\n"
4193 " disable [NAME...] Disable one or more unit files\n"
4194 " reenable [NAME...] Reenable one or more unit files\n"
4195 " preset [NAME...] Enable/disable one or more unit files\n"
4196 " based on preset configuration\n"
4197 " mask [NAME...] Mask one or more units\n"
4198 " unmask [NAME...] Unmask one or more units\n"
4199 " link [PATH...] Link one or more units files into\n"
4200 " the search path\n"
4201 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4203 " list-jobs List jobs\n"
4204 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4205 "Status Commands:\n"
4206 " dump Dump server status\n"
4207 "Snapshot Commands:\n"
4208 " snapshot [NAME] Create a snapshot\n"
4209 " delete [NAME...] Remove one or more snapshots\n\n"
4210 "Environment Commands:\n"
4211 " show-environment Dump environment\n"
4212 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4213 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4214 "Manager Lifecycle Commands:\n"
4215 " daemon-reload Reload systemd manager configuration\n"
4216 " daemon-reexec Reexecute systemd manager\n\n"
4217 "System Commands:\n"
4218 " default Enter system default mode\n"
4219 " rescue Enter system rescue mode\n"
4220 " emergency Enter system emergency mode\n"
4221 " halt Shut down and halt the system\n"
4222 " poweroff Shut down and power-off the system\n"
4223 " reboot Shut down and reboot the system\n"
4224 " kexec Shut down and reboot the system with kexec\n"
4225 " exit Request user instance exit\n"
4226 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4227 " suspend Suspend the system\n"
4228 " hibernate Hibernate the system\n"
4229 " hybrid-sleep Hibernate and suspend the system\n",
4230 program_invocation_short_name);
4235 static int halt_help(void) {
4237 printf("%s [OPTIONS...]\n\n"
4238 "%s the system.\n\n"
4239 " --help Show this help\n"
4240 " --halt Halt the machine\n"
4241 " -p --poweroff Switch off the machine\n"
4242 " --reboot Reboot the machine\n"
4243 " -f --force Force immediate halt/power-off/reboot\n"
4244 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4245 " -d --no-wtmp Don't write wtmp record\n"
4246 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4247 program_invocation_short_name,
4248 arg_action == ACTION_REBOOT ? "Reboot" :
4249 arg_action == ACTION_POWEROFF ? "Power off" :
4255 static int shutdown_help(void) {
4257 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4258 "Shut down the system.\n\n"
4259 " --help Show this help\n"
4260 " -H --halt Halt the machine\n"
4261 " -P --poweroff Power-off the machine\n"
4262 " -r --reboot Reboot the machine\n"
4263 " -h Equivalent to --poweroff, overridden by --halt\n"
4264 " -k Don't halt/power-off/reboot, just send warnings\n"
4265 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4266 " -c Cancel a pending shutdown\n",
4267 program_invocation_short_name);
4272 static int telinit_help(void) {
4274 printf("%s [OPTIONS...] {COMMAND}\n\n"
4275 "Send control commands to the init daemon.\n\n"
4276 " --help Show this help\n"
4277 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4279 " 0 Power-off the machine\n"
4280 " 6 Reboot the machine\n"
4281 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4282 " 1, s, S Enter rescue mode\n"
4283 " q, Q Reload init daemon configuration\n"
4284 " u, U Reexecute init daemon\n",
4285 program_invocation_short_name);
4290 static int runlevel_help(void) {
4292 printf("%s [OPTIONS...]\n\n"
4293 "Prints the previous and current runlevel of the init system.\n\n"
4294 " --help Show this help\n",
4295 program_invocation_short_name);
4300 static int help_types(void) {
4303 puts("Available unit types:");
4304 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4305 if (unit_type_table[i])
4306 puts(unit_type_table[i]);
4308 puts("\nAvailable unit load states: ");
4309 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4310 if (unit_type_table[i])
4311 puts(unit_load_state_table[i]);
4316 static int systemctl_parse_argv(int argc, char *argv[]) {
4321 ARG_IGNORE_DEPENDENCIES,
4334 ARG_NO_ASK_PASSWORD,
4340 static const struct option options[] = {
4341 { "help", no_argument, NULL, 'h' },
4342 { "version", no_argument, NULL, ARG_VERSION },
4343 { "type", required_argument, NULL, 't' },
4344 { "property", required_argument, NULL, 'p' },
4345 { "all", no_argument, NULL, 'a' },
4346 { "failed", no_argument, NULL, ARG_FAILED },
4347 { "full", no_argument, NULL, ARG_FULL },
4348 { "fail", no_argument, NULL, ARG_FAIL },
4349 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4350 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4351 { "ignore-inhibitors", no_argument, NULL, 'i' },
4352 { "user", no_argument, NULL, ARG_USER },
4353 { "system", no_argument, NULL, ARG_SYSTEM },
4354 { "global", no_argument, NULL, ARG_GLOBAL },
4355 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4356 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4357 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4358 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4359 { "quiet", no_argument, NULL, 'q' },
4360 { "root", required_argument, NULL, ARG_ROOT },
4361 { "force", no_argument, NULL, ARG_FORCE },
4362 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4363 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4364 { "signal", required_argument, NULL, 's' },
4365 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4366 { "host", required_argument, NULL, 'H' },
4367 { "privileged",no_argument, NULL, 'P' },
4368 { "runtime", no_argument, NULL, ARG_RUNTIME },
4369 { "lines", required_argument, NULL, 'n' },
4370 { "output", required_argument, NULL, 'o' },
4371 { NULL, 0, NULL, 0 }
4379 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4388 puts(PACKAGE_STRING);
4389 puts(SYSTEMD_FEATURES);
4393 if (streq(optarg, "help")) {
4398 if (unit_type_from_string(optarg) >= 0) {
4402 if (unit_load_state_from_string(optarg) >= 0) {
4403 arg_load_state = optarg;
4406 log_error("Unkown unit type or load state '%s'.",
4408 log_info("Use -t help to see a list of allowed values.");
4413 /* Make sure that if the empty property list
4414 was specified, we won't show any properties. */
4415 const char *source = isempty(optarg) ? " " : optarg;
4417 FOREACH_WORD_SEPARATOR(word, size, source, ",", state) {
4418 char _cleanup_free_ *prop;
4421 prop = strndup(word, size);
4425 tmp = strv_append(arg_property, prop);
4429 strv_free(arg_property);
4433 /* If the user asked for a particular
4434 * property, show it to him, even if it is
4446 arg_job_mode = "fail";
4449 case ARG_IRREVERSIBLE:
4450 arg_job_mode = "replace-irreversibly";
4453 case ARG_IGNORE_DEPENDENCIES:
4454 arg_job_mode = "ignore-dependencies";
4458 arg_scope = UNIT_FILE_USER;
4462 arg_scope = UNIT_FILE_SYSTEM;
4466 arg_scope = UNIT_FILE_GLOBAL;
4470 arg_no_block = true;
4474 arg_no_legend = true;
4478 arg_no_pager = true;
4510 arg_no_reload = true;
4514 arg_kill_who = optarg;
4518 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4519 log_error("Failed to parse signal string %s.", optarg);
4524 case ARG_NO_ASK_PASSWORD:
4525 arg_ask_password = false;
4529 arg_transport = TRANSPORT_POLKIT;
4533 arg_transport = TRANSPORT_SSH;
4542 if (safe_atou(optarg, &arg_lines) < 0) {
4543 log_error("Failed to parse lines '%s'", optarg);
4549 arg_output = output_mode_from_string(optarg);
4550 if (arg_output < 0) {
4551 log_error("Unknown output '%s'.", optarg);
4557 arg_ignore_inhibitors = true;
4564 log_error("Unknown option code '%c'.", c);
4569 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4570 log_error("Cannot access user instance remotely.");
4577 static int halt_parse_argv(int argc, char *argv[]) {
4586 static const struct option options[] = {
4587 { "help", no_argument, NULL, ARG_HELP },
4588 { "halt", no_argument, NULL, ARG_HALT },
4589 { "poweroff", no_argument, NULL, 'p' },
4590 { "reboot", no_argument, NULL, ARG_REBOOT },
4591 { "force", no_argument, NULL, 'f' },
4592 { "wtmp-only", no_argument, NULL, 'w' },
4593 { "no-wtmp", no_argument, NULL, 'd' },
4594 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4595 { NULL, 0, NULL, 0 }
4603 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4604 if (runlevel == '0' || runlevel == '6')
4607 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4615 arg_action = ACTION_HALT;
4619 if (arg_action != ACTION_REBOOT)
4620 arg_action = ACTION_POWEROFF;
4624 arg_action = ACTION_REBOOT;
4646 /* Compatibility nops */
4653 log_error("Unknown option code '%c'.", c);
4658 if (optind < argc) {
4659 log_error("Too many arguments.");
4666 static int parse_time_spec(const char *t, usec_t *_u) {
4670 if (streq(t, "now"))
4672 else if (!strchr(t, ':')) {
4675 if (safe_atou64(t, &u) < 0)
4678 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4687 hour = strtol(t, &e, 10);
4688 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4691 minute = strtol(e+1, &e, 10);
4692 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4695 n = now(CLOCK_REALTIME);
4696 s = (time_t) (n / USEC_PER_SEC);
4699 assert_se(localtime_r(&s, &tm));
4701 tm.tm_hour = (int) hour;
4702 tm.tm_min = (int) minute;
4705 assert_se(s = mktime(&tm));
4707 *_u = (usec_t) s * USEC_PER_SEC;
4710 *_u += USEC_PER_DAY;
4716 static int shutdown_parse_argv(int argc, char *argv[]) {
4723 static const struct option options[] = {
4724 { "help", no_argument, NULL, ARG_HELP },
4725 { "halt", no_argument, NULL, 'H' },
4726 { "poweroff", no_argument, NULL, 'P' },
4727 { "reboot", no_argument, NULL, 'r' },
4728 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4729 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4730 { NULL, 0, NULL, 0 }
4738 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4746 arg_action = ACTION_HALT;
4750 arg_action = ACTION_POWEROFF;
4755 arg_action = ACTION_KEXEC;
4757 arg_action = ACTION_REBOOT;
4761 arg_action = ACTION_KEXEC;
4765 if (arg_action != ACTION_HALT)
4766 arg_action = ACTION_POWEROFF;
4779 /* Compatibility nops */
4783 arg_action = ACTION_CANCEL_SHUTDOWN;
4790 log_error("Unknown option code '%c'.", c);
4795 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4796 r = parse_time_spec(argv[optind], &arg_when);
4798 log_error("Failed to parse time specification: %s", argv[optind]);
4802 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4804 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4805 /* No time argument for shutdown cancel */
4806 arg_wall = argv + optind;
4807 else if (argc > optind + 1)
4808 /* We skip the time argument */
4809 arg_wall = argv + optind + 1;
4816 static int telinit_parse_argv(int argc, char *argv[]) {
4823 static const struct option options[] = {
4824 { "help", no_argument, NULL, ARG_HELP },
4825 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4826 { NULL, 0, NULL, 0 }
4829 static const struct {
4833 { '0', ACTION_POWEROFF },
4834 { '6', ACTION_REBOOT },
4835 { '1', ACTION_RESCUE },
4836 { '2', ACTION_RUNLEVEL2 },
4837 { '3', ACTION_RUNLEVEL3 },
4838 { '4', ACTION_RUNLEVEL4 },
4839 { '5', ACTION_RUNLEVEL5 },
4840 { 's', ACTION_RESCUE },
4841 { 'S', ACTION_RESCUE },
4842 { 'q', ACTION_RELOAD },
4843 { 'Q', ACTION_RELOAD },
4844 { 'u', ACTION_REEXEC },
4845 { 'U', ACTION_REEXEC }
4854 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4869 log_error("Unknown option code '%c'.", c);
4874 if (optind >= argc) {
4879 if (optind + 1 < argc) {
4880 log_error("Too many arguments.");
4884 if (strlen(argv[optind]) != 1) {
4885 log_error("Expected single character argument.");
4889 for (i = 0; i < ELEMENTSOF(table); i++)
4890 if (table[i].from == argv[optind][0])
4893 if (i >= ELEMENTSOF(table)) {
4894 log_error("Unknown command '%s'.", argv[optind]);
4898 arg_action = table[i].to;
4905 static int runlevel_parse_argv(int argc, char *argv[]) {
4911 static const struct option options[] = {
4912 { "help", no_argument, NULL, ARG_HELP },
4913 { NULL, 0, NULL, 0 }
4921 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4932 log_error("Unknown option code '%c'.", c);
4937 if (optind < argc) {
4938 log_error("Too many arguments.");
4945 static int parse_argv(int argc, char *argv[]) {
4949 if (program_invocation_short_name) {
4951 if (strstr(program_invocation_short_name, "halt")) {
4952 arg_action = ACTION_HALT;
4953 return halt_parse_argv(argc, argv);
4954 } else if (strstr(program_invocation_short_name, "poweroff")) {
4955 arg_action = ACTION_POWEROFF;
4956 return halt_parse_argv(argc, argv);
4957 } else if (strstr(program_invocation_short_name, "reboot")) {
4959 arg_action = ACTION_KEXEC;
4961 arg_action = ACTION_REBOOT;
4962 return halt_parse_argv(argc, argv);
4963 } else if (strstr(program_invocation_short_name, "shutdown")) {
4964 arg_action = ACTION_POWEROFF;
4965 return shutdown_parse_argv(argc, argv);
4966 } else if (strstr(program_invocation_short_name, "init")) {
4968 if (sd_booted() > 0) {
4969 arg_action = ACTION_INVALID;
4970 return telinit_parse_argv(argc, argv);
4972 /* Hmm, so some other init system is
4973 * running, we need to forward this
4974 * request to it. For now we simply
4975 * guess that it is Upstart. */
4977 execv("/lib/upstart/telinit", argv);
4979 log_error("Couldn't find an alternative telinit implementation to spawn.");
4983 } else if (strstr(program_invocation_short_name, "runlevel")) {
4984 arg_action = ACTION_RUNLEVEL;
4985 return runlevel_parse_argv(argc, argv);
4989 arg_action = ACTION_SYSTEMCTL;
4990 return systemctl_parse_argv(argc, argv);
4993 static int action_to_runlevel(void) {
4995 static const char table[_ACTION_MAX] = {
4996 [ACTION_HALT] = '0',
4997 [ACTION_POWEROFF] = '0',
4998 [ACTION_REBOOT] = '6',
4999 [ACTION_RUNLEVEL2] = '2',
5000 [ACTION_RUNLEVEL3] = '3',
5001 [ACTION_RUNLEVEL4] = '4',
5002 [ACTION_RUNLEVEL5] = '5',
5003 [ACTION_RESCUE] = '1'
5006 assert(arg_action < _ACTION_MAX);
5008 return table[arg_action];
5011 static int talk_upstart(void) {
5012 DBusMessage _cleanup_dbus_message_unref_ *m = NULL, *reply = NULL;
5013 DBusError _cleanup_dbus_error_free_ error;
5014 int previous, rl, r;
5016 env1_buf[] = "RUNLEVEL=X",
5017 env2_buf[] = "PREVLEVEL=X";
5018 char *env1 = env1_buf, *env2 = env2_buf;
5019 const char *emit = "runlevel";
5020 dbus_bool_t b_false = FALSE;
5021 DBusMessageIter iter, sub;
5022 DBusConnection *bus;
5024 dbus_error_init(&error);
5026 if (!(rl = action_to_runlevel()))
5029 if (utmp_get_runlevel(&previous, NULL) < 0)
5032 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5033 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5038 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5043 if ((r = bus_check_peercred(bus)) < 0) {
5044 log_error("Failed to verify owner of bus.");
5048 if (!(m = dbus_message_new_method_call(
5049 "com.ubuntu.Upstart",
5050 "/com/ubuntu/Upstart",
5051 "com.ubuntu.Upstart0_6",
5054 log_error("Could not allocate message.");
5059 dbus_message_iter_init_append(m, &iter);
5061 env1_buf[sizeof(env1_buf)-2] = rl;
5062 env2_buf[sizeof(env2_buf)-2] = previous;
5064 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5065 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5066 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5067 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5068 !dbus_message_iter_close_container(&iter, &sub) ||
5069 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5070 log_error("Could not append arguments to message.");
5075 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5077 if (bus_error_is_no_service(&error)) {
5082 log_error("Failed to issue method call: %s", bus_error_message(&error));
5091 dbus_connection_flush(bus);
5092 dbus_connection_close(bus);
5093 dbus_connection_unref(bus);
5099 static int talk_initctl(void) {
5100 struct init_request request;
5104 if (!(rl = action_to_runlevel()))
5108 request.magic = INIT_MAGIC;
5109 request.sleeptime = 0;
5110 request.cmd = INIT_CMD_RUNLVL;
5111 request.runlevel = rl;
5113 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5115 if (errno == ENOENT)
5118 log_error("Failed to open "INIT_FIFO": %m");
5123 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5124 close_nointr_nofail(fd);
5127 log_error("Failed to write to "INIT_FIFO": %m");
5128 return errno ? -errno : -EIO;
5134 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5136 static const struct {
5144 int (* const dispatch)(DBusConnection *bus, char **args);
5146 { "list-units", LESS, 1, list_units },
5147 { "list-unit-files", EQUAL, 1, list_unit_files },
5148 { "list-jobs", EQUAL, 1, list_jobs },
5149 { "clear-jobs", EQUAL, 1, daemon_reload },
5150 { "load", MORE, 2, load_unit },
5151 { "cancel", MORE, 2, cancel_job },
5152 { "start", MORE, 2, start_unit },
5153 { "stop", MORE, 2, start_unit },
5154 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5155 { "reload", MORE, 2, start_unit },
5156 { "restart", MORE, 2, start_unit },
5157 { "try-restart", MORE, 2, start_unit },
5158 { "reload-or-restart", MORE, 2, start_unit },
5159 { "reload-or-try-restart", MORE, 2, start_unit },
5160 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5161 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5162 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5163 { "isolate", EQUAL, 2, start_unit },
5164 { "set-cgroup", MORE, 2, set_cgroup },
5165 { "unset-cgroup", MORE, 2, set_cgroup },
5166 { "get-cgroup-attr", MORE, 2, get_cgroup_attr },
5167 { "set-cgroup-attr", MORE, 2, set_cgroup_attr },
5168 { "unset-cgroup-attr", MORE, 2, set_cgroup },
5169 { "kill", MORE, 2, kill_unit },
5170 { "is-active", MORE, 2, check_unit_active },
5171 { "check", MORE, 2, check_unit_active },
5172 { "is-failed", MORE, 2, check_unit_failed },
5173 { "show", MORE, 1, show },
5174 { "status", MORE, 1, show },
5175 { "help", MORE, 2, show },
5176 { "dump", EQUAL, 1, dump },
5177 { "snapshot", LESS, 2, snapshot },
5178 { "delete", MORE, 2, delete_snapshot },
5179 { "daemon-reload", EQUAL, 1, daemon_reload },
5180 { "daemon-reexec", EQUAL, 1, daemon_reload },
5181 { "show-environment", EQUAL, 1, show_enviroment },
5182 { "set-environment", MORE, 2, set_environment },
5183 { "unset-environment", MORE, 2, set_environment },
5184 { "halt", EQUAL, 1, start_special },
5185 { "poweroff", EQUAL, 1, start_special },
5186 { "reboot", EQUAL, 1, start_special },
5187 { "kexec", EQUAL, 1, start_special },
5188 { "suspend", EQUAL, 1, start_special },
5189 { "hibernate", EQUAL, 1, start_special },
5190 { "hybrid-sleep", EQUAL, 1, start_special },
5191 { "default", EQUAL, 1, start_special },
5192 { "rescue", EQUAL, 1, start_special },
5193 { "emergency", EQUAL, 1, start_special },
5194 { "exit", EQUAL, 1, start_special },
5195 { "reset-failed", MORE, 1, reset_failed },
5196 { "enable", MORE, 2, enable_unit },
5197 { "disable", MORE, 2, enable_unit },
5198 { "is-enabled", MORE, 2, unit_is_enabled },
5199 { "reenable", MORE, 2, enable_unit },
5200 { "preset", MORE, 2, enable_unit },
5201 { "mask", MORE, 2, enable_unit },
5202 { "unmask", MORE, 2, enable_unit },
5203 { "link", MORE, 2, enable_unit },
5204 { "switch-root", MORE, 2, switch_root },
5205 { "list-dependencies", LESS, 2, list_dependencies },
5215 left = argc - optind;
5218 /* Special rule: no arguments means "list-units" */
5221 if (streq(argv[optind], "help") && !argv[optind+1]) {
5222 log_error("This command expects one or more "
5223 "unit names. Did you mean --help?");
5227 for (i = 0; i < ELEMENTSOF(verbs); i++)
5228 if (streq(argv[optind], verbs[i].verb))
5231 if (i >= ELEMENTSOF(verbs)) {
5232 log_error("Unknown operation '%s'.", argv[optind]);
5237 switch (verbs[i].argc_cmp) {
5240 if (left != verbs[i].argc) {
5241 log_error("Invalid number of arguments.");
5248 if (left < verbs[i].argc) {
5249 log_error("Too few arguments.");
5256 if (left > verbs[i].argc) {
5257 log_error("Too many arguments.");
5264 assert_not_reached("Unknown comparison operator.");
5267 /* Require a bus connection for all operations but
5269 if (!streq(verbs[i].verb, "enable") &&
5270 !streq(verbs[i].verb, "disable") &&
5271 !streq(verbs[i].verb, "is-enabled") &&
5272 !streq(verbs[i].verb, "list-unit-files") &&
5273 !streq(verbs[i].verb, "reenable") &&
5274 !streq(verbs[i].verb, "preset") &&
5275 !streq(verbs[i].verb, "mask") &&
5276 !streq(verbs[i].verb, "unmask") &&
5277 !streq(verbs[i].verb, "link")) {
5279 if (running_in_chroot() > 0) {
5280 log_info("Running in chroot, ignoring request.");
5284 if (((!streq(verbs[i].verb, "reboot") &&
5285 !streq(verbs[i].verb, "halt") &&
5286 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5287 log_error("Failed to get D-Bus connection: %s",
5288 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5294 if (!bus && !avoid_bus()) {
5295 log_error("Failed to get D-Bus connection: %s",
5296 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5301 return verbs[i].dispatch(bus, argv + optind);
5304 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5305 int _cleanup_close_ fd;
5306 struct msghdr msghdr;
5307 struct iovec iovec[2];
5308 union sockaddr_union sockaddr;
5309 struct sd_shutdown_command c;
5311 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5318 c.dry_run = dry_run;
5322 sockaddr.sa.sa_family = AF_UNIX;
5323 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5326 msghdr.msg_name = &sockaddr;
5327 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5330 iovec[0].iov_base = (char*) &c;
5331 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5333 if (isempty(message))
5334 msghdr.msg_iovlen = 1;
5336 iovec[1].iov_base = (char*) message;
5337 iovec[1].iov_len = strlen(message);
5338 msghdr.msg_iovlen = 2;
5340 msghdr.msg_iov = iovec;
5342 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5348 static int reload_with_fallback(DBusConnection *bus) {
5351 /* First, try systemd via D-Bus. */
5352 if (daemon_reload(bus, NULL) >= 0)
5356 /* Nothing else worked, so let's try signals */
5357 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5359 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5360 log_error("kill() failed: %m");
5367 static int start_with_fallback(DBusConnection *bus) {
5370 /* First, try systemd via D-Bus. */
5371 if (start_unit(bus, NULL) >= 0)
5375 /* Hmm, talking to systemd via D-Bus didn't work. Then
5376 * let's try to talk to Upstart via D-Bus. */
5377 if (talk_upstart() > 0)
5380 /* Nothing else worked, so let's try
5382 if (talk_initctl() > 0)
5385 log_error("Failed to talk to init daemon.");
5389 warn_wall(arg_action);
5393 static _noreturn_ void halt_now(enum action a) {
5395 /* Make sure C-A-D is handled by the kernel from this
5397 reboot(RB_ENABLE_CAD);
5402 log_info("Halting.");
5403 reboot(RB_HALT_SYSTEM);
5406 case ACTION_POWEROFF:
5407 log_info("Powering off.");
5408 reboot(RB_POWER_OFF);
5412 log_info("Rebooting.");
5413 reboot(RB_AUTOBOOT);
5417 assert_not_reached("Unknown halt action.");
5420 assert_not_reached("Uh? This shouldn't happen.");
5423 static int halt_main(DBusConnection *bus) {
5426 r = check_inhibitors(bus, arg_action);
5430 if (geteuid() != 0) {
5431 /* Try logind if we are a normal user and no special
5432 * mode applies. Maybe PolicyKit allows us to shutdown
5435 if (arg_when <= 0 &&
5438 (arg_action == ACTION_POWEROFF ||
5439 arg_action == ACTION_REBOOT)) {
5440 r = reboot_with_logind(bus, arg_action);
5445 log_error("Must be root.");
5450 char _cleanup_free_ *m;
5452 m = strv_join(arg_wall, " ");
5453 r = send_shutdownd(arg_when,
5454 arg_action == ACTION_HALT ? 'H' :
5455 arg_action == ACTION_POWEROFF ? 'P' :
5456 arg_action == ACTION_KEXEC ? 'K' :
5463 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5465 char date[FORMAT_TIMESTAMP_MAX];
5467 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5468 format_timestamp(date, sizeof(date), arg_when));
5473 if (!arg_dry && !arg_force)
5474 return start_with_fallback(bus);
5477 if (sd_booted() > 0)
5478 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5480 r = utmp_put_shutdown();
5482 log_warning("Failed to write utmp record: %s", strerror(-r));
5489 halt_now(arg_action);
5490 /* We should never reach this. */
5494 static int runlevel_main(void) {
5495 int r, runlevel, previous;
5497 r = utmp_get_runlevel(&runlevel, &previous);
5504 previous <= 0 ? 'N' : previous,
5505 runlevel <= 0 ? 'N' : runlevel);
5510 int main(int argc, char*argv[]) {
5511 int r, retval = EXIT_FAILURE;
5512 DBusConnection *bus = NULL;
5513 DBusError _cleanup_dbus_error_free_ error;
5515 dbus_error_init(&error);
5517 setlocale(LC_ALL, "");
5518 log_parse_environment();
5521 r = parse_argv(argc, argv);
5525 retval = EXIT_SUCCESS;
5529 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5530 * let's shortcut this */
5531 if (arg_action == ACTION_RUNLEVEL) {
5532 r = runlevel_main();
5533 retval = r < 0 ? EXIT_FAILURE : r;
5537 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5538 log_info("Running in chroot, ignoring request.");
5544 if (arg_transport == TRANSPORT_NORMAL)
5545 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5546 else if (arg_transport == TRANSPORT_POLKIT) {
5547 bus_connect_system_polkit(&bus, &error);
5548 private_bus = false;
5549 } else if (arg_transport == TRANSPORT_SSH) {
5550 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5551 private_bus = false;
5553 assert_not_reached("Uh, invalid transport...");
5556 switch (arg_action) {
5558 case ACTION_SYSTEMCTL:
5559 r = systemctl_main(bus, argc, argv, &error);
5563 case ACTION_POWEROFF:
5569 case ACTION_RUNLEVEL2:
5570 case ACTION_RUNLEVEL3:
5571 case ACTION_RUNLEVEL4:
5572 case ACTION_RUNLEVEL5:
5574 case ACTION_EMERGENCY:
5575 case ACTION_DEFAULT:
5576 r = start_with_fallback(bus);
5581 r = reload_with_fallback(bus);
5584 case ACTION_CANCEL_SHUTDOWN: {
5588 m = strv_join(arg_wall, " ");
5590 retval = EXIT_FAILURE;
5594 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5596 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5601 case ACTION_INVALID:
5602 case ACTION_RUNLEVEL:
5604 assert_not_reached("Unknown action");
5607 retval = r < 0 ? EXIT_FAILURE : r;
5611 dbus_connection_flush(bus);
5612 dbus_connection_close(bus);
5613 dbus_connection_unref(bus);
5618 strv_free(arg_property);
5621 ask_password_agent_close();
5622 polkit_agent_close();