1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/reboot.h>
29 #include <sys/ioctl.h>
33 #include <sys/socket.h>
36 #include <sys/prctl.h>
37 #include <dbus/dbus.h>
39 #include <systemd/sd-daemon.h>
40 #include <systemd/sd-shutdown.h>
41 #include <systemd/sd-login.h>
47 #include "utmp-wtmp.h"
50 #include "path-util.h"
52 #include "dbus-common.h"
53 #include "cgroup-show.h"
54 #include "cgroup-util.h"
56 #include "path-lookup.h"
57 #include "conf-parser.h"
58 #include "exit-status.h"
59 #include "bus-errors.h"
61 #include "unit-name.h"
63 #include "spawn-ask-password-agent.h"
64 #include "spawn-polkit-agent.h"
66 #include "logs-show.h"
67 #include "path-util.h"
68 #include "socket-util.h"
71 static const char *arg_type = NULL;
72 static const char *arg_load_state = NULL;
73 static char **arg_property = NULL;
74 static bool arg_all = false;
75 static const char *arg_job_mode = "replace";
76 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
77 static bool arg_no_block = false;
78 static bool arg_no_legend = false;
79 static bool arg_no_pager = false;
80 static bool arg_no_wtmp = false;
81 static bool arg_no_wall = false;
82 static bool arg_no_reload = false;
83 static bool arg_ignore_inhibitors = false;
84 static bool arg_dry = false;
85 static bool arg_quiet = false;
86 static bool arg_full = false;
87 static int arg_force = 0;
88 static bool arg_ask_password = true;
89 static bool arg_failed = false;
90 static bool arg_runtime = false;
91 static char **arg_wall = NULL;
92 static const char *arg_kill_who = NULL;
93 static int arg_signal = SIGTERM;
94 static const char *arg_root = NULL;
95 static usec_t arg_when = 0;
117 ACTION_CANCEL_SHUTDOWN,
119 } arg_action = ACTION_SYSTEMCTL;
120 static enum transport {
124 } arg_transport = TRANSPORT_NORMAL;
125 static const char *arg_host = NULL;
126 static unsigned arg_lines = 10;
127 static OutputMode arg_output = OUTPUT_SHORT;
129 static bool private_bus = false;
131 static int daemon_reload(DBusConnection *bus, char **args);
132 static void halt_now(enum action a);
134 static void pager_open_if_enabled(void) {
142 static void ask_password_agent_open_if_enabled(void) {
144 /* Open the password agent as a child process if necessary */
146 if (!arg_ask_password)
149 if (arg_scope != UNIT_FILE_SYSTEM)
152 ask_password_agent_open();
156 static void polkit_agent_open_if_enabled(void) {
158 /* Open the polkit agent as a child process if necessary */
160 if (!arg_ask_password)
163 if (arg_scope != UNIT_FILE_SYSTEM)
170 static const char *ansi_highlight(bool b) {
175 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
178 static const char *ansi_highlight_red(bool b) {
183 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
186 static const char *ansi_highlight_green(bool b) {
191 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
194 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
197 if (!dbus_error_is_set(error))
200 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
201 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
202 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
203 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
204 return EXIT_NOPERMISSION;
206 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
207 return EXIT_NOTINSTALLED;
209 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
210 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
211 return EXIT_NOTIMPLEMENTED;
213 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
214 return EXIT_NOTCONFIGURED;
222 static void warn_wall(enum action a) {
223 static const char *table[_ACTION_MAX] = {
224 [ACTION_HALT] = "The system is going down for system halt NOW!",
225 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
226 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
227 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
228 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
229 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
230 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
237 _cleanup_free_ char *p;
239 p = strv_join(arg_wall, " ");
254 utmp_wall(table[a], NULL);
257 static bool avoid_bus(void) {
259 if (running_in_chroot() > 0)
262 if (sd_booted() <= 0)
265 if (!isempty(arg_root))
268 if (arg_scope == UNIT_FILE_GLOBAL)
274 static int compare_unit_info(const void *a, const void *b) {
276 const struct unit_info *u = a, *v = b;
278 d1 = strrchr(u->id, '.');
279 d2 = strrchr(v->id, '.');
284 r = strcasecmp(d1, d2);
289 return strcasecmp(u->id, v->id);
292 static bool output_show_unit(const struct unit_info *u) {
296 return streq(u->active_state, "failed");
298 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
299 streq(dot+1, arg_type))) &&
300 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
301 (arg_all || !(streq(u->active_state, "inactive")
302 || u->following[0]) || u->job_id > 0);
305 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
306 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
307 const struct unit_info *u;
310 max_id_len = sizeof("UNIT")-1;
311 active_len = sizeof("ACTIVE")-1;
312 sub_len = sizeof("SUB")-1;
313 job_len = sizeof("JOB")-1;
316 for (u = unit_infos; u < unit_infos + c; u++) {
317 if (!output_show_unit(u))
320 max_id_len = MAX(max_id_len, strlen(u->id));
321 active_len = MAX(active_len, strlen(u->active_state));
322 sub_len = MAX(sub_len, strlen(u->sub_state));
323 if (u->job_id != 0) {
324 job_len = MAX(job_len, strlen(u->job_type));
331 id_len = MIN(max_id_len, 25);
332 basic_len = 5 + id_len + 5 + active_len + sub_len;
334 basic_len += job_len + 1;
335 if (basic_len < (unsigned) columns()) {
336 unsigned extra_len, incr;
337 extra_len = columns() - basic_len;
338 /* Either UNIT already got 25, or is fully satisfied.
339 * Grant up to 25 to DESC now. */
340 incr = MIN(extra_len, 25);
343 /* split the remaining space between UNIT and DESC,
344 * but do not give UNIT more than it needs. */
346 incr = MIN(extra_len / 2, max_id_len - id_len);
348 desc_len += extra_len - incr;
354 for (u = unit_infos; u < unit_infos + c; u++) {
355 char _cleanup_free_ *e = NULL;
356 const char *on_loaded, *off_loaded;
357 const char *on_active, *off_active;
359 if (!output_show_unit(u))
362 if (!n_shown && !arg_no_legend) {
363 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
364 active_len, "ACTIVE", sub_len, "SUB");
366 printf("%-*s ", job_len, "JOB");
367 if (!arg_full && arg_no_pager)
368 printf("%.*s\n", desc_len, "DESCRIPTION");
370 printf("%s\n", "DESCRIPTION");
375 if (streq(u->load_state, "error")) {
376 on_loaded = ansi_highlight_red(true);
377 off_loaded = ansi_highlight_red(false);
379 on_loaded = off_loaded = "";
381 if (streq(u->active_state, "failed")) {
382 on_active = ansi_highlight_red(true);
383 off_active = ansi_highlight_red(false);
385 on_active = off_active = "";
387 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
389 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s",
390 id_len, e ? e : u->id,
391 on_loaded, u->load_state, off_loaded,
392 on_active, active_len, u->active_state,
393 sub_len, u->sub_state, off_active,
394 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
395 if (!arg_full && arg_no_pager)
396 printf("%.*s\n", desc_len, u->description);
398 printf("%s\n", u->description);
401 if (!arg_no_legend) {
402 const char *on, *off;
405 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
406 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
407 "SUB = The low-level unit activation state, values depend on unit type.\n");
409 printf("JOB = Pending job for the unit.\n");
411 on = ansi_highlight(true);
412 off = ansi_highlight(false);
414 on = ansi_highlight_red(true);
415 off = ansi_highlight_red(false);
419 printf("%s%u loaded units listed.%s\n"
420 "To show all installed unit files use 'systemctl list-unit-files'.\n",
423 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
424 "To show all installed unit files use 'systemctl list-unit-files'.\n",
429 static int get_unit_list(DBusConnection *bus, DBusMessage **reply,
430 struct unit_info **unit_infos, unsigned *c) {
431 DBusMessageIter iter, sub;
432 unsigned n_units = 0;
439 r = bus_method_call_with_reply(
441 "org.freedesktop.systemd1",
442 "/org/freedesktop/systemd1",
443 "org.freedesktop.systemd1.Manager",
451 if (!dbus_message_iter_init(*reply, &iter) ||
452 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
453 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
454 log_error("Failed to parse reply.");
458 dbus_message_iter_recurse(&iter, &sub);
460 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
466 n_units = MAX(2 * *c, 16);
467 w = realloc(*unit_infos, sizeof(struct unit_info) * n_units);
474 u = *unit_infos + *c;
476 bus_parse_unit_info(&sub, u);
478 dbus_message_iter_next(&sub);
483 qsort(*unit_infos, *c, sizeof(struct unit_info), compare_unit_info);
488 static int list_units(DBusConnection *bus, char **args) {
489 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
490 _cleanup_free_ struct unit_info *unit_infos = NULL;
494 pager_open_if_enabled();
496 r = get_unit_list(bus, &reply, &unit_infos, &c);
501 output_units_list(unit_infos, c);
506 static int compare_unit_file_list(const void *a, const void *b) {
508 const UnitFileList *u = a, *v = b;
510 d1 = strrchr(u->path, '.');
511 d2 = strrchr(v->path, '.');
516 r = strcasecmp(d1, d2);
521 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
524 static bool output_show_unit_file(const UnitFileList *u) {
527 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
530 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
531 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
532 const UnitFileList *u;
534 max_id_len = sizeof("UNIT FILE")-1;
535 state_cols = sizeof("STATE")-1;
536 for (u = units; u < units + c; u++) {
537 if (!output_show_unit_file(u))
540 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
541 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
546 id_cols = MIN(max_id_len, 25);
547 basic_cols = 1 + id_cols + state_cols;
548 if (basic_cols < (unsigned) columns())
549 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
551 id_cols = max_id_len;
554 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
556 for (u = units; u < units + c; u++) {
557 char _cleanup_free_ *e = NULL;
558 const char *on, *off;
561 if (!output_show_unit_file(u))
566 if (u->state == UNIT_FILE_MASKED ||
567 u->state == UNIT_FILE_MASKED_RUNTIME ||
568 u->state == UNIT_FILE_DISABLED ||
569 u->state == UNIT_FILE_INVALID) {
570 on = ansi_highlight_red(true);
571 off = ansi_highlight_red(false);
572 } else if (u->state == UNIT_FILE_ENABLED) {
573 on = ansi_highlight_green(true);
574 off = ansi_highlight_green(false);
578 id = path_get_file_name(u->path);
580 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
582 printf("%-*s %s%-*s%s\n",
584 on, state_cols, unit_file_state_to_string(u->state), off);
588 printf("\n%u unit files listed.\n", n_shown);
591 static int list_unit_files(DBusConnection *bus, char **args) {
592 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
593 _cleanup_free_ UnitFileList *units = NULL;
594 DBusMessageIter iter, sub, sub2;
595 unsigned c = 0, n_units = 0;
598 pager_open_if_enabled();
605 h = hashmap_new(string_hash_func, string_compare_func);
609 r = unit_file_get_list(arg_scope, arg_root, h);
611 unit_file_list_free(h);
612 log_error("Failed to get unit file list: %s", strerror(-r));
616 n_units = hashmap_size(h);
617 units = new(UnitFileList, n_units);
619 unit_file_list_free(h);
623 HASHMAP_FOREACH(u, h, i) {
624 memcpy(units + c++, u, sizeof(UnitFileList));
630 r = bus_method_call_with_reply(
632 "org.freedesktop.systemd1",
633 "/org/freedesktop/systemd1",
634 "org.freedesktop.systemd1.Manager",
642 if (!dbus_message_iter_init(reply, &iter) ||
643 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
644 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
645 log_error("Failed to parse reply.");
649 dbus_message_iter_recurse(&iter, &sub);
651 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
655 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
660 n_units = MAX(2*c, 16);
661 w = realloc(units, sizeof(struct UnitFileList) * n_units);
670 dbus_message_iter_recurse(&sub, &sub2);
672 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
673 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
674 log_error("Failed to parse reply.");
678 u->state = unit_file_state_from_string(state);
680 dbus_message_iter_next(&sub);
686 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
687 output_unit_file_list(units, c);
693 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
695 _cleanup_free_ char *n = NULL;
697 size_t max_len = MAX(columns(),20);
699 for (i = level - 1; i >= 0; i--) {
701 if(len > max_len - 3 && !arg_full) {
702 printf("%s...\n",max_len % 2 ? "" : " ");
705 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
708 if(len > max_len - 3 && !arg_full) {
709 printf("%s...\n",max_len % 2 ? "" : " ");
712 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
715 printf("%s\n", name);
719 n = ellipsize(name, max_len-len, 100);
727 static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
728 static const char dependencies[] =
730 "RequiresOverridable\0"
732 "RequisiteOverridable\0"
735 _cleanup_free_ char *path;
736 const char *interface = "org.freedesktop.systemd1.Unit";
738 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
739 DBusMessageIter iter, sub, sub2, sub3;
748 path = unit_dbus_path_from_name(name);
754 r = bus_method_call_with_reply(
756 "org.freedesktop.systemd1",
758 "org.freedesktop.DBus.Properties",
762 DBUS_TYPE_STRING, &interface,
767 if (!dbus_message_iter_init(reply, &iter) ||
768 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
769 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
770 log_error("Failed to parse reply.");
775 dbus_message_iter_recurse(&iter, &sub);
777 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
780 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
781 dbus_message_iter_recurse(&sub, &sub2);
783 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
784 log_error("Failed to parse reply.");
789 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
790 log_error("Failed to parse reply.");
795 dbus_message_iter_recurse(&sub2, &sub3);
796 dbus_message_iter_next(&sub);
798 if (!nulstr_contains(dependencies, prop))
801 if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
802 if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
803 DBusMessageIter sub4;
804 dbus_message_iter_recurse(&sub3, &sub4);
806 while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
809 assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
810 dbus_message_iter_get_basic(&sub4, &s);
812 r = strv_extend(&ret, s);
818 dbus_message_iter_next(&sub4);
831 static int list_dependencies_compare(const void *_a, const void *_b) {
832 const char **a = (const char**) _a, **b = (const char**) _b;
833 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
835 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
837 return strcasecmp(*a, *b);
840 static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char **units, unsigned int branches) {
841 char _cleanup_strv_free_ **deps = NULL, **u;
845 u = strv_append(units, name);
849 r = list_dependencies_get_dependencies(bus, name, &deps);
853 qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
855 STRV_FOREACH(c, deps) {
856 if (strv_contains(u, *c)) {
857 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
863 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
867 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
868 r = list_dependencies_one(bus, *c, level + 1, u, (branches << 1) | (c[1] == NULL ? 0 : 1));
877 static int list_dependencies(DBusConnection *bus, char **args) {
878 _cleanup_free_ char *unit = NULL;
884 unit = unit_name_mangle(args[1]);
889 u = SPECIAL_DEFAULT_TARGET;
891 pager_open_if_enabled();
895 return list_dependencies_one(bus, u, 0, NULL, 0);
898 static int list_jobs(DBusConnection *bus, char **args) {
899 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
900 DBusMessageIter iter, sub, sub2;
904 pager_open_if_enabled();
906 r = bus_method_call_with_reply(
908 "org.freedesktop.systemd1",
909 "/org/freedesktop/systemd1",
910 "org.freedesktop.systemd1.Manager",
918 if (!dbus_message_iter_init(reply, &iter) ||
919 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
920 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
921 log_error("Failed to parse reply.");
925 dbus_message_iter_recurse(&iter, &sub);
928 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
930 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
931 const char *name, *type, *state, *job_path, *unit_path;
933 char _cleanup_free_ *e = NULL;
935 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
936 log_error("Failed to parse reply.");
940 dbus_message_iter_recurse(&sub, &sub2);
942 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
943 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
944 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
945 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
946 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
947 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
948 log_error("Failed to parse reply.");
952 e = arg_full ? NULL : ellipsize(name, 25, 33);
953 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
957 dbus_message_iter_next(&sub);
961 printf("\n%u jobs listed.\n", k);
966 static int load_unit(DBusConnection *bus, char **args) {
971 STRV_FOREACH(name, args+1) {
972 _cleanup_free_ char *n = NULL;
975 n = unit_name_mangle(*name);
979 r = bus_method_call_with_reply(
981 "org.freedesktop.systemd1",
982 "/org/freedesktop/systemd1",
983 "org.freedesktop.systemd1.Manager",
987 DBUS_TYPE_STRING, &n,
996 static int cancel_job(DBusConnection *bus, char **args) {
1001 if (strv_length(args) <= 1)
1002 return daemon_reload(bus, args);
1004 STRV_FOREACH(name, args+1) {
1008 r = safe_atou32(*name, &id);
1010 log_error("Failed to parse job id: %s", strerror(-r));
1014 r = bus_method_call_with_reply(
1016 "org.freedesktop.systemd1",
1017 "/org/freedesktop/systemd1",
1018 "org.freedesktop.systemd1.Manager",
1022 DBUS_TYPE_UINT32, &id,
1031 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1032 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1033 dbus_bool_t b = FALSE;
1034 DBusMessageIter iter, sub;
1036 *interface = "org.freedesktop.systemd1.Unit",
1037 *property = "NeedDaemonReload",
1039 _cleanup_free_ char *n = NULL;
1042 /* We ignore all errors here, since this is used to show a warning only */
1044 n = unit_name_mangle(unit);
1048 r = bus_method_call_with_reply (
1050 "org.freedesktop.systemd1",
1051 "/org/freedesktop/systemd1",
1052 "org.freedesktop.systemd1.Manager",
1056 DBUS_TYPE_STRING, &n,
1061 if (!dbus_message_get_args(reply, NULL,
1062 DBUS_TYPE_OBJECT_PATH, &path,
1066 dbus_message_unref(reply);
1069 r = bus_method_call_with_reply(
1071 "org.freedesktop.systemd1",
1073 "org.freedesktop.DBus.Properties",
1077 DBUS_TYPE_STRING, &interface,
1078 DBUS_TYPE_STRING, &property,
1083 if (!dbus_message_iter_init(reply, &iter) ||
1084 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1087 dbus_message_iter_recurse(&iter, &sub);
1088 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1091 dbus_message_iter_get_basic(&sub, &b);
1095 typedef struct WaitData {
1102 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1103 DBusError _cleanup_dbus_error_free_ error;
1106 dbus_error_init(&error);
1112 log_debug("Got D-Bus request: %s.%s() on %s",
1113 dbus_message_get_interface(message),
1114 dbus_message_get_member(message),
1115 dbus_message_get_path(message));
1117 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1118 log_error("Warning! D-Bus connection terminated.");
1119 dbus_connection_close(connection);
1121 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1123 const char *path, *result, *unit;
1125 if (dbus_message_get_args(message, &error,
1126 DBUS_TYPE_UINT32, &id,
1127 DBUS_TYPE_OBJECT_PATH, &path,
1128 DBUS_TYPE_STRING, &unit,
1129 DBUS_TYPE_STRING, &result,
1130 DBUS_TYPE_INVALID)) {
1132 free(set_remove(d->set, (char*) path));
1134 if (!isempty(result))
1135 d->result = strdup(result);
1138 d->name = strdup(unit);
1140 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1143 dbus_error_free(&error);
1144 if (dbus_message_get_args(message, &error,
1145 DBUS_TYPE_UINT32, &id,
1146 DBUS_TYPE_OBJECT_PATH, &path,
1147 DBUS_TYPE_STRING, &result,
1148 DBUS_TYPE_INVALID)) {
1149 /* Compatibility with older systemd versions <
1150 * 183 during upgrades. This should be dropped
1152 free(set_remove(d->set, (char*) path));
1155 d->result = strdup(result);
1157 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1161 log_error("Failed to parse message: %s", bus_error_message(&error));
1164 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1167 static int enable_wait_for_jobs(DBusConnection *bus) {
1175 dbus_error_init(&error);
1176 dbus_bus_add_match(bus,
1178 "sender='org.freedesktop.systemd1',"
1179 "interface='org.freedesktop.systemd1.Manager',"
1180 "member='JobRemoved',"
1181 "path='/org/freedesktop/systemd1'",
1184 if (dbus_error_is_set(&error)) {
1185 log_error("Failed to add match: %s", bus_error_message(&error));
1186 dbus_error_free(&error);
1190 /* This is slightly dirty, since we don't undo the match registrations. */
1194 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1204 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1207 while (!set_isempty(s)) {
1209 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1210 log_error("Disconnected from bus.");
1211 return -ECONNREFUSED;
1218 if (streq(d.result, "timeout"))
1219 log_error("Job for %s timed out.", strna(d.name));
1220 else if (streq(d.result, "canceled"))
1221 log_error("Job for %s canceled.", strna(d.name));
1222 else if (streq(d.result, "dependency"))
1223 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1224 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1225 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1228 if (streq_ptr(d.result, "timeout"))
1230 else if (streq_ptr(d.result, "canceled"))
1232 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1243 dbus_connection_remove_filter(bus, wait_filter, &d);
1247 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1248 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1249 _cleanup_free_ char *n = NULL;
1250 DBusMessageIter iter, sub;
1252 *interface = "org.freedesktop.systemd1.Unit",
1253 *property = "ActiveState";
1254 const char *state, *path;
1260 dbus_error_init(&error);
1262 n = unit_name_mangle(name);
1266 r = bus_method_call_with_reply (
1268 "org.freedesktop.systemd1",
1269 "/org/freedesktop/systemd1",
1270 "org.freedesktop.systemd1.Manager",
1274 DBUS_TYPE_STRING, &n,
1277 dbus_error_free(&error);
1284 if (!dbus_message_get_args(reply, NULL,
1285 DBUS_TYPE_OBJECT_PATH, &path,
1286 DBUS_TYPE_INVALID)) {
1287 log_error("Failed to parse reply.");
1291 dbus_message_unref(reply);
1294 r = bus_method_call_with_reply(
1296 "org.freedesktop.systemd1",
1298 "org.freedesktop.DBus.Properties",
1302 DBUS_TYPE_STRING, &interface,
1303 DBUS_TYPE_STRING, &property,
1311 if (!dbus_message_iter_init(reply, &iter) ||
1312 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1313 log_error("Failed to parse reply.");
1317 dbus_message_iter_recurse(&iter, &sub);
1319 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1320 log_error("Failed to parse reply.");
1324 dbus_message_iter_get_basic(&sub, &state);
1329 return strv_find(check_states, state) ? 1 : 0;
1332 static void check_triggering_units(
1333 DBusConnection *bus,
1334 const char *unit_name) {
1336 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1337 DBusMessageIter iter, sub;
1338 const char *interface = "org.freedesktop.systemd1.Unit",
1339 *load_state_property = "LoadState",
1340 *triggered_by_property = "TriggeredBy",
1342 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1343 bool print_warning_label = true;
1346 n = unit_name_mangle(unit_name);
1352 unit_path = unit_dbus_path_from_name(n);
1358 r = bus_method_call_with_reply(
1360 "org.freedesktop.systemd1",
1362 "org.freedesktop.DBus.Properties",
1366 DBUS_TYPE_STRING, &interface,
1367 DBUS_TYPE_STRING, &load_state_property,
1372 if (!dbus_message_iter_init(reply, &iter) ||
1373 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1374 log_error("Failed to parse reply.");
1378 dbus_message_iter_recurse(&iter, &sub);
1380 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1381 log_error("Failed to parse reply.");
1385 dbus_message_iter_get_basic(&sub, &state);
1387 if (streq(state, "masked"))
1390 dbus_message_unref(reply);
1393 r = bus_method_call_with_reply(
1395 "org.freedesktop.systemd1",
1397 "org.freedesktop.DBus.Properties",
1401 DBUS_TYPE_STRING, &interface,
1402 DBUS_TYPE_STRING, &triggered_by_property,
1407 if (!dbus_message_iter_init(reply, &iter) ||
1408 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1409 log_error("Failed to parse reply.");
1413 dbus_message_iter_recurse(&iter, &sub);
1414 dbus_message_iter_recurse(&sub, &iter);
1417 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1418 const char * const check_states[] = {
1423 const char *service_trigger;
1425 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1426 log_error("Failed to parse reply.");
1430 dbus_message_iter_get_basic(&sub, &service_trigger);
1432 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1436 if (print_warning_label) {
1437 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1438 print_warning_label = false;
1441 log_warning(" %s", service_trigger);
1444 dbus_message_iter_next(&sub);
1448 static int start_unit_one(
1449 DBusConnection *bus,
1456 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1457 _cleanup_free_ char *n;
1466 n = unit_name_mangle(name);
1470 r = bus_method_call_with_reply(
1472 "org.freedesktop.systemd1",
1473 "/org/freedesktop/systemd1",
1474 "org.freedesktop.systemd1.Manager",
1478 DBUS_TYPE_STRING, &n,
1479 DBUS_TYPE_STRING, &mode,
1482 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1483 /* There's always a fallback possible for
1484 * legacy actions. */
1487 log_error("Failed to issue method call: %s", bus_error_message(error));
1492 if (!dbus_message_get_args(reply, error,
1493 DBUS_TYPE_OBJECT_PATH, &path,
1494 DBUS_TYPE_INVALID)) {
1495 log_error("Failed to parse reply: %s", bus_error_message(error));
1499 if (need_daemon_reload(bus, n))
1500 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1501 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1513 log_error("Failed to add path to set.");
1521 static enum action verb_to_action(const char *verb) {
1522 if (streq(verb, "halt"))
1524 else if (streq(verb, "poweroff"))
1525 return ACTION_POWEROFF;
1526 else if (streq(verb, "reboot"))
1527 return ACTION_REBOOT;
1528 else if (streq(verb, "kexec"))
1529 return ACTION_KEXEC;
1530 else if (streq(verb, "rescue"))
1531 return ACTION_RESCUE;
1532 else if (streq(verb, "emergency"))
1533 return ACTION_EMERGENCY;
1534 else if (streq(verb, "default"))
1535 return ACTION_DEFAULT;
1536 else if (streq(verb, "exit"))
1538 else if (streq(verb, "suspend"))
1539 return ACTION_SUSPEND;
1540 else if (streq(verb, "hibernate"))
1541 return ACTION_HIBERNATE;
1542 else if (streq(verb, "hybrid-sleep"))
1543 return ACTION_HYBRID_SLEEP;
1545 return ACTION_INVALID;
1548 static int start_unit(DBusConnection *bus, char **args) {
1550 static const char * const table[_ACTION_MAX] = {
1551 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1552 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1553 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1554 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1555 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1556 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1557 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1558 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1559 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1560 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1561 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1562 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1563 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1564 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
1565 [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
1569 const char *method, *mode, *one_name;
1570 Set _cleanup_set_free_free_ *s = NULL;
1571 DBusError _cleanup_dbus_error_free_ error;
1574 dbus_error_init(&error);
1578 ask_password_agent_open_if_enabled();
1580 if (arg_action == ACTION_SYSTEMCTL) {
1582 streq(args[0], "stop") ||
1583 streq(args[0], "condstop") ? "StopUnit" :
1584 streq(args[0], "reload") ? "ReloadUnit" :
1585 streq(args[0], "restart") ? "RestartUnit" :
1587 streq(args[0], "try-restart") ||
1588 streq(args[0], "condrestart") ? "TryRestartUnit" :
1590 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1592 streq(args[0], "reload-or-try-restart") ||
1593 streq(args[0], "condreload") ||
1595 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1599 (streq(args[0], "isolate") ||
1600 streq(args[0], "rescue") ||
1601 streq(args[0], "emergency") ||
1602 streq(args[0], "default")) ? "isolate" : arg_job_mode;
1604 one_name = table[verb_to_action(args[0])];
1607 assert(arg_action < ELEMENTSOF(table));
1608 assert(table[arg_action]);
1610 method = "StartUnit";
1612 mode = (arg_action == ACTION_EMERGENCY ||
1613 arg_action == ACTION_RESCUE ||
1614 arg_action == ACTION_RUNLEVEL2 ||
1615 arg_action == ACTION_RUNLEVEL3 ||
1616 arg_action == ACTION_RUNLEVEL4 ||
1617 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1619 one_name = table[arg_action];
1622 if (!arg_no_block) {
1623 ret = enable_wait_for_jobs(bus);
1625 log_error("Could not watch jobs: %s", strerror(-ret));
1629 s = set_new(string_hash_func, string_compare_func);
1635 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1637 ret = translate_bus_error_to_exit_status(ret, &error);
1639 STRV_FOREACH(name, args+1) {
1640 r = start_unit_one(bus, method, *name, mode, &error, s);
1642 ret = translate_bus_error_to_exit_status(r, &error);
1643 dbus_error_free(&error);
1648 if (!arg_no_block) {
1649 r = wait_for_jobs(bus, s);
1653 /* When stopping units, warn if they can still be triggered by
1654 * another active unit (socket, path, timer) */
1655 if (!arg_quiet && streq(method, "StopUnit")) {
1657 check_triggering_units(bus, one_name);
1659 STRV_FOREACH(name, args+1)
1660 check_triggering_units(bus, *name);
1667 /* Ask systemd-logind, which might grant access to unprivileged users
1668 * through PolicyKit */
1669 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1672 dbus_bool_t interactive = true;
1677 polkit_agent_open_if_enabled();
1685 case ACTION_POWEROFF:
1686 method = "PowerOff";
1689 case ACTION_SUSPEND:
1693 case ACTION_HIBERNATE:
1694 method = "Hibernate";
1697 case ACTION_HYBRID_SLEEP:
1698 method = "HybridSleep";
1705 return bus_method_call_with_reply(
1707 "org.freedesktop.login1",
1708 "/org/freedesktop/login1",
1709 "org.freedesktop.login1.Manager",
1713 DBUS_TYPE_BOOLEAN, &interactive,
1720 static int check_inhibitors(DBusConnection *bus, enum action a) {
1722 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1723 DBusMessageIter iter, sub, sub2;
1726 _cleanup_strv_free_ char **sessions = NULL;
1732 if (arg_ignore_inhibitors || arg_force > 0)
1744 r = bus_method_call_with_reply(
1746 "org.freedesktop.login1",
1747 "/org/freedesktop/login1",
1748 "org.freedesktop.login1.Manager",
1754 /* If logind is not around, then there are no inhibitors... */
1757 if (!dbus_message_iter_init(reply, &iter) ||
1758 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1759 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1760 log_error("Failed to parse reply.");
1764 dbus_message_iter_recurse(&iter, &sub);
1765 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1766 const char *what, *who, *why, *mode;
1768 _cleanup_strv_free_ char **sv = NULL;
1769 _cleanup_free_ char *comm = NULL, *user = NULL;
1771 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1772 log_error("Failed to parse reply.");
1776 dbus_message_iter_recurse(&sub, &sub2);
1778 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
1779 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
1780 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
1781 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
1782 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
1783 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
1784 log_error("Failed to parse reply.");
1788 if (!streq(mode, "block"))
1791 sv = strv_split(what, ":");
1795 if (!strv_contains(sv,
1797 a == ACTION_POWEROFF ||
1798 a == ACTION_REBOOT ||
1799 a == ACTION_KEXEC ? "shutdown" : "sleep"))
1802 get_process_comm(pid, &comm);
1803 user = uid_to_name(uid);
1804 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
1805 who, (unsigned long) pid, strna(comm), strna(user), why);
1809 dbus_message_iter_next(&sub);
1812 dbus_message_iter_recurse(&iter, &sub);
1814 /* Check for current sessions */
1815 sd_get_sessions(&sessions);
1816 STRV_FOREACH(s, sessions) {
1818 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
1820 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
1823 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
1826 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
1829 sd_session_get_tty(*s, &tty);
1830 sd_session_get_seat(*s, &seat);
1831 sd_session_get_service(*s, &service);
1832 user = uid_to_name(uid);
1834 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
1841 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
1842 a == ACTION_HALT ? "halt" :
1843 a == ACTION_POWEROFF ? "poweroff" :
1844 a == ACTION_REBOOT ? "reboot" :
1845 a == ACTION_KEXEC ? "kexec" :
1846 a == ACTION_SUSPEND ? "suspend" :
1847 a == ACTION_HIBERNATE ? "hibernate" : "hybrid-sleep");
1855 static int start_special(DBusConnection *bus, char **args) {
1861 a = verb_to_action(args[0]);
1863 r = check_inhibitors(bus, a);
1867 if (arg_force >= 2 && geteuid() != 0) {
1868 log_error("Must be root.");
1872 if (arg_force >= 2 &&
1873 (a == ACTION_HALT ||
1874 a == ACTION_POWEROFF ||
1875 a == ACTION_REBOOT))
1878 if (arg_force >= 1 &&
1879 (a == ACTION_HALT ||
1880 a == ACTION_POWEROFF ||
1881 a == ACTION_REBOOT ||
1882 a == ACTION_KEXEC ||
1884 return daemon_reload(bus, args);
1886 /* first try logind, to allow authentication with polkit */
1887 if (geteuid() != 0 &&
1888 (a == ACTION_POWEROFF ||
1889 a == ACTION_REBOOT ||
1890 a == ACTION_SUSPEND ||
1891 a == ACTION_HIBERNATE ||
1892 a == ACTION_HYBRID_SLEEP)) {
1893 r = reboot_with_logind(bus, a);
1898 r = start_unit(bus, args);
1899 if (r == EXIT_SUCCESS)
1905 static int check_unit_active(DBusConnection *bus, char **args) {
1906 const char * const check_states[] = {
1913 int r = 3; /* According to LSB: "program is not running" */
1918 STRV_FOREACH(name, args+1) {
1921 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1931 static int check_unit_failed(DBusConnection *bus, char **args) {
1932 const char * const check_states[] = {
1943 STRV_FOREACH(name, args+1) {
1946 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1956 static int kill_unit(DBusConnection *bus, char **args) {
1964 arg_kill_who = "all";
1966 STRV_FOREACH(name, args+1) {
1967 _cleanup_free_ char *n = NULL;
1969 n = unit_name_mangle(*name);
1973 r = bus_method_call_with_reply(
1975 "org.freedesktop.systemd1",
1976 "/org/freedesktop/systemd1",
1977 "org.freedesktop.systemd1.Manager",
1981 DBUS_TYPE_STRING, &n,
1982 DBUS_TYPE_STRING, &arg_kill_who,
1983 DBUS_TYPE_INT32, &arg_signal,
1991 static int set_cgroup(DBusConnection *bus, char **args) {
1992 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
1995 DBusMessageIter iter;
1997 _cleanup_free_ char *n = NULL;
1998 const char *runtime;
2003 dbus_error_init(&error);
2006 streq(args[0], "set-cgroup") ? "SetUnitControlGroups" :
2007 streq(args[0], "unset-group") ? "UnsetUnitControlGroups"
2008 : "UnsetUnitControlGroupAttributes";
2010 n = unit_name_mangle(args[1]);
2014 m = dbus_message_new_method_call(
2015 "org.freedesktop.systemd1",
2016 "/org/freedesktop/systemd1",
2017 "org.freedesktop.systemd1.Manager",
2022 dbus_message_iter_init_append(m, &iter);
2023 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
2026 r = bus_append_strv_iter(&iter, args + 2);
2030 runtime = arg_runtime ? "runtime" : "persistent";
2031 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2034 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2036 log_error("Failed to issue method call: %s", bus_error_message(&error));
2037 dbus_error_free(&error);
2044 static int set_cgroup_attr(DBusConnection *bus, char **args) {
2045 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2047 DBusMessageIter iter, sub, sub2;
2049 _cleanup_free_ char *n = NULL;
2050 const char *runtime;
2055 dbus_error_init(&error);
2057 if (strv_length(args) % 2 != 0) {
2058 log_error("Expecting an uneven number of arguments!");
2062 n = unit_name_mangle(args[1]);
2066 m = dbus_message_new_method_call(
2067 "org.freedesktop.systemd1",
2068 "/org/freedesktop/systemd1",
2069 "org.freedesktop.systemd1.Manager",
2070 "SetUnitControlGroupAttributes");
2074 dbus_message_iter_init_append(m, &iter);
2075 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2076 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub))
2079 STRV_FOREACH_PAIR(x, y, args + 2) {
2080 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
2081 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, x) ||
2082 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, y) ||
2083 !dbus_message_iter_close_container(&sub, &sub2))
2087 runtime = arg_runtime ? "runtime" : "persistent";
2088 if (!dbus_message_iter_close_container(&iter, &sub) ||
2089 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2092 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2094 log_error("Failed to issue method call: %s", bus_error_message(&error));
2095 dbus_error_free(&error);
2102 static int get_cgroup_attr(DBusConnection *bus, char **args) {
2103 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2105 DBusMessageIter iter;
2107 _cleanup_free_ char *n = NULL;
2108 _cleanup_strv_free_ char **list = NULL;
2114 dbus_error_init(&error);
2116 n = unit_name_mangle(args[1]);
2120 m = dbus_message_new_method_call(
2121 "org.freedesktop.systemd1",
2122 "/org/freedesktop/systemd1",
2123 "org.freedesktop.systemd1.Manager",
2124 "GetUnitControlGroupAttributes");
2128 dbus_message_iter_init_append(m, &iter);
2129 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
2132 r = bus_append_strv_iter(&iter, args + 2);
2136 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2138 log_error("Failed to issue method call: %s", bus_error_message(&error));
2139 dbus_error_free(&error);
2143 dbus_message_iter_init(reply, &iter);
2144 r = bus_parse_strv_iter(&iter, &list);
2146 log_error("Failed to parse value list.");
2150 STRV_FOREACH(a, list) {
2151 if (endswith(*a, "\n"))
2160 typedef struct ExecStatusInfo {
2168 usec_t start_timestamp;
2169 usec_t exit_timestamp;
2174 LIST_FIELDS(struct ExecStatusInfo, exec);
2177 static void exec_status_info_free(ExecStatusInfo *i) {
2186 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2187 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2188 DBusMessageIter sub2, sub3;
2192 int32_t code, status;
2198 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2201 dbus_message_iter_recurse(sub, &sub2);
2203 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2206 i->path = strdup(path);
2210 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2211 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2215 dbus_message_iter_recurse(&sub2, &sub3);
2216 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2217 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2218 dbus_message_iter_next(&sub3);
2222 i->argv = new0(char*, n+1);
2227 dbus_message_iter_recurse(&sub2, &sub3);
2228 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2231 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2232 dbus_message_iter_get_basic(&sub3, &s);
2233 dbus_message_iter_next(&sub3);
2235 i->argv[n] = strdup(s);
2242 if (!dbus_message_iter_next(&sub2) ||
2243 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2244 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2245 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2246 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2247 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2248 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2249 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2250 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2254 i->start_timestamp = (usec_t) start_timestamp;
2255 i->exit_timestamp = (usec_t) exit_timestamp;
2256 i->pid = (pid_t) pid;
2263 typedef struct UnitStatusInfo {
2265 const char *load_state;
2266 const char *active_state;
2267 const char *sub_state;
2268 const char *unit_file_state;
2270 const char *description;
2271 const char *following;
2273 char **documentation;
2275 const char *fragment_path;
2276 const char *source_path;
2277 const char *default_control_group;
2279 const char *load_error;
2282 usec_t inactive_exit_timestamp;
2283 usec_t inactive_exit_timestamp_monotonic;
2284 usec_t active_enter_timestamp;
2285 usec_t active_exit_timestamp;
2286 usec_t inactive_enter_timestamp;
2288 bool need_daemon_reload;
2293 const char *status_text;
2296 usec_t start_timestamp;
2297 usec_t exit_timestamp;
2299 int exit_code, exit_status;
2301 usec_t condition_timestamp;
2302 bool condition_result;
2305 unsigned n_accepted;
2306 unsigned n_connections;
2310 const char *sysfs_path;
2312 /* Mount, Automount */
2318 LIST_HEAD(ExecStatusInfo, exec);
2321 static void print_status_info(UnitStatusInfo *i) {
2323 const char *on, *off, *ss;
2325 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2326 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2329 arg_all * OUTPUT_SHOW_ALL |
2330 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2331 on_tty() * OUTPUT_COLOR |
2332 !arg_quiet * OUTPUT_WARN_CUTOFF |
2333 arg_full * OUTPUT_FULL_WIDTH;
2337 /* This shows pretty information about a unit. See
2338 * print_property() for a low-level property printer */
2340 printf("%s", strna(i->id));
2342 if (i->description && !streq_ptr(i->id, i->description))
2343 printf(" - %s", i->description);
2348 printf("\t Follow: unit currently follows state of %s\n", i->following);
2350 if (streq_ptr(i->load_state, "error")) {
2351 on = ansi_highlight_red(true);
2352 off = ansi_highlight_red(false);
2356 path = i->source_path ? i->source_path : i->fragment_path;
2359 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2360 else if (path && i->unit_file_state)
2361 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2363 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2365 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2367 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2369 if (streq_ptr(i->active_state, "failed")) {
2370 on = ansi_highlight_red(true);
2371 off = ansi_highlight_red(false);
2372 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2373 on = ansi_highlight_green(true);
2374 off = ansi_highlight_green(false);
2379 printf("\t Active: %s%s (%s)%s",
2381 strna(i->active_state),
2385 printf("\t Active: %s%s%s",
2387 strna(i->active_state),
2390 if (!isempty(i->result) && !streq(i->result, "success"))
2391 printf(" (Result: %s)", i->result);
2393 timestamp = (streq_ptr(i->active_state, "active") ||
2394 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2395 (streq_ptr(i->active_state, "inactive") ||
2396 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2397 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2398 i->active_exit_timestamp;
2400 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2401 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2404 printf(" since %s; %s\n", s2, s1);
2406 printf(" since %s\n", s2);
2410 if (!i->condition_result && i->condition_timestamp > 0) {
2411 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2412 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2415 printf("\t start condition failed at %s; %s\n", s2, s1);
2417 printf("\t start condition failed at %s\n", s2);
2421 printf("\t Device: %s\n", i->sysfs_path);
2423 printf("\t Where: %s\n", i->where);
2425 printf("\t What: %s\n", i->what);
2427 if (!strv_isempty(i->documentation)) {
2431 STRV_FOREACH(t, i->documentation) {
2433 printf("\t Docs: %s\n", *t);
2436 printf("\t %s\n", *t);
2441 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2443 LIST_FOREACH(exec, p, i->exec) {
2444 _cleanup_free_ char *t = NULL;
2447 /* Only show exited processes here */
2451 t = strv_join(p->argv, " ");
2452 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2454 good = is_clean_exit_lsb(p->code, p->status, NULL);
2456 on = ansi_highlight_red(true);
2457 off = ansi_highlight_red(false);
2461 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2463 if (p->code == CLD_EXITED) {
2466 printf("status=%i", p->status);
2468 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2473 printf("signal=%s", signal_to_string(p->status));
2475 printf(")%s\n", off);
2477 if (i->main_pid == p->pid &&
2478 i->start_timestamp == p->start_timestamp &&
2479 i->exit_timestamp == p->start_timestamp)
2480 /* Let's not show this twice */
2483 if (p->pid == i->control_pid)
2487 if (i->main_pid > 0 || i->control_pid > 0) {
2490 if (i->main_pid > 0) {
2491 printf("Main PID: %u", (unsigned) i->main_pid);
2494 _cleanup_free_ char *t = NULL;
2495 get_process_comm(i->main_pid, &t);
2498 } else if (i->exit_code > 0) {
2499 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2501 if (i->exit_code == CLD_EXITED) {
2504 printf("status=%i", i->exit_status);
2506 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2511 printf("signal=%s", signal_to_string(i->exit_status));
2516 if (i->main_pid > 0 && i->control_pid > 0)
2519 if (i->control_pid > 0) {
2520 _cleanup_free_ char *t = NULL;
2522 printf(" Control: %u", (unsigned) i->control_pid);
2524 get_process_comm(i->control_pid, &t);
2533 printf("\t Status: \"%s\"\n", i->status_text);
2535 if (i->default_control_group &&
2536 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2539 printf("\t CGroup: %s\n", i->default_control_group);
2541 if (arg_transport != TRANSPORT_SSH) {
2551 if (i->main_pid > 0)
2552 extra[k++] = i->main_pid;
2554 if (i->control_pid > 0)
2555 extra[k++] = i->control_pid;
2557 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, extra, k, flags);
2561 if (i->id && arg_transport != TRANSPORT_SSH) {
2563 if(arg_scope == UNIT_FILE_SYSTEM)
2564 show_journal_by_unit(stdout,
2568 i->inactive_exit_timestamp_monotonic,
2572 show_journal_by_user_unit(stdout,
2576 i->inactive_exit_timestamp_monotonic,
2582 if (i->need_daemon_reload)
2583 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2584 ansi_highlight_red(true),
2585 ansi_highlight_red(false),
2586 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2589 static void show_unit_help(UnitStatusInfo *i) {
2594 if (!i->documentation) {
2595 log_info("Documentation for %s not known.", i->id);
2599 STRV_FOREACH(p, i->documentation) {
2601 if (startswith(*p, "man:")) {
2604 char _cleanup_free_ *page = NULL, *section = NULL;
2605 const char *args[4] = { "man", NULL, NULL, NULL };
2610 if ((*p)[k-1] == ')')
2611 e = strrchr(*p, '(');
2614 page = strndup((*p) + 4, e - *p - 4);
2615 section = strndup(e + 1, *p + k - e - 2);
2616 if (!page || !section) {
2628 log_error("Failed to fork: %m");
2634 execvp(args[0], (char**) args);
2635 log_error("Failed to execute man: %m");
2636 _exit(EXIT_FAILURE);
2639 wait_for_terminate(pid, NULL);
2641 log_info("Can't show: %s", *p);
2645 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2651 switch (dbus_message_iter_get_arg_type(iter)) {
2653 case DBUS_TYPE_STRING: {
2656 dbus_message_iter_get_basic(iter, &s);
2659 if (streq(name, "Id"))
2661 else if (streq(name, "LoadState"))
2663 else if (streq(name, "ActiveState"))
2664 i->active_state = s;
2665 else if (streq(name, "SubState"))
2667 else if (streq(name, "Description"))
2669 else if (streq(name, "FragmentPath"))
2670 i->fragment_path = s;
2671 else if (streq(name, "SourcePath"))
2673 else if (streq(name, "DefaultControlGroup"))
2674 i->default_control_group = s;
2675 else if (streq(name, "StatusText"))
2677 else if (streq(name, "SysFSPath"))
2679 else if (streq(name, "Where"))
2681 else if (streq(name, "What"))
2683 else if (streq(name, "Following"))
2685 else if (streq(name, "UnitFileState"))
2686 i->unit_file_state = s;
2687 else if (streq(name, "Result"))
2694 case DBUS_TYPE_BOOLEAN: {
2697 dbus_message_iter_get_basic(iter, &b);
2699 if (streq(name, "Accept"))
2701 else if (streq(name, "NeedDaemonReload"))
2702 i->need_daemon_reload = b;
2703 else if (streq(name, "ConditionResult"))
2704 i->condition_result = b;
2709 case DBUS_TYPE_UINT32: {
2712 dbus_message_iter_get_basic(iter, &u);
2714 if (streq(name, "MainPID")) {
2716 i->main_pid = (pid_t) u;
2719 } else if (streq(name, "ControlPID"))
2720 i->control_pid = (pid_t) u;
2721 else if (streq(name, "ExecMainPID")) {
2723 i->main_pid = (pid_t) u;
2724 } else if (streq(name, "NAccepted"))
2726 else if (streq(name, "NConnections"))
2727 i->n_connections = u;
2732 case DBUS_TYPE_INT32: {
2735 dbus_message_iter_get_basic(iter, &j);
2737 if (streq(name, "ExecMainCode"))
2738 i->exit_code = (int) j;
2739 else if (streq(name, "ExecMainStatus"))
2740 i->exit_status = (int) j;
2745 case DBUS_TYPE_UINT64: {
2748 dbus_message_iter_get_basic(iter, &u);
2750 if (streq(name, "ExecMainStartTimestamp"))
2751 i->start_timestamp = (usec_t) u;
2752 else if (streq(name, "ExecMainExitTimestamp"))
2753 i->exit_timestamp = (usec_t) u;
2754 else if (streq(name, "ActiveEnterTimestamp"))
2755 i->active_enter_timestamp = (usec_t) u;
2756 else if (streq(name, "InactiveEnterTimestamp"))
2757 i->inactive_enter_timestamp = (usec_t) u;
2758 else if (streq(name, "InactiveExitTimestamp"))
2759 i->inactive_exit_timestamp = (usec_t) u;
2760 else if (streq(name, "InactiveExitTimestampMonotonic"))
2761 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2762 else if (streq(name, "ActiveExitTimestamp"))
2763 i->active_exit_timestamp = (usec_t) u;
2764 else if (streq(name, "ConditionTimestamp"))
2765 i->condition_timestamp = (usec_t) u;
2770 case DBUS_TYPE_ARRAY: {
2772 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2773 startswith(name, "Exec")) {
2774 DBusMessageIter sub;
2776 dbus_message_iter_recurse(iter, &sub);
2777 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2778 ExecStatusInfo *info;
2781 if (!(info = new0(ExecStatusInfo, 1)))
2784 if (!(info->name = strdup(name))) {
2789 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2794 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2796 dbus_message_iter_next(&sub);
2798 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2799 streq(name, "Documentation")) {
2801 DBusMessageIter sub;
2803 dbus_message_iter_recurse(iter, &sub);
2804 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2808 dbus_message_iter_get_basic(&sub, &s);
2810 l = strv_append(i->documentation, s);
2814 strv_free(i->documentation);
2815 i->documentation = l;
2817 dbus_message_iter_next(&sub);
2824 case DBUS_TYPE_STRUCT: {
2826 if (streq(name, "LoadError")) {
2827 DBusMessageIter sub;
2828 const char *n, *message;
2831 dbus_message_iter_recurse(iter, &sub);
2833 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2837 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2841 if (!isempty(message))
2842 i->load_error = message;
2852 static int print_property(const char *name, DBusMessageIter *iter) {
2856 /* This is a low-level property printer, see
2857 * print_status_info() for the nicer output */
2859 if (arg_property && !strv_find(arg_property, name))
2862 switch (dbus_message_iter_get_arg_type(iter)) {
2864 case DBUS_TYPE_STRUCT: {
2865 DBusMessageIter sub;
2866 dbus_message_iter_recurse(iter, &sub);
2868 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2871 dbus_message_iter_get_basic(&sub, &u);
2874 printf("%s=%u\n", name, (unsigned) u);
2876 printf("%s=\n", name);
2879 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2882 dbus_message_iter_get_basic(&sub, &s);
2884 if (arg_all || s[0])
2885 printf("%s=%s\n", name, s);
2888 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2889 const char *a = NULL, *b = NULL;
2891 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2892 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2894 if (arg_all || !isempty(a) || !isempty(b))
2895 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2903 case DBUS_TYPE_ARRAY:
2905 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2906 DBusMessageIter sub, sub2;
2908 dbus_message_iter_recurse(iter, &sub);
2909 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2913 dbus_message_iter_recurse(&sub, &sub2);
2915 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2916 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2917 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2919 dbus_message_iter_next(&sub);
2924 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2925 DBusMessageIter sub, sub2;
2927 dbus_message_iter_recurse(iter, &sub);
2928 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2929 const char *type, *path;
2931 dbus_message_iter_recurse(&sub, &sub2);
2933 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2934 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2935 printf("%s=%s\n", type, path);
2937 dbus_message_iter_next(&sub);
2942 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2943 DBusMessageIter sub, sub2;
2945 dbus_message_iter_recurse(iter, &sub);
2946 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2948 uint64_t value, next_elapse;
2950 dbus_message_iter_recurse(&sub, &sub2);
2952 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2953 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2954 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2955 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2957 printf("%s={ value=%s ; next_elapse=%s }\n",
2959 format_timespan(timespan1, sizeof(timespan1), value),
2960 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2963 dbus_message_iter_next(&sub);
2968 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2969 DBusMessageIter sub, sub2;
2971 dbus_message_iter_recurse(iter, &sub);
2972 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2973 const char *controller, *attr, *value;
2975 dbus_message_iter_recurse(&sub, &sub2);
2977 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2978 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2979 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2981 printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2987 dbus_message_iter_next(&sub);
2992 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2993 DBusMessageIter sub;
2995 dbus_message_iter_recurse(iter, &sub);
2996 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2997 ExecStatusInfo info;
3000 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3001 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3002 char _cleanup_free_ *t;
3004 t = strv_join(info.argv, " ");
3006 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3010 yes_no(info.ignore),
3011 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3012 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3013 (unsigned) info. pid,
3014 sigchld_code_to_string(info.code),
3016 info.code == CLD_EXITED ? "" : "/",
3017 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3021 strv_free(info.argv);
3023 dbus_message_iter_next(&sub);
3032 if (generic_print_property(name, iter, arg_all) > 0)
3036 printf("%s=[unprintable]\n", name);
3041 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3042 _cleanup_free_ DBusMessage *reply = NULL;
3043 const char *interface = "";
3045 DBusMessageIter iter, sub, sub2, sub3;
3046 UnitStatusInfo info;
3054 r = bus_method_call_with_reply(
3056 "org.freedesktop.systemd1",
3058 "org.freedesktop.DBus.Properties",
3062 DBUS_TYPE_STRING, &interface,
3067 if (!dbus_message_iter_init(reply, &iter) ||
3068 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3069 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3070 log_error("Failed to parse reply.");
3074 dbus_message_iter_recurse(&iter, &sub);
3081 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3084 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3085 dbus_message_iter_recurse(&sub, &sub2);
3087 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3088 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3089 log_error("Failed to parse reply.");
3093 dbus_message_iter_recurse(&sub2, &sub3);
3095 if (show_properties)
3096 r = print_property(name, &sub3);
3098 r = status_property(name, &sub3, &info);
3100 log_error("Failed to parse reply.");
3104 dbus_message_iter_next(&sub);
3109 if (!show_properties) {
3110 if (streq(verb, "help"))
3111 show_unit_help(&info);
3113 print_status_info(&info);
3116 strv_free(info.documentation);
3118 if (!streq_ptr(info.active_state, "active") &&
3119 !streq_ptr(info.active_state, "reloading") &&
3120 streq(verb, "status"))
3121 /* According to LSB: "program not running" */
3124 while ((p = info.exec)) {
3125 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3126 exec_status_info_free(p);
3132 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3133 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3134 const char *path = NULL;
3135 DBusError _cleanup_dbus_error_free_ error;
3138 dbus_error_init(&error);
3140 r = bus_method_call_with_reply(
3142 "org.freedesktop.systemd1",
3143 "/org/freedesktop/systemd1",
3144 "org.freedesktop.systemd1.Manager",
3148 DBUS_TYPE_UINT32, &pid,
3153 if (!dbus_message_get_args(reply, &error,
3154 DBUS_TYPE_OBJECT_PATH, &path,
3155 DBUS_TYPE_INVALID)) {
3156 log_error("Failed to parse reply: %s", bus_error_message(&error));
3160 r = show_one(verb, bus, path, false, new_line);
3164 static int show_all(const char* verb, DBusConnection *bus, bool show_properties, bool *new_line) {
3165 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3166 _cleanup_free_ struct unit_info *unit_infos = NULL;
3168 const struct unit_info *u;
3171 r = get_unit_list(bus, &reply, &unit_infos, &c);
3175 for (u = unit_infos; u < unit_infos + c; u++) {
3176 char _cleanup_free_ *p = NULL;
3178 if (!output_show_unit(u))
3181 p = unit_dbus_path_from_name(u->id);
3185 printf("%s -> '%s'\n", u->id, p);
3187 r = show_one(verb, bus, p, show_properties, new_line);
3195 static int show(DBusConnection *bus, char **args) {
3197 bool show_properties, show_status, new_line = false;
3203 show_properties = streq(args[0], "show");
3204 show_status = streq(args[0], "status");
3206 if (show_properties)
3207 pager_open_if_enabled();
3209 /* If no argument is specified inspect the manager itself */
3211 if (show_properties && strv_length(args) <= 1)
3212 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3214 if (show_status && strv_length(args) <= 1)
3215 return show_all(args[0], bus, false, &new_line);
3217 STRV_FOREACH(name, args+1) {
3220 if (safe_atou32(*name, &id) < 0) {
3221 _cleanup_free_ char *p = NULL, *n = NULL;
3222 /* Interpret as unit name */
3224 n = unit_name_mangle(*name);
3228 p = unit_dbus_path_from_name(n);
3232 r = show_one(args[0], bus, p, show_properties, &new_line);
3236 } else if (show_properties) {
3237 _cleanup_free_ char *p = NULL;
3239 /* Interpret as job id */
3240 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3243 r = show_one(args[0], bus, p, show_properties, &new_line);
3248 /* Interpret as PID */
3249 r = show_one_by_pid(args[0], bus, id, &new_line);
3258 static int dump(DBusConnection *bus, char **args) {
3259 _cleanup_free_ DBusMessage *reply = NULL;
3264 dbus_error_init(&error);
3266 pager_open_if_enabled();
3268 r = bus_method_call_with_reply(
3270 "org.freedesktop.systemd1",
3271 "/org/freedesktop/systemd1",
3272 "org.freedesktop.systemd1.Manager",
3280 if (!dbus_message_get_args(reply, &error,
3281 DBUS_TYPE_STRING, &text,
3282 DBUS_TYPE_INVALID)) {
3283 log_error("Failed to parse reply: %s", bus_error_message(&error));
3284 dbus_error_free(&error);
3288 fputs(text, stdout);
3292 static int snapshot(DBusConnection *bus, char **args) {
3293 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3296 dbus_bool_t cleanup = FALSE;
3297 DBusMessageIter iter, sub;
3300 *interface = "org.freedesktop.systemd1.Unit",
3302 _cleanup_free_ char *n = NULL;
3304 dbus_error_init(&error);
3306 if (strv_length(args) > 1)
3307 n = snapshot_name_mangle(args[1]);
3313 r = bus_method_call_with_reply (
3315 "org.freedesktop.systemd1",
3316 "/org/freedesktop/systemd1",
3317 "org.freedesktop.systemd1.Manager",
3321 DBUS_TYPE_STRING, &n,
3322 DBUS_TYPE_BOOLEAN, &cleanup,
3327 if (!dbus_message_get_args(reply, &error,
3328 DBUS_TYPE_OBJECT_PATH, &path,
3329 DBUS_TYPE_INVALID)) {
3330 log_error("Failed to parse reply: %s", bus_error_message(&error));
3331 dbus_error_free(&error);
3335 dbus_message_unref(reply);
3338 r = bus_method_call_with_reply (
3340 "org.freedesktop.systemd1",
3342 "org.freedesktop.DBus.Properties",
3346 DBUS_TYPE_STRING, &interface,
3347 DBUS_TYPE_STRING, &property,
3352 if (!dbus_message_iter_init(reply, &iter) ||
3353 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3354 log_error("Failed to parse reply.");
3358 dbus_message_iter_recurse(&iter, &sub);
3360 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3361 log_error("Failed to parse reply.");
3365 dbus_message_iter_get_basic(&sub, &id);
3373 static int delete_snapshot(DBusConnection *bus, char **args) {
3378 STRV_FOREACH(name, args+1) {
3379 _cleanup_free_ char *n = NULL;
3382 n = snapshot_name_mangle(*name);
3386 r = bus_method_call_with_reply(
3388 "org.freedesktop.systemd1",
3389 "/org/freedesktop/systemd1",
3390 "org.freedesktop.systemd1.Manager",
3394 DBUS_TYPE_STRING, &n,
3403 static int daemon_reload(DBusConnection *bus, char **args) {
3408 if (arg_action == ACTION_RELOAD)
3410 else if (arg_action == ACTION_REEXEC)
3411 method = "Reexecute";
3413 assert(arg_action == ACTION_SYSTEMCTL);
3416 streq(args[0], "clear-jobs") ||
3417 streq(args[0], "cancel") ? "ClearJobs" :
3418 streq(args[0], "daemon-reexec") ? "Reexecute" :
3419 streq(args[0], "reset-failed") ? "ResetFailed" :
3420 streq(args[0], "halt") ? "Halt" :
3421 streq(args[0], "poweroff") ? "PowerOff" :
3422 streq(args[0], "reboot") ? "Reboot" :
3423 streq(args[0], "kexec") ? "KExec" :
3424 streq(args[0], "exit") ? "Exit" :
3425 /* "daemon-reload" */ "Reload";
3428 r = bus_method_call_with_reply(
3430 "org.freedesktop.systemd1",
3431 "/org/freedesktop/systemd1",
3432 "org.freedesktop.systemd1.Manager",
3438 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3439 /* There's always a fallback possible for
3440 * legacy actions. */
3442 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3443 /* On reexecution, we expect a disconnect, not
3447 log_error("Failed to issue method call: %s", bus_error_message(&error));
3449 dbus_error_free(&error);
3453 static int reset_failed(DBusConnection *bus, char **args) {
3457 if (strv_length(args) <= 1)
3458 return daemon_reload(bus, args);
3460 STRV_FOREACH(name, args+1) {
3461 _cleanup_free_ char *n;
3463 n = unit_name_mangle(*name);
3467 r = bus_method_call_with_reply(
3469 "org.freedesktop.systemd1",
3470 "/org/freedesktop/systemd1",
3471 "org.freedesktop.systemd1.Manager",
3475 DBUS_TYPE_STRING, &n,
3484 static int show_enviroment(DBusConnection *bus, char **args) {
3485 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3486 DBusMessageIter iter, sub, sub2;
3489 *interface = "org.freedesktop.systemd1.Manager",
3490 *property = "Environment";
3492 pager_open_if_enabled();
3494 r = bus_method_call_with_reply(
3496 "org.freedesktop.systemd1",
3497 "/org/freedesktop/systemd1",
3498 "org.freedesktop.DBus.Properties",
3502 DBUS_TYPE_STRING, &interface,
3503 DBUS_TYPE_STRING, &property,
3508 if (!dbus_message_iter_init(reply, &iter) ||
3509 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3510 log_error("Failed to parse reply.");
3514 dbus_message_iter_recurse(&iter, &sub);
3516 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3517 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3518 log_error("Failed to parse reply.");
3522 dbus_message_iter_recurse(&sub, &sub2);
3524 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3527 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3528 log_error("Failed to parse reply.");
3532 dbus_message_iter_get_basic(&sub2, &text);
3535 dbus_message_iter_next(&sub2);
3541 static int switch_root(DBusConnection *bus, char **args) {
3544 _cleanup_free_ char *init = NULL;
3546 l = strv_length(args);
3547 if (l < 2 || l > 3) {
3548 log_error("Wrong number of arguments.");
3555 init = strdup(args[2]);
3557 parse_env_file("/proc/cmdline", WHITESPACE,
3567 log_debug("switching root - root: %s; init: %s", root, init);
3569 return bus_method_call_with_reply(
3571 "org.freedesktop.systemd1",
3572 "/org/freedesktop/systemd1",
3573 "org.freedesktop.systemd1.Manager",
3577 DBUS_TYPE_STRING, &root,
3578 DBUS_TYPE_STRING, &init,
3582 static int set_environment(DBusConnection *bus, char **args) {
3583 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3586 DBusMessageIter iter;
3592 dbus_error_init(&error);
3594 method = streq(args[0], "set-environment")
3596 : "UnsetEnvironment";
3598 m = dbus_message_new_method_call(
3599 "org.freedesktop.systemd1",
3600 "/org/freedesktop/systemd1",
3601 "org.freedesktop.systemd1.Manager",
3606 dbus_message_iter_init_append(m, &iter);
3608 r = bus_append_strv_iter(&iter, args + 1);
3612 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3614 log_error("Failed to issue method call: %s", bus_error_message(&error));
3615 dbus_error_free(&error);
3622 static int enable_sysv_units(char **args) {
3625 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3626 const char *verb = args[0];
3627 unsigned f = 1, t = 1;
3630 if (arg_scope != UNIT_FILE_SYSTEM)
3633 if (!streq(verb, "enable") &&
3634 !streq(verb, "disable") &&
3635 !streq(verb, "is-enabled"))
3638 /* Processes all SysV units, and reshuffles the array so that
3639 * afterwards only the native units remain */
3642 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3647 for (f = 1; args[f]; f++) {
3650 bool found_native = false, found_sysv;
3652 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3653 char **k, *l, *q = NULL;
3660 if (!endswith(name, ".service"))
3663 if (path_is_absolute(name))
3666 STRV_FOREACH(k, paths.unit_path) {
3669 if (!isempty(arg_root))
3670 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3672 asprintf(&p, "%s/%s", *k, name);
3679 found_native = access(p, F_OK) >= 0;
3690 if (!isempty(arg_root))
3691 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3693 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3699 p[strlen(p) - sizeof(".service") + 1] = 0;
3700 found_sysv = access(p, F_OK) >= 0;
3707 /* Mark this entry, so that we don't try enabling it as native unit */
3708 args[f] = (char*) "";
3710 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3712 if (!isempty(arg_root))
3713 argv[c++] = q = strappend("--root=", arg_root);
3715 argv[c++] = path_get_file_name(p);
3717 streq(verb, "enable") ? "on" :
3718 streq(verb, "disable") ? "off" : "--level=5";
3721 l = strv_join((char**)argv, " ");
3729 log_info("Executing %s", l);
3734 log_error("Failed to fork: %m");
3739 } else if (pid == 0) {
3742 execv(argv[0], (char**) argv);
3743 _exit(EXIT_FAILURE);
3749 j = wait_for_terminate(pid, &status);
3751 log_error("Failed to wait for child: %s", strerror(-r));
3756 if (status.si_code == CLD_EXITED) {
3757 if (streq(verb, "is-enabled")) {
3758 if (status.si_status == 0) {
3767 } else if (status.si_status != 0) {
3778 lookup_paths_free(&paths);
3780 /* Drop all SysV units */
3781 for (f = 1, t = 1; args[f]; f++) {
3783 if (isempty(args[f]))
3786 args[t++] = args[f];
3795 static int mangle_names(char **original_names, char ***mangled_names) {
3796 char **i, **l, **name;
3798 l = new(char*, strv_length(original_names) + 1);
3803 STRV_FOREACH(name, original_names) {
3805 /* When enabling units qualified path names are OK,
3806 * too, hence allow them explicitly. */
3811 *i = unit_name_mangle(*name);
3827 static int enable_unit(DBusConnection *bus, char **args) {
3828 const char *verb = args[0];
3829 UnitFileChange *changes = NULL;
3830 unsigned n_changes = 0, i;
3831 int carries_install_info = -1;
3832 DBusMessage _cleanup_dbus_message_unref_ *m = NULL, *reply = NULL;
3834 DBusError _cleanup_dbus_error_free_ error;
3835 char _cleanup_strv_free_ **mangled_names = NULL;
3837 dbus_error_init(&error);
3839 r = enable_sysv_units(args);
3846 if (!bus || avoid_bus()) {
3847 if (streq(verb, "enable")) {
3848 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3849 carries_install_info = r;
3850 } else if (streq(verb, "disable"))
3851 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3852 else if (streq(verb, "reenable")) {
3853 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3854 carries_install_info = r;
3855 } else if (streq(verb, "link"))
3856 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3857 else if (streq(verb, "preset")) {
3858 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3859 carries_install_info = r;
3860 } else if (streq(verb, "mask"))
3861 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3862 else if (streq(verb, "unmask"))
3863 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3865 assert_not_reached("Unknown verb");
3868 log_error("Operation failed: %s", strerror(-r));
3873 for (i = 0; i < n_changes; i++) {
3874 if (changes[i].type == UNIT_FILE_SYMLINK)
3875 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3877 log_info("rm '%s'", changes[i].path);
3884 bool send_force = true, expect_carries_install_info = false;
3886 DBusMessageIter iter, sub, sub2;
3888 if (streq(verb, "enable")) {
3889 method = "EnableUnitFiles";
3890 expect_carries_install_info = true;
3891 } else if (streq(verb, "disable")) {
3892 method = "DisableUnitFiles";
3894 } else if (streq(verb, "reenable")) {
3895 method = "ReenableUnitFiles";
3896 expect_carries_install_info = true;
3897 } else if (streq(verb, "link"))
3898 method = "LinkUnitFiles";
3899 else if (streq(verb, "preset")) {
3900 method = "PresetUnitFiles";
3901 expect_carries_install_info = true;
3902 } else if (streq(verb, "mask"))
3903 method = "MaskUnitFiles";
3904 else if (streq(verb, "unmask")) {
3905 method = "UnmaskUnitFiles";
3908 assert_not_reached("Unknown verb");
3910 m = dbus_message_new_method_call(
3911 "org.freedesktop.systemd1",
3912 "/org/freedesktop/systemd1",
3913 "org.freedesktop.systemd1.Manager",
3920 dbus_message_iter_init_append(m, &iter);
3922 r = mangle_names(args+1, &mangled_names);
3926 r = bus_append_strv_iter(&iter, mangled_names);
3928 log_error("Failed to append unit files.");
3933 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3934 log_error("Failed to append runtime boolean.");
3942 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3943 log_error("Failed to append force boolean.");
3949 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3951 log_error("Failed to issue method call: %s", bus_error_message(&error));
3956 if (!dbus_message_iter_init(reply, &iter)) {
3957 log_error("Failed to initialize iterator.");
3961 if (expect_carries_install_info) {
3962 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3964 log_error("Failed to parse reply.");
3968 carries_install_info = b;
3971 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3972 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3973 log_error("Failed to parse reply.");
3978 dbus_message_iter_recurse(&iter, &sub);
3979 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3980 const char *type, *path, *source;
3982 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3983 log_error("Failed to parse reply.");
3988 dbus_message_iter_recurse(&sub, &sub2);
3990 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3991 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3992 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3993 log_error("Failed to parse reply.");
3999 if (streq(type, "symlink"))
4000 log_info("ln -s '%s' '%s'", source, path);
4002 log_info("rm '%s'", path);
4005 dbus_message_iter_next(&sub);
4008 /* Try to reload if enabeld */
4010 r = daemon_reload(bus, args);
4013 if (carries_install_info == 0)
4015 "The unit files have no [Install] section. They are not meant to be enabled\n"
4016 "using systemctl.\n"
4017 "Possible reasons for having this kind of units are:\n"
4018 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4019 " .wants/ or .requires/ directory.\n"
4020 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4021 " a requirement dependency on it.\n"
4022 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4023 " D-Bus, udev, scripted systemctl call, ...).\n");
4026 unit_file_changes_free(changes, n_changes);
4031 static int unit_is_enabled(DBusConnection *bus, char **args) {
4032 DBusError _cleanup_dbus_error_free_ error;
4034 DBusMessage _cleanup_dbus_message_unref_ *reply = NULL;
4038 dbus_error_init(&error);
4040 r = enable_sysv_units(args);
4046 if (!bus || avoid_bus()) {
4048 STRV_FOREACH(name, args+1) {
4049 UnitFileState state;
4051 state = unit_file_get_state(arg_scope, arg_root, *name);
4055 if (state == UNIT_FILE_ENABLED ||
4056 state == UNIT_FILE_ENABLED_RUNTIME ||
4057 state == UNIT_FILE_STATIC)
4061 puts(unit_file_state_to_string(state));
4065 STRV_FOREACH(name, args+1) {
4068 r = bus_method_call_with_reply (
4070 "org.freedesktop.systemd1",
4071 "/org/freedesktop/systemd1",
4072 "org.freedesktop.systemd1.Manager",
4076 DBUS_TYPE_STRING, name,
4081 if (!dbus_message_get_args(reply, &error,
4082 DBUS_TYPE_STRING, &s,
4083 DBUS_TYPE_INVALID)) {
4084 log_error("Failed to parse reply: %s", bus_error_message(&error));
4088 dbus_message_unref(reply);
4091 if (streq(s, "enabled") ||
4092 streq(s, "enabled-runtime") ||
4101 return enabled ? 0 : 1;
4104 static int systemctl_help(void) {
4106 pager_open_if_enabled();
4108 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4109 "Query or send control commands to the systemd manager.\n\n"
4110 " -h --help Show this help\n"
4111 " --version Show package version\n"
4112 " -t --type=TYPE List only units of a particular type\n"
4113 " -p --property=NAME Show only properties by this name\n"
4114 " -a --all Show all units/properties, including dead/empty ones\n"
4115 " --failed Show only failed units\n"
4116 " --full Don't ellipsize unit names on output\n"
4117 " --fail When queueing a new job, fail if conflicting jobs are\n"
4119 " --ignore-dependencies\n"
4120 " When queueing a new job, ignore all its dependencies\n"
4121 " -i --ignore-inhibitors\n"
4122 " When shutting down or sleeping, ignore inhibitors\n"
4123 " --kill-who=WHO Who to send signal to\n"
4124 " -s --signal=SIGNAL Which signal to send\n"
4125 " -H --host=[USER@]HOST\n"
4126 " Show information for remote host\n"
4127 " -P --privileged Acquire privileges before execution\n"
4128 " -q --quiet Suppress output\n"
4129 " --no-block Do not wait until operation finished\n"
4130 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4131 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4133 " --no-legend Do not print a legend (column headers and hints)\n"
4134 " --no-pager Do not pipe output into a pager\n"
4135 " --no-ask-password\n"
4136 " Do not ask for system passwords\n"
4137 " --system Connect to system manager\n"
4138 " --user Connect to user service manager\n"
4139 " --global Enable/disable unit files globally\n"
4140 " -f --force When enabling unit files, override existing symlinks\n"
4141 " When shutting down, execute action immediately\n"
4142 " --root=PATH Enable unit files in the specified root directory\n"
4143 " --runtime Enable unit files only temporarily until next reboot\n"
4144 " -n --lines=INTEGER Journal entries to show\n"
4145 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4146 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4148 " list-units List loaded units\n"
4149 " start [NAME...] Start (activate) one or more units\n"
4150 " stop [NAME...] Stop (deactivate) one or more units\n"
4151 " reload [NAME...] Reload one or more units\n"
4152 " restart [NAME...] Start or restart one or more units\n"
4153 " try-restart [NAME...] Restart one or more units if active\n"
4154 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4155 " otherwise start or restart\n"
4156 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4157 " otherwise restart if active\n"
4158 " isolate [NAME] Start one unit and stop all others\n"
4159 " kill [NAME...] Send signal to processes of a unit\n"
4160 " is-active [NAME...] Check whether units are active\n"
4161 " is-failed [NAME...] Check whether units are failed\n"
4162 " status [NAME...|PID...] Show runtime status of one or more units\n"
4163 " show [NAME...|JOB...] Show properties of one or more\n"
4164 " units/jobs or the manager\n"
4165 " help [NAME...|PID...] Show manual for one or more units\n"
4166 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4168 " get-cgroup-attr [NAME] [ATTR] ...\n"
4169 " Get control group attrubute\n"
4170 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4171 " Set control group attribute\n"
4172 " unset-cgroup-attr [NAME] [ATTR...]\n"
4173 " Unset control group attribute\n"
4174 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4175 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4176 " load [NAME...] Load one or more units\n"
4177 " list-dependencies [NAME] Recursively show units which are required\n"
4178 " or wanted by this unit\n\n"
4179 "Unit File Commands:\n"
4180 " list-unit-files List installed unit files\n"
4181 " enable [NAME...] Enable one or more unit files\n"
4182 " disable [NAME...] Disable one or more unit files\n"
4183 " reenable [NAME...] Reenable one or more unit files\n"
4184 " preset [NAME...] Enable/disable one or more unit files\n"
4185 " based on preset configuration\n"
4186 " mask [NAME...] Mask one or more units\n"
4187 " unmask [NAME...] Unmask one or more units\n"
4188 " link [PATH...] Link one or more units files into\n"
4189 " the search path\n"
4190 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4192 " list-jobs List jobs\n"
4193 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4194 "Status Commands:\n"
4195 " dump Dump server status\n"
4196 "Snapshot Commands:\n"
4197 " snapshot [NAME] Create a snapshot\n"
4198 " delete [NAME...] Remove one or more snapshots\n\n"
4199 "Environment Commands:\n"
4200 " show-environment Dump environment\n"
4201 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4202 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4203 "Manager Lifecycle Commands:\n"
4204 " daemon-reload Reload systemd manager configuration\n"
4205 " daemon-reexec Reexecute systemd manager\n\n"
4206 "System Commands:\n"
4207 " default Enter system default mode\n"
4208 " rescue Enter system rescue mode\n"
4209 " emergency Enter system emergency mode\n"
4210 " halt Shut down and halt the system\n"
4211 " poweroff Shut down and power-off the system\n"
4212 " reboot Shut down and reboot the system\n"
4213 " kexec Shut down and reboot the system with kexec\n"
4214 " exit Request user instance exit\n"
4215 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4216 " suspend Suspend the system\n"
4217 " hibernate Hibernate the system\n"
4218 " hybrid-sleep Hibernate and suspend the system\n",
4219 program_invocation_short_name);
4224 static int halt_help(void) {
4226 printf("%s [OPTIONS...]\n\n"
4227 "%s the system.\n\n"
4228 " --help Show this help\n"
4229 " --halt Halt the machine\n"
4230 " -p --poweroff Switch off the machine\n"
4231 " --reboot Reboot the machine\n"
4232 " -f --force Force immediate halt/power-off/reboot\n"
4233 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4234 " -d --no-wtmp Don't write wtmp record\n"
4235 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4236 program_invocation_short_name,
4237 arg_action == ACTION_REBOOT ? "Reboot" :
4238 arg_action == ACTION_POWEROFF ? "Power off" :
4244 static int shutdown_help(void) {
4246 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4247 "Shut down the system.\n\n"
4248 " --help Show this help\n"
4249 " -H --halt Halt the machine\n"
4250 " -P --poweroff Power-off the machine\n"
4251 " -r --reboot Reboot the machine\n"
4252 " -h Equivalent to --poweroff, overridden by --halt\n"
4253 " -k Don't halt/power-off/reboot, just send warnings\n"
4254 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4255 " -c Cancel a pending shutdown\n",
4256 program_invocation_short_name);
4261 static int telinit_help(void) {
4263 printf("%s [OPTIONS...] {COMMAND}\n\n"
4264 "Send control commands to the init daemon.\n\n"
4265 " --help Show this help\n"
4266 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4268 " 0 Power-off the machine\n"
4269 " 6 Reboot the machine\n"
4270 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4271 " 1, s, S Enter rescue mode\n"
4272 " q, Q Reload init daemon configuration\n"
4273 " u, U Reexecute init daemon\n",
4274 program_invocation_short_name);
4279 static int runlevel_help(void) {
4281 printf("%s [OPTIONS...]\n\n"
4282 "Prints the previous and current runlevel of the init system.\n\n"
4283 " --help Show this help\n",
4284 program_invocation_short_name);
4289 static int help_types(void) {
4292 puts("Available unit types:");
4293 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4294 if (unit_type_table[i])
4295 puts(unit_type_table[i]);
4297 puts("\nAvailable unit load states: ");
4298 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4299 if (unit_type_table[i])
4300 puts(unit_load_state_table[i]);
4305 static int systemctl_parse_argv(int argc, char *argv[]) {
4310 ARG_IGNORE_DEPENDENCIES,
4323 ARG_NO_ASK_PASSWORD,
4329 static const struct option options[] = {
4330 { "help", no_argument, NULL, 'h' },
4331 { "version", no_argument, NULL, ARG_VERSION },
4332 { "type", required_argument, NULL, 't' },
4333 { "property", required_argument, NULL, 'p' },
4334 { "all", no_argument, NULL, 'a' },
4335 { "failed", no_argument, NULL, ARG_FAILED },
4336 { "full", no_argument, NULL, ARG_FULL },
4337 { "fail", no_argument, NULL, ARG_FAIL },
4338 { "irreversible", no_argument, NULL, ARG_IRREVERSIBLE },
4339 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4340 { "ignore-inhibitors", no_argument, NULL, 'i' },
4341 { "user", no_argument, NULL, ARG_USER },
4342 { "system", no_argument, NULL, ARG_SYSTEM },
4343 { "global", no_argument, NULL, ARG_GLOBAL },
4344 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4345 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4346 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4347 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4348 { "quiet", no_argument, NULL, 'q' },
4349 { "root", required_argument, NULL, ARG_ROOT },
4350 { "force", no_argument, NULL, ARG_FORCE },
4351 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4352 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4353 { "signal", required_argument, NULL, 's' },
4354 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4355 { "host", required_argument, NULL, 'H' },
4356 { "privileged",no_argument, NULL, 'P' },
4357 { "runtime", no_argument, NULL, ARG_RUNTIME },
4358 { "lines", required_argument, NULL, 'n' },
4359 { "output", required_argument, NULL, 'o' },
4360 { NULL, 0, NULL, 0 }
4368 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4377 puts(PACKAGE_STRING);
4378 puts(SYSTEMD_FEATURES);
4382 if (streq(optarg, "help")) {
4387 if (unit_type_from_string(optarg) >= 0) {
4391 if (unit_load_state_from_string(optarg) >= 0) {
4392 arg_load_state = optarg;
4395 log_error("Unkown unit type or load state '%s'.",
4397 log_info("Use -t help to see a list of allowed values.");
4402 /* Make sure that if the empty property list
4403 was specified, we won't show any properties. */
4404 const char *source = isempty(optarg) ? " " : optarg;
4406 FOREACH_WORD_SEPARATOR(word, size, source, ",", state) {
4407 char _cleanup_free_ *prop;
4410 prop = strndup(word, size);
4414 tmp = strv_append(arg_property, prop);
4418 strv_free(arg_property);
4422 /* If the user asked for a particular
4423 * property, show it to him, even if it is
4435 arg_job_mode = "fail";
4438 case ARG_IRREVERSIBLE:
4439 arg_job_mode = "replace-irreversibly";
4442 case ARG_IGNORE_DEPENDENCIES:
4443 arg_job_mode = "ignore-dependencies";
4447 arg_scope = UNIT_FILE_USER;
4451 arg_scope = UNIT_FILE_SYSTEM;
4455 arg_scope = UNIT_FILE_GLOBAL;
4459 arg_no_block = true;
4463 arg_no_legend = true;
4467 arg_no_pager = true;
4499 arg_no_reload = true;
4503 arg_kill_who = optarg;
4507 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4508 log_error("Failed to parse signal string %s.", optarg);
4513 case ARG_NO_ASK_PASSWORD:
4514 arg_ask_password = false;
4518 arg_transport = TRANSPORT_POLKIT;
4522 arg_transport = TRANSPORT_SSH;
4531 if (safe_atou(optarg, &arg_lines) < 0) {
4532 log_error("Failed to parse lines '%s'", optarg);
4538 arg_output = output_mode_from_string(optarg);
4539 if (arg_output < 0) {
4540 log_error("Unknown output '%s'.", optarg);
4546 arg_ignore_inhibitors = true;
4553 log_error("Unknown option code '%c'.", c);
4558 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4559 log_error("Cannot access user instance remotely.");
4566 static int halt_parse_argv(int argc, char *argv[]) {
4575 static const struct option options[] = {
4576 { "help", no_argument, NULL, ARG_HELP },
4577 { "halt", no_argument, NULL, ARG_HALT },
4578 { "poweroff", no_argument, NULL, 'p' },
4579 { "reboot", no_argument, NULL, ARG_REBOOT },
4580 { "force", no_argument, NULL, 'f' },
4581 { "wtmp-only", no_argument, NULL, 'w' },
4582 { "no-wtmp", no_argument, NULL, 'd' },
4583 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4584 { NULL, 0, NULL, 0 }
4592 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4593 if (runlevel == '0' || runlevel == '6')
4596 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4604 arg_action = ACTION_HALT;
4608 if (arg_action != ACTION_REBOOT)
4609 arg_action = ACTION_POWEROFF;
4613 arg_action = ACTION_REBOOT;
4635 /* Compatibility nops */
4642 log_error("Unknown option code '%c'.", c);
4647 if (optind < argc) {
4648 log_error("Too many arguments.");
4655 static int parse_time_spec(const char *t, usec_t *_u) {
4659 if (streq(t, "now"))
4661 else if (!strchr(t, ':')) {
4664 if (safe_atou64(t, &u) < 0)
4667 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4676 hour = strtol(t, &e, 10);
4677 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4680 minute = strtol(e+1, &e, 10);
4681 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4684 n = now(CLOCK_REALTIME);
4685 s = (time_t) (n / USEC_PER_SEC);
4688 assert_se(localtime_r(&s, &tm));
4690 tm.tm_hour = (int) hour;
4691 tm.tm_min = (int) minute;
4694 assert_se(s = mktime(&tm));
4696 *_u = (usec_t) s * USEC_PER_SEC;
4699 *_u += USEC_PER_DAY;
4705 static int shutdown_parse_argv(int argc, char *argv[]) {
4712 static const struct option options[] = {
4713 { "help", no_argument, NULL, ARG_HELP },
4714 { "halt", no_argument, NULL, 'H' },
4715 { "poweroff", no_argument, NULL, 'P' },
4716 { "reboot", no_argument, NULL, 'r' },
4717 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4718 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4719 { NULL, 0, NULL, 0 }
4727 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4735 arg_action = ACTION_HALT;
4739 arg_action = ACTION_POWEROFF;
4744 arg_action = ACTION_KEXEC;
4746 arg_action = ACTION_REBOOT;
4750 arg_action = ACTION_KEXEC;
4754 if (arg_action != ACTION_HALT)
4755 arg_action = ACTION_POWEROFF;
4768 /* Compatibility nops */
4772 arg_action = ACTION_CANCEL_SHUTDOWN;
4779 log_error("Unknown option code '%c'.", c);
4784 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4785 r = parse_time_spec(argv[optind], &arg_when);
4787 log_error("Failed to parse time specification: %s", argv[optind]);
4791 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4793 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4794 /* No time argument for shutdown cancel */
4795 arg_wall = argv + optind;
4796 else if (argc > optind + 1)
4797 /* We skip the time argument */
4798 arg_wall = argv + optind + 1;
4805 static int telinit_parse_argv(int argc, char *argv[]) {
4812 static const struct option options[] = {
4813 { "help", no_argument, NULL, ARG_HELP },
4814 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4815 { NULL, 0, NULL, 0 }
4818 static const struct {
4822 { '0', ACTION_POWEROFF },
4823 { '6', ACTION_REBOOT },
4824 { '1', ACTION_RESCUE },
4825 { '2', ACTION_RUNLEVEL2 },
4826 { '3', ACTION_RUNLEVEL3 },
4827 { '4', ACTION_RUNLEVEL4 },
4828 { '5', ACTION_RUNLEVEL5 },
4829 { 's', ACTION_RESCUE },
4830 { 'S', ACTION_RESCUE },
4831 { 'q', ACTION_RELOAD },
4832 { 'Q', ACTION_RELOAD },
4833 { 'u', ACTION_REEXEC },
4834 { 'U', ACTION_REEXEC }
4843 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4858 log_error("Unknown option code '%c'.", c);
4863 if (optind >= argc) {
4868 if (optind + 1 < argc) {
4869 log_error("Too many arguments.");
4873 if (strlen(argv[optind]) != 1) {
4874 log_error("Expected single character argument.");
4878 for (i = 0; i < ELEMENTSOF(table); i++)
4879 if (table[i].from == argv[optind][0])
4882 if (i >= ELEMENTSOF(table)) {
4883 log_error("Unknown command '%s'.", argv[optind]);
4887 arg_action = table[i].to;
4894 static int runlevel_parse_argv(int argc, char *argv[]) {
4900 static const struct option options[] = {
4901 { "help", no_argument, NULL, ARG_HELP },
4902 { NULL, 0, NULL, 0 }
4910 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4921 log_error("Unknown option code '%c'.", c);
4926 if (optind < argc) {
4927 log_error("Too many arguments.");
4934 static int parse_argv(int argc, char *argv[]) {
4938 if (program_invocation_short_name) {
4940 if (strstr(program_invocation_short_name, "halt")) {
4941 arg_action = ACTION_HALT;
4942 return halt_parse_argv(argc, argv);
4943 } else if (strstr(program_invocation_short_name, "poweroff")) {
4944 arg_action = ACTION_POWEROFF;
4945 return halt_parse_argv(argc, argv);
4946 } else if (strstr(program_invocation_short_name, "reboot")) {
4948 arg_action = ACTION_KEXEC;
4950 arg_action = ACTION_REBOOT;
4951 return halt_parse_argv(argc, argv);
4952 } else if (strstr(program_invocation_short_name, "shutdown")) {
4953 arg_action = ACTION_POWEROFF;
4954 return shutdown_parse_argv(argc, argv);
4955 } else if (strstr(program_invocation_short_name, "init")) {
4957 if (sd_booted() > 0) {
4958 arg_action = ACTION_INVALID;
4959 return telinit_parse_argv(argc, argv);
4961 /* Hmm, so some other init system is
4962 * running, we need to forward this
4963 * request to it. For now we simply
4964 * guess that it is Upstart. */
4966 execv("/lib/upstart/telinit", argv);
4968 log_error("Couldn't find an alternative telinit implementation to spawn.");
4972 } else if (strstr(program_invocation_short_name, "runlevel")) {
4973 arg_action = ACTION_RUNLEVEL;
4974 return runlevel_parse_argv(argc, argv);
4978 arg_action = ACTION_SYSTEMCTL;
4979 return systemctl_parse_argv(argc, argv);
4982 static int action_to_runlevel(void) {
4984 static const char table[_ACTION_MAX] = {
4985 [ACTION_HALT] = '0',
4986 [ACTION_POWEROFF] = '0',
4987 [ACTION_REBOOT] = '6',
4988 [ACTION_RUNLEVEL2] = '2',
4989 [ACTION_RUNLEVEL3] = '3',
4990 [ACTION_RUNLEVEL4] = '4',
4991 [ACTION_RUNLEVEL5] = '5',
4992 [ACTION_RESCUE] = '1'
4995 assert(arg_action < _ACTION_MAX);
4997 return table[arg_action];
5000 static int talk_upstart(void) {
5001 DBusMessage _cleanup_dbus_message_unref_ *m = NULL, *reply = NULL;
5002 DBusError _cleanup_dbus_error_free_ error;
5003 int previous, rl, r;
5005 env1_buf[] = "RUNLEVEL=X",
5006 env2_buf[] = "PREVLEVEL=X";
5007 char *env1 = env1_buf, *env2 = env2_buf;
5008 const char *emit = "runlevel";
5009 dbus_bool_t b_false = FALSE;
5010 DBusMessageIter iter, sub;
5011 DBusConnection *bus;
5013 dbus_error_init(&error);
5015 if (!(rl = action_to_runlevel()))
5018 if (utmp_get_runlevel(&previous, NULL) < 0)
5021 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5022 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5027 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5032 if ((r = bus_check_peercred(bus)) < 0) {
5033 log_error("Failed to verify owner of bus.");
5037 if (!(m = dbus_message_new_method_call(
5038 "com.ubuntu.Upstart",
5039 "/com/ubuntu/Upstart",
5040 "com.ubuntu.Upstart0_6",
5043 log_error("Could not allocate message.");
5048 dbus_message_iter_init_append(m, &iter);
5050 env1_buf[sizeof(env1_buf)-2] = rl;
5051 env2_buf[sizeof(env2_buf)-2] = previous;
5053 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5054 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5055 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5056 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5057 !dbus_message_iter_close_container(&iter, &sub) ||
5058 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5059 log_error("Could not append arguments to message.");
5064 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5066 if (bus_error_is_no_service(&error)) {
5071 log_error("Failed to issue method call: %s", bus_error_message(&error));
5080 dbus_connection_flush(bus);
5081 dbus_connection_close(bus);
5082 dbus_connection_unref(bus);
5088 static int talk_initctl(void) {
5089 struct init_request request;
5093 if (!(rl = action_to_runlevel()))
5097 request.magic = INIT_MAGIC;
5098 request.sleeptime = 0;
5099 request.cmd = INIT_CMD_RUNLVL;
5100 request.runlevel = rl;
5102 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5104 if (errno == ENOENT)
5107 log_error("Failed to open "INIT_FIFO": %m");
5112 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5113 close_nointr_nofail(fd);
5116 log_error("Failed to write to "INIT_FIFO": %m");
5117 return errno ? -errno : -EIO;
5123 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5125 static const struct {
5133 int (* const dispatch)(DBusConnection *bus, char **args);
5135 { "list-units", LESS, 1, list_units },
5136 { "list-unit-files", EQUAL, 1, list_unit_files },
5137 { "list-jobs", EQUAL, 1, list_jobs },
5138 { "clear-jobs", EQUAL, 1, daemon_reload },
5139 { "load", MORE, 2, load_unit },
5140 { "cancel", MORE, 2, cancel_job },
5141 { "start", MORE, 2, start_unit },
5142 { "stop", MORE, 2, start_unit },
5143 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5144 { "reload", MORE, 2, start_unit },
5145 { "restart", MORE, 2, start_unit },
5146 { "try-restart", MORE, 2, start_unit },
5147 { "reload-or-restart", MORE, 2, start_unit },
5148 { "reload-or-try-restart", MORE, 2, start_unit },
5149 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5150 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5151 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5152 { "isolate", EQUAL, 2, start_unit },
5153 { "set-cgroup", MORE, 2, set_cgroup },
5154 { "unset-cgroup", MORE, 2, set_cgroup },
5155 { "get-cgroup-attr", MORE, 2, get_cgroup_attr },
5156 { "set-cgroup-attr", MORE, 2, set_cgroup_attr },
5157 { "unset-cgroup-attr", MORE, 2, set_cgroup },
5158 { "kill", MORE, 2, kill_unit },
5159 { "is-active", MORE, 2, check_unit_active },
5160 { "check", MORE, 2, check_unit_active },
5161 { "is-failed", MORE, 2, check_unit_failed },
5162 { "show", MORE, 1, show },
5163 { "status", MORE, 1, show },
5164 { "help", MORE, 2, show },
5165 { "dump", EQUAL, 1, dump },
5166 { "snapshot", LESS, 2, snapshot },
5167 { "delete", MORE, 2, delete_snapshot },
5168 { "daemon-reload", EQUAL, 1, daemon_reload },
5169 { "daemon-reexec", EQUAL, 1, daemon_reload },
5170 { "show-environment", EQUAL, 1, show_enviroment },
5171 { "set-environment", MORE, 2, set_environment },
5172 { "unset-environment", MORE, 2, set_environment },
5173 { "halt", EQUAL, 1, start_special },
5174 { "poweroff", EQUAL, 1, start_special },
5175 { "reboot", EQUAL, 1, start_special },
5176 { "kexec", EQUAL, 1, start_special },
5177 { "suspend", EQUAL, 1, start_special },
5178 { "hibernate", EQUAL, 1, start_special },
5179 { "hybrid-sleep", EQUAL, 1, start_special },
5180 { "default", EQUAL, 1, start_special },
5181 { "rescue", EQUAL, 1, start_special },
5182 { "emergency", EQUAL, 1, start_special },
5183 { "exit", EQUAL, 1, start_special },
5184 { "reset-failed", MORE, 1, reset_failed },
5185 { "enable", MORE, 2, enable_unit },
5186 { "disable", MORE, 2, enable_unit },
5187 { "is-enabled", MORE, 2, unit_is_enabled },
5188 { "reenable", MORE, 2, enable_unit },
5189 { "preset", MORE, 2, enable_unit },
5190 { "mask", MORE, 2, enable_unit },
5191 { "unmask", MORE, 2, enable_unit },
5192 { "link", MORE, 2, enable_unit },
5193 { "switch-root", MORE, 2, switch_root },
5194 { "list-dependencies", LESS, 2, list_dependencies },
5204 left = argc - optind;
5207 /* Special rule: no arguments means "list-units" */
5210 if (streq(argv[optind], "help") && !argv[optind+1]) {
5211 log_error("This command expects one or more "
5212 "unit names. Did you mean --help?");
5216 for (i = 0; i < ELEMENTSOF(verbs); i++)
5217 if (streq(argv[optind], verbs[i].verb))
5220 if (i >= ELEMENTSOF(verbs)) {
5221 log_error("Unknown operation '%s'.", argv[optind]);
5226 switch (verbs[i].argc_cmp) {
5229 if (left != verbs[i].argc) {
5230 log_error("Invalid number of arguments.");
5237 if (left < verbs[i].argc) {
5238 log_error("Too few arguments.");
5245 if (left > verbs[i].argc) {
5246 log_error("Too many arguments.");
5253 assert_not_reached("Unknown comparison operator.");
5256 /* Require a bus connection for all operations but
5258 if (!streq(verbs[i].verb, "enable") &&
5259 !streq(verbs[i].verb, "disable") &&
5260 !streq(verbs[i].verb, "is-enabled") &&
5261 !streq(verbs[i].verb, "list-unit-files") &&
5262 !streq(verbs[i].verb, "reenable") &&
5263 !streq(verbs[i].verb, "preset") &&
5264 !streq(verbs[i].verb, "mask") &&
5265 !streq(verbs[i].verb, "unmask") &&
5266 !streq(verbs[i].verb, "link")) {
5268 if (running_in_chroot() > 0) {
5269 log_info("Running in chroot, ignoring request.");
5273 if (((!streq(verbs[i].verb, "reboot") &&
5274 !streq(verbs[i].verb, "halt") &&
5275 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5276 log_error("Failed to get D-Bus connection: %s",
5277 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5283 if (!bus && !avoid_bus()) {
5284 log_error("Failed to get D-Bus connection: %s",
5285 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5290 return verbs[i].dispatch(bus, argv + optind);
5293 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5294 int _cleanup_close_ fd;
5295 struct msghdr msghdr;
5296 struct iovec iovec[2];
5297 union sockaddr_union sockaddr;
5298 struct sd_shutdown_command c;
5300 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5307 c.dry_run = dry_run;
5311 sockaddr.sa.sa_family = AF_UNIX;
5312 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5315 msghdr.msg_name = &sockaddr;
5316 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5319 iovec[0].iov_base = (char*) &c;
5320 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5322 if (isempty(message))
5323 msghdr.msg_iovlen = 1;
5325 iovec[1].iov_base = (char*) message;
5326 iovec[1].iov_len = strlen(message);
5327 msghdr.msg_iovlen = 2;
5329 msghdr.msg_iov = iovec;
5331 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0)
5337 static int reload_with_fallback(DBusConnection *bus) {
5340 /* First, try systemd via D-Bus. */
5341 if (daemon_reload(bus, NULL) >= 0)
5345 /* Nothing else worked, so let's try signals */
5346 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5348 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5349 log_error("kill() failed: %m");
5356 static int start_with_fallback(DBusConnection *bus) {
5359 /* First, try systemd via D-Bus. */
5360 if (start_unit(bus, NULL) >= 0)
5364 /* Hmm, talking to systemd via D-Bus didn't work. Then
5365 * let's try to talk to Upstart via D-Bus. */
5366 if (talk_upstart() > 0)
5369 /* Nothing else worked, so let's try
5371 if (talk_initctl() > 0)
5374 log_error("Failed to talk to init daemon.");
5378 warn_wall(arg_action);
5382 static _noreturn_ void halt_now(enum action a) {
5384 /* Make sure C-A-D is handled by the kernel from this
5386 reboot(RB_ENABLE_CAD);
5391 log_info("Halting.");
5392 reboot(RB_HALT_SYSTEM);
5395 case ACTION_POWEROFF:
5396 log_info("Powering off.");
5397 reboot(RB_POWER_OFF);
5401 log_info("Rebooting.");
5402 reboot(RB_AUTOBOOT);
5406 assert_not_reached("Unknown halt action.");
5409 assert_not_reached("Uh? This shouldn't happen.");
5412 static int halt_main(DBusConnection *bus) {
5415 r = check_inhibitors(bus, arg_action);
5419 if (geteuid() != 0) {
5420 /* Try logind if we are a normal user and no special
5421 * mode applies. Maybe PolicyKit allows us to shutdown
5424 if (arg_when <= 0 &&
5427 (arg_action == ACTION_POWEROFF ||
5428 arg_action == ACTION_REBOOT)) {
5429 r = reboot_with_logind(bus, arg_action);
5434 log_error("Must be root.");
5439 char _cleanup_free_ *m;
5441 m = strv_join(arg_wall, " ");
5442 r = send_shutdownd(arg_when,
5443 arg_action == ACTION_HALT ? 'H' :
5444 arg_action == ACTION_POWEROFF ? 'P' :
5445 arg_action == ACTION_KEXEC ? 'K' :
5452 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5454 char date[FORMAT_TIMESTAMP_MAX];
5456 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5457 format_timestamp(date, sizeof(date), arg_when));
5462 if (!arg_dry && !arg_force)
5463 return start_with_fallback(bus);
5466 if (sd_booted() > 0)
5467 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5469 r = utmp_put_shutdown();
5471 log_warning("Failed to write utmp record: %s", strerror(-r));
5478 halt_now(arg_action);
5479 /* We should never reach this. */
5483 static int runlevel_main(void) {
5484 int r, runlevel, previous;
5486 r = utmp_get_runlevel(&runlevel, &previous);
5493 previous <= 0 ? 'N' : previous,
5494 runlevel <= 0 ? 'N' : runlevel);
5499 int main(int argc, char*argv[]) {
5500 int r, retval = EXIT_FAILURE;
5501 DBusConnection *bus = NULL;
5502 DBusError _cleanup_dbus_error_free_ error;
5504 dbus_error_init(&error);
5506 setlocale(LC_ALL, "");
5507 log_parse_environment();
5510 r = parse_argv(argc, argv);
5514 retval = EXIT_SUCCESS;
5518 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5519 * let's shortcut this */
5520 if (arg_action == ACTION_RUNLEVEL) {
5521 r = runlevel_main();
5522 retval = r < 0 ? EXIT_FAILURE : r;
5526 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5527 log_info("Running in chroot, ignoring request.");
5533 if (arg_transport == TRANSPORT_NORMAL)
5534 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5535 else if (arg_transport == TRANSPORT_POLKIT) {
5536 bus_connect_system_polkit(&bus, &error);
5537 private_bus = false;
5538 } else if (arg_transport == TRANSPORT_SSH) {
5539 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5540 private_bus = false;
5542 assert_not_reached("Uh, invalid transport...");
5545 switch (arg_action) {
5547 case ACTION_SYSTEMCTL:
5548 r = systemctl_main(bus, argc, argv, &error);
5552 case ACTION_POWEROFF:
5558 case ACTION_RUNLEVEL2:
5559 case ACTION_RUNLEVEL3:
5560 case ACTION_RUNLEVEL4:
5561 case ACTION_RUNLEVEL5:
5563 case ACTION_EMERGENCY:
5564 case ACTION_DEFAULT:
5565 r = start_with_fallback(bus);
5570 r = reload_with_fallback(bus);
5573 case ACTION_CANCEL_SHUTDOWN: {
5577 m = strv_join(arg_wall, " ");
5579 retval = EXIT_FAILURE;
5583 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5585 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5590 case ACTION_INVALID:
5591 case ACTION_RUNLEVEL:
5593 assert_not_reached("Unknown action");
5596 retval = r < 0 ? EXIT_FAILURE : r;
5600 dbus_connection_flush(bus);
5601 dbus_connection_close(bus);
5602 dbus_connection_unref(bus);
5607 strv_free(arg_property);
5610 ask_password_agent_close();
5611 polkit_agent_close();