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 *triggered_by_property = "TriggeredBy";
1340 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1341 bool print_warning_label = true;
1344 n = unit_name_mangle(unit_name);
1350 unit_path = unit_dbus_path_from_name(n);
1356 r = bus_method_call_with_reply(
1358 "org.freedesktop.systemd1",
1360 "org.freedesktop.DBus.Properties",
1364 DBUS_TYPE_STRING, &interface,
1365 DBUS_TYPE_STRING, &triggered_by_property,
1370 if (!dbus_message_iter_init(reply, &iter) ||
1371 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1372 log_error("Failed to parse reply.");
1376 dbus_message_iter_recurse(&iter, &sub);
1377 dbus_message_iter_recurse(&sub, &iter);
1380 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1381 const char * const check_states[] = {
1386 const char *service_trigger;
1388 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1389 log_error("Failed to parse reply.");
1393 dbus_message_iter_get_basic(&sub, &service_trigger);
1395 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1399 if (print_warning_label) {
1400 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1401 print_warning_label = false;
1404 log_warning(" %s", service_trigger);
1407 dbus_message_iter_next(&sub);
1411 static int start_unit_one(
1412 DBusConnection *bus,
1419 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1420 _cleanup_free_ char *n;
1429 n = unit_name_mangle(name);
1433 r = bus_method_call_with_reply(
1435 "org.freedesktop.systemd1",
1436 "/org/freedesktop/systemd1",
1437 "org.freedesktop.systemd1.Manager",
1441 DBUS_TYPE_STRING, &n,
1442 DBUS_TYPE_STRING, &mode,
1445 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1446 /* There's always a fallback possible for
1447 * legacy actions. */
1450 log_error("Failed to issue method call: %s", bus_error_message(error));
1455 if (!dbus_message_get_args(reply, error,
1456 DBUS_TYPE_OBJECT_PATH, &path,
1457 DBUS_TYPE_INVALID)) {
1458 log_error("Failed to parse reply: %s", bus_error_message(error));
1462 if (need_daemon_reload(bus, n))
1463 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1464 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1476 log_error("Failed to add path to set.");
1484 static enum action verb_to_action(const char *verb) {
1485 if (streq(verb, "halt"))
1487 else if (streq(verb, "poweroff"))
1488 return ACTION_POWEROFF;
1489 else if (streq(verb, "reboot"))
1490 return ACTION_REBOOT;
1491 else if (streq(verb, "kexec"))
1492 return ACTION_KEXEC;
1493 else if (streq(verb, "rescue"))
1494 return ACTION_RESCUE;
1495 else if (streq(verb, "emergency"))
1496 return ACTION_EMERGENCY;
1497 else if (streq(verb, "default"))
1498 return ACTION_DEFAULT;
1499 else if (streq(verb, "exit"))
1501 else if (streq(verb, "suspend"))
1502 return ACTION_SUSPEND;
1503 else if (streq(verb, "hibernate"))
1504 return ACTION_HIBERNATE;
1505 else if (streq(verb, "hybrid-sleep"))
1506 return ACTION_HYBRID_SLEEP;
1508 return ACTION_INVALID;
1511 static int start_unit(DBusConnection *bus, char **args) {
1513 static const char * const table[_ACTION_MAX] = {
1514 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1515 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1516 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1517 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1518 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1519 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1520 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1521 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1522 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1523 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1524 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1525 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1526 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1527 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
1528 [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
1532 const char *method, *mode, *one_name;
1533 Set _cleanup_set_free_free_ *s = NULL;
1534 DBusError _cleanup_dbus_error_free_ error;
1537 dbus_error_init(&error);
1541 ask_password_agent_open_if_enabled();
1543 if (arg_action == ACTION_SYSTEMCTL) {
1545 streq(args[0], "stop") ||
1546 streq(args[0], "condstop") ? "StopUnit" :
1547 streq(args[0], "reload") ? "ReloadUnit" :
1548 streq(args[0], "restart") ? "RestartUnit" :
1550 streq(args[0], "try-restart") ||
1551 streq(args[0], "condrestart") ? "TryRestartUnit" :
1553 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1555 streq(args[0], "reload-or-try-restart") ||
1556 streq(args[0], "condreload") ||
1558 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1562 (streq(args[0], "isolate") ||
1563 streq(args[0], "rescue") ||
1564 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1566 one_name = table[verb_to_action(args[0])];
1569 assert(arg_action < ELEMENTSOF(table));
1570 assert(table[arg_action]);
1572 method = "StartUnit";
1574 mode = (arg_action == ACTION_EMERGENCY ||
1575 arg_action == ACTION_RESCUE ||
1576 arg_action == ACTION_RUNLEVEL2 ||
1577 arg_action == ACTION_RUNLEVEL3 ||
1578 arg_action == ACTION_RUNLEVEL4 ||
1579 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1581 one_name = table[arg_action];
1584 if (!arg_no_block) {
1585 ret = enable_wait_for_jobs(bus);
1587 log_error("Could not watch jobs: %s", strerror(-ret));
1591 s = set_new(string_hash_func, string_compare_func);
1597 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1599 ret = translate_bus_error_to_exit_status(ret, &error);
1601 STRV_FOREACH(name, args+1) {
1602 r = start_unit_one(bus, method, *name, mode, &error, s);
1604 ret = translate_bus_error_to_exit_status(r, &error);
1605 dbus_error_free(&error);
1610 if (!arg_no_block) {
1611 r = wait_for_jobs(bus, s);
1615 /* When stopping units, warn if they can still be triggered by
1616 * another active unit (socket, path, timer) */
1617 if (!arg_quiet && streq(method, "StopUnit")) {
1619 check_triggering_units(bus, one_name);
1621 STRV_FOREACH(name, args+1)
1622 check_triggering_units(bus, *name);
1629 /* Ask systemd-logind, which might grant access to unprivileged users
1630 * through PolicyKit */
1631 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1634 dbus_bool_t interactive = true;
1639 polkit_agent_open_if_enabled();
1647 case ACTION_POWEROFF:
1648 method = "PowerOff";
1651 case ACTION_SUSPEND:
1655 case ACTION_HIBERNATE:
1656 method = "Hibernate";
1659 case ACTION_HYBRID_SLEEP:
1660 method = "HybridSleep";
1667 return bus_method_call_with_reply(
1669 "org.freedesktop.login1",
1670 "/org/freedesktop/login1",
1671 "org.freedesktop.login1.Manager",
1675 DBUS_TYPE_BOOLEAN, &interactive,
1682 static int check_inhibitors(DBusConnection *bus, enum action a) {
1684 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1685 DBusMessageIter iter, sub, sub2;
1688 _cleanup_strv_free_ char **sessions = NULL;
1694 if (arg_ignore_inhibitors || arg_force > 0)
1706 r = bus_method_call_with_reply(
1708 "org.freedesktop.login1",
1709 "/org/freedesktop/login1",
1710 "org.freedesktop.login1.Manager",
1716 /* If logind is not around, then there are no inhibitors... */
1719 if (!dbus_message_iter_init(reply, &iter) ||
1720 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1721 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1722 log_error("Failed to parse reply.");
1726 dbus_message_iter_recurse(&iter, &sub);
1727 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1728 const char *what, *who, *why, *mode;
1730 _cleanup_strv_free_ char **sv = NULL;
1731 _cleanup_free_ char *comm = NULL, *user = NULL;
1733 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1734 log_error("Failed to parse reply.");
1738 dbus_message_iter_recurse(&sub, &sub2);
1740 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
1741 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
1742 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
1743 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
1744 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
1745 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
1746 log_error("Failed to parse reply.");
1750 if (!streq(mode, "block"))
1753 sv = strv_split(what, ":");
1757 if (!strv_contains(sv,
1759 a == ACTION_POWEROFF ||
1760 a == ACTION_REBOOT ||
1761 a == ACTION_KEXEC ? "shutdown" : "sleep"))
1764 get_process_comm(pid, &comm);
1765 user = uid_to_name(uid);
1766 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
1767 who, (unsigned long) pid, strna(comm), strna(user), why);
1771 dbus_message_iter_next(&sub);
1774 dbus_message_iter_recurse(&iter, &sub);
1776 /* Check for current sessions */
1777 sd_get_sessions(&sessions);
1778 STRV_FOREACH(s, sessions) {
1780 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
1782 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
1785 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
1788 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
1791 sd_session_get_tty(*s, &tty);
1792 sd_session_get_seat(*s, &seat);
1793 sd_session_get_service(*s, &service);
1794 user = uid_to_name(uid);
1796 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
1803 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
1804 a == ACTION_HALT ? "halt" :
1805 a == ACTION_POWEROFF ? "poweroff" :
1806 a == ACTION_REBOOT ? "reboot" :
1807 a == ACTION_KEXEC ? "kexec" :
1808 a == ACTION_SUSPEND ? "suspend" :
1809 a == ACTION_HIBERNATE ? "hibernate" : "hybrid-sleep");
1817 static int start_special(DBusConnection *bus, char **args) {
1823 a = verb_to_action(args[0]);
1825 r = check_inhibitors(bus, a);
1829 if (arg_force >= 2 && geteuid() != 0) {
1830 log_error("Must be root.");
1834 if (arg_force >= 2 &&
1835 (a == ACTION_HALT ||
1836 a == ACTION_POWEROFF ||
1837 a == ACTION_REBOOT))
1840 if (arg_force >= 1 &&
1841 (a == ACTION_HALT ||
1842 a == ACTION_POWEROFF ||
1843 a == ACTION_REBOOT ||
1844 a == ACTION_KEXEC ||
1846 return daemon_reload(bus, args);
1848 /* first try logind, to allow authentication with polkit */
1849 if (geteuid() != 0 &&
1850 (a == ACTION_POWEROFF ||
1851 a == ACTION_REBOOT ||
1852 a == ACTION_SUSPEND ||
1853 a == ACTION_HIBERNATE ||
1854 a == ACTION_HYBRID_SLEEP)) {
1855 r = reboot_with_logind(bus, a);
1860 r = start_unit(bus, args);
1861 if (r == EXIT_SUCCESS)
1867 static int check_unit_active(DBusConnection *bus, char **args) {
1868 const char * const check_states[] = {
1875 int r = 3; /* According to LSB: "program is not running" */
1880 STRV_FOREACH(name, args+1) {
1883 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1893 static int check_unit_failed(DBusConnection *bus, char **args) {
1894 const char * const check_states[] = {
1905 STRV_FOREACH(name, args+1) {
1908 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1918 static int kill_unit(DBusConnection *bus, char **args) {
1926 arg_kill_who = "all";
1928 STRV_FOREACH(name, args+1) {
1929 _cleanup_free_ char *n = NULL;
1931 n = unit_name_mangle(*name);
1935 r = bus_method_call_with_reply(
1937 "org.freedesktop.systemd1",
1938 "/org/freedesktop/systemd1",
1939 "org.freedesktop.systemd1.Manager",
1943 DBUS_TYPE_STRING, &n,
1944 DBUS_TYPE_STRING, &arg_kill_who,
1945 DBUS_TYPE_INT32, &arg_signal,
1953 static int set_cgroup(DBusConnection *bus, char **args) {
1954 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
1957 DBusMessageIter iter;
1959 _cleanup_free_ char *n = NULL;
1960 const char *runtime;
1965 dbus_error_init(&error);
1968 streq(args[0], "set-cgroup") ? "SetUnitControlGroups" :
1969 streq(args[0], "unset-group") ? "UnsetUnitControlGroups"
1970 : "UnsetUnitControlGroupAttributes";
1972 n = unit_name_mangle(args[1]);
1976 m = dbus_message_new_method_call(
1977 "org.freedesktop.systemd1",
1978 "/org/freedesktop/systemd1",
1979 "org.freedesktop.systemd1.Manager",
1984 dbus_message_iter_init_append(m, &iter);
1985 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
1988 r = bus_append_strv_iter(&iter, args + 2);
1992 runtime = arg_runtime ? "runtime" : "persistent";
1993 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
1996 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
1998 log_error("Failed to issue method call: %s", bus_error_message(&error));
1999 dbus_error_free(&error);
2006 static int set_cgroup_attr(DBusConnection *bus, char **args) {
2007 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2009 DBusMessageIter iter, sub, sub2;
2011 _cleanup_free_ char *n = NULL;
2012 const char *runtime;
2017 dbus_error_init(&error);
2019 if (strv_length(args) % 2 != 0) {
2020 log_error("Expecting an uneven number of arguments!");
2024 n = unit_name_mangle(args[1]);
2028 m = dbus_message_new_method_call(
2029 "org.freedesktop.systemd1",
2030 "/org/freedesktop/systemd1",
2031 "org.freedesktop.systemd1.Manager",
2032 "SetUnitControlGroupAttributes");
2036 dbus_message_iter_init_append(m, &iter);
2037 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2038 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub))
2041 STRV_FOREACH_PAIR(x, y, args + 2) {
2042 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
2043 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, x) ||
2044 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, y) ||
2045 !dbus_message_iter_close_container(&sub, &sub2))
2049 runtime = arg_runtime ? "runtime" : "persistent";
2050 if (!dbus_message_iter_close_container(&iter, &sub) ||
2051 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2054 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2056 log_error("Failed to issue method call: %s", bus_error_message(&error));
2057 dbus_error_free(&error);
2064 static int get_cgroup_attr(DBusConnection *bus, char **args) {
2065 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2067 DBusMessageIter iter;
2069 _cleanup_free_ char *n = NULL;
2070 _cleanup_strv_free_ char **list = NULL;
2076 dbus_error_init(&error);
2078 n = unit_name_mangle(args[1]);
2082 m = dbus_message_new_method_call(
2083 "org.freedesktop.systemd1",
2084 "/org/freedesktop/systemd1",
2085 "org.freedesktop.systemd1.Manager",
2086 "GetUnitControlGroupAttributes");
2090 dbus_message_iter_init_append(m, &iter);
2091 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
2094 r = bus_append_strv_iter(&iter, args + 2);
2098 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2100 log_error("Failed to issue method call: %s", bus_error_message(&error));
2101 dbus_error_free(&error);
2105 dbus_message_iter_init(reply, &iter);
2106 r = bus_parse_strv_iter(&iter, &list);
2108 log_error("Failed to parse value list.");
2112 STRV_FOREACH(a, list) {
2113 if (endswith(*a, "\n"))
2122 typedef struct ExecStatusInfo {
2130 usec_t start_timestamp;
2131 usec_t exit_timestamp;
2136 LIST_FIELDS(struct ExecStatusInfo, exec);
2139 static void exec_status_info_free(ExecStatusInfo *i) {
2148 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2149 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2150 DBusMessageIter sub2, sub3;
2154 int32_t code, status;
2160 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2163 dbus_message_iter_recurse(sub, &sub2);
2165 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2168 i->path = strdup(path);
2172 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2173 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2177 dbus_message_iter_recurse(&sub2, &sub3);
2178 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2179 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2180 dbus_message_iter_next(&sub3);
2184 i->argv = new0(char*, n+1);
2189 dbus_message_iter_recurse(&sub2, &sub3);
2190 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2193 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2194 dbus_message_iter_get_basic(&sub3, &s);
2195 dbus_message_iter_next(&sub3);
2197 i->argv[n] = strdup(s);
2204 if (!dbus_message_iter_next(&sub2) ||
2205 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2206 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2207 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2208 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2209 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2210 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2211 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2212 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2216 i->start_timestamp = (usec_t) start_timestamp;
2217 i->exit_timestamp = (usec_t) exit_timestamp;
2218 i->pid = (pid_t) pid;
2225 typedef struct UnitStatusInfo {
2227 const char *load_state;
2228 const char *active_state;
2229 const char *sub_state;
2230 const char *unit_file_state;
2232 const char *description;
2233 const char *following;
2235 char **documentation;
2237 const char *fragment_path;
2238 const char *source_path;
2239 const char *default_control_group;
2241 const char *load_error;
2244 usec_t inactive_exit_timestamp;
2245 usec_t inactive_exit_timestamp_monotonic;
2246 usec_t active_enter_timestamp;
2247 usec_t active_exit_timestamp;
2248 usec_t inactive_enter_timestamp;
2250 bool need_daemon_reload;
2255 const char *status_text;
2258 usec_t start_timestamp;
2259 usec_t exit_timestamp;
2261 int exit_code, exit_status;
2263 usec_t condition_timestamp;
2264 bool condition_result;
2267 unsigned n_accepted;
2268 unsigned n_connections;
2272 const char *sysfs_path;
2274 /* Mount, Automount */
2280 LIST_HEAD(ExecStatusInfo, exec);
2283 static void print_status_info(UnitStatusInfo *i) {
2285 const char *on, *off, *ss;
2287 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2288 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2291 arg_all * OUTPUT_SHOW_ALL |
2292 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2293 on_tty() * OUTPUT_COLOR |
2294 !arg_quiet * OUTPUT_WARN_CUTOFF |
2295 arg_full * OUTPUT_FULL_WIDTH;
2299 /* This shows pretty information about a unit. See
2300 * print_property() for a low-level property printer */
2302 printf("%s", strna(i->id));
2304 if (i->description && !streq_ptr(i->id, i->description))
2305 printf(" - %s", i->description);
2310 printf("\t Follow: unit currently follows state of %s\n", i->following);
2312 if (streq_ptr(i->load_state, "error")) {
2313 on = ansi_highlight_red(true);
2314 off = ansi_highlight_red(false);
2318 path = i->source_path ? i->source_path : i->fragment_path;
2321 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2322 else if (path && i->unit_file_state)
2323 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2325 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2327 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2329 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2331 if (streq_ptr(i->active_state, "failed")) {
2332 on = ansi_highlight_red(true);
2333 off = ansi_highlight_red(false);
2334 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2335 on = ansi_highlight_green(true);
2336 off = ansi_highlight_green(false);
2341 printf("\t Active: %s%s (%s)%s",
2343 strna(i->active_state),
2347 printf("\t Active: %s%s%s",
2349 strna(i->active_state),
2352 if (!isempty(i->result) && !streq(i->result, "success"))
2353 printf(" (Result: %s)", i->result);
2355 timestamp = (streq_ptr(i->active_state, "active") ||
2356 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2357 (streq_ptr(i->active_state, "inactive") ||
2358 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2359 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2360 i->active_exit_timestamp;
2362 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2363 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2366 printf(" since %s; %s\n", s2, s1);
2368 printf(" since %s\n", s2);
2372 if (!i->condition_result && i->condition_timestamp > 0) {
2373 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2374 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2377 printf("\t start condition failed at %s; %s\n", s2, s1);
2379 printf("\t start condition failed at %s\n", s2);
2383 printf("\t Device: %s\n", i->sysfs_path);
2385 printf("\t Where: %s\n", i->where);
2387 printf("\t What: %s\n", i->what);
2389 if (!strv_isempty(i->documentation)) {
2393 STRV_FOREACH(t, i->documentation) {
2395 printf("\t Docs: %s\n", *t);
2398 printf("\t %s\n", *t);
2403 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2405 LIST_FOREACH(exec, p, i->exec) {
2406 _cleanup_free_ char *t = NULL;
2409 /* Only show exited processes here */
2413 t = strv_join(p->argv, " ");
2414 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2416 good = is_clean_exit_lsb(p->code, p->status, NULL);
2418 on = ansi_highlight_red(true);
2419 off = ansi_highlight_red(false);
2423 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2425 if (p->code == CLD_EXITED) {
2428 printf("status=%i", p->status);
2430 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2435 printf("signal=%s", signal_to_string(p->status));
2437 printf(")%s\n", off);
2439 if (i->main_pid == p->pid &&
2440 i->start_timestamp == p->start_timestamp &&
2441 i->exit_timestamp == p->start_timestamp)
2442 /* Let's not show this twice */
2445 if (p->pid == i->control_pid)
2449 if (i->main_pid > 0 || i->control_pid > 0) {
2452 if (i->main_pid > 0) {
2453 printf("Main PID: %u", (unsigned) i->main_pid);
2456 _cleanup_free_ char *t = NULL;
2457 get_process_comm(i->main_pid, &t);
2460 } else if (i->exit_code > 0) {
2461 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2463 if (i->exit_code == CLD_EXITED) {
2466 printf("status=%i", i->exit_status);
2468 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2473 printf("signal=%s", signal_to_string(i->exit_status));
2478 if (i->main_pid > 0 && i->control_pid > 0)
2481 if (i->control_pid > 0) {
2482 _cleanup_free_ char *t = NULL;
2484 printf(" Control: %u", (unsigned) i->control_pid);
2486 get_process_comm(i->control_pid, &t);
2495 printf("\t Status: \"%s\"\n", i->status_text);
2497 if (i->default_control_group &&
2498 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2501 printf("\t CGroup: %s\n", i->default_control_group);
2503 if (arg_transport != TRANSPORT_SSH) {
2513 if (i->main_pid > 0)
2514 extra[k++] = i->main_pid;
2516 if (i->control_pid > 0)
2517 extra[k++] = i->control_pid;
2519 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, extra, k, flags);
2523 if (i->id && arg_transport != TRANSPORT_SSH) {
2525 if(arg_scope == UNIT_FILE_SYSTEM)
2526 show_journal_by_unit(stdout,
2530 i->inactive_exit_timestamp_monotonic,
2534 show_journal_by_user_unit(stdout,
2538 i->inactive_exit_timestamp_monotonic,
2544 if (i->need_daemon_reload)
2545 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2546 ansi_highlight_red(true),
2547 ansi_highlight_red(false),
2548 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2551 static void show_unit_help(UnitStatusInfo *i) {
2556 if (!i->documentation) {
2557 log_info("Documentation for %s not known.", i->id);
2561 STRV_FOREACH(p, i->documentation) {
2563 if (startswith(*p, "man:")) {
2566 char _cleanup_free_ *page = NULL, *section = NULL;
2567 const char *args[4] = { "man", NULL, NULL, NULL };
2572 if ((*p)[k-1] == ')')
2573 e = strrchr(*p, '(');
2576 page = strndup((*p) + 4, e - *p - 4);
2577 section = strndup(e + 1, *p + k - e - 2);
2578 if (!page || !section) {
2590 log_error("Failed to fork: %m");
2596 execvp(args[0], (char**) args);
2597 log_error("Failed to execute man: %m");
2598 _exit(EXIT_FAILURE);
2601 wait_for_terminate(pid, NULL);
2603 log_info("Can't show: %s", *p);
2607 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2613 switch (dbus_message_iter_get_arg_type(iter)) {
2615 case DBUS_TYPE_STRING: {
2618 dbus_message_iter_get_basic(iter, &s);
2621 if (streq(name, "Id"))
2623 else if (streq(name, "LoadState"))
2625 else if (streq(name, "ActiveState"))
2626 i->active_state = s;
2627 else if (streq(name, "SubState"))
2629 else if (streq(name, "Description"))
2631 else if (streq(name, "FragmentPath"))
2632 i->fragment_path = s;
2633 else if (streq(name, "SourcePath"))
2635 else if (streq(name, "DefaultControlGroup"))
2636 i->default_control_group = s;
2637 else if (streq(name, "StatusText"))
2639 else if (streq(name, "SysFSPath"))
2641 else if (streq(name, "Where"))
2643 else if (streq(name, "What"))
2645 else if (streq(name, "Following"))
2647 else if (streq(name, "UnitFileState"))
2648 i->unit_file_state = s;
2649 else if (streq(name, "Result"))
2656 case DBUS_TYPE_BOOLEAN: {
2659 dbus_message_iter_get_basic(iter, &b);
2661 if (streq(name, "Accept"))
2663 else if (streq(name, "NeedDaemonReload"))
2664 i->need_daemon_reload = b;
2665 else if (streq(name, "ConditionResult"))
2666 i->condition_result = b;
2671 case DBUS_TYPE_UINT32: {
2674 dbus_message_iter_get_basic(iter, &u);
2676 if (streq(name, "MainPID")) {
2678 i->main_pid = (pid_t) u;
2681 } else if (streq(name, "ControlPID"))
2682 i->control_pid = (pid_t) u;
2683 else if (streq(name, "ExecMainPID")) {
2685 i->main_pid = (pid_t) u;
2686 } else if (streq(name, "NAccepted"))
2688 else if (streq(name, "NConnections"))
2689 i->n_connections = u;
2694 case DBUS_TYPE_INT32: {
2697 dbus_message_iter_get_basic(iter, &j);
2699 if (streq(name, "ExecMainCode"))
2700 i->exit_code = (int) j;
2701 else if (streq(name, "ExecMainStatus"))
2702 i->exit_status = (int) j;
2707 case DBUS_TYPE_UINT64: {
2710 dbus_message_iter_get_basic(iter, &u);
2712 if (streq(name, "ExecMainStartTimestamp"))
2713 i->start_timestamp = (usec_t) u;
2714 else if (streq(name, "ExecMainExitTimestamp"))
2715 i->exit_timestamp = (usec_t) u;
2716 else if (streq(name, "ActiveEnterTimestamp"))
2717 i->active_enter_timestamp = (usec_t) u;
2718 else if (streq(name, "InactiveEnterTimestamp"))
2719 i->inactive_enter_timestamp = (usec_t) u;
2720 else if (streq(name, "InactiveExitTimestamp"))
2721 i->inactive_exit_timestamp = (usec_t) u;
2722 else if (streq(name, "InactiveExitTimestampMonotonic"))
2723 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2724 else if (streq(name, "ActiveExitTimestamp"))
2725 i->active_exit_timestamp = (usec_t) u;
2726 else if (streq(name, "ConditionTimestamp"))
2727 i->condition_timestamp = (usec_t) u;
2732 case DBUS_TYPE_ARRAY: {
2734 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2735 startswith(name, "Exec")) {
2736 DBusMessageIter sub;
2738 dbus_message_iter_recurse(iter, &sub);
2739 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2740 ExecStatusInfo *info;
2743 if (!(info = new0(ExecStatusInfo, 1)))
2746 if (!(info->name = strdup(name))) {
2751 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2756 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2758 dbus_message_iter_next(&sub);
2760 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2761 streq(name, "Documentation")) {
2763 DBusMessageIter sub;
2765 dbus_message_iter_recurse(iter, &sub);
2766 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2770 dbus_message_iter_get_basic(&sub, &s);
2772 l = strv_append(i->documentation, s);
2776 strv_free(i->documentation);
2777 i->documentation = l;
2779 dbus_message_iter_next(&sub);
2786 case DBUS_TYPE_STRUCT: {
2788 if (streq(name, "LoadError")) {
2789 DBusMessageIter sub;
2790 const char *n, *message;
2793 dbus_message_iter_recurse(iter, &sub);
2795 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2799 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2803 if (!isempty(message))
2804 i->load_error = message;
2814 static int print_property(const char *name, DBusMessageIter *iter) {
2818 /* This is a low-level property printer, see
2819 * print_status_info() for the nicer output */
2821 if (arg_property && !strv_find(arg_property, name))
2824 switch (dbus_message_iter_get_arg_type(iter)) {
2826 case DBUS_TYPE_STRUCT: {
2827 DBusMessageIter sub;
2828 dbus_message_iter_recurse(iter, &sub);
2830 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2833 dbus_message_iter_get_basic(&sub, &u);
2836 printf("%s=%u\n", name, (unsigned) u);
2838 printf("%s=\n", name);
2841 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2844 dbus_message_iter_get_basic(&sub, &s);
2846 if (arg_all || s[0])
2847 printf("%s=%s\n", name, s);
2850 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2851 const char *a = NULL, *b = NULL;
2853 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2854 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2856 if (arg_all || !isempty(a) || !isempty(b))
2857 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2865 case DBUS_TYPE_ARRAY:
2867 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2868 DBusMessageIter sub, sub2;
2870 dbus_message_iter_recurse(iter, &sub);
2871 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2875 dbus_message_iter_recurse(&sub, &sub2);
2877 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2878 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2879 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2881 dbus_message_iter_next(&sub);
2886 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2887 DBusMessageIter sub, sub2;
2889 dbus_message_iter_recurse(iter, &sub);
2890 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2891 const char *type, *path;
2893 dbus_message_iter_recurse(&sub, &sub2);
2895 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2896 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2897 printf("%s=%s\n", type, path);
2899 dbus_message_iter_next(&sub);
2904 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2905 DBusMessageIter sub, sub2;
2907 dbus_message_iter_recurse(iter, &sub);
2908 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2910 uint64_t value, next_elapse;
2912 dbus_message_iter_recurse(&sub, &sub2);
2914 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2915 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2916 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2917 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2919 printf("%s={ value=%s ; next_elapse=%s }\n",
2921 format_timespan(timespan1, sizeof(timespan1), value),
2922 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2925 dbus_message_iter_next(&sub);
2930 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2931 DBusMessageIter sub, sub2;
2933 dbus_message_iter_recurse(iter, &sub);
2934 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2935 const char *controller, *attr, *value;
2937 dbus_message_iter_recurse(&sub, &sub2);
2939 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2940 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2941 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2943 printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2949 dbus_message_iter_next(&sub);
2954 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2955 DBusMessageIter sub;
2957 dbus_message_iter_recurse(iter, &sub);
2958 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2959 ExecStatusInfo info;
2962 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2963 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2964 char _cleanup_free_ *t;
2966 t = strv_join(info.argv, " ");
2968 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2972 yes_no(info.ignore),
2973 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2974 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2975 (unsigned) info. pid,
2976 sigchld_code_to_string(info.code),
2978 info.code == CLD_EXITED ? "" : "/",
2979 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2983 strv_free(info.argv);
2985 dbus_message_iter_next(&sub);
2994 if (generic_print_property(name, iter, arg_all) > 0)
2998 printf("%s=[unprintable]\n", name);
3003 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3004 _cleanup_free_ DBusMessage *reply = NULL;
3005 const char *interface = "";
3007 DBusMessageIter iter, sub, sub2, sub3;
3008 UnitStatusInfo info;
3016 r = bus_method_call_with_reply(
3018 "org.freedesktop.systemd1",
3020 "org.freedesktop.DBus.Properties",
3024 DBUS_TYPE_STRING, &interface,
3029 if (!dbus_message_iter_init(reply, &iter) ||
3030 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3031 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3032 log_error("Failed to parse reply.");
3036 dbus_message_iter_recurse(&iter, &sub);
3043 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3046 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3047 dbus_message_iter_recurse(&sub, &sub2);
3049 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3050 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3051 log_error("Failed to parse reply.");
3055 dbus_message_iter_recurse(&sub2, &sub3);
3057 if (show_properties)
3058 r = print_property(name, &sub3);
3060 r = status_property(name, &sub3, &info);
3062 log_error("Failed to parse reply.");
3066 dbus_message_iter_next(&sub);
3071 if (!show_properties) {
3072 if (streq(verb, "help"))
3073 show_unit_help(&info);
3075 print_status_info(&info);
3078 strv_free(info.documentation);
3080 if (!streq_ptr(info.active_state, "active") &&
3081 !streq_ptr(info.active_state, "reloading") &&
3082 streq(verb, "status"))
3083 /* According to LSB: "program not running" */
3086 while ((p = info.exec)) {
3087 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3088 exec_status_info_free(p);
3094 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3095 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3096 const char *path = NULL;
3097 DBusError _cleanup_dbus_error_free_ error;
3100 dbus_error_init(&error);
3102 r = bus_method_call_with_reply(
3104 "org.freedesktop.systemd1",
3105 "/org/freedesktop/systemd1",
3106 "org.freedesktop.systemd1.Manager",
3110 DBUS_TYPE_UINT32, &pid,
3115 if (!dbus_message_get_args(reply, &error,
3116 DBUS_TYPE_OBJECT_PATH, &path,
3117 DBUS_TYPE_INVALID)) {
3118 log_error("Failed to parse reply: %s", bus_error_message(&error));
3122 r = show_one(verb, bus, path, false, new_line);
3126 static int show_all(const char* verb, DBusConnection *bus, bool show_properties, bool *new_line) {
3127 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3128 _cleanup_free_ struct unit_info *unit_infos = NULL;
3130 const struct unit_info *u;
3133 r = get_unit_list(bus, &reply, &unit_infos, &c);
3137 for (u = unit_infos; u < unit_infos + c; u++) {
3138 char _cleanup_free_ *p = NULL;
3140 if (!output_show_unit(u))
3143 p = unit_dbus_path_from_name(u->id);
3147 printf("%s -> '%s'\n", u->id, p);
3149 r = show_one(verb, bus, p, show_properties, new_line);
3157 static int show(DBusConnection *bus, char **args) {
3159 bool show_properties, show_status, new_line = false;
3165 show_properties = streq(args[0], "show");
3166 show_status = streq(args[0], "status");
3168 if (show_properties)
3169 pager_open_if_enabled();
3171 /* If no argument is specified inspect the manager itself */
3173 if (show_properties && strv_length(args) <= 1)
3174 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3176 if (show_status && strv_length(args) <= 1)
3177 return show_all(args[0], bus, false, &new_line);
3179 STRV_FOREACH(name, args+1) {
3182 if (safe_atou32(*name, &id) < 0) {
3183 _cleanup_free_ char *p = NULL, *n = NULL;
3184 /* Interpret as unit name */
3186 n = unit_name_mangle(*name);
3190 p = unit_dbus_path_from_name(n);
3194 r = show_one(args[0], bus, p, show_properties, &new_line);
3198 } else if (show_properties) {
3199 _cleanup_free_ char *p = NULL;
3201 /* Interpret as job id */
3202 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3205 r = show_one(args[0], bus, p, show_properties, &new_line);
3210 /* Interpret as PID */
3211 r = show_one_by_pid(args[0], bus, id, &new_line);
3220 static int dump(DBusConnection *bus, char **args) {
3221 _cleanup_free_ DBusMessage *reply = NULL;
3226 dbus_error_init(&error);
3228 pager_open_if_enabled();
3230 r = bus_method_call_with_reply(
3232 "org.freedesktop.systemd1",
3233 "/org/freedesktop/systemd1",
3234 "org.freedesktop.systemd1.Manager",
3242 if (!dbus_message_get_args(reply, &error,
3243 DBUS_TYPE_STRING, &text,
3244 DBUS_TYPE_INVALID)) {
3245 log_error("Failed to parse reply: %s", bus_error_message(&error));
3246 dbus_error_free(&error);
3250 fputs(text, stdout);
3254 static int snapshot(DBusConnection *bus, char **args) {
3255 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3258 dbus_bool_t cleanup = FALSE;
3259 DBusMessageIter iter, sub;
3262 *interface = "org.freedesktop.systemd1.Unit",
3264 _cleanup_free_ char *n = NULL;
3266 dbus_error_init(&error);
3268 if (strv_length(args) > 1)
3269 n = snapshot_name_mangle(args[1]);
3275 r = bus_method_call_with_reply (
3277 "org.freedesktop.systemd1",
3278 "/org/freedesktop/systemd1",
3279 "org.freedesktop.systemd1.Manager",
3283 DBUS_TYPE_STRING, &n,
3284 DBUS_TYPE_BOOLEAN, &cleanup,
3289 if (!dbus_message_get_args(reply, &error,
3290 DBUS_TYPE_OBJECT_PATH, &path,
3291 DBUS_TYPE_INVALID)) {
3292 log_error("Failed to parse reply: %s", bus_error_message(&error));
3293 dbus_error_free(&error);
3297 dbus_message_unref(reply);
3300 r = bus_method_call_with_reply (
3302 "org.freedesktop.systemd1",
3304 "org.freedesktop.DBus.Properties",
3308 DBUS_TYPE_STRING, &interface,
3309 DBUS_TYPE_STRING, &property,
3314 if (!dbus_message_iter_init(reply, &iter) ||
3315 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3316 log_error("Failed to parse reply.");
3320 dbus_message_iter_recurse(&iter, &sub);
3322 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3323 log_error("Failed to parse reply.");
3327 dbus_message_iter_get_basic(&sub, &id);
3335 static int delete_snapshot(DBusConnection *bus, char **args) {
3340 STRV_FOREACH(name, args+1) {
3341 _cleanup_free_ char *n = NULL;
3344 n = snapshot_name_mangle(*name);
3348 r = bus_method_call_with_reply(
3350 "org.freedesktop.systemd1",
3351 "/org/freedesktop/systemd1",
3352 "org.freedesktop.systemd1.Manager",
3356 DBUS_TYPE_STRING, &n,
3365 static int daemon_reload(DBusConnection *bus, char **args) {
3370 if (arg_action == ACTION_RELOAD)
3372 else if (arg_action == ACTION_REEXEC)
3373 method = "Reexecute";
3375 assert(arg_action == ACTION_SYSTEMCTL);
3378 streq(args[0], "clear-jobs") ||
3379 streq(args[0], "cancel") ? "ClearJobs" :
3380 streq(args[0], "daemon-reexec") ? "Reexecute" :
3381 streq(args[0], "reset-failed") ? "ResetFailed" :
3382 streq(args[0], "halt") ? "Halt" :
3383 streq(args[0], "poweroff") ? "PowerOff" :
3384 streq(args[0], "reboot") ? "Reboot" :
3385 streq(args[0], "kexec") ? "KExec" :
3386 streq(args[0], "exit") ? "Exit" :
3387 /* "daemon-reload" */ "Reload";
3390 r = bus_method_call_with_reply(
3392 "org.freedesktop.systemd1",
3393 "/org/freedesktop/systemd1",
3394 "org.freedesktop.systemd1.Manager",
3400 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3401 /* There's always a fallback possible for
3402 * legacy actions. */
3404 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3405 /* On reexecution, we expect a disconnect, not
3409 log_error("Failed to issue method call: %s", bus_error_message(&error));
3411 dbus_error_free(&error);
3415 static int reset_failed(DBusConnection *bus, char **args) {
3419 if (strv_length(args) <= 1)
3420 return daemon_reload(bus, args);
3422 STRV_FOREACH(name, args+1) {
3423 _cleanup_free_ char *n;
3425 n = unit_name_mangle(*name);
3429 r = bus_method_call_with_reply(
3431 "org.freedesktop.systemd1",
3432 "/org/freedesktop/systemd1",
3433 "org.freedesktop.systemd1.Manager",
3437 DBUS_TYPE_STRING, &n,
3446 static int show_enviroment(DBusConnection *bus, char **args) {
3447 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3448 DBusMessageIter iter, sub, sub2;
3451 *interface = "org.freedesktop.systemd1.Manager",
3452 *property = "Environment";
3454 pager_open_if_enabled();
3456 r = bus_method_call_with_reply(
3458 "org.freedesktop.systemd1",
3459 "/org/freedesktop/systemd1",
3460 "org.freedesktop.DBus.Properties",
3464 DBUS_TYPE_STRING, &interface,
3465 DBUS_TYPE_STRING, &property,
3470 if (!dbus_message_iter_init(reply, &iter) ||
3471 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3472 log_error("Failed to parse reply.");
3476 dbus_message_iter_recurse(&iter, &sub);
3478 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3479 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3480 log_error("Failed to parse reply.");
3484 dbus_message_iter_recurse(&sub, &sub2);
3486 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3489 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3490 log_error("Failed to parse reply.");
3494 dbus_message_iter_get_basic(&sub2, &text);
3497 dbus_message_iter_next(&sub2);
3503 static int switch_root(DBusConnection *bus, char **args) {
3506 _cleanup_free_ char *init = NULL;
3508 l = strv_length(args);
3509 if (l < 2 || l > 3) {
3510 log_error("Wrong number of arguments.");
3517 init = strdup(args[2]);
3519 parse_env_file("/proc/cmdline", WHITESPACE,
3529 log_debug("switching root - root: %s; init: %s", root, init);
3531 return bus_method_call_with_reply(
3533 "org.freedesktop.systemd1",
3534 "/org/freedesktop/systemd1",
3535 "org.freedesktop.systemd1.Manager",
3539 DBUS_TYPE_STRING, &root,
3540 DBUS_TYPE_STRING, &init,
3544 static int set_environment(DBusConnection *bus, char **args) {
3545 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3548 DBusMessageIter iter;
3554 dbus_error_init(&error);
3556 method = streq(args[0], "set-environment")
3558 : "UnsetEnvironment";
3560 m = dbus_message_new_method_call(
3561 "org.freedesktop.systemd1",
3562 "/org/freedesktop/systemd1",
3563 "org.freedesktop.systemd1.Manager",
3568 dbus_message_iter_init_append(m, &iter);
3570 r = bus_append_strv_iter(&iter, args + 1);
3574 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3576 log_error("Failed to issue method call: %s", bus_error_message(&error));
3577 dbus_error_free(&error);
3584 static int enable_sysv_units(char **args) {
3587 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3588 const char *verb = args[0];
3589 unsigned f = 1, t = 1;
3592 if (arg_scope != UNIT_FILE_SYSTEM)
3595 if (!streq(verb, "enable") &&
3596 !streq(verb, "disable") &&
3597 !streq(verb, "is-enabled"))
3600 /* Processes all SysV units, and reshuffles the array so that
3601 * afterwards only the native units remain */
3604 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3609 for (f = 1; args[f]; f++) {
3612 bool found_native = false, found_sysv;
3614 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3615 char **k, *l, *q = NULL;
3622 if (!endswith(name, ".service"))
3625 if (path_is_absolute(name))
3628 STRV_FOREACH(k, paths.unit_path) {
3631 if (!isempty(arg_root))
3632 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3634 asprintf(&p, "%s/%s", *k, name);
3641 found_native = access(p, F_OK) >= 0;
3652 if (!isempty(arg_root))
3653 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3655 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3661 p[strlen(p) - sizeof(".service") + 1] = 0;
3662 found_sysv = access(p, F_OK) >= 0;
3669 /* Mark this entry, so that we don't try enabling it as native unit */
3670 args[f] = (char*) "";
3672 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3674 if (!isempty(arg_root))
3675 argv[c++] = q = strappend("--root=", arg_root);
3677 argv[c++] = path_get_file_name(p);
3679 streq(verb, "enable") ? "on" :
3680 streq(verb, "disable") ? "off" : "--level=5";
3683 l = strv_join((char**)argv, " ");
3691 log_info("Executing %s", l);
3696 log_error("Failed to fork: %m");
3701 } else if (pid == 0) {
3704 execv(argv[0], (char**) argv);
3705 _exit(EXIT_FAILURE);
3711 j = wait_for_terminate(pid, &status);
3713 log_error("Failed to wait for child: %s", strerror(-r));
3718 if (status.si_code == CLD_EXITED) {
3719 if (streq(verb, "is-enabled")) {
3720 if (status.si_status == 0) {
3729 } else if (status.si_status != 0) {
3740 lookup_paths_free(&paths);
3742 /* Drop all SysV units */
3743 for (f = 1, t = 1; args[f]; f++) {
3745 if (isempty(args[f]))
3748 args[t++] = args[f];
3757 static int mangle_names(char **original_names, char ***mangled_names) {
3758 char **i, **l, **name;
3760 l = new(char*, strv_length(original_names) + 1);
3765 STRV_FOREACH(name, original_names) {
3767 /* When enabling units qualified path names are OK,
3768 * too, hence allow them explicitly. */
3773 *i = unit_name_mangle(*name);
3789 static int enable_unit(DBusConnection *bus, char **args) {
3790 const char *verb = args[0];
3791 UnitFileChange *changes = NULL;
3792 unsigned n_changes = 0, i;
3793 int carries_install_info = -1;
3794 DBusMessage _cleanup_dbus_message_unref_ *m = NULL, *reply = NULL;
3796 DBusError _cleanup_dbus_error_free_ error;
3797 char _cleanup_strv_free_ **mangled_names = NULL;
3799 dbus_error_init(&error);
3801 r = enable_sysv_units(args);
3808 if (!bus || avoid_bus()) {
3809 if (streq(verb, "enable")) {
3810 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3811 carries_install_info = r;
3812 } else if (streq(verb, "disable"))
3813 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3814 else if (streq(verb, "reenable")) {
3815 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3816 carries_install_info = r;
3817 } else if (streq(verb, "link"))
3818 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3819 else if (streq(verb, "preset")) {
3820 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3821 carries_install_info = r;
3822 } else if (streq(verb, "mask"))
3823 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3824 else if (streq(verb, "unmask"))
3825 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3827 assert_not_reached("Unknown verb");
3830 log_error("Operation failed: %s", strerror(-r));
3835 for (i = 0; i < n_changes; i++) {
3836 if (changes[i].type == UNIT_FILE_SYMLINK)
3837 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3839 log_info("rm '%s'", changes[i].path);
3846 bool send_force = true, expect_carries_install_info = false;
3848 DBusMessageIter iter, sub, sub2;
3850 if (streq(verb, "enable")) {
3851 method = "EnableUnitFiles";
3852 expect_carries_install_info = true;
3853 } else if (streq(verb, "disable")) {
3854 method = "DisableUnitFiles";
3856 } else if (streq(verb, "reenable")) {
3857 method = "ReenableUnitFiles";
3858 expect_carries_install_info = true;
3859 } else if (streq(verb, "link"))
3860 method = "LinkUnitFiles";
3861 else if (streq(verb, "preset")) {
3862 method = "PresetUnitFiles";
3863 expect_carries_install_info = true;
3864 } else if (streq(verb, "mask"))
3865 method = "MaskUnitFiles";
3866 else if (streq(verb, "unmask")) {
3867 method = "UnmaskUnitFiles";
3870 assert_not_reached("Unknown verb");
3872 m = dbus_message_new_method_call(
3873 "org.freedesktop.systemd1",
3874 "/org/freedesktop/systemd1",
3875 "org.freedesktop.systemd1.Manager",
3882 dbus_message_iter_init_append(m, &iter);
3884 r = mangle_names(args+1, &mangled_names);
3888 r = bus_append_strv_iter(&iter, mangled_names);
3890 log_error("Failed to append unit files.");
3895 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3896 log_error("Failed to append runtime boolean.");
3904 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3905 log_error("Failed to append force boolean.");
3911 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3913 log_error("Failed to issue method call: %s", bus_error_message(&error));
3918 if (!dbus_message_iter_init(reply, &iter)) {
3919 log_error("Failed to initialize iterator.");
3923 if (expect_carries_install_info) {
3924 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3926 log_error("Failed to parse reply.");
3930 carries_install_info = b;
3933 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3934 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3935 log_error("Failed to parse reply.");
3940 dbus_message_iter_recurse(&iter, &sub);
3941 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3942 const char *type, *path, *source;
3944 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3945 log_error("Failed to parse reply.");
3950 dbus_message_iter_recurse(&sub, &sub2);
3952 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3953 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3954 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3955 log_error("Failed to parse reply.");
3961 if (streq(type, "symlink"))
3962 log_info("ln -s '%s' '%s'", source, path);
3964 log_info("rm '%s'", path);
3967 dbus_message_iter_next(&sub);
3970 /* Try to reload if enabeld */
3972 r = daemon_reload(bus, args);
3975 if (carries_install_info == 0)
3977 "The unit files have no [Install] section. They are not meant to be enabled\n"
3978 "using systemctl.\n"
3979 "Possible reasons for having this kind of units are:\n"
3980 "1) A unit may be statically enabled by being symlinked from another unit's\n"
3981 " .wants/ or .requires/ directory.\n"
3982 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
3983 " a requirement dependency on it.\n"
3984 "3) A unit may be started when needed via activation (socket, path, timer,\n"
3985 " D-Bus, udev, scripted systemctl call, ...).\n");
3988 unit_file_changes_free(changes, n_changes);
3993 static int unit_is_enabled(DBusConnection *bus, char **args) {
3994 DBusError _cleanup_dbus_error_free_ error;
3996 DBusMessage _cleanup_dbus_message_unref_ *reply = NULL;
4000 dbus_error_init(&error);
4002 r = enable_sysv_units(args);
4008 if (!bus || avoid_bus()) {
4010 STRV_FOREACH(name, args+1) {
4011 UnitFileState state;
4013 state = unit_file_get_state(arg_scope, arg_root, *name);
4017 if (state == UNIT_FILE_ENABLED ||
4018 state == UNIT_FILE_ENABLED_RUNTIME ||
4019 state == UNIT_FILE_STATIC)
4023 puts(unit_file_state_to_string(state));
4027 STRV_FOREACH(name, args+1) {
4030 r = bus_method_call_with_reply (
4032 "org.freedesktop.systemd1",
4033 "/org/freedesktop/systemd1",
4034 "org.freedesktop.systemd1.Manager",
4038 DBUS_TYPE_STRING, name,
4043 if (!dbus_message_get_args(reply, &error,
4044 DBUS_TYPE_STRING, &s,
4045 DBUS_TYPE_INVALID)) {
4046 log_error("Failed to parse reply: %s", bus_error_message(&error));
4050 dbus_message_unref(reply);
4053 if (streq(s, "enabled") ||
4054 streq(s, "enabled-runtime") ||
4063 return enabled ? 0 : 1;
4066 static int systemctl_help(void) {
4068 pager_open_if_enabled();
4070 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4071 "Query or send control commands to the systemd manager.\n\n"
4072 " -h --help Show this help\n"
4073 " --version Show package version\n"
4074 " -t --type=TYPE List only units of a particular type\n"
4075 " -p --property=NAME Show only properties by this name\n"
4076 " -a --all Show all units/properties, including dead/empty ones\n"
4077 " --failed Show only failed units\n"
4078 " --full Don't ellipsize unit names on output\n"
4079 " --fail When queueing a new job, fail if conflicting jobs are\n"
4081 " --ignore-dependencies\n"
4082 " When queueing a new job, ignore all its dependencies\n"
4083 " -i --ignore-inhibitors\n"
4084 " When shutting down or sleeping, ignore inhibitors\n"
4085 " --kill-who=WHO Who to send signal to\n"
4086 " -s --signal=SIGNAL Which signal to send\n"
4087 " -H --host=[USER@]HOST\n"
4088 " Show information for remote host\n"
4089 " -P --privileged Acquire privileges before execution\n"
4090 " -q --quiet Suppress output\n"
4091 " --no-block Do not wait until operation finished\n"
4092 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4093 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4095 " --no-legend Do not print a legend (column headers and hints)\n"
4096 " --no-pager Do not pipe output into a pager\n"
4097 " --no-ask-password\n"
4098 " Do not ask for system passwords\n"
4099 " --system Connect to system manager\n"
4100 " --user Connect to user service manager\n"
4101 " --global Enable/disable unit files globally\n"
4102 " -f --force When enabling unit files, override existing symlinks\n"
4103 " When shutting down, execute action immediately\n"
4104 " --root=PATH Enable unit files in the specified root directory\n"
4105 " --runtime Enable unit files only temporarily until next reboot\n"
4106 " -n --lines=INTEGER Journal entries to show\n"
4107 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4108 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4110 " list-units List loaded units\n"
4111 " start [NAME...] Start (activate) one or more units\n"
4112 " stop [NAME...] Stop (deactivate) one or more units\n"
4113 " reload [NAME...] Reload one or more units\n"
4114 " restart [NAME...] Start or restart one or more units\n"
4115 " try-restart [NAME...] Restart one or more units if active\n"
4116 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4117 " otherwise start or restart\n"
4118 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4119 " otherwise restart if active\n"
4120 " isolate [NAME] Start one unit and stop all others\n"
4121 " kill [NAME...] Send signal to processes of a unit\n"
4122 " is-active [NAME...] Check whether units are active\n"
4123 " is-failed [NAME...] Check whether units are failed\n"
4124 " status [NAME...|PID...] Show runtime status of one or more units\n"
4125 " show [NAME...|JOB...] Show properties of one or more\n"
4126 " units/jobs or the manager\n"
4127 " help [NAME...|PID...] Show manual for one or more units\n"
4128 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4130 " get-cgroup-attr [NAME] [ATTR] ...\n"
4131 " Get control group attrubute\n"
4132 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4133 " Set control group attribute\n"
4134 " unset-cgroup-attr [NAME] [ATTR...]\n"
4135 " Unset control group attribute\n"
4136 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4137 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4138 " load [NAME...] Load one or more units\n"
4139 " list-dependencies [NAME] Recursively show units which are required\n"
4140 " or wanted by this unit\n\n"
4141 "Unit File Commands:\n"
4142 " list-unit-files List installed unit files\n"
4143 " enable [NAME...] Enable one or more unit files\n"
4144 " disable [NAME...] Disable one or more unit files\n"
4145 " reenable [NAME...] Reenable one or more unit files\n"
4146 " preset [NAME...] Enable/disable one or more unit files\n"
4147 " based on preset configuration\n"
4148 " mask [NAME...] Mask one or more units\n"
4149 " unmask [NAME...] Unmask one or more units\n"
4150 " link [PATH...] Link one or more units files into\n"
4151 " the search path\n"
4152 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4154 " list-jobs List jobs\n"
4155 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4156 "Status Commands:\n"
4157 " dump Dump server status\n"
4158 "Snapshot Commands:\n"
4159 " snapshot [NAME] Create a snapshot\n"
4160 " delete [NAME...] Remove one or more snapshots\n\n"
4161 "Environment Commands:\n"
4162 " show-environment Dump environment\n"
4163 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4164 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4165 "Manager Lifecycle Commands:\n"
4166 " daemon-reload Reload systemd manager configuration\n"
4167 " daemon-reexec Reexecute systemd manager\n\n"
4168 "System Commands:\n"
4169 " default Enter system default mode\n"
4170 " rescue Enter system rescue mode\n"
4171 " emergency Enter system emergency mode\n"
4172 " halt Shut down and halt the system\n"
4173 " poweroff Shut down and power-off the system\n"
4174 " reboot Shut down and reboot the system\n"
4175 " kexec Shut down and reboot the system with kexec\n"
4176 " exit Request user instance exit\n"
4177 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4178 " suspend Suspend the system\n"
4179 " hibernate Hibernate the system\n"
4180 " hybrid-sleep Hibernate and suspend the system\n",
4181 program_invocation_short_name);
4186 static int halt_help(void) {
4188 printf("%s [OPTIONS...]\n\n"
4189 "%s the system.\n\n"
4190 " --help Show this help\n"
4191 " --halt Halt the machine\n"
4192 " -p --poweroff Switch off the machine\n"
4193 " --reboot Reboot the machine\n"
4194 " -f --force Force immediate halt/power-off/reboot\n"
4195 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4196 " -d --no-wtmp Don't write wtmp record\n"
4197 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4198 program_invocation_short_name,
4199 arg_action == ACTION_REBOOT ? "Reboot" :
4200 arg_action == ACTION_POWEROFF ? "Power off" :
4206 static int shutdown_help(void) {
4208 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4209 "Shut down the system.\n\n"
4210 " --help Show this help\n"
4211 " -H --halt Halt the machine\n"
4212 " -P --poweroff Power-off the machine\n"
4213 " -r --reboot Reboot the machine\n"
4214 " -h Equivalent to --poweroff, overridden by --halt\n"
4215 " -k Don't halt/power-off/reboot, just send warnings\n"
4216 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4217 " -c Cancel a pending shutdown\n",
4218 program_invocation_short_name);
4223 static int telinit_help(void) {
4225 printf("%s [OPTIONS...] {COMMAND}\n\n"
4226 "Send control commands to the init daemon.\n\n"
4227 " --help Show this help\n"
4228 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4230 " 0 Power-off the machine\n"
4231 " 6 Reboot the machine\n"
4232 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4233 " 1, s, S Enter rescue mode\n"
4234 " q, Q Reload init daemon configuration\n"
4235 " u, U Reexecute init daemon\n",
4236 program_invocation_short_name);
4241 static int runlevel_help(void) {
4243 printf("%s [OPTIONS...]\n\n"
4244 "Prints the previous and current runlevel of the init system.\n\n"
4245 " --help Show this help\n",
4246 program_invocation_short_name);
4251 static int help_types(void) {
4254 puts("Available unit types:");
4255 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4256 if (unit_type_table[i])
4257 puts(unit_type_table[i]);
4259 puts("\nAvailable unit load states: ");
4260 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4261 if (unit_type_table[i])
4262 puts(unit_load_state_table[i]);
4267 static int systemctl_parse_argv(int argc, char *argv[]) {
4271 ARG_IGNORE_DEPENDENCIES,
4284 ARG_NO_ASK_PASSWORD,
4290 static const struct option options[] = {
4291 { "help", no_argument, NULL, 'h' },
4292 { "version", no_argument, NULL, ARG_VERSION },
4293 { "type", required_argument, NULL, 't' },
4294 { "property", required_argument, NULL, 'p' },
4295 { "all", no_argument, NULL, 'a' },
4296 { "failed", no_argument, NULL, ARG_FAILED },
4297 { "full", no_argument, NULL, ARG_FULL },
4298 { "fail", no_argument, NULL, ARG_FAIL },
4299 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4300 { "ignore-inhibitors", no_argument, NULL, 'i' },
4301 { "user", no_argument, NULL, ARG_USER },
4302 { "system", no_argument, NULL, ARG_SYSTEM },
4303 { "global", no_argument, NULL, ARG_GLOBAL },
4304 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4305 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4306 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4307 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4308 { "quiet", no_argument, NULL, 'q' },
4309 { "root", required_argument, NULL, ARG_ROOT },
4310 { "force", no_argument, NULL, ARG_FORCE },
4311 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4312 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4313 { "signal", required_argument, NULL, 's' },
4314 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4315 { "host", required_argument, NULL, 'H' },
4316 { "privileged",no_argument, NULL, 'P' },
4317 { "runtime", no_argument, NULL, ARG_RUNTIME },
4318 { "lines", required_argument, NULL, 'n' },
4319 { "output", required_argument, NULL, 'o' },
4320 { NULL, 0, NULL, 0 }
4328 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4337 puts(PACKAGE_STRING);
4338 puts(SYSTEMD_FEATURES);
4342 if (streq(optarg, "help")) {
4347 if (unit_type_from_string(optarg) >= 0) {
4351 if (unit_load_state_from_string(optarg) >= 0) {
4352 arg_load_state = optarg;
4355 log_error("Unkown unit type or load state '%s'.",
4357 log_info("Use -t help to see a list of allowed values.");
4362 if (!(l = strv_append(arg_property, optarg)))
4365 strv_free(arg_property);
4368 /* If the user asked for a particular
4369 * property, show it to him, even if it is
4380 arg_job_mode = "fail";
4383 case ARG_IGNORE_DEPENDENCIES:
4384 arg_job_mode = "ignore-dependencies";
4388 arg_scope = UNIT_FILE_USER;
4392 arg_scope = UNIT_FILE_SYSTEM;
4396 arg_scope = UNIT_FILE_GLOBAL;
4400 arg_no_block = true;
4404 arg_no_legend = true;
4408 arg_no_pager = true;
4440 arg_no_reload = true;
4444 arg_kill_who = optarg;
4448 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4449 log_error("Failed to parse signal string %s.", optarg);
4454 case ARG_NO_ASK_PASSWORD:
4455 arg_ask_password = false;
4459 arg_transport = TRANSPORT_POLKIT;
4463 arg_transport = TRANSPORT_SSH;
4472 if (safe_atou(optarg, &arg_lines) < 0) {
4473 log_error("Failed to parse lines '%s'", optarg);
4479 arg_output = output_mode_from_string(optarg);
4480 if (arg_output < 0) {
4481 log_error("Unknown output '%s'.", optarg);
4487 arg_ignore_inhibitors = true;
4494 log_error("Unknown option code '%c'.", c);
4499 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4500 log_error("Cannot access user instance remotely.");
4507 static int halt_parse_argv(int argc, char *argv[]) {
4516 static const struct option options[] = {
4517 { "help", no_argument, NULL, ARG_HELP },
4518 { "halt", no_argument, NULL, ARG_HALT },
4519 { "poweroff", no_argument, NULL, 'p' },
4520 { "reboot", no_argument, NULL, ARG_REBOOT },
4521 { "force", no_argument, NULL, 'f' },
4522 { "wtmp-only", no_argument, NULL, 'w' },
4523 { "no-wtmp", no_argument, NULL, 'd' },
4524 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4525 { NULL, 0, NULL, 0 }
4533 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4534 if (runlevel == '0' || runlevel == '6')
4537 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4545 arg_action = ACTION_HALT;
4549 if (arg_action != ACTION_REBOOT)
4550 arg_action = ACTION_POWEROFF;
4554 arg_action = ACTION_REBOOT;
4576 /* Compatibility nops */
4583 log_error("Unknown option code '%c'.", c);
4588 if (optind < argc) {
4589 log_error("Too many arguments.");
4596 static int parse_time_spec(const char *t, usec_t *_u) {
4600 if (streq(t, "now"))
4602 else if (!strchr(t, ':')) {
4605 if (safe_atou64(t, &u) < 0)
4608 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4617 hour = strtol(t, &e, 10);
4618 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4621 minute = strtol(e+1, &e, 10);
4622 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4625 n = now(CLOCK_REALTIME);
4626 s = (time_t) (n / USEC_PER_SEC);
4629 assert_se(localtime_r(&s, &tm));
4631 tm.tm_hour = (int) hour;
4632 tm.tm_min = (int) minute;
4635 assert_se(s = mktime(&tm));
4637 *_u = (usec_t) s * USEC_PER_SEC;
4640 *_u += USEC_PER_DAY;
4646 static int shutdown_parse_argv(int argc, char *argv[]) {
4653 static const struct option options[] = {
4654 { "help", no_argument, NULL, ARG_HELP },
4655 { "halt", no_argument, NULL, 'H' },
4656 { "poweroff", no_argument, NULL, 'P' },
4657 { "reboot", no_argument, NULL, 'r' },
4658 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4659 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4660 { NULL, 0, NULL, 0 }
4668 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4676 arg_action = ACTION_HALT;
4680 arg_action = ACTION_POWEROFF;
4685 arg_action = ACTION_KEXEC;
4687 arg_action = ACTION_REBOOT;
4691 arg_action = ACTION_KEXEC;
4695 if (arg_action != ACTION_HALT)
4696 arg_action = ACTION_POWEROFF;
4709 /* Compatibility nops */
4713 arg_action = ACTION_CANCEL_SHUTDOWN;
4720 log_error("Unknown option code '%c'.", c);
4725 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4726 r = parse_time_spec(argv[optind], &arg_when);
4728 log_error("Failed to parse time specification: %s", argv[optind]);
4732 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4734 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4735 /* No time argument for shutdown cancel */
4736 arg_wall = argv + optind;
4737 else if (argc > optind + 1)
4738 /* We skip the time argument */
4739 arg_wall = argv + optind + 1;
4746 static int telinit_parse_argv(int argc, char *argv[]) {
4753 static const struct option options[] = {
4754 { "help", no_argument, NULL, ARG_HELP },
4755 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4756 { NULL, 0, NULL, 0 }
4759 static const struct {
4763 { '0', ACTION_POWEROFF },
4764 { '6', ACTION_REBOOT },
4765 { '1', ACTION_RESCUE },
4766 { '2', ACTION_RUNLEVEL2 },
4767 { '3', ACTION_RUNLEVEL3 },
4768 { '4', ACTION_RUNLEVEL4 },
4769 { '5', ACTION_RUNLEVEL5 },
4770 { 's', ACTION_RESCUE },
4771 { 'S', ACTION_RESCUE },
4772 { 'q', ACTION_RELOAD },
4773 { 'Q', ACTION_RELOAD },
4774 { 'u', ACTION_REEXEC },
4775 { 'U', ACTION_REEXEC }
4784 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4799 log_error("Unknown option code '%c'.", c);
4804 if (optind >= argc) {
4809 if (optind + 1 < argc) {
4810 log_error("Too many arguments.");
4814 if (strlen(argv[optind]) != 1) {
4815 log_error("Expected single character argument.");
4819 for (i = 0; i < ELEMENTSOF(table); i++)
4820 if (table[i].from == argv[optind][0])
4823 if (i >= ELEMENTSOF(table)) {
4824 log_error("Unknown command '%s'.", argv[optind]);
4828 arg_action = table[i].to;
4835 static int runlevel_parse_argv(int argc, char *argv[]) {
4841 static const struct option options[] = {
4842 { "help", no_argument, NULL, ARG_HELP },
4843 { NULL, 0, NULL, 0 }
4851 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4862 log_error("Unknown option code '%c'.", c);
4867 if (optind < argc) {
4868 log_error("Too many arguments.");
4875 static int parse_argv(int argc, char *argv[]) {
4879 if (program_invocation_short_name) {
4881 if (strstr(program_invocation_short_name, "halt")) {
4882 arg_action = ACTION_HALT;
4883 return halt_parse_argv(argc, argv);
4884 } else if (strstr(program_invocation_short_name, "poweroff")) {
4885 arg_action = ACTION_POWEROFF;
4886 return halt_parse_argv(argc, argv);
4887 } else if (strstr(program_invocation_short_name, "reboot")) {
4889 arg_action = ACTION_KEXEC;
4891 arg_action = ACTION_REBOOT;
4892 return halt_parse_argv(argc, argv);
4893 } else if (strstr(program_invocation_short_name, "shutdown")) {
4894 arg_action = ACTION_POWEROFF;
4895 return shutdown_parse_argv(argc, argv);
4896 } else if (strstr(program_invocation_short_name, "init")) {
4898 if (sd_booted() > 0) {
4899 arg_action = ACTION_INVALID;
4900 return telinit_parse_argv(argc, argv);
4902 /* Hmm, so some other init system is
4903 * running, we need to forward this
4904 * request to it. For now we simply
4905 * guess that it is Upstart. */
4907 execv("/lib/upstart/telinit", argv);
4909 log_error("Couldn't find an alternative telinit implementation to spawn.");
4913 } else if (strstr(program_invocation_short_name, "runlevel")) {
4914 arg_action = ACTION_RUNLEVEL;
4915 return runlevel_parse_argv(argc, argv);
4919 arg_action = ACTION_SYSTEMCTL;
4920 return systemctl_parse_argv(argc, argv);
4923 static int action_to_runlevel(void) {
4925 static const char table[_ACTION_MAX] = {
4926 [ACTION_HALT] = '0',
4927 [ACTION_POWEROFF] = '0',
4928 [ACTION_REBOOT] = '6',
4929 [ACTION_RUNLEVEL2] = '2',
4930 [ACTION_RUNLEVEL3] = '3',
4931 [ACTION_RUNLEVEL4] = '4',
4932 [ACTION_RUNLEVEL5] = '5',
4933 [ACTION_RESCUE] = '1'
4936 assert(arg_action < _ACTION_MAX);
4938 return table[arg_action];
4941 static int talk_upstart(void) {
4942 DBusMessage _cleanup_dbus_message_unref_ *m = NULL, *reply = NULL;
4943 DBusError _cleanup_dbus_error_free_ error;
4944 int previous, rl, r;
4946 env1_buf[] = "RUNLEVEL=X",
4947 env2_buf[] = "PREVLEVEL=X";
4948 char *env1 = env1_buf, *env2 = env2_buf;
4949 const char *emit = "runlevel";
4950 dbus_bool_t b_false = FALSE;
4951 DBusMessageIter iter, sub;
4952 DBusConnection *bus;
4954 dbus_error_init(&error);
4956 if (!(rl = action_to_runlevel()))
4959 if (utmp_get_runlevel(&previous, NULL) < 0)
4962 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4963 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4968 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4973 if ((r = bus_check_peercred(bus)) < 0) {
4974 log_error("Failed to verify owner of bus.");
4978 if (!(m = dbus_message_new_method_call(
4979 "com.ubuntu.Upstart",
4980 "/com/ubuntu/Upstart",
4981 "com.ubuntu.Upstart0_6",
4984 log_error("Could not allocate message.");
4989 dbus_message_iter_init_append(m, &iter);
4991 env1_buf[sizeof(env1_buf)-2] = rl;
4992 env2_buf[sizeof(env2_buf)-2] = previous;
4994 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4995 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4996 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4997 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4998 !dbus_message_iter_close_container(&iter, &sub) ||
4999 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5000 log_error("Could not append arguments to message.");
5005 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5007 if (bus_error_is_no_service(&error)) {
5012 log_error("Failed to issue method call: %s", bus_error_message(&error));
5021 dbus_connection_flush(bus);
5022 dbus_connection_close(bus);
5023 dbus_connection_unref(bus);
5029 static int talk_initctl(void) {
5030 struct init_request request;
5034 if (!(rl = action_to_runlevel()))
5038 request.magic = INIT_MAGIC;
5039 request.sleeptime = 0;
5040 request.cmd = INIT_CMD_RUNLVL;
5041 request.runlevel = rl;
5043 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5045 if (errno == ENOENT)
5048 log_error("Failed to open "INIT_FIFO": %m");
5053 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5054 close_nointr_nofail(fd);
5057 log_error("Failed to write to "INIT_FIFO": %m");
5058 return errno ? -errno : -EIO;
5064 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5066 static const struct {
5074 int (* const dispatch)(DBusConnection *bus, char **args);
5076 { "list-units", LESS, 1, list_units },
5077 { "list-unit-files", EQUAL, 1, list_unit_files },
5078 { "list-jobs", EQUAL, 1, list_jobs },
5079 { "clear-jobs", EQUAL, 1, daemon_reload },
5080 { "load", MORE, 2, load_unit },
5081 { "cancel", MORE, 2, cancel_job },
5082 { "start", MORE, 2, start_unit },
5083 { "stop", MORE, 2, start_unit },
5084 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5085 { "reload", MORE, 2, start_unit },
5086 { "restart", MORE, 2, start_unit },
5087 { "try-restart", MORE, 2, start_unit },
5088 { "reload-or-restart", MORE, 2, start_unit },
5089 { "reload-or-try-restart", MORE, 2, start_unit },
5090 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5091 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5092 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5093 { "isolate", EQUAL, 2, start_unit },
5094 { "set-cgroup", MORE, 2, set_cgroup },
5095 { "unset-cgroup", MORE, 2, set_cgroup },
5096 { "get-cgroup-attr", MORE, 2, get_cgroup_attr },
5097 { "set-cgroup-attr", MORE, 2, set_cgroup_attr },
5098 { "unset-cgroup-attr", MORE, 2, set_cgroup },
5099 { "kill", MORE, 2, kill_unit },
5100 { "is-active", MORE, 2, check_unit_active },
5101 { "check", MORE, 2, check_unit_active },
5102 { "is-failed", MORE, 2, check_unit_failed },
5103 { "show", MORE, 1, show },
5104 { "status", MORE, 1, show },
5105 { "help", MORE, 2, show },
5106 { "dump", EQUAL, 1, dump },
5107 { "snapshot", LESS, 2, snapshot },
5108 { "delete", MORE, 2, delete_snapshot },
5109 { "daemon-reload", EQUAL, 1, daemon_reload },
5110 { "daemon-reexec", EQUAL, 1, daemon_reload },
5111 { "show-environment", EQUAL, 1, show_enviroment },
5112 { "set-environment", MORE, 2, set_environment },
5113 { "unset-environment", MORE, 2, set_environment },
5114 { "halt", EQUAL, 1, start_special },
5115 { "poweroff", EQUAL, 1, start_special },
5116 { "reboot", EQUAL, 1, start_special },
5117 { "kexec", EQUAL, 1, start_special },
5118 { "suspend", EQUAL, 1, start_special },
5119 { "hibernate", EQUAL, 1, start_special },
5120 { "hybrid-sleep", EQUAL, 1, start_special },
5121 { "default", EQUAL, 1, start_special },
5122 { "rescue", EQUAL, 1, start_special },
5123 { "emergency", EQUAL, 1, start_special },
5124 { "exit", EQUAL, 1, start_special },
5125 { "reset-failed", MORE, 1, reset_failed },
5126 { "enable", MORE, 2, enable_unit },
5127 { "disable", MORE, 2, enable_unit },
5128 { "is-enabled", MORE, 2, unit_is_enabled },
5129 { "reenable", MORE, 2, enable_unit },
5130 { "preset", MORE, 2, enable_unit },
5131 { "mask", MORE, 2, enable_unit },
5132 { "unmask", MORE, 2, enable_unit },
5133 { "link", MORE, 2, enable_unit },
5134 { "switch-root", MORE, 2, switch_root },
5135 { "list-dependencies", LESS, 2, list_dependencies },
5145 left = argc - optind;
5148 /* Special rule: no arguments means "list-units" */
5151 if (streq(argv[optind], "help") && !argv[optind+1]) {
5152 log_error("This command expects one or more "
5153 "unit names. Did you mean --help?");
5157 for (i = 0; i < ELEMENTSOF(verbs); i++)
5158 if (streq(argv[optind], verbs[i].verb))
5161 if (i >= ELEMENTSOF(verbs)) {
5162 log_error("Unknown operation '%s'.", argv[optind]);
5167 switch (verbs[i].argc_cmp) {
5170 if (left != verbs[i].argc) {
5171 log_error("Invalid number of arguments.");
5178 if (left < verbs[i].argc) {
5179 log_error("Too few arguments.");
5186 if (left > verbs[i].argc) {
5187 log_error("Too many arguments.");
5194 assert_not_reached("Unknown comparison operator.");
5197 /* Require a bus connection for all operations but
5199 if (!streq(verbs[i].verb, "enable") &&
5200 !streq(verbs[i].verb, "disable") &&
5201 !streq(verbs[i].verb, "is-enabled") &&
5202 !streq(verbs[i].verb, "list-unit-files") &&
5203 !streq(verbs[i].verb, "reenable") &&
5204 !streq(verbs[i].verb, "preset") &&
5205 !streq(verbs[i].verb, "mask") &&
5206 !streq(verbs[i].verb, "unmask") &&
5207 !streq(verbs[i].verb, "link")) {
5209 if (running_in_chroot() > 0) {
5210 log_info("Running in chroot, ignoring request.");
5214 if (((!streq(verbs[i].verb, "reboot") &&
5215 !streq(verbs[i].verb, "halt") &&
5216 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5217 log_error("Failed to get D-Bus connection: %s",
5218 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5224 if (!bus && !avoid_bus()) {
5225 log_error("Failed to get D-Bus connection: %s",
5226 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5231 return verbs[i].dispatch(bus, argv + optind);
5234 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5235 int _cleanup_close_ fd;
5236 struct msghdr msghdr;
5237 struct iovec iovec[2];
5238 union sockaddr_union sockaddr;
5239 struct sd_shutdown_command c;
5241 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5248 c.dry_run = dry_run;
5252 sockaddr.sa.sa_family = AF_UNIX;
5253 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5256 msghdr.msg_name = &sockaddr;
5257 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5260 iovec[0].iov_base = (char*) &c;
5261 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5263 if (isempty(message))
5264 msghdr.msg_iovlen = 1;
5266 iovec[1].iov_base = (char*) message;
5267 iovec[1].iov_len = strlen(message);
5268 msghdr.msg_iovlen = 2;
5270 msghdr.msg_iov = iovec;
5272 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5278 static int reload_with_fallback(DBusConnection *bus) {
5281 /* First, try systemd via D-Bus. */
5282 if (daemon_reload(bus, NULL) >= 0)
5286 /* Nothing else worked, so let's try signals */
5287 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5289 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5290 log_error("kill() failed: %m");
5297 static int start_with_fallback(DBusConnection *bus) {
5300 /* First, try systemd via D-Bus. */
5301 if (start_unit(bus, NULL) >= 0)
5305 /* Hmm, talking to systemd via D-Bus didn't work. Then
5306 * let's try to talk to Upstart via D-Bus. */
5307 if (talk_upstart() > 0)
5310 /* Nothing else worked, so let's try
5312 if (talk_initctl() > 0)
5315 log_error("Failed to talk to init daemon.");
5319 warn_wall(arg_action);
5323 static _noreturn_ void halt_now(enum action a) {
5325 /* Make sure C-A-D is handled by the kernel from this
5327 reboot(RB_ENABLE_CAD);
5332 log_info("Halting.");
5333 reboot(RB_HALT_SYSTEM);
5336 case ACTION_POWEROFF:
5337 log_info("Powering off.");
5338 reboot(RB_POWER_OFF);
5342 log_info("Rebooting.");
5343 reboot(RB_AUTOBOOT);
5347 assert_not_reached("Unknown halt action.");
5350 assert_not_reached("Uh? This shouldn't happen.");
5353 static int halt_main(DBusConnection *bus) {
5356 r = check_inhibitors(bus, arg_action);
5360 if (geteuid() != 0) {
5361 /* Try logind if we are a normal user and no special
5362 * mode applies. Maybe PolicyKit allows us to shutdown
5365 if (arg_when <= 0 &&
5368 (arg_action == ACTION_POWEROFF ||
5369 arg_action == ACTION_REBOOT)) {
5370 r = reboot_with_logind(bus, arg_action);
5375 log_error("Must be root.");
5380 char _cleanup_free_ *m;
5382 m = strv_join(arg_wall, " ");
5383 r = send_shutdownd(arg_when,
5384 arg_action == ACTION_HALT ? 'H' :
5385 arg_action == ACTION_POWEROFF ? 'P' :
5386 arg_action == ACTION_KEXEC ? 'K' :
5393 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5395 char date[FORMAT_TIMESTAMP_MAX];
5397 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5398 format_timestamp(date, sizeof(date), arg_when));
5403 if (!arg_dry && !arg_force)
5404 return start_with_fallback(bus);
5407 if (sd_booted() > 0)
5408 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5410 r = utmp_put_shutdown();
5412 log_warning("Failed to write utmp record: %s", strerror(-r));
5419 halt_now(arg_action);
5420 /* We should never reach this. */
5424 static int runlevel_main(void) {
5425 int r, runlevel, previous;
5427 r = utmp_get_runlevel(&runlevel, &previous);
5434 previous <= 0 ? 'N' : previous,
5435 runlevel <= 0 ? 'N' : runlevel);
5440 int main(int argc, char*argv[]) {
5441 int r, retval = EXIT_FAILURE;
5442 DBusConnection *bus = NULL;
5443 DBusError _cleanup_dbus_error_free_ error;
5445 dbus_error_init(&error);
5447 setlocale(LC_ALL, "");
5448 log_parse_environment();
5451 r = parse_argv(argc, argv);
5455 retval = EXIT_SUCCESS;
5459 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5460 * let's shortcut this */
5461 if (arg_action == ACTION_RUNLEVEL) {
5462 r = runlevel_main();
5463 retval = r < 0 ? EXIT_FAILURE : r;
5467 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5468 log_info("Running in chroot, ignoring request.");
5474 if (arg_transport == TRANSPORT_NORMAL)
5475 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5476 else if (arg_transport == TRANSPORT_POLKIT) {
5477 bus_connect_system_polkit(&bus, &error);
5478 private_bus = false;
5479 } else if (arg_transport == TRANSPORT_SSH) {
5480 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5481 private_bus = false;
5483 assert_not_reached("Uh, invalid transport...");
5486 switch (arg_action) {
5488 case ACTION_SYSTEMCTL:
5489 r = systemctl_main(bus, argc, argv, &error);
5493 case ACTION_POWEROFF:
5499 case ACTION_RUNLEVEL2:
5500 case ACTION_RUNLEVEL3:
5501 case ACTION_RUNLEVEL4:
5502 case ACTION_RUNLEVEL5:
5504 case ACTION_EMERGENCY:
5505 case ACTION_DEFAULT:
5506 r = start_with_fallback(bus);
5511 r = reload_with_fallback(bus);
5514 case ACTION_CANCEL_SHUTDOWN: {
5518 m = strv_join(arg_wall, " ");
5520 retval = EXIT_FAILURE;
5524 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5526 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5531 case ACTION_INVALID:
5532 case ACTION_RUNLEVEL:
5534 assert_not_reached("Unknown action");
5537 retval = r < 0 ? EXIT_FAILURE : r;
5541 dbus_connection_flush(bus);
5542 dbus_connection_close(bus);
5543 dbus_connection_unref(bus);
5548 strv_free(arg_property);
5551 ask_password_agent_close();
5552 polkit_agent_close();