1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/reboot.h>
29 #include <sys/ioctl.h>
33 #include <sys/socket.h>
36 #include <sys/prctl.h>
37 #include <dbus/dbus.h>
39 #include <systemd/sd-daemon.h>
40 #include <systemd/sd-shutdown.h>
41 #include <systemd/sd-login.h>
47 #include "utmp-wtmp.h"
50 #include "path-util.h"
52 #include "dbus-common.h"
53 #include "cgroup-show.h"
54 #include "cgroup-util.h"
56 #include "path-lookup.h"
57 #include "conf-parser.h"
58 #include "exit-status.h"
59 #include "bus-errors.h"
61 #include "unit-name.h"
63 #include "spawn-ask-password-agent.h"
64 #include "spawn-polkit-agent.h"
66 #include "logs-show.h"
67 #include "path-util.h"
68 #include "socket-util.h"
71 static const char *arg_type = NULL;
72 static const char *arg_load_state = NULL;
73 static char **arg_property = NULL;
74 static bool arg_all = false;
75 static const char *arg_job_mode = "replace";
76 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
77 static bool arg_no_block = false;
78 static bool arg_no_legend = false;
79 static bool arg_no_pager = false;
80 static bool arg_no_wtmp = false;
81 static bool arg_no_wall = false;
82 static bool arg_no_reload = false;
83 static bool arg_ignore_inhibitors = false;
84 static bool arg_dry = false;
85 static bool arg_quiet = false;
86 static bool arg_full = false;
87 static int arg_force = 0;
88 static bool arg_ask_password = true;
89 static bool arg_failed = false;
90 static bool arg_runtime = false;
91 static char **arg_wall = NULL;
92 static const char *arg_kill_who = NULL;
93 static int arg_signal = SIGTERM;
94 static const char *arg_root = NULL;
95 static usec_t arg_when = 0;
117 ACTION_CANCEL_SHUTDOWN,
119 } arg_action = ACTION_SYSTEMCTL;
120 static enum transport {
124 } arg_transport = TRANSPORT_NORMAL;
125 static const char *arg_host = NULL;
126 static unsigned arg_lines = 10;
127 static OutputMode arg_output = OUTPUT_SHORT;
129 static bool private_bus = false;
131 static int daemon_reload(DBusConnection *bus, char **args);
132 static void halt_now(enum action a);
134 static void pager_open_if_enabled(void) {
142 static void ask_password_agent_open_if_enabled(void) {
144 /* Open the password agent as a child process if necessary */
146 if (!arg_ask_password)
149 if (arg_scope != UNIT_FILE_SYSTEM)
152 ask_password_agent_open();
156 static void polkit_agent_open_if_enabled(void) {
158 /* Open the polkit agent as a child process if necessary */
160 if (!arg_ask_password)
163 if (arg_scope != UNIT_FILE_SYSTEM)
170 static const char *ansi_highlight(bool b) {
175 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
178 static const char *ansi_highlight_red(bool b) {
183 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
186 static const char *ansi_highlight_green(bool b) {
191 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
194 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
197 if (!dbus_error_is_set(error))
200 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
201 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
202 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
203 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
204 return EXIT_NOPERMISSION;
206 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
207 return EXIT_NOTINSTALLED;
209 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
210 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
211 return EXIT_NOTIMPLEMENTED;
213 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
214 return EXIT_NOTCONFIGURED;
222 static void warn_wall(enum action a) {
223 static const char *table[_ACTION_MAX] = {
224 [ACTION_HALT] = "The system is going down for system halt NOW!",
225 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
226 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
227 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
228 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
229 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
230 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
237 _cleanup_free_ char *p;
239 p = strv_join(arg_wall, " ");
254 utmp_wall(table[a], NULL);
257 static bool avoid_bus(void) {
259 if (running_in_chroot() > 0)
262 if (sd_booted() <= 0)
265 if (!isempty(arg_root))
268 if (arg_scope == UNIT_FILE_GLOBAL)
274 static int compare_unit_info(const void *a, const void *b) {
276 const struct unit_info *u = a, *v = b;
278 d1 = strrchr(u->id, '.');
279 d2 = strrchr(v->id, '.');
284 r = strcasecmp(d1, d2);
289 return strcasecmp(u->id, v->id);
292 static bool output_show_unit(const struct unit_info *u) {
296 return streq(u->active_state, "failed");
298 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
299 streq(dot+1, arg_type))) &&
300 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
301 (arg_all || !(streq(u->active_state, "inactive")
302 || u->following[0]) || u->job_id > 0);
305 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
306 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
307 const struct unit_info *u;
310 max_id_len = sizeof("UNIT")-1;
311 active_len = sizeof("ACTIVE")-1;
312 sub_len = sizeof("SUB")-1;
313 job_len = sizeof("JOB")-1;
316 for (u = unit_infos; u < unit_infos + c; u++) {
317 if (!output_show_unit(u))
320 max_id_len = MAX(max_id_len, strlen(u->id));
321 active_len = MAX(active_len, strlen(u->active_state));
322 sub_len = MAX(sub_len, strlen(u->sub_state));
323 if (u->job_id != 0) {
324 job_len = MAX(job_len, strlen(u->job_type));
331 id_len = MIN(max_id_len, 25);
332 basic_len = 5 + id_len + 5 + active_len + sub_len;
334 basic_len += job_len + 1;
335 if (basic_len < (unsigned) columns()) {
336 unsigned extra_len, incr;
337 extra_len = columns() - basic_len;
338 /* Either UNIT already got 25, or is fully satisfied.
339 * Grant up to 25 to DESC now. */
340 incr = MIN(extra_len, 25);
343 /* split the remaining space between UNIT and DESC,
344 * but do not give UNIT more than it needs. */
346 incr = MIN(extra_len / 2, max_id_len - id_len);
348 desc_len += extra_len - incr;
354 for (u = unit_infos; u < unit_infos + c; u++) {
355 char _cleanup_free_ *e = NULL;
356 const char *on_loaded, *off_loaded;
357 const char *on_active, *off_active;
359 if (!output_show_unit(u))
362 if (!n_shown && !arg_no_legend) {
363 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
364 active_len, "ACTIVE", sub_len, "SUB");
366 printf("%-*s ", job_len, "JOB");
367 if (!arg_full && arg_no_pager)
368 printf("%.*s\n", desc_len, "DESCRIPTION");
370 printf("%s\n", "DESCRIPTION");
375 if (streq(u->load_state, "error")) {
376 on_loaded = ansi_highlight_red(true);
377 off_loaded = ansi_highlight_red(false);
379 on_loaded = off_loaded = "";
381 if (streq(u->active_state, "failed")) {
382 on_active = ansi_highlight_red(true);
383 off_active = ansi_highlight_red(false);
385 on_active = off_active = "";
387 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
389 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s",
390 id_len, e ? e : u->id,
391 on_loaded, u->load_state, off_loaded,
392 on_active, active_len, u->active_state,
393 sub_len, u->sub_state, off_active,
394 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
395 if (!arg_full && arg_no_pager)
396 printf("%.*s\n", desc_len, u->description);
398 printf("%s\n", u->description);
401 if (!arg_no_legend) {
402 const char *on, *off;
405 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
406 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
407 "SUB = The low-level unit activation state, values depend on unit type.\n");
409 printf("JOB = Pending job for the unit.\n");
411 on = ansi_highlight(true);
412 off = ansi_highlight(false);
414 on = ansi_highlight_red(true);
415 off = ansi_highlight_red(false);
419 printf("%s%u loaded units listed.%s\n"
420 "To show all installed unit files use 'systemctl list-unit-files'.\n",
423 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
424 "To show all installed unit files use 'systemctl list-unit-files'.\n",
429 static int get_unit_list(DBusConnection *bus, DBusMessage **reply,
430 struct unit_info **unit_infos, unsigned *c) {
431 DBusMessageIter iter, sub;
432 unsigned n_units = 0;
439 r = bus_method_call_with_reply(
441 "org.freedesktop.systemd1",
442 "/org/freedesktop/systemd1",
443 "org.freedesktop.systemd1.Manager",
451 if (!dbus_message_iter_init(*reply, &iter) ||
452 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
453 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
454 log_error("Failed to parse reply.");
458 dbus_message_iter_recurse(&iter, &sub);
460 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
466 n_units = MAX(2 * *c, 16);
467 w = realloc(*unit_infos, sizeof(struct unit_info) * n_units);
474 u = *unit_infos + *c;
476 bus_parse_unit_info(&sub, u);
478 dbus_message_iter_next(&sub);
483 qsort(*unit_infos, *c, sizeof(struct unit_info), compare_unit_info);
488 static int list_units(DBusConnection *bus, char **args) {
489 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
490 _cleanup_free_ struct unit_info *unit_infos = NULL;
494 pager_open_if_enabled();
496 r = get_unit_list(bus, &reply, &unit_infos, &c);
501 output_units_list(unit_infos, c);
506 static int compare_unit_file_list(const void *a, const void *b) {
508 const UnitFileList *u = a, *v = b;
510 d1 = strrchr(u->path, '.');
511 d2 = strrchr(v->path, '.');
516 r = strcasecmp(d1, d2);
521 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
524 static bool output_show_unit_file(const UnitFileList *u) {
527 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
530 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
531 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
532 const UnitFileList *u;
534 max_id_len = sizeof("UNIT FILE")-1;
535 state_cols = sizeof("STATE")-1;
536 for (u = units; u < units + c; u++) {
537 if (!output_show_unit_file(u))
540 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
541 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
546 id_cols = MIN(max_id_len, 25);
547 basic_cols = 1 + id_cols + state_cols;
548 if (basic_cols < (unsigned) columns())
549 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
551 id_cols = max_id_len;
554 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
556 for (u = units; u < units + c; u++) {
557 char _cleanup_free_ *e = NULL;
558 const char *on, *off;
561 if (!output_show_unit_file(u))
566 if (u->state == UNIT_FILE_MASKED ||
567 u->state == UNIT_FILE_MASKED_RUNTIME ||
568 u->state == UNIT_FILE_DISABLED ||
569 u->state == UNIT_FILE_INVALID) {
570 on = ansi_highlight_red(true);
571 off = ansi_highlight_red(false);
572 } else if (u->state == UNIT_FILE_ENABLED) {
573 on = ansi_highlight_green(true);
574 off = ansi_highlight_green(false);
578 id = path_get_file_name(u->path);
580 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
582 printf("%-*s %s%-*s%s\n",
584 on, state_cols, unit_file_state_to_string(u->state), off);
588 printf("\n%u unit files listed.\n", n_shown);
591 static int list_unit_files(DBusConnection *bus, char **args) {
592 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
593 _cleanup_free_ UnitFileList *units = NULL;
594 DBusMessageIter iter, sub, sub2;
595 unsigned c = 0, n_units = 0;
598 pager_open_if_enabled();
605 h = hashmap_new(string_hash_func, string_compare_func);
609 r = unit_file_get_list(arg_scope, arg_root, h);
611 unit_file_list_free(h);
612 log_error("Failed to get unit file list: %s", strerror(-r));
616 n_units = hashmap_size(h);
617 units = new(UnitFileList, n_units);
619 unit_file_list_free(h);
623 HASHMAP_FOREACH(u, h, i) {
624 memcpy(units + c++, u, sizeof(UnitFileList));
630 r = bus_method_call_with_reply(
632 "org.freedesktop.systemd1",
633 "/org/freedesktop/systemd1",
634 "org.freedesktop.systemd1.Manager",
642 if (!dbus_message_iter_init(reply, &iter) ||
643 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
644 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
645 log_error("Failed to parse reply.");
649 dbus_message_iter_recurse(&iter, &sub);
651 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
655 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
660 n_units = MAX(2*c, 16);
661 w = realloc(units, sizeof(struct UnitFileList) * n_units);
670 dbus_message_iter_recurse(&sub, &sub2);
672 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
673 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
674 log_error("Failed to parse reply.");
678 u->state = unit_file_state_from_string(state);
680 dbus_message_iter_next(&sub);
686 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
687 output_unit_file_list(units, c);
693 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
695 _cleanup_free_ char *n = NULL;
697 size_t max_len = MAX(columns(),20);
699 for (i = level - 1; i >= 0; i--) {
701 if(len > max_len - 3 && !arg_full) {
702 printf("%s...\n",max_len % 2 ? "" : " ");
705 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
708 if(len > max_len - 3 && !arg_full) {
709 printf("%s...\n",max_len % 2 ? "" : " ");
712 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
715 printf("%s\n", name);
719 n = ellipsize(name, max_len-len, 100);
727 static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
728 static const char dependencies[] =
730 "RequiresOverridable\0"
732 "RequisiteOverridable\0"
735 _cleanup_free_ char *path;
736 const char *interface = "org.freedesktop.systemd1.Unit";
738 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
739 DBusMessageIter iter, sub, sub2, sub3;
748 path = unit_dbus_path_from_name(name);
754 r = bus_method_call_with_reply(
756 "org.freedesktop.systemd1",
758 "org.freedesktop.DBus.Properties",
762 DBUS_TYPE_STRING, &interface,
767 if (!dbus_message_iter_init(reply, &iter) ||
768 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
769 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
770 log_error("Failed to parse reply.");
775 dbus_message_iter_recurse(&iter, &sub);
777 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
780 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
781 dbus_message_iter_recurse(&sub, &sub2);
783 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
784 log_error("Failed to parse reply.");
789 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
790 log_error("Failed to parse reply.");
795 dbus_message_iter_recurse(&sub2, &sub3);
796 dbus_message_iter_next(&sub);
798 if (!nulstr_contains(dependencies, prop))
801 if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
802 if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
803 DBusMessageIter sub4;
804 dbus_message_iter_recurse(&sub3, &sub4);
806 while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
809 assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
810 dbus_message_iter_get_basic(&sub4, &s);
812 r = strv_extend(&ret, s);
818 dbus_message_iter_next(&sub4);
831 static int list_dependencies_compare(const void *_a, const void *_b) {
832 const char **a = (const char**) _a, **b = (const char**) _b;
833 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
835 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
837 return strcasecmp(*a, *b);
840 static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char **units, unsigned int branches) {
841 char _cleanup_strv_free_ **deps = NULL, **u;
845 u = strv_append(units, name);
849 r = list_dependencies_get_dependencies(bus, name, &deps);
853 qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
855 STRV_FOREACH(c, deps) {
856 if (strv_contains(u, *c)) {
857 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
863 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
867 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
868 r = list_dependencies_one(bus, *c, level + 1, u, (branches << 1) | (c[1] == NULL ? 0 : 1));
877 static int list_dependencies(DBusConnection *bus, char **args) {
878 _cleanup_free_ char *unit = NULL;
884 unit = unit_name_mangle(args[1]);
889 u = SPECIAL_DEFAULT_TARGET;
891 pager_open_if_enabled();
895 return list_dependencies_one(bus, u, 0, NULL, 0);
898 static int list_jobs(DBusConnection *bus, char **args) {
899 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
900 DBusMessageIter iter, sub, sub2;
904 pager_open_if_enabled();
906 r = bus_method_call_with_reply(
908 "org.freedesktop.systemd1",
909 "/org/freedesktop/systemd1",
910 "org.freedesktop.systemd1.Manager",
918 if (!dbus_message_iter_init(reply, &iter) ||
919 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
920 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
921 log_error("Failed to parse reply.");
925 dbus_message_iter_recurse(&iter, &sub);
928 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
930 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
931 const char *name, *type, *state, *job_path, *unit_path;
933 char _cleanup_free_ *e = NULL;
935 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
936 log_error("Failed to parse reply.");
940 dbus_message_iter_recurse(&sub, &sub2);
942 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
943 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
944 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
945 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
946 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
947 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
948 log_error("Failed to parse reply.");
952 e = arg_full ? NULL : ellipsize(name, 25, 33);
953 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
957 dbus_message_iter_next(&sub);
961 printf("\n%u jobs listed.\n", k);
966 static int load_unit(DBusConnection *bus, char **args) {
971 STRV_FOREACH(name, args+1) {
972 _cleanup_free_ char *n = NULL;
975 n = unit_name_mangle(*name);
979 r = bus_method_call_with_reply(
981 "org.freedesktop.systemd1",
982 "/org/freedesktop/systemd1",
983 "org.freedesktop.systemd1.Manager",
987 DBUS_TYPE_STRING, &n,
996 static int cancel_job(DBusConnection *bus, char **args) {
1001 if (strv_length(args) <= 1)
1002 return daemon_reload(bus, args);
1004 STRV_FOREACH(name, args+1) {
1008 r = safe_atou32(*name, &id);
1010 log_error("Failed to parse job id: %s", strerror(-r));
1014 r = bus_method_call_with_reply(
1016 "org.freedesktop.systemd1",
1017 "/org/freedesktop/systemd1",
1018 "org.freedesktop.systemd1.Manager",
1022 DBUS_TYPE_UINT32, &id,
1031 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1032 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1033 dbus_bool_t b = FALSE;
1034 DBusMessageIter iter, sub;
1036 *interface = "org.freedesktop.systemd1.Unit",
1037 *property = "NeedDaemonReload",
1039 _cleanup_free_ char *n = NULL;
1042 /* We ignore all errors here, since this is used to show a warning only */
1044 n = unit_name_mangle(unit);
1048 r = bus_method_call_with_reply(
1050 "org.freedesktop.systemd1",
1051 "/org/freedesktop/systemd1",
1052 "org.freedesktop.systemd1.Manager",
1056 DBUS_TYPE_STRING, &n,
1061 if (!dbus_message_get_args(reply, NULL,
1062 DBUS_TYPE_OBJECT_PATH, &path,
1066 dbus_message_unref(reply);
1069 r = bus_method_call_with_reply(
1071 "org.freedesktop.systemd1",
1073 "org.freedesktop.DBus.Properties",
1077 DBUS_TYPE_STRING, &interface,
1078 DBUS_TYPE_STRING, &property,
1083 if (!dbus_message_iter_init(reply, &iter) ||
1084 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1087 dbus_message_iter_recurse(&iter, &sub);
1088 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1091 dbus_message_iter_get_basic(&sub, &b);
1095 typedef struct WaitData {
1102 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1103 DBusError _cleanup_dbus_error_free_ error;
1106 dbus_error_init(&error);
1112 log_debug("Got D-Bus request: %s.%s() on %s",
1113 dbus_message_get_interface(message),
1114 dbus_message_get_member(message),
1115 dbus_message_get_path(message));
1117 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1118 log_error("Warning! D-Bus connection terminated.");
1119 dbus_connection_close(connection);
1121 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1123 const char *path, *result, *unit;
1125 if (dbus_message_get_args(message, &error,
1126 DBUS_TYPE_UINT32, &id,
1127 DBUS_TYPE_OBJECT_PATH, &path,
1128 DBUS_TYPE_STRING, &unit,
1129 DBUS_TYPE_STRING, &result,
1130 DBUS_TYPE_INVALID)) {
1132 free(set_remove(d->set, (char*) path));
1134 if (!isempty(result))
1135 d->result = strdup(result);
1138 d->name = strdup(unit);
1140 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1143 dbus_error_free(&error);
1144 if (dbus_message_get_args(message, &error,
1145 DBUS_TYPE_UINT32, &id,
1146 DBUS_TYPE_OBJECT_PATH, &path,
1147 DBUS_TYPE_STRING, &result,
1148 DBUS_TYPE_INVALID)) {
1149 /* Compatibility with older systemd versions <
1150 * 183 during upgrades. This should be dropped
1152 free(set_remove(d->set, (char*) path));
1155 d->result = strdup(result);
1157 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1161 log_error("Failed to parse message: %s", bus_error_message(&error));
1164 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1167 static int enable_wait_for_jobs(DBusConnection *bus) {
1175 dbus_error_init(&error);
1176 dbus_bus_add_match(bus,
1178 "sender='org.freedesktop.systemd1',"
1179 "interface='org.freedesktop.systemd1.Manager',"
1180 "member='JobRemoved',"
1181 "path='/org/freedesktop/systemd1'",
1184 if (dbus_error_is_set(&error)) {
1185 log_error("Failed to add match: %s", bus_error_message(&error));
1186 dbus_error_free(&error);
1190 /* This is slightly dirty, since we don't undo the match registrations. */
1194 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1204 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1207 while (!set_isempty(s)) {
1209 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1210 log_error("Disconnected from bus.");
1211 return -ECONNREFUSED;
1218 if (streq(d.result, "timeout"))
1219 log_error("Job for %s timed out.", strna(d.name));
1220 else if (streq(d.result, "canceled"))
1221 log_error("Job for %s canceled.", strna(d.name));
1222 else if (streq(d.result, "dependency"))
1223 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1224 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1225 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1228 if (streq_ptr(d.result, "timeout"))
1230 else if (streq_ptr(d.result, "canceled"))
1232 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1243 dbus_connection_remove_filter(bus, wait_filter, &d);
1247 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1248 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1249 _cleanup_free_ char *n = NULL;
1250 DBusMessageIter iter, sub;
1252 *interface = "org.freedesktop.systemd1.Unit",
1253 *property = "ActiveState";
1254 const char *state, *path;
1260 dbus_error_init(&error);
1262 n = unit_name_mangle(name);
1266 r = bus_method_call_with_reply (
1268 "org.freedesktop.systemd1",
1269 "/org/freedesktop/systemd1",
1270 "org.freedesktop.systemd1.Manager",
1274 DBUS_TYPE_STRING, &n,
1277 dbus_error_free(&error);
1284 if (!dbus_message_get_args(reply, NULL,
1285 DBUS_TYPE_OBJECT_PATH, &path,
1286 DBUS_TYPE_INVALID)) {
1287 log_error("Failed to parse reply.");
1291 dbus_message_unref(reply);
1294 r = bus_method_call_with_reply(
1296 "org.freedesktop.systemd1",
1298 "org.freedesktop.DBus.Properties",
1302 DBUS_TYPE_STRING, &interface,
1303 DBUS_TYPE_STRING, &property,
1311 if (!dbus_message_iter_init(reply, &iter) ||
1312 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1313 log_error("Failed to parse reply.");
1317 dbus_message_iter_recurse(&iter, &sub);
1319 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1320 log_error("Failed to parse reply.");
1324 dbus_message_iter_get_basic(&sub, &state);
1329 return strv_find(check_states, state) ? 1 : 0;
1332 static void check_triggering_units(
1333 DBusConnection *bus,
1334 const char *unit_name) {
1336 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1337 DBusMessageIter iter, sub;
1338 const char *interface = "org.freedesktop.systemd1.Unit",
1339 *load_state_property = "LoadState",
1340 *triggered_by_property = "TriggeredBy",
1342 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1343 bool print_warning_label = true;
1346 n = unit_name_mangle(unit_name);
1352 unit_path = unit_dbus_path_from_name(n);
1358 r = bus_method_call_with_reply(
1360 "org.freedesktop.systemd1",
1362 "org.freedesktop.DBus.Properties",
1366 DBUS_TYPE_STRING, &interface,
1367 DBUS_TYPE_STRING, &load_state_property,
1372 if (!dbus_message_iter_init(reply, &iter) ||
1373 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1374 log_error("Failed to parse reply.");
1378 dbus_message_iter_recurse(&iter, &sub);
1380 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1381 log_error("Failed to parse reply.");
1385 dbus_message_iter_get_basic(&sub, &state);
1387 if (streq(state, "masked"))
1390 dbus_message_unref(reply);
1393 r = bus_method_call_with_reply(
1395 "org.freedesktop.systemd1",
1397 "org.freedesktop.DBus.Properties",
1401 DBUS_TYPE_STRING, &interface,
1402 DBUS_TYPE_STRING, &triggered_by_property,
1407 if (!dbus_message_iter_init(reply, &iter) ||
1408 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1409 log_error("Failed to parse reply.");
1413 dbus_message_iter_recurse(&iter, &sub);
1414 dbus_message_iter_recurse(&sub, &iter);
1417 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1418 const char * const check_states[] = {
1423 const char *service_trigger;
1425 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1426 log_error("Failed to parse reply.");
1430 dbus_message_iter_get_basic(&sub, &service_trigger);
1432 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1436 if (print_warning_label) {
1437 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1438 print_warning_label = false;
1441 log_warning(" %s", service_trigger);
1444 dbus_message_iter_next(&sub);
1448 static int start_unit_one(
1449 DBusConnection *bus,
1456 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1457 _cleanup_free_ char *n;
1466 n = unit_name_mangle(name);
1470 r = bus_method_call_with_reply(
1472 "org.freedesktop.systemd1",
1473 "/org/freedesktop/systemd1",
1474 "org.freedesktop.systemd1.Manager",
1478 DBUS_TYPE_STRING, &n,
1479 DBUS_TYPE_STRING, &mode,
1482 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1483 /* There's always a fallback possible for
1484 * legacy actions. */
1487 log_error("Failed to issue method call: %s", bus_error_message(error));
1492 if (!dbus_message_get_args(reply, error,
1493 DBUS_TYPE_OBJECT_PATH, &path,
1494 DBUS_TYPE_INVALID)) {
1495 log_error("Failed to parse reply: %s", bus_error_message(error));
1499 if (need_daemon_reload(bus, n))
1500 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1501 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1513 log_error("Failed to add path to set.");
1521 static const struct {
1525 } action_table[_ACTION_MAX] = {
1526 [ACTION_HALT] = { SPECIAL_HALT_TARGET, "halt", "replace-irreversibly" },
1527 [ACTION_POWEROFF] = { SPECIAL_POWEROFF_TARGET, "poweroff", "replace-irreversibly" },
1528 [ACTION_REBOOT] = { SPECIAL_REBOOT_TARGET, "reboot", "replace-irreversibly" },
1529 [ACTION_KEXEC] = { SPECIAL_KEXEC_TARGET, "kexec", "replace-irreversibly" },
1530 [ACTION_RUNLEVEL2] = { SPECIAL_RUNLEVEL2_TARGET, NULL, "isolate" },
1531 [ACTION_RUNLEVEL3] = { SPECIAL_RUNLEVEL3_TARGET, NULL, "isolate" },
1532 [ACTION_RUNLEVEL4] = { SPECIAL_RUNLEVEL4_TARGET, NULL, "isolate" },
1533 [ACTION_RUNLEVEL5] = { SPECIAL_RUNLEVEL5_TARGET, NULL, "isolate" },
1534 [ACTION_RESCUE] = { SPECIAL_RESCUE_TARGET, "rescue", "isolate" },
1535 [ACTION_EMERGENCY] = { SPECIAL_EMERGENCY_TARGET, "emergency", "isolate" },
1536 [ACTION_DEFAULT] = { SPECIAL_DEFAULT_TARGET, "default", "isolate" },
1537 [ACTION_EXIT] = { SPECIAL_EXIT_TARGET, "exit", "replace-irreversibly" },
1538 [ACTION_SUSPEND] = { SPECIAL_SUSPEND_TARGET, "suspend", "replace-irreversibly" },
1539 [ACTION_HIBERNATE] = { SPECIAL_HIBERNATE_TARGET, "hibernate", "replace-irreversibly" },
1540 [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
1543 static enum action verb_to_action(const char *verb) {
1546 for (i = ACTION_INVALID; i < _ACTION_MAX; i++)
1547 if (action_table[i].verb && streq(verb, action_table[i].verb))
1549 return ACTION_INVALID;
1552 static int start_unit(DBusConnection *bus, char **args) {
1555 const char *method, *mode, *one_name;
1556 Set _cleanup_set_free_free_ *s = NULL;
1557 DBusError _cleanup_dbus_error_free_ error;
1560 dbus_error_init(&error);
1564 ask_password_agent_open_if_enabled();
1566 if (arg_action == ACTION_SYSTEMCTL) {
1569 streq(args[0], "stop") ||
1570 streq(args[0], "condstop") ? "StopUnit" :
1571 streq(args[0], "reload") ? "ReloadUnit" :
1572 streq(args[0], "restart") ? "RestartUnit" :
1574 streq(args[0], "try-restart") ||
1575 streq(args[0], "condrestart") ? "TryRestartUnit" :
1577 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1579 streq(args[0], "reload-or-try-restart") ||
1580 streq(args[0], "condreload") ||
1582 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1584 action = verb_to_action(args[0]);
1586 mode = streq(args[0], "isolate") ? "isolate" :
1587 action_table[action].mode ?: arg_job_mode;
1589 one_name = action_table[action].target;
1592 assert(arg_action < ELEMENTSOF(action_table));
1593 assert(action_table[arg_action].target);
1595 method = "StartUnit";
1597 mode = action_table[arg_action].mode;
1598 one_name = action_table[arg_action].target;
1601 if (!arg_no_block) {
1602 ret = enable_wait_for_jobs(bus);
1604 log_error("Could not watch jobs: %s", strerror(-ret));
1608 s = set_new(string_hash_func, string_compare_func);
1614 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1616 ret = translate_bus_error_to_exit_status(ret, &error);
1618 STRV_FOREACH(name, args+1) {
1619 r = start_unit_one(bus, method, *name, mode, &error, s);
1621 ret = translate_bus_error_to_exit_status(r, &error);
1622 dbus_error_free(&error);
1627 if (!arg_no_block) {
1628 r = wait_for_jobs(bus, s);
1632 /* When stopping units, warn if they can still be triggered by
1633 * another active unit (socket, path, timer) */
1634 if (!arg_quiet && streq(method, "StopUnit")) {
1636 check_triggering_units(bus, one_name);
1638 STRV_FOREACH(name, args+1)
1639 check_triggering_units(bus, *name);
1646 /* Ask systemd-logind, which might grant access to unprivileged users
1647 * through PolicyKit */
1648 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1651 dbus_bool_t interactive = true;
1656 polkit_agent_open_if_enabled();
1664 case ACTION_POWEROFF:
1665 method = "PowerOff";
1668 case ACTION_SUSPEND:
1672 case ACTION_HIBERNATE:
1673 method = "Hibernate";
1676 case ACTION_HYBRID_SLEEP:
1677 method = "HybridSleep";
1684 return bus_method_call_with_reply(
1686 "org.freedesktop.login1",
1687 "/org/freedesktop/login1",
1688 "org.freedesktop.login1.Manager",
1692 DBUS_TYPE_BOOLEAN, &interactive,
1699 static int check_inhibitors(DBusConnection *bus, enum action a) {
1701 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1702 DBusMessageIter iter, sub, sub2;
1705 _cleanup_strv_free_ char **sessions = NULL;
1711 if (arg_ignore_inhibitors || arg_force > 0)
1723 r = bus_method_call_with_reply(
1725 "org.freedesktop.login1",
1726 "/org/freedesktop/login1",
1727 "org.freedesktop.login1.Manager",
1733 /* If logind is not around, then there are no inhibitors... */
1736 if (!dbus_message_iter_init(reply, &iter) ||
1737 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1738 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1739 log_error("Failed to parse reply.");
1743 dbus_message_iter_recurse(&iter, &sub);
1744 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1745 const char *what, *who, *why, *mode;
1747 _cleanup_strv_free_ char **sv = NULL;
1748 _cleanup_free_ char *comm = NULL, *user = NULL;
1750 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1751 log_error("Failed to parse reply.");
1755 dbus_message_iter_recurse(&sub, &sub2);
1757 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
1758 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
1759 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
1760 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
1761 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
1762 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
1763 log_error("Failed to parse reply.");
1767 if (!streq(mode, "block"))
1770 sv = strv_split(what, ":");
1774 if (!strv_contains(sv,
1776 a == ACTION_POWEROFF ||
1777 a == ACTION_REBOOT ||
1778 a == ACTION_KEXEC ? "shutdown" : "sleep"))
1781 get_process_comm(pid, &comm);
1782 user = uid_to_name(uid);
1783 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
1784 who, (unsigned long) pid, strna(comm), strna(user), why);
1788 dbus_message_iter_next(&sub);
1791 dbus_message_iter_recurse(&iter, &sub);
1793 /* Check for current sessions */
1794 sd_get_sessions(&sessions);
1795 STRV_FOREACH(s, sessions) {
1797 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
1799 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
1802 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
1805 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
1808 sd_session_get_tty(*s, &tty);
1809 sd_session_get_seat(*s, &seat);
1810 sd_session_get_service(*s, &service);
1811 user = uid_to_name(uid);
1813 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
1820 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
1821 action_table[a].verb);
1829 static int start_special(DBusConnection *bus, char **args) {
1835 a = verb_to_action(args[0]);
1837 r = check_inhibitors(bus, a);
1841 if (arg_force >= 2 && geteuid() != 0) {
1842 log_error("Must be root.");
1846 if (arg_force >= 2 &&
1847 (a == ACTION_HALT ||
1848 a == ACTION_POWEROFF ||
1849 a == ACTION_REBOOT))
1852 if (arg_force >= 1 &&
1853 (a == ACTION_HALT ||
1854 a == ACTION_POWEROFF ||
1855 a == ACTION_REBOOT ||
1856 a == ACTION_KEXEC ||
1858 return daemon_reload(bus, args);
1860 /* first try logind, to allow authentication with polkit */
1861 if (geteuid() != 0 &&
1862 (a == ACTION_POWEROFF ||
1863 a == ACTION_REBOOT ||
1864 a == ACTION_SUSPEND ||
1865 a == ACTION_HIBERNATE ||
1866 a == ACTION_HYBRID_SLEEP)) {
1867 r = reboot_with_logind(bus, a);
1872 r = start_unit(bus, args);
1873 if (r == EXIT_SUCCESS)
1879 static int check_unit_active(DBusConnection *bus, char **args) {
1880 const char * const check_states[] = {
1887 int r = 3; /* According to LSB: "program is not running" */
1892 STRV_FOREACH(name, args+1) {
1895 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1905 static int check_unit_failed(DBusConnection *bus, char **args) {
1906 const char * const check_states[] = {
1917 STRV_FOREACH(name, args+1) {
1920 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1930 static int kill_unit(DBusConnection *bus, char **args) {
1938 arg_kill_who = "all";
1940 STRV_FOREACH(name, args+1) {
1941 _cleanup_free_ char *n = NULL;
1943 n = unit_name_mangle(*name);
1947 r = bus_method_call_with_reply(
1949 "org.freedesktop.systemd1",
1950 "/org/freedesktop/systemd1",
1951 "org.freedesktop.systemd1.Manager",
1955 DBUS_TYPE_STRING, &n,
1956 DBUS_TYPE_STRING, &arg_kill_who,
1957 DBUS_TYPE_INT32, &arg_signal,
1965 static int set_cgroup(DBusConnection *bus, char **args) {
1966 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
1969 DBusMessageIter iter;
1971 _cleanup_free_ char *n = NULL;
1972 const char *runtime;
1977 dbus_error_init(&error);
1980 streq(args[0], "set-cgroup") ? "SetUnitControlGroups" :
1981 streq(args[0], "unset-group") ? "UnsetUnitControlGroups"
1982 : "UnsetUnitControlGroupAttributes";
1984 n = unit_name_mangle(args[1]);
1988 m = dbus_message_new_method_call(
1989 "org.freedesktop.systemd1",
1990 "/org/freedesktop/systemd1",
1991 "org.freedesktop.systemd1.Manager",
1996 dbus_message_iter_init_append(m, &iter);
1997 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
2000 r = bus_append_strv_iter(&iter, args + 2);
2004 runtime = arg_runtime ? "runtime" : "persistent";
2005 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2008 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2010 log_error("Failed to issue method call: %s", bus_error_message(&error));
2011 dbus_error_free(&error);
2018 static int set_cgroup_attr(DBusConnection *bus, char **args) {
2019 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2021 DBusMessageIter iter, sub, sub2;
2023 _cleanup_free_ char *n = NULL;
2024 const char *runtime;
2029 dbus_error_init(&error);
2031 if (strv_length(args) % 2 != 0) {
2032 log_error("Expecting an uneven number of arguments!");
2036 n = unit_name_mangle(args[1]);
2040 m = dbus_message_new_method_call(
2041 "org.freedesktop.systemd1",
2042 "/org/freedesktop/systemd1",
2043 "org.freedesktop.systemd1.Manager",
2044 "SetUnitControlGroupAttributes");
2048 dbus_message_iter_init_append(m, &iter);
2049 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2050 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub))
2053 STRV_FOREACH_PAIR(x, y, args + 2) {
2054 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
2055 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, x) ||
2056 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, y) ||
2057 !dbus_message_iter_close_container(&sub, &sub2))
2061 runtime = arg_runtime ? "runtime" : "persistent";
2062 if (!dbus_message_iter_close_container(&iter, &sub) ||
2063 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2066 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2068 log_error("Failed to issue method call: %s", bus_error_message(&error));
2069 dbus_error_free(&error);
2076 static int get_cgroup_attr(DBusConnection *bus, char **args) {
2077 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2079 DBusMessageIter iter;
2081 _cleanup_free_ char *n = NULL;
2082 _cleanup_strv_free_ char **list = NULL;
2088 dbus_error_init(&error);
2090 n = unit_name_mangle(args[1]);
2094 m = dbus_message_new_method_call(
2095 "org.freedesktop.systemd1",
2096 "/org/freedesktop/systemd1",
2097 "org.freedesktop.systemd1.Manager",
2098 "GetUnitControlGroupAttributes");
2102 dbus_message_iter_init_append(m, &iter);
2103 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
2106 r = bus_append_strv_iter(&iter, args + 2);
2110 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2112 log_error("Failed to issue method call: %s", bus_error_message(&error));
2113 dbus_error_free(&error);
2117 dbus_message_iter_init(reply, &iter);
2118 r = bus_parse_strv_iter(&iter, &list);
2120 log_error("Failed to parse value list.");
2124 STRV_FOREACH(a, list) {
2125 if (endswith(*a, "\n"))
2134 typedef struct ExecStatusInfo {
2142 usec_t start_timestamp;
2143 usec_t exit_timestamp;
2148 LIST_FIELDS(struct ExecStatusInfo, exec);
2151 static void exec_status_info_free(ExecStatusInfo *i) {
2160 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2161 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2162 DBusMessageIter sub2, sub3;
2166 int32_t code, status;
2172 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2175 dbus_message_iter_recurse(sub, &sub2);
2177 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2180 i->path = strdup(path);
2184 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2185 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2189 dbus_message_iter_recurse(&sub2, &sub3);
2190 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2191 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2192 dbus_message_iter_next(&sub3);
2196 i->argv = new0(char*, n+1);
2201 dbus_message_iter_recurse(&sub2, &sub3);
2202 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2205 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2206 dbus_message_iter_get_basic(&sub3, &s);
2207 dbus_message_iter_next(&sub3);
2209 i->argv[n] = strdup(s);
2216 if (!dbus_message_iter_next(&sub2) ||
2217 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2218 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2219 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2220 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2221 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2222 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2223 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2224 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2228 i->start_timestamp = (usec_t) start_timestamp;
2229 i->exit_timestamp = (usec_t) exit_timestamp;
2230 i->pid = (pid_t) pid;
2237 typedef struct UnitStatusInfo {
2239 const char *load_state;
2240 const char *active_state;
2241 const char *sub_state;
2242 const char *unit_file_state;
2244 const char *description;
2245 const char *following;
2247 char **documentation;
2249 const char *fragment_path;
2250 const char *source_path;
2251 const char *default_control_group;
2253 const char *load_error;
2256 usec_t inactive_exit_timestamp;
2257 usec_t inactive_exit_timestamp_monotonic;
2258 usec_t active_enter_timestamp;
2259 usec_t active_exit_timestamp;
2260 usec_t inactive_enter_timestamp;
2262 bool need_daemon_reload;
2267 const char *status_text;
2270 usec_t start_timestamp;
2271 usec_t exit_timestamp;
2273 int exit_code, exit_status;
2275 usec_t condition_timestamp;
2276 bool condition_result;
2279 unsigned n_accepted;
2280 unsigned n_connections;
2284 const char *sysfs_path;
2286 /* Mount, Automount */
2292 LIST_HEAD(ExecStatusInfo, exec);
2295 static void print_status_info(UnitStatusInfo *i) {
2297 const char *on, *off, *ss;
2299 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2300 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2303 arg_all * OUTPUT_SHOW_ALL |
2304 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2305 on_tty() * OUTPUT_COLOR |
2306 !arg_quiet * OUTPUT_WARN_CUTOFF |
2307 arg_full * OUTPUT_FULL_WIDTH;
2311 /* This shows pretty information about a unit. See
2312 * print_property() for a low-level property printer */
2314 printf("%s", strna(i->id));
2316 if (i->description && !streq_ptr(i->id, i->description))
2317 printf(" - %s", i->description);
2322 printf("\t Follow: unit currently follows state of %s\n", i->following);
2324 if (streq_ptr(i->load_state, "error")) {
2325 on = ansi_highlight_red(true);
2326 off = ansi_highlight_red(false);
2330 path = i->source_path ? i->source_path : i->fragment_path;
2333 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2334 else if (path && i->unit_file_state)
2335 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2337 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2339 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2341 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2343 if (streq_ptr(i->active_state, "failed")) {
2344 on = ansi_highlight_red(true);
2345 off = ansi_highlight_red(false);
2346 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2347 on = ansi_highlight_green(true);
2348 off = ansi_highlight_green(false);
2353 printf("\t Active: %s%s (%s)%s",
2355 strna(i->active_state),
2359 printf("\t Active: %s%s%s",
2361 strna(i->active_state),
2364 if (!isempty(i->result) && !streq(i->result, "success"))
2365 printf(" (Result: %s)", i->result);
2367 timestamp = (streq_ptr(i->active_state, "active") ||
2368 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2369 (streq_ptr(i->active_state, "inactive") ||
2370 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2371 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2372 i->active_exit_timestamp;
2374 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2375 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2378 printf(" since %s; %s\n", s2, s1);
2380 printf(" since %s\n", s2);
2384 if (!i->condition_result && i->condition_timestamp > 0) {
2385 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2386 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2389 printf("\t start condition failed at %s; %s\n", s2, s1);
2391 printf("\t start condition failed at %s\n", s2);
2395 printf("\t Device: %s\n", i->sysfs_path);
2397 printf("\t Where: %s\n", i->where);
2399 printf("\t What: %s\n", i->what);
2401 if (!strv_isempty(i->documentation)) {
2405 STRV_FOREACH(t, i->documentation) {
2407 printf("\t Docs: %s\n", *t);
2410 printf("\t %s\n", *t);
2415 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2417 LIST_FOREACH(exec, p, i->exec) {
2418 _cleanup_free_ char *t = NULL;
2421 /* Only show exited processes here */
2425 t = strv_join(p->argv, " ");
2426 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2428 good = is_clean_exit_lsb(p->code, p->status, NULL);
2430 on = ansi_highlight_red(true);
2431 off = ansi_highlight_red(false);
2435 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2437 if (p->code == CLD_EXITED) {
2440 printf("status=%i", p->status);
2442 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2447 printf("signal=%s", signal_to_string(p->status));
2449 printf(")%s\n", off);
2451 if (i->main_pid == p->pid &&
2452 i->start_timestamp == p->start_timestamp &&
2453 i->exit_timestamp == p->start_timestamp)
2454 /* Let's not show this twice */
2457 if (p->pid == i->control_pid)
2461 if (i->main_pid > 0 || i->control_pid > 0) {
2464 if (i->main_pid > 0) {
2465 printf("Main PID: %u", (unsigned) i->main_pid);
2468 _cleanup_free_ char *t = NULL;
2469 get_process_comm(i->main_pid, &t);
2472 } else if (i->exit_code > 0) {
2473 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2475 if (i->exit_code == CLD_EXITED) {
2478 printf("status=%i", i->exit_status);
2480 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2485 printf("signal=%s", signal_to_string(i->exit_status));
2490 if (i->main_pid > 0 && i->control_pid > 0)
2493 if (i->control_pid > 0) {
2494 _cleanup_free_ char *t = NULL;
2496 printf(" Control: %u", (unsigned) i->control_pid);
2498 get_process_comm(i->control_pid, &t);
2507 printf("\t Status: \"%s\"\n", i->status_text);
2509 if (i->default_control_group &&
2510 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2513 printf("\t CGroup: %s\n", i->default_control_group);
2515 if (arg_transport != TRANSPORT_SSH) {
2525 if (i->main_pid > 0)
2526 extra[k++] = i->main_pid;
2528 if (i->control_pid > 0)
2529 extra[k++] = i->control_pid;
2531 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, extra, k, flags);
2535 if (i->id && arg_transport != TRANSPORT_SSH) {
2537 if(arg_scope == UNIT_FILE_SYSTEM)
2538 show_journal_by_unit(stdout,
2542 i->inactive_exit_timestamp_monotonic,
2546 show_journal_by_user_unit(stdout,
2550 i->inactive_exit_timestamp_monotonic,
2556 if (i->need_daemon_reload)
2557 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2558 ansi_highlight_red(true),
2559 ansi_highlight_red(false),
2560 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2563 static void show_unit_help(UnitStatusInfo *i) {
2568 if (!i->documentation) {
2569 log_info("Documentation for %s not known.", i->id);
2573 STRV_FOREACH(p, i->documentation) {
2575 if (startswith(*p, "man:")) {
2578 char _cleanup_free_ *page = NULL, *section = NULL;
2579 const char *args[4] = { "man", NULL, NULL, NULL };
2584 if ((*p)[k-1] == ')')
2585 e = strrchr(*p, '(');
2588 page = strndup((*p) + 4, e - *p - 4);
2589 section = strndup(e + 1, *p + k - e - 2);
2590 if (!page || !section) {
2602 log_error("Failed to fork: %m");
2608 execvp(args[0], (char**) args);
2609 log_error("Failed to execute man: %m");
2610 _exit(EXIT_FAILURE);
2613 wait_for_terminate(pid, NULL);
2615 log_info("Can't show: %s", *p);
2619 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2625 switch (dbus_message_iter_get_arg_type(iter)) {
2627 case DBUS_TYPE_STRING: {
2630 dbus_message_iter_get_basic(iter, &s);
2633 if (streq(name, "Id"))
2635 else if (streq(name, "LoadState"))
2637 else if (streq(name, "ActiveState"))
2638 i->active_state = s;
2639 else if (streq(name, "SubState"))
2641 else if (streq(name, "Description"))
2643 else if (streq(name, "FragmentPath"))
2644 i->fragment_path = s;
2645 else if (streq(name, "SourcePath"))
2647 else if (streq(name, "DefaultControlGroup"))
2648 i->default_control_group = s;
2649 else if (streq(name, "StatusText"))
2651 else if (streq(name, "SysFSPath"))
2653 else if (streq(name, "Where"))
2655 else if (streq(name, "What"))
2657 else if (streq(name, "Following"))
2659 else if (streq(name, "UnitFileState"))
2660 i->unit_file_state = s;
2661 else if (streq(name, "Result"))
2668 case DBUS_TYPE_BOOLEAN: {
2671 dbus_message_iter_get_basic(iter, &b);
2673 if (streq(name, "Accept"))
2675 else if (streq(name, "NeedDaemonReload"))
2676 i->need_daemon_reload = b;
2677 else if (streq(name, "ConditionResult"))
2678 i->condition_result = b;
2683 case DBUS_TYPE_UINT32: {
2686 dbus_message_iter_get_basic(iter, &u);
2688 if (streq(name, "MainPID")) {
2690 i->main_pid = (pid_t) u;
2693 } else if (streq(name, "ControlPID"))
2694 i->control_pid = (pid_t) u;
2695 else if (streq(name, "ExecMainPID")) {
2697 i->main_pid = (pid_t) u;
2698 } else if (streq(name, "NAccepted"))
2700 else if (streq(name, "NConnections"))
2701 i->n_connections = u;
2706 case DBUS_TYPE_INT32: {
2709 dbus_message_iter_get_basic(iter, &j);
2711 if (streq(name, "ExecMainCode"))
2712 i->exit_code = (int) j;
2713 else if (streq(name, "ExecMainStatus"))
2714 i->exit_status = (int) j;
2719 case DBUS_TYPE_UINT64: {
2722 dbus_message_iter_get_basic(iter, &u);
2724 if (streq(name, "ExecMainStartTimestamp"))
2725 i->start_timestamp = (usec_t) u;
2726 else if (streq(name, "ExecMainExitTimestamp"))
2727 i->exit_timestamp = (usec_t) u;
2728 else if (streq(name, "ActiveEnterTimestamp"))
2729 i->active_enter_timestamp = (usec_t) u;
2730 else if (streq(name, "InactiveEnterTimestamp"))
2731 i->inactive_enter_timestamp = (usec_t) u;
2732 else if (streq(name, "InactiveExitTimestamp"))
2733 i->inactive_exit_timestamp = (usec_t) u;
2734 else if (streq(name, "InactiveExitTimestampMonotonic"))
2735 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2736 else if (streq(name, "ActiveExitTimestamp"))
2737 i->active_exit_timestamp = (usec_t) u;
2738 else if (streq(name, "ConditionTimestamp"))
2739 i->condition_timestamp = (usec_t) u;
2744 case DBUS_TYPE_ARRAY: {
2746 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2747 startswith(name, "Exec")) {
2748 DBusMessageIter sub;
2750 dbus_message_iter_recurse(iter, &sub);
2751 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2752 ExecStatusInfo *info;
2755 if (!(info = new0(ExecStatusInfo, 1)))
2758 if (!(info->name = strdup(name))) {
2763 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2768 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2770 dbus_message_iter_next(&sub);
2772 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2773 streq(name, "Documentation")) {
2775 DBusMessageIter sub;
2777 dbus_message_iter_recurse(iter, &sub);
2778 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2782 dbus_message_iter_get_basic(&sub, &s);
2784 l = strv_append(i->documentation, s);
2788 strv_free(i->documentation);
2789 i->documentation = l;
2791 dbus_message_iter_next(&sub);
2798 case DBUS_TYPE_STRUCT: {
2800 if (streq(name, "LoadError")) {
2801 DBusMessageIter sub;
2802 const char *n, *message;
2805 dbus_message_iter_recurse(iter, &sub);
2807 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2811 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2815 if (!isempty(message))
2816 i->load_error = message;
2826 static int print_property(const char *name, DBusMessageIter *iter) {
2830 /* This is a low-level property printer, see
2831 * print_status_info() for the nicer output */
2833 if (arg_property && !strv_find(arg_property, name))
2836 switch (dbus_message_iter_get_arg_type(iter)) {
2838 case DBUS_TYPE_STRUCT: {
2839 DBusMessageIter sub;
2840 dbus_message_iter_recurse(iter, &sub);
2842 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2845 dbus_message_iter_get_basic(&sub, &u);
2848 printf("%s=%u\n", name, (unsigned) u);
2850 printf("%s=\n", name);
2853 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2856 dbus_message_iter_get_basic(&sub, &s);
2858 if (arg_all || s[0])
2859 printf("%s=%s\n", name, s);
2862 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2863 const char *a = NULL, *b = NULL;
2865 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2866 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2868 if (arg_all || !isempty(a) || !isempty(b))
2869 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2877 case DBUS_TYPE_ARRAY:
2879 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2880 DBusMessageIter sub, sub2;
2882 dbus_message_iter_recurse(iter, &sub);
2883 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2887 dbus_message_iter_recurse(&sub, &sub2);
2889 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2890 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2891 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2893 dbus_message_iter_next(&sub);
2898 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2899 DBusMessageIter sub, sub2;
2901 dbus_message_iter_recurse(iter, &sub);
2902 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2903 const char *type, *path;
2905 dbus_message_iter_recurse(&sub, &sub2);
2907 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2908 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2909 printf("%s=%s\n", type, path);
2911 dbus_message_iter_next(&sub);
2916 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2917 DBusMessageIter sub, sub2;
2919 dbus_message_iter_recurse(iter, &sub);
2920 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2922 uint64_t value, next_elapse;
2924 dbus_message_iter_recurse(&sub, &sub2);
2926 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2927 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2928 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2929 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2931 printf("%s={ value=%s ; next_elapse=%s }\n",
2933 format_timespan(timespan1, sizeof(timespan1), value),
2934 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2937 dbus_message_iter_next(&sub);
2942 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2943 DBusMessageIter sub, sub2;
2945 dbus_message_iter_recurse(iter, &sub);
2946 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2947 const char *controller, *attr, *value;
2949 dbus_message_iter_recurse(&sub, &sub2);
2951 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2952 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2953 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2955 printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2961 dbus_message_iter_next(&sub);
2966 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2967 DBusMessageIter sub;
2969 dbus_message_iter_recurse(iter, &sub);
2970 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2971 ExecStatusInfo info;
2974 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2975 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2976 char _cleanup_free_ *t;
2978 t = strv_join(info.argv, " ");
2980 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2984 yes_no(info.ignore),
2985 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2986 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2987 (unsigned) info. pid,
2988 sigchld_code_to_string(info.code),
2990 info.code == CLD_EXITED ? "" : "/",
2991 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2995 strv_free(info.argv);
2997 dbus_message_iter_next(&sub);
3006 if (generic_print_property(name, iter, arg_all) > 0)
3010 printf("%s=[unprintable]\n", name);
3015 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3016 _cleanup_free_ DBusMessage *reply = NULL;
3017 const char *interface = "";
3019 DBusMessageIter iter, sub, sub2, sub3;
3020 UnitStatusInfo info;
3028 r = bus_method_call_with_reply(
3030 "org.freedesktop.systemd1",
3032 "org.freedesktop.DBus.Properties",
3036 DBUS_TYPE_STRING, &interface,
3041 if (!dbus_message_iter_init(reply, &iter) ||
3042 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3043 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3044 log_error("Failed to parse reply.");
3048 dbus_message_iter_recurse(&iter, &sub);
3055 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3058 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3059 dbus_message_iter_recurse(&sub, &sub2);
3061 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3062 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3063 log_error("Failed to parse reply.");
3067 dbus_message_iter_recurse(&sub2, &sub3);
3069 if (show_properties)
3070 r = print_property(name, &sub3);
3072 r = status_property(name, &sub3, &info);
3074 log_error("Failed to parse reply.");
3078 dbus_message_iter_next(&sub);
3083 if (!show_properties) {
3084 if (streq(verb, "help"))
3085 show_unit_help(&info);
3087 print_status_info(&info);
3090 strv_free(info.documentation);
3092 if (!streq_ptr(info.active_state, "active") &&
3093 !streq_ptr(info.active_state, "reloading") &&
3094 streq(verb, "status"))
3095 /* According to LSB: "program not running" */
3098 while ((p = info.exec)) {
3099 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3100 exec_status_info_free(p);
3106 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3107 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3108 const char *path = NULL;
3109 DBusError _cleanup_dbus_error_free_ error;
3112 dbus_error_init(&error);
3114 r = bus_method_call_with_reply(
3116 "org.freedesktop.systemd1",
3117 "/org/freedesktop/systemd1",
3118 "org.freedesktop.systemd1.Manager",
3122 DBUS_TYPE_UINT32, &pid,
3127 if (!dbus_message_get_args(reply, &error,
3128 DBUS_TYPE_OBJECT_PATH, &path,
3129 DBUS_TYPE_INVALID)) {
3130 log_error("Failed to parse reply: %s", bus_error_message(&error));
3134 r = show_one(verb, bus, path, false, new_line);
3138 static int show_all(const char* verb, DBusConnection *bus, bool show_properties, bool *new_line) {
3139 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3140 _cleanup_free_ struct unit_info *unit_infos = NULL;
3142 const struct unit_info *u;
3145 r = get_unit_list(bus, &reply, &unit_infos, &c);
3149 for (u = unit_infos; u < unit_infos + c; u++) {
3150 char _cleanup_free_ *p = NULL;
3152 if (!output_show_unit(u))
3155 p = unit_dbus_path_from_name(u->id);
3159 printf("%s -> '%s'\n", u->id, p);
3161 r = show_one(verb, bus, p, show_properties, new_line);
3169 static int show(DBusConnection *bus, char **args) {
3171 bool show_properties, show_status, new_line = false;
3177 show_properties = streq(args[0], "show");
3178 show_status = streq(args[0], "status");
3180 if (show_properties)
3181 pager_open_if_enabled();
3183 /* If no argument is specified inspect the manager itself */
3185 if (show_properties && strv_length(args) <= 1)
3186 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3188 if (show_status && strv_length(args) <= 1)
3189 return show_all(args[0], bus, false, &new_line);
3191 STRV_FOREACH(name, args+1) {
3194 if (safe_atou32(*name, &id) < 0) {
3195 _cleanup_free_ char *p = NULL, *n = NULL;
3196 /* Interpret as unit name */
3198 n = unit_name_mangle(*name);
3202 p = unit_dbus_path_from_name(n);
3206 r = show_one(args[0], bus, p, show_properties, &new_line);
3210 } else if (show_properties) {
3211 _cleanup_free_ char *p = NULL;
3213 /* Interpret as job id */
3214 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3217 r = show_one(args[0], bus, p, show_properties, &new_line);
3222 /* Interpret as PID */
3223 r = show_one_by_pid(args[0], bus, id, &new_line);
3232 static int dump(DBusConnection *bus, char **args) {
3233 _cleanup_free_ DBusMessage *reply = NULL;
3238 dbus_error_init(&error);
3240 pager_open_if_enabled();
3242 r = bus_method_call_with_reply(
3244 "org.freedesktop.systemd1",
3245 "/org/freedesktop/systemd1",
3246 "org.freedesktop.systemd1.Manager",
3254 if (!dbus_message_get_args(reply, &error,
3255 DBUS_TYPE_STRING, &text,
3256 DBUS_TYPE_INVALID)) {
3257 log_error("Failed to parse reply: %s", bus_error_message(&error));
3258 dbus_error_free(&error);
3262 fputs(text, stdout);
3266 static int snapshot(DBusConnection *bus, char **args) {
3267 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3270 dbus_bool_t cleanup = FALSE;
3271 DBusMessageIter iter, sub;
3274 *interface = "org.freedesktop.systemd1.Unit",
3276 _cleanup_free_ char *n = NULL;
3278 dbus_error_init(&error);
3280 if (strv_length(args) > 1)
3281 n = snapshot_name_mangle(args[1]);
3287 r = bus_method_call_with_reply (
3289 "org.freedesktop.systemd1",
3290 "/org/freedesktop/systemd1",
3291 "org.freedesktop.systemd1.Manager",
3295 DBUS_TYPE_STRING, &n,
3296 DBUS_TYPE_BOOLEAN, &cleanup,
3301 if (!dbus_message_get_args(reply, &error,
3302 DBUS_TYPE_OBJECT_PATH, &path,
3303 DBUS_TYPE_INVALID)) {
3304 log_error("Failed to parse reply: %s", bus_error_message(&error));
3305 dbus_error_free(&error);
3309 dbus_message_unref(reply);
3312 r = bus_method_call_with_reply (
3314 "org.freedesktop.systemd1",
3316 "org.freedesktop.DBus.Properties",
3320 DBUS_TYPE_STRING, &interface,
3321 DBUS_TYPE_STRING, &property,
3326 if (!dbus_message_iter_init(reply, &iter) ||
3327 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3328 log_error("Failed to parse reply.");
3332 dbus_message_iter_recurse(&iter, &sub);
3334 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3335 log_error("Failed to parse reply.");
3339 dbus_message_iter_get_basic(&sub, &id);
3347 static int delete_snapshot(DBusConnection *bus, char **args) {
3352 STRV_FOREACH(name, args+1) {
3353 _cleanup_free_ char *n = NULL;
3356 n = snapshot_name_mangle(*name);
3360 r = bus_method_call_with_reply(
3362 "org.freedesktop.systemd1",
3363 "/org/freedesktop/systemd1",
3364 "org.freedesktop.systemd1.Manager",
3368 DBUS_TYPE_STRING, &n,
3377 static int daemon_reload(DBusConnection *bus, char **args) {
3382 if (arg_action == ACTION_RELOAD)
3384 else if (arg_action == ACTION_REEXEC)
3385 method = "Reexecute";
3387 assert(arg_action == ACTION_SYSTEMCTL);
3390 streq(args[0], "clear-jobs") ||
3391 streq(args[0], "cancel") ? "ClearJobs" :
3392 streq(args[0], "daemon-reexec") ? "Reexecute" :
3393 streq(args[0], "reset-failed") ? "ResetFailed" :
3394 streq(args[0], "halt") ? "Halt" :
3395 streq(args[0], "poweroff") ? "PowerOff" :
3396 streq(args[0], "reboot") ? "Reboot" :
3397 streq(args[0], "kexec") ? "KExec" :
3398 streq(args[0], "exit") ? "Exit" :
3399 /* "daemon-reload" */ "Reload";
3402 r = bus_method_call_with_reply(
3404 "org.freedesktop.systemd1",
3405 "/org/freedesktop/systemd1",
3406 "org.freedesktop.systemd1.Manager",
3412 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3413 /* There's always a fallback possible for
3414 * legacy actions. */
3416 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3417 /* On reexecution, we expect a disconnect, not
3421 log_error("Failed to issue method call: %s", bus_error_message(&error));
3423 dbus_error_free(&error);
3427 static int reset_failed(DBusConnection *bus, char **args) {
3431 if (strv_length(args) <= 1)
3432 return daemon_reload(bus, args);
3434 STRV_FOREACH(name, args+1) {
3435 _cleanup_free_ char *n;
3437 n = unit_name_mangle(*name);
3441 r = bus_method_call_with_reply(
3443 "org.freedesktop.systemd1",
3444 "/org/freedesktop/systemd1",
3445 "org.freedesktop.systemd1.Manager",
3449 DBUS_TYPE_STRING, &n,
3458 static int show_enviroment(DBusConnection *bus, char **args) {
3459 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3460 DBusMessageIter iter, sub, sub2;
3463 *interface = "org.freedesktop.systemd1.Manager",
3464 *property = "Environment";
3466 pager_open_if_enabled();
3468 r = bus_method_call_with_reply(
3470 "org.freedesktop.systemd1",
3471 "/org/freedesktop/systemd1",
3472 "org.freedesktop.DBus.Properties",
3476 DBUS_TYPE_STRING, &interface,
3477 DBUS_TYPE_STRING, &property,
3482 if (!dbus_message_iter_init(reply, &iter) ||
3483 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3484 log_error("Failed to parse reply.");
3488 dbus_message_iter_recurse(&iter, &sub);
3490 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3491 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3492 log_error("Failed to parse reply.");
3496 dbus_message_iter_recurse(&sub, &sub2);
3498 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3501 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3502 log_error("Failed to parse reply.");
3506 dbus_message_iter_get_basic(&sub2, &text);
3509 dbus_message_iter_next(&sub2);
3515 static int switch_root(DBusConnection *bus, char **args) {
3518 _cleanup_free_ char *init = NULL;
3520 l = strv_length(args);
3521 if (l < 2 || l > 3) {
3522 log_error("Wrong number of arguments.");
3529 init = strdup(args[2]);
3531 parse_env_file("/proc/cmdline", WHITESPACE,
3541 log_debug("switching root - root: %s; init: %s", root, init);
3543 return bus_method_call_with_reply(
3545 "org.freedesktop.systemd1",
3546 "/org/freedesktop/systemd1",
3547 "org.freedesktop.systemd1.Manager",
3551 DBUS_TYPE_STRING, &root,
3552 DBUS_TYPE_STRING, &init,
3556 static int set_environment(DBusConnection *bus, char **args) {
3557 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3560 DBusMessageIter iter;
3566 dbus_error_init(&error);
3568 method = streq(args[0], "set-environment")
3570 : "UnsetEnvironment";
3572 m = dbus_message_new_method_call(
3573 "org.freedesktop.systemd1",
3574 "/org/freedesktop/systemd1",
3575 "org.freedesktop.systemd1.Manager",
3580 dbus_message_iter_init_append(m, &iter);
3582 r = bus_append_strv_iter(&iter, args + 1);
3586 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3588 log_error("Failed to issue method call: %s", bus_error_message(&error));
3589 dbus_error_free(&error);
3596 static int enable_sysv_units(char **args) {
3599 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3600 const char *verb = args[0];
3601 unsigned f = 1, t = 1;
3604 if (arg_scope != UNIT_FILE_SYSTEM)
3607 if (!streq(verb, "enable") &&
3608 !streq(verb, "disable") &&
3609 !streq(verb, "is-enabled"))
3612 /* Processes all SysV units, and reshuffles the array so that
3613 * afterwards only the native units remain */
3616 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3621 for (f = 1; args[f]; f++) {
3624 bool found_native = false, found_sysv;
3626 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3627 char **k, *l, *q = NULL;
3634 if (!endswith(name, ".service"))
3637 if (path_is_absolute(name))
3640 STRV_FOREACH(k, paths.unit_path) {
3643 if (!isempty(arg_root))
3644 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3646 asprintf(&p, "%s/%s", *k, name);
3653 found_native = access(p, F_OK) >= 0;
3664 if (!isempty(arg_root))
3665 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3667 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3673 p[strlen(p) - sizeof(".service") + 1] = 0;
3674 found_sysv = access(p, F_OK) >= 0;
3681 /* Mark this entry, so that we don't try enabling it as native unit */
3682 args[f] = (char*) "";
3684 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3686 if (!isempty(arg_root))
3687 argv[c++] = q = strappend("--root=", arg_root);
3689 argv[c++] = path_get_file_name(p);
3691 streq(verb, "enable") ? "on" :
3692 streq(verb, "disable") ? "off" : "--level=5";
3695 l = strv_join((char**)argv, " ");
3703 log_info("Executing %s", l);
3708 log_error("Failed to fork: %m");
3713 } else if (pid == 0) {
3716 execv(argv[0], (char**) argv);
3717 _exit(EXIT_FAILURE);
3723 j = wait_for_terminate(pid, &status);
3725 log_error("Failed to wait for child: %s", strerror(-r));
3730 if (status.si_code == CLD_EXITED) {
3731 if (streq(verb, "is-enabled")) {
3732 if (status.si_status == 0) {
3741 } else if (status.si_status != 0) {
3752 lookup_paths_free(&paths);
3754 /* Drop all SysV units */
3755 for (f = 1, t = 1; args[f]; f++) {
3757 if (isempty(args[f]))
3760 args[t++] = args[f];
3769 static int mangle_names(char **original_names, char ***mangled_names) {
3770 char **i, **l, **name;
3772 l = new(char*, strv_length(original_names) + 1);
3777 STRV_FOREACH(name, original_names) {
3779 /* When enabling units qualified path names are OK,
3780 * too, hence allow them explicitly. */
3785 *i = unit_name_mangle(*name);
3801 static int enable_unit(DBusConnection *bus, char **args) {
3802 const char *verb = args[0];
3803 UnitFileChange *changes = NULL;
3804 unsigned n_changes = 0, i;
3805 int carries_install_info = -1;
3806 DBusMessage _cleanup_dbus_message_unref_ *m = NULL, *reply = NULL;
3808 DBusError _cleanup_dbus_error_free_ error;
3809 char _cleanup_strv_free_ **mangled_names = NULL;
3811 dbus_error_init(&error);
3813 r = enable_sysv_units(args);
3820 if (!bus || avoid_bus()) {
3821 if (streq(verb, "enable")) {
3822 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3823 carries_install_info = r;
3824 } else if (streq(verb, "disable"))
3825 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3826 else if (streq(verb, "reenable")) {
3827 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3828 carries_install_info = r;
3829 } else if (streq(verb, "link"))
3830 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3831 else if (streq(verb, "preset")) {
3832 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3833 carries_install_info = r;
3834 } else if (streq(verb, "mask"))
3835 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3836 else if (streq(verb, "unmask"))
3837 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3839 assert_not_reached("Unknown verb");
3842 log_error("Operation failed: %s", strerror(-r));
3847 for (i = 0; i < n_changes; i++) {
3848 if (changes[i].type == UNIT_FILE_SYMLINK)
3849 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3851 log_info("rm '%s'", changes[i].path);
3858 bool send_force = true, expect_carries_install_info = false;
3860 DBusMessageIter iter, sub, sub2;
3862 if (streq(verb, "enable")) {
3863 method = "EnableUnitFiles";
3864 expect_carries_install_info = true;
3865 } else if (streq(verb, "disable")) {
3866 method = "DisableUnitFiles";
3868 } else if (streq(verb, "reenable")) {
3869 method = "ReenableUnitFiles";
3870 expect_carries_install_info = true;
3871 } else if (streq(verb, "link"))
3872 method = "LinkUnitFiles";
3873 else if (streq(verb, "preset")) {
3874 method = "PresetUnitFiles";
3875 expect_carries_install_info = true;
3876 } else if (streq(verb, "mask"))
3877 method = "MaskUnitFiles";
3878 else if (streq(verb, "unmask")) {
3879 method = "UnmaskUnitFiles";
3882 assert_not_reached("Unknown verb");
3884 m = dbus_message_new_method_call(
3885 "org.freedesktop.systemd1",
3886 "/org/freedesktop/systemd1",
3887 "org.freedesktop.systemd1.Manager",
3894 dbus_message_iter_init_append(m, &iter);
3896 r = mangle_names(args+1, &mangled_names);
3900 r = bus_append_strv_iter(&iter, mangled_names);
3902 log_error("Failed to append unit files.");
3907 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3908 log_error("Failed to append runtime boolean.");
3916 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3917 log_error("Failed to append force boolean.");
3923 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3925 log_error("Failed to issue method call: %s", bus_error_message(&error));
3930 if (!dbus_message_iter_init(reply, &iter)) {
3931 log_error("Failed to initialize iterator.");
3935 if (expect_carries_install_info) {
3936 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3938 log_error("Failed to parse reply.");
3942 carries_install_info = b;
3945 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3946 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3947 log_error("Failed to parse reply.");
3952 dbus_message_iter_recurse(&iter, &sub);
3953 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3954 const char *type, *path, *source;
3956 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3957 log_error("Failed to parse reply.");
3962 dbus_message_iter_recurse(&sub, &sub2);
3964 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3965 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3966 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3967 log_error("Failed to parse reply.");
3973 if (streq(type, "symlink"))
3974 log_info("ln -s '%s' '%s'", source, path);
3976 log_info("rm '%s'", path);
3979 dbus_message_iter_next(&sub);
3982 /* Try to reload if enabeld */
3984 r = daemon_reload(bus, args);
3987 if (carries_install_info == 0)
3988 log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
3989 "using systemctl.\n"
3990 "Possible reasons for having this kind of units are:\n"
3991 "1) A unit may be statically enabled by being symlinked from another unit's\n"
3992 " .wants/ or .requires/ directory.\n"
3993 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
3994 " a requirement dependency on it.\n"
3995 "3) A unit may be started when needed via activation (socket, path, timer,\n"
3996 " D-Bus, udev, scripted systemctl call, ...).\n");
3999 unit_file_changes_free(changes, n_changes);
4004 static int unit_is_enabled(DBusConnection *bus, char **args) {
4005 DBusError _cleanup_dbus_error_free_ error;
4007 DBusMessage _cleanup_dbus_message_unref_ *reply = NULL;
4011 dbus_error_init(&error);
4013 r = enable_sysv_units(args);
4019 if (!bus || avoid_bus()) {
4021 STRV_FOREACH(name, args+1) {
4022 UnitFileState state;
4024 state = unit_file_get_state(arg_scope, arg_root, *name);
4028 if (state == UNIT_FILE_ENABLED ||
4029 state == UNIT_FILE_ENABLED_RUNTIME ||
4030 state == UNIT_FILE_STATIC)
4034 puts(unit_file_state_to_string(state));
4038 STRV_FOREACH(name, args+1) {
4041 r = bus_method_call_with_reply (
4043 "org.freedesktop.systemd1",
4044 "/org/freedesktop/systemd1",
4045 "org.freedesktop.systemd1.Manager",
4049 DBUS_TYPE_STRING, name,
4054 if (!dbus_message_get_args(reply, &error,
4055 DBUS_TYPE_STRING, &s,
4056 DBUS_TYPE_INVALID)) {
4057 log_error("Failed to parse reply: %s", bus_error_message(&error));
4061 dbus_message_unref(reply);
4064 if (streq(s, "enabled") ||
4065 streq(s, "enabled-runtime") ||
4074 return enabled ? 0 : 1;
4077 static int systemctl_help(void) {
4079 pager_open_if_enabled();
4081 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4082 "Query or send control commands to the systemd manager.\n\n"
4083 " -h --help Show this help\n"
4084 " --version Show package version\n"
4085 " -t --type=TYPE List only units of a particular type\n"
4086 " -p --property=NAME Show only properties by this name\n"
4087 " -a --all Show all units/properties, including dead/empty ones\n"
4088 " --failed Show only failed units\n"
4089 " --full Don't ellipsize unit names on output\n"
4090 " --fail When queueing a new job, fail if conflicting jobs are\n"
4092 " --ignore-dependencies\n"
4093 " When queueing a new job, ignore all its dependencies\n"
4094 " -i --ignore-inhibitors\n"
4095 " When shutting down or sleeping, ignore inhibitors\n"
4096 " --kill-who=WHO Who to send signal to\n"
4097 " -s --signal=SIGNAL Which signal to send\n"
4098 " -H --host=[USER@]HOST\n"
4099 " Show information for remote host\n"
4100 " -P --privileged Acquire privileges before execution\n"
4101 " -q --quiet Suppress output\n"
4102 " --no-block Do not wait until operation finished\n"
4103 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4104 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4106 " --no-legend Do not print a legend (column headers and hints)\n"
4107 " --no-pager Do not pipe output into a pager\n"
4108 " --no-ask-password\n"
4109 " Do not ask for system passwords\n"
4110 " --system Connect to system manager\n"
4111 " --user Connect to user service manager\n"
4112 " --global Enable/disable unit files globally\n"
4113 " -f --force When enabling unit files, override existing symlinks\n"
4114 " When shutting down, execute action immediately\n"
4115 " --root=PATH Enable unit files in the specified root directory\n"
4116 " --runtime Enable unit files only temporarily until next reboot\n"
4117 " -n --lines=INTEGER Journal entries to show\n"
4118 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4119 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4121 " list-units List loaded units\n"
4122 " start [NAME...] Start (activate) one or more units\n"
4123 " stop [NAME...] Stop (deactivate) one or more units\n"
4124 " reload [NAME...] Reload one or more units\n"
4125 " restart [NAME...] Start or restart one or more units\n"
4126 " try-restart [NAME...] Restart one or more units if active\n"
4127 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4128 " otherwise start or restart\n"
4129 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4130 " otherwise restart if active\n"
4131 " isolate [NAME] Start one unit and stop all others\n"
4132 " kill [NAME...] Send signal to processes of a unit\n"
4133 " is-active [NAME...] Check whether units are active\n"
4134 " is-failed [NAME...] Check whether units are failed\n"
4135 " status [NAME...|PID...] Show runtime status of one or more units\n"
4136 " show [NAME...|JOB...] Show properties of one or more\n"
4137 " units/jobs or the manager\n"
4138 " help [NAME...|PID...] Show manual for one or more units\n"
4139 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4141 " get-cgroup-attr [NAME] [ATTR] ...\n"
4142 " Get control group attrubute\n"
4143 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4144 " Set control group attribute\n"
4145 " unset-cgroup-attr [NAME] [ATTR...]\n"
4146 " Unset control group attribute\n"
4147 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4148 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4149 " load [NAME...] Load one or more units\n"
4150 " list-dependencies [NAME] Recursively show units which are required\n"
4151 " or wanted by this unit\n\n"
4152 "Unit File Commands:\n"
4153 " list-unit-files List installed unit files\n"
4154 " enable [NAME...] Enable one or more unit files\n"
4155 " disable [NAME...] Disable one or more unit files\n"
4156 " reenable [NAME...] Reenable one or more unit files\n"
4157 " preset [NAME...] Enable/disable one or more unit files\n"
4158 " based on preset configuration\n"
4159 " mask [NAME...] Mask one or more units\n"
4160 " unmask [NAME...] Unmask one or more units\n"
4161 " link [PATH...] Link one or more units files into\n"
4162 " the search path\n"
4163 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4165 " list-jobs List jobs\n"
4166 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4167 "Status Commands:\n"
4168 " dump Dump server status\n"
4169 "Snapshot Commands:\n"
4170 " snapshot [NAME] Create a snapshot\n"
4171 " delete [NAME...] Remove one or more snapshots\n\n"
4172 "Environment Commands:\n"
4173 " show-environment Dump environment\n"
4174 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4175 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4176 "Manager Lifecycle Commands:\n"
4177 " daemon-reload Reload systemd manager configuration\n"
4178 " daemon-reexec Reexecute systemd manager\n\n"
4179 "System Commands:\n"
4180 " default Enter system default mode\n"
4181 " rescue Enter system rescue mode\n"
4182 " emergency Enter system emergency mode\n"
4183 " halt Shut down and halt the system\n"
4184 " poweroff Shut down and power-off the system\n"
4185 " reboot Shut down and reboot the system\n"
4186 " kexec Shut down and reboot the system with kexec\n"
4187 " exit Request user instance exit\n"
4188 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4189 " suspend Suspend the system\n"
4190 " hibernate Hibernate the system\n"
4191 " hybrid-sleep Hibernate and suspend the system\n",
4192 program_invocation_short_name);
4197 static int halt_help(void) {
4199 printf("%s [OPTIONS...]\n\n"
4200 "%s the system.\n\n"
4201 " --help Show this help\n"
4202 " --halt Halt the machine\n"
4203 " -p --poweroff Switch off the machine\n"
4204 " --reboot Reboot the machine\n"
4205 " -f --force Force immediate halt/power-off/reboot\n"
4206 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4207 " -d --no-wtmp Don't write wtmp record\n"
4208 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4209 program_invocation_short_name,
4210 arg_action == ACTION_REBOOT ? "Reboot" :
4211 arg_action == ACTION_POWEROFF ? "Power off" :
4217 static int shutdown_help(void) {
4219 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4220 "Shut down the system.\n\n"
4221 " --help Show this help\n"
4222 " -H --halt Halt the machine\n"
4223 " -P --poweroff Power-off the machine\n"
4224 " -r --reboot Reboot the machine\n"
4225 " -h Equivalent to --poweroff, overridden by --halt\n"
4226 " -k Don't halt/power-off/reboot, just send warnings\n"
4227 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4228 " -c Cancel a pending shutdown\n",
4229 program_invocation_short_name);
4234 static int telinit_help(void) {
4236 printf("%s [OPTIONS...] {COMMAND}\n\n"
4237 "Send control commands to the init daemon.\n\n"
4238 " --help Show this help\n"
4239 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4241 " 0 Power-off the machine\n"
4242 " 6 Reboot the machine\n"
4243 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4244 " 1, s, S Enter rescue mode\n"
4245 " q, Q Reload init daemon configuration\n"
4246 " u, U Reexecute init daemon\n",
4247 program_invocation_short_name);
4252 static int runlevel_help(void) {
4254 printf("%s [OPTIONS...]\n\n"
4255 "Prints the previous and current runlevel of the init system.\n\n"
4256 " --help Show this help\n",
4257 program_invocation_short_name);
4262 static int help_types(void) {
4265 puts("Available unit types:");
4266 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4267 if (unit_type_table[i])
4268 puts(unit_type_table[i]);
4270 puts("\nAvailable unit load states: ");
4271 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4272 if (unit_type_table[i])
4273 puts(unit_load_state_table[i]);
4278 static int systemctl_parse_argv(int argc, char *argv[]) {
4283 ARG_IGNORE_DEPENDENCIES,
4296 ARG_NO_ASK_PASSWORD,
4302 static const struct option options[] = {
4303 { "help", no_argument, NULL, 'h' },
4304 { "version", no_argument, NULL, ARG_VERSION },
4305 { "type", required_argument, NULL, 't' },
4306 { "property", required_argument, NULL, 'p' },
4307 { "all", no_argument, NULL, 'a' },
4308 { "failed", no_argument, NULL, ARG_FAILED },
4309 { "full", no_argument, NULL, ARG_FULL },
4310 { "fail", no_argument, NULL, ARG_FAIL },
4311 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4312 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4313 { "ignore-inhibitors", no_argument, NULL, 'i' },
4314 { "user", no_argument, NULL, ARG_USER },
4315 { "system", no_argument, NULL, ARG_SYSTEM },
4316 { "global", no_argument, NULL, ARG_GLOBAL },
4317 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4318 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4319 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4320 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4321 { "quiet", no_argument, NULL, 'q' },
4322 { "root", required_argument, NULL, ARG_ROOT },
4323 { "force", no_argument, NULL, ARG_FORCE },
4324 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4325 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4326 { "signal", required_argument, NULL, 's' },
4327 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4328 { "host", required_argument, NULL, 'H' },
4329 { "privileged",no_argument, NULL, 'P' },
4330 { "runtime", no_argument, NULL, ARG_RUNTIME },
4331 { "lines", required_argument, NULL, 'n' },
4332 { "output", required_argument, NULL, 'o' },
4333 { NULL, 0, NULL, 0 }
4341 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4350 puts(PACKAGE_STRING);
4351 puts(SYSTEMD_FEATURES);
4355 if (streq(optarg, "help")) {
4360 if (unit_type_from_string(optarg) >= 0) {
4364 if (unit_load_state_from_string(optarg) >= 0) {
4365 arg_load_state = optarg;
4368 log_error("Unkown unit type or load state '%s'.",
4370 log_info("Use -t help to see a list of allowed values.");
4375 /* Make sure that if the empty property list
4376 was specified, we won't show any properties. */
4377 const char *source = isempty(optarg) ? " " : optarg;
4379 FOREACH_WORD_SEPARATOR(word, size, source, ",", state) {
4380 char _cleanup_free_ *prop;
4383 prop = strndup(word, size);
4387 tmp = strv_append(arg_property, prop);
4391 strv_free(arg_property);
4395 /* If the user asked for a particular
4396 * property, show it to him, even if it is
4408 arg_job_mode = "fail";
4411 case ARG_IRREVERSIBLE:
4412 arg_job_mode = "replace-irreversibly";
4415 case ARG_IGNORE_DEPENDENCIES:
4416 arg_job_mode = "ignore-dependencies";
4420 arg_scope = UNIT_FILE_USER;
4424 arg_scope = UNIT_FILE_SYSTEM;
4428 arg_scope = UNIT_FILE_GLOBAL;
4432 arg_no_block = true;
4436 arg_no_legend = true;
4440 arg_no_pager = true;
4472 arg_no_reload = true;
4476 arg_kill_who = optarg;
4480 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4481 log_error("Failed to parse signal string %s.", optarg);
4486 case ARG_NO_ASK_PASSWORD:
4487 arg_ask_password = false;
4491 arg_transport = TRANSPORT_POLKIT;
4495 arg_transport = TRANSPORT_SSH;
4504 if (safe_atou(optarg, &arg_lines) < 0) {
4505 log_error("Failed to parse lines '%s'", optarg);
4511 arg_output = output_mode_from_string(optarg);
4512 if (arg_output < 0) {
4513 log_error("Unknown output '%s'.", optarg);
4519 arg_ignore_inhibitors = true;
4526 log_error("Unknown option code '%c'.", c);
4531 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4532 log_error("Cannot access user instance remotely.");
4539 static int halt_parse_argv(int argc, char *argv[]) {
4548 static const struct option options[] = {
4549 { "help", no_argument, NULL, ARG_HELP },
4550 { "halt", no_argument, NULL, ARG_HALT },
4551 { "poweroff", no_argument, NULL, 'p' },
4552 { "reboot", no_argument, NULL, ARG_REBOOT },
4553 { "force", no_argument, NULL, 'f' },
4554 { "wtmp-only", no_argument, NULL, 'w' },
4555 { "no-wtmp", no_argument, NULL, 'd' },
4556 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4557 { NULL, 0, NULL, 0 }
4565 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4566 if (runlevel == '0' || runlevel == '6')
4569 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4577 arg_action = ACTION_HALT;
4581 if (arg_action != ACTION_REBOOT)
4582 arg_action = ACTION_POWEROFF;
4586 arg_action = ACTION_REBOOT;
4608 /* Compatibility nops */
4615 log_error("Unknown option code '%c'.", c);
4620 if (optind < argc) {
4621 log_error("Too many arguments.");
4628 static int parse_time_spec(const char *t, usec_t *_u) {
4632 if (streq(t, "now"))
4634 else if (!strchr(t, ':')) {
4637 if (safe_atou64(t, &u) < 0)
4640 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4649 hour = strtol(t, &e, 10);
4650 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4653 minute = strtol(e+1, &e, 10);
4654 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4657 n = now(CLOCK_REALTIME);
4658 s = (time_t) (n / USEC_PER_SEC);
4661 assert_se(localtime_r(&s, &tm));
4663 tm.tm_hour = (int) hour;
4664 tm.tm_min = (int) minute;
4667 assert_se(s = mktime(&tm));
4669 *_u = (usec_t) s * USEC_PER_SEC;
4672 *_u += USEC_PER_DAY;
4678 static int shutdown_parse_argv(int argc, char *argv[]) {
4685 static const struct option options[] = {
4686 { "help", no_argument, NULL, ARG_HELP },
4687 { "halt", no_argument, NULL, 'H' },
4688 { "poweroff", no_argument, NULL, 'P' },
4689 { "reboot", no_argument, NULL, 'r' },
4690 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4691 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4692 { NULL, 0, NULL, 0 }
4700 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4708 arg_action = ACTION_HALT;
4712 arg_action = ACTION_POWEROFF;
4717 arg_action = ACTION_KEXEC;
4719 arg_action = ACTION_REBOOT;
4723 arg_action = ACTION_KEXEC;
4727 if (arg_action != ACTION_HALT)
4728 arg_action = ACTION_POWEROFF;
4741 /* Compatibility nops */
4745 arg_action = ACTION_CANCEL_SHUTDOWN;
4752 log_error("Unknown option code '%c'.", c);
4757 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4758 r = parse_time_spec(argv[optind], &arg_when);
4760 log_error("Failed to parse time specification: %s", argv[optind]);
4764 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4766 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4767 /* No time argument for shutdown cancel */
4768 arg_wall = argv + optind;
4769 else if (argc > optind + 1)
4770 /* We skip the time argument */
4771 arg_wall = argv + optind + 1;
4778 static int telinit_parse_argv(int argc, char *argv[]) {
4785 static const struct option options[] = {
4786 { "help", no_argument, NULL, ARG_HELP },
4787 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4788 { NULL, 0, NULL, 0 }
4791 static const struct {
4795 { '0', ACTION_POWEROFF },
4796 { '6', ACTION_REBOOT },
4797 { '1', ACTION_RESCUE },
4798 { '2', ACTION_RUNLEVEL2 },
4799 { '3', ACTION_RUNLEVEL3 },
4800 { '4', ACTION_RUNLEVEL4 },
4801 { '5', ACTION_RUNLEVEL5 },
4802 { 's', ACTION_RESCUE },
4803 { 'S', ACTION_RESCUE },
4804 { 'q', ACTION_RELOAD },
4805 { 'Q', ACTION_RELOAD },
4806 { 'u', ACTION_REEXEC },
4807 { 'U', ACTION_REEXEC }
4816 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4831 log_error("Unknown option code '%c'.", c);
4836 if (optind >= argc) {
4841 if (optind + 1 < argc) {
4842 log_error("Too many arguments.");
4846 if (strlen(argv[optind]) != 1) {
4847 log_error("Expected single character argument.");
4851 for (i = 0; i < ELEMENTSOF(table); i++)
4852 if (table[i].from == argv[optind][0])
4855 if (i >= ELEMENTSOF(table)) {
4856 log_error("Unknown command '%s'.", argv[optind]);
4860 arg_action = table[i].to;
4867 static int runlevel_parse_argv(int argc, char *argv[]) {
4873 static const struct option options[] = {
4874 { "help", no_argument, NULL, ARG_HELP },
4875 { NULL, 0, NULL, 0 }
4883 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4894 log_error("Unknown option code '%c'.", c);
4899 if (optind < argc) {
4900 log_error("Too many arguments.");
4907 static int parse_argv(int argc, char *argv[]) {
4911 if (program_invocation_short_name) {
4913 if (strstr(program_invocation_short_name, "halt")) {
4914 arg_action = ACTION_HALT;
4915 return halt_parse_argv(argc, argv);
4916 } else if (strstr(program_invocation_short_name, "poweroff")) {
4917 arg_action = ACTION_POWEROFF;
4918 return halt_parse_argv(argc, argv);
4919 } else if (strstr(program_invocation_short_name, "reboot")) {
4921 arg_action = ACTION_KEXEC;
4923 arg_action = ACTION_REBOOT;
4924 return halt_parse_argv(argc, argv);
4925 } else if (strstr(program_invocation_short_name, "shutdown")) {
4926 arg_action = ACTION_POWEROFF;
4927 return shutdown_parse_argv(argc, argv);
4928 } else if (strstr(program_invocation_short_name, "init")) {
4930 if (sd_booted() > 0) {
4931 arg_action = ACTION_INVALID;
4932 return telinit_parse_argv(argc, argv);
4934 /* Hmm, so some other init system is
4935 * running, we need to forward this
4936 * request to it. For now we simply
4937 * guess that it is Upstart. */
4939 execv("/lib/upstart/telinit", argv);
4941 log_error("Couldn't find an alternative telinit implementation to spawn.");
4945 } else if (strstr(program_invocation_short_name, "runlevel")) {
4946 arg_action = ACTION_RUNLEVEL;
4947 return runlevel_parse_argv(argc, argv);
4951 arg_action = ACTION_SYSTEMCTL;
4952 return systemctl_parse_argv(argc, argv);
4955 static int action_to_runlevel(void) {
4957 static const char table[_ACTION_MAX] = {
4958 [ACTION_HALT] = '0',
4959 [ACTION_POWEROFF] = '0',
4960 [ACTION_REBOOT] = '6',
4961 [ACTION_RUNLEVEL2] = '2',
4962 [ACTION_RUNLEVEL3] = '3',
4963 [ACTION_RUNLEVEL4] = '4',
4964 [ACTION_RUNLEVEL5] = '5',
4965 [ACTION_RESCUE] = '1'
4968 assert(arg_action < _ACTION_MAX);
4970 return table[arg_action];
4973 static int talk_upstart(void) {
4974 DBusMessage _cleanup_dbus_message_unref_ *m = NULL, *reply = NULL;
4975 DBusError _cleanup_dbus_error_free_ error;
4976 int previous, rl, r;
4978 env1_buf[] = "RUNLEVEL=X",
4979 env2_buf[] = "PREVLEVEL=X";
4980 char *env1 = env1_buf, *env2 = env2_buf;
4981 const char *emit = "runlevel";
4982 dbus_bool_t b_false = FALSE;
4983 DBusMessageIter iter, sub;
4984 DBusConnection *bus;
4986 dbus_error_init(&error);
4988 if (!(rl = action_to_runlevel()))
4991 if (utmp_get_runlevel(&previous, NULL) < 0)
4994 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4995 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5000 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5005 if ((r = bus_check_peercred(bus)) < 0) {
5006 log_error("Failed to verify owner of bus.");
5010 if (!(m = dbus_message_new_method_call(
5011 "com.ubuntu.Upstart",
5012 "/com/ubuntu/Upstart",
5013 "com.ubuntu.Upstart0_6",
5016 log_error("Could not allocate message.");
5021 dbus_message_iter_init_append(m, &iter);
5023 env1_buf[sizeof(env1_buf)-2] = rl;
5024 env2_buf[sizeof(env2_buf)-2] = previous;
5026 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5027 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5028 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5029 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5030 !dbus_message_iter_close_container(&iter, &sub) ||
5031 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5032 log_error("Could not append arguments to message.");
5037 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5039 if (bus_error_is_no_service(&error)) {
5044 log_error("Failed to issue method call: %s", bus_error_message(&error));
5053 dbus_connection_flush(bus);
5054 dbus_connection_close(bus);
5055 dbus_connection_unref(bus);
5061 static int talk_initctl(void) {
5062 struct init_request request;
5066 if (!(rl = action_to_runlevel()))
5070 request.magic = INIT_MAGIC;
5071 request.sleeptime = 0;
5072 request.cmd = INIT_CMD_RUNLVL;
5073 request.runlevel = rl;
5075 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5077 if (errno == ENOENT)
5080 log_error("Failed to open "INIT_FIFO": %m");
5085 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5086 close_nointr_nofail(fd);
5089 log_error("Failed to write to "INIT_FIFO": %m");
5090 return errno ? -errno : -EIO;
5096 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5098 static const struct {
5106 int (* const dispatch)(DBusConnection *bus, char **args);
5108 { "list-units", LESS, 1, list_units },
5109 { "list-unit-files", EQUAL, 1, list_unit_files },
5110 { "list-jobs", EQUAL, 1, list_jobs },
5111 { "clear-jobs", EQUAL, 1, daemon_reload },
5112 { "load", MORE, 2, load_unit },
5113 { "cancel", MORE, 2, cancel_job },
5114 { "start", MORE, 2, start_unit },
5115 { "stop", MORE, 2, start_unit },
5116 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5117 { "reload", MORE, 2, start_unit },
5118 { "restart", MORE, 2, start_unit },
5119 { "try-restart", MORE, 2, start_unit },
5120 { "reload-or-restart", MORE, 2, start_unit },
5121 { "reload-or-try-restart", MORE, 2, start_unit },
5122 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5123 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5124 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5125 { "isolate", EQUAL, 2, start_unit },
5126 { "set-cgroup", MORE, 2, set_cgroup },
5127 { "unset-cgroup", MORE, 2, set_cgroup },
5128 { "get-cgroup-attr", MORE, 2, get_cgroup_attr },
5129 { "set-cgroup-attr", MORE, 2, set_cgroup_attr },
5130 { "unset-cgroup-attr", MORE, 2, set_cgroup },
5131 { "kill", MORE, 2, kill_unit },
5132 { "is-active", MORE, 2, check_unit_active },
5133 { "check", MORE, 2, check_unit_active },
5134 { "is-failed", MORE, 2, check_unit_failed },
5135 { "show", MORE, 1, show },
5136 { "status", MORE, 1, show },
5137 { "help", MORE, 2, show },
5138 { "dump", EQUAL, 1, dump },
5139 { "snapshot", LESS, 2, snapshot },
5140 { "delete", MORE, 2, delete_snapshot },
5141 { "daemon-reload", EQUAL, 1, daemon_reload },
5142 { "daemon-reexec", EQUAL, 1, daemon_reload },
5143 { "show-environment", EQUAL, 1, show_enviroment },
5144 { "set-environment", MORE, 2, set_environment },
5145 { "unset-environment", MORE, 2, set_environment },
5146 { "halt", EQUAL, 1, start_special },
5147 { "poweroff", EQUAL, 1, start_special },
5148 { "reboot", EQUAL, 1, start_special },
5149 { "kexec", EQUAL, 1, start_special },
5150 { "suspend", EQUAL, 1, start_special },
5151 { "hibernate", EQUAL, 1, start_special },
5152 { "hybrid-sleep", EQUAL, 1, start_special },
5153 { "default", EQUAL, 1, start_special },
5154 { "rescue", EQUAL, 1, start_special },
5155 { "emergency", EQUAL, 1, start_special },
5156 { "exit", EQUAL, 1, start_special },
5157 { "reset-failed", MORE, 1, reset_failed },
5158 { "enable", MORE, 2, enable_unit },
5159 { "disable", MORE, 2, enable_unit },
5160 { "is-enabled", MORE, 2, unit_is_enabled },
5161 { "reenable", MORE, 2, enable_unit },
5162 { "preset", MORE, 2, enable_unit },
5163 { "mask", MORE, 2, enable_unit },
5164 { "unmask", MORE, 2, enable_unit },
5165 { "link", MORE, 2, enable_unit },
5166 { "switch-root", MORE, 2, switch_root },
5167 { "list-dependencies", LESS, 2, list_dependencies },
5177 left = argc - optind;
5180 /* Special rule: no arguments means "list-units" */
5183 if (streq(argv[optind], "help") && !argv[optind+1]) {
5184 log_error("This command expects one or more "
5185 "unit names. Did you mean --help?");
5189 for (i = 0; i < ELEMENTSOF(verbs); i++)
5190 if (streq(argv[optind], verbs[i].verb))
5193 if (i >= ELEMENTSOF(verbs)) {
5194 log_error("Unknown operation '%s'.", argv[optind]);
5199 switch (verbs[i].argc_cmp) {
5202 if (left != verbs[i].argc) {
5203 log_error("Invalid number of arguments.");
5210 if (left < verbs[i].argc) {
5211 log_error("Too few arguments.");
5218 if (left > verbs[i].argc) {
5219 log_error("Too many arguments.");
5226 assert_not_reached("Unknown comparison operator.");
5229 /* Require a bus connection for all operations but
5231 if (!streq(verbs[i].verb, "enable") &&
5232 !streq(verbs[i].verb, "disable") &&
5233 !streq(verbs[i].verb, "is-enabled") &&
5234 !streq(verbs[i].verb, "list-unit-files") &&
5235 !streq(verbs[i].verb, "reenable") &&
5236 !streq(verbs[i].verb, "preset") &&
5237 !streq(verbs[i].verb, "mask") &&
5238 !streq(verbs[i].verb, "unmask") &&
5239 !streq(verbs[i].verb, "link")) {
5241 if (running_in_chroot() > 0) {
5242 log_info("Running in chroot, ignoring request.");
5246 if (((!streq(verbs[i].verb, "reboot") &&
5247 !streq(verbs[i].verb, "halt") &&
5248 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5249 log_error("Failed to get D-Bus connection: %s",
5250 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5256 if (!bus && !avoid_bus()) {
5257 log_error("Failed to get D-Bus connection: %s",
5258 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5263 return verbs[i].dispatch(bus, argv + optind);
5266 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5267 int _cleanup_close_ fd;
5268 struct msghdr msghdr;
5269 struct iovec iovec[2];
5270 union sockaddr_union sockaddr;
5271 struct sd_shutdown_command c;
5273 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5280 c.dry_run = dry_run;
5284 sockaddr.sa.sa_family = AF_UNIX;
5285 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5288 msghdr.msg_name = &sockaddr;
5289 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5292 iovec[0].iov_base = (char*) &c;
5293 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5295 if (isempty(message))
5296 msghdr.msg_iovlen = 1;
5298 iovec[1].iov_base = (char*) message;
5299 iovec[1].iov_len = strlen(message);
5300 msghdr.msg_iovlen = 2;
5302 msghdr.msg_iov = iovec;
5304 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5310 static int reload_with_fallback(DBusConnection *bus) {
5313 /* First, try systemd via D-Bus. */
5314 if (daemon_reload(bus, NULL) >= 0)
5318 /* Nothing else worked, so let's try signals */
5319 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5321 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5322 log_error("kill() failed: %m");
5329 static int start_with_fallback(DBusConnection *bus) {
5332 /* First, try systemd via D-Bus. */
5333 if (start_unit(bus, NULL) >= 0)
5337 /* Hmm, talking to systemd via D-Bus didn't work. Then
5338 * let's try to talk to Upstart via D-Bus. */
5339 if (talk_upstart() > 0)
5342 /* Nothing else worked, so let's try
5344 if (talk_initctl() > 0)
5347 log_error("Failed to talk to init daemon.");
5351 warn_wall(arg_action);
5355 static _noreturn_ void halt_now(enum action a) {
5357 /* Make sure C-A-D is handled by the kernel from this
5359 reboot(RB_ENABLE_CAD);
5364 log_info("Halting.");
5365 reboot(RB_HALT_SYSTEM);
5368 case ACTION_POWEROFF:
5369 log_info("Powering off.");
5370 reboot(RB_POWER_OFF);
5374 log_info("Rebooting.");
5375 reboot(RB_AUTOBOOT);
5379 assert_not_reached("Unknown halt action.");
5382 assert_not_reached("Uh? This shouldn't happen.");
5385 static int halt_main(DBusConnection *bus) {
5388 r = check_inhibitors(bus, arg_action);
5392 if (geteuid() != 0) {
5393 /* Try logind if we are a normal user and no special
5394 * mode applies. Maybe PolicyKit allows us to shutdown
5397 if (arg_when <= 0 &&
5400 (arg_action == ACTION_POWEROFF ||
5401 arg_action == ACTION_REBOOT)) {
5402 r = reboot_with_logind(bus, arg_action);
5407 log_error("Must be root.");
5412 char _cleanup_free_ *m;
5414 m = strv_join(arg_wall, " ");
5415 r = send_shutdownd(arg_when,
5416 arg_action == ACTION_HALT ? 'H' :
5417 arg_action == ACTION_POWEROFF ? 'P' :
5418 arg_action == ACTION_KEXEC ? 'K' :
5425 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5427 char date[FORMAT_TIMESTAMP_MAX];
5429 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5430 format_timestamp(date, sizeof(date), arg_when));
5435 if (!arg_dry && !arg_force)
5436 return start_with_fallback(bus);
5439 if (sd_booted() > 0)
5440 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5442 r = utmp_put_shutdown();
5444 log_warning("Failed to write utmp record: %s", strerror(-r));
5451 halt_now(arg_action);
5452 /* We should never reach this. */
5456 static int runlevel_main(void) {
5457 int r, runlevel, previous;
5459 r = utmp_get_runlevel(&runlevel, &previous);
5466 previous <= 0 ? 'N' : previous,
5467 runlevel <= 0 ? 'N' : runlevel);
5472 int main(int argc, char*argv[]) {
5473 int r, retval = EXIT_FAILURE;
5474 DBusConnection *bus = NULL;
5475 DBusError _cleanup_dbus_error_free_ error;
5477 dbus_error_init(&error);
5479 setlocale(LC_ALL, "");
5480 log_parse_environment();
5483 r = parse_argv(argc, argv);
5487 retval = EXIT_SUCCESS;
5491 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5492 * let's shortcut this */
5493 if (arg_action == ACTION_RUNLEVEL) {
5494 r = runlevel_main();
5495 retval = r < 0 ? EXIT_FAILURE : r;
5499 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5500 log_info("Running in chroot, ignoring request.");
5506 if (arg_transport == TRANSPORT_NORMAL)
5507 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5508 else if (arg_transport == TRANSPORT_POLKIT) {
5509 bus_connect_system_polkit(&bus, &error);
5510 private_bus = false;
5511 } else if (arg_transport == TRANSPORT_SSH) {
5512 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5513 private_bus = false;
5515 assert_not_reached("Uh, invalid transport...");
5518 switch (arg_action) {
5520 case ACTION_SYSTEMCTL:
5521 r = systemctl_main(bus, argc, argv, &error);
5525 case ACTION_POWEROFF:
5531 case ACTION_RUNLEVEL2:
5532 case ACTION_RUNLEVEL3:
5533 case ACTION_RUNLEVEL4:
5534 case ACTION_RUNLEVEL5:
5536 case ACTION_EMERGENCY:
5537 case ACTION_DEFAULT:
5538 r = start_with_fallback(bus);
5543 r = reload_with_fallback(bus);
5546 case ACTION_CANCEL_SHUTDOWN: {
5550 m = strv_join(arg_wall, " ");
5552 retval = EXIT_FAILURE;
5556 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5558 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5563 case ACTION_INVALID:
5564 case ACTION_RUNLEVEL:
5566 assert_not_reached("Unknown action");
5569 retval = r < 0 ? EXIT_FAILURE : r;
5573 dbus_connection_flush(bus);
5574 dbus_connection_close(bus);
5575 dbus_connection_unref(bus);
5580 strv_free(arg_property);
5583 ask_password_agent_close();
5584 polkit_agent_close();