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++) {
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);
403 if (!arg_no_legend) {
404 const char *on, *off;
407 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
408 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
409 "SUB = The low-level unit activation state, values depend on unit type.\n");
411 printf("JOB = Pending job for the unit.\n");
413 on = ansi_highlight(true);
414 off = ansi_highlight(false);
416 on = ansi_highlight_red(true);
417 off = ansi_highlight_red(false);
421 printf("%s%u loaded units listed.%s\n"
422 "To show all installed unit files use 'systemctl list-unit-files'.\n",
425 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
426 "To show all installed unit files use 'systemctl list-unit-files'.\n",
431 static int list_units(DBusConnection *bus, char **args) {
432 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
433 _cleanup_free_ struct unit_info *unit_infos = NULL;
434 DBusMessageIter iter, sub;
435 unsigned c = 0, n_units = 0;
438 pager_open_if_enabled();
440 r = bus_method_call_with_reply(
442 "org.freedesktop.systemd1",
443 "/org/freedesktop/systemd1",
444 "org.freedesktop.systemd1.Manager",
452 if (!dbus_message_iter_init(reply, &iter) ||
453 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
454 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
455 log_error("Failed to parse reply.");
459 dbus_message_iter_recurse(&iter, &sub);
461 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
467 n_units = MAX(2*c, 16);
468 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
477 bus_parse_unit_info(&sub, u);
479 dbus_message_iter_next(&sub);
484 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
485 output_units_list(unit_infos, c);
491 static int compare_unit_file_list(const void *a, const void *b) {
493 const UnitFileList *u = a, *v = b;
495 d1 = strrchr(u->path, '.');
496 d2 = strrchr(v->path, '.');
501 r = strcasecmp(d1, d2);
506 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
509 static bool output_show_unit_file(const UnitFileList *u) {
512 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
515 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
516 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
517 const UnitFileList *u;
519 max_id_len = sizeof("UNIT FILE")-1;
520 state_cols = sizeof("STATE")-1;
521 for (u = units; u < units + c; u++) {
522 if (!output_show_unit_file(u))
525 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
526 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
531 id_cols = MIN(max_id_len, 25);
532 basic_cols = 1 + id_cols + state_cols;
533 if (basic_cols < (unsigned) columns())
534 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
536 id_cols = max_id_len;
539 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
541 for (u = units; u < units + c; u++) {
543 const char *on, *off;
546 if (!output_show_unit_file(u))
551 if (u->state == UNIT_FILE_MASKED ||
552 u->state == UNIT_FILE_MASKED_RUNTIME ||
553 u->state == UNIT_FILE_DISABLED ||
554 u->state == UNIT_FILE_INVALID) {
555 on = ansi_highlight_red(true);
556 off = ansi_highlight_red(false);
557 } else if (u->state == UNIT_FILE_ENABLED) {
558 on = ansi_highlight_green(true);
559 off = ansi_highlight_green(false);
563 id = path_get_file_name(u->path);
565 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
567 printf("%-*s %s%-*s%s\n",
569 on, state_cols, unit_file_state_to_string(u->state), off);
575 printf("\n%u unit files listed.\n", n_shown);
578 static int list_unit_files(DBusConnection *bus, char **args) {
579 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
580 _cleanup_free_ UnitFileList *units = NULL;
581 DBusMessageIter iter, sub, sub2;
582 unsigned c = 0, n_units = 0;
585 pager_open_if_enabled();
592 h = hashmap_new(string_hash_func, string_compare_func);
596 r = unit_file_get_list(arg_scope, arg_root, h);
598 unit_file_list_free(h);
599 log_error("Failed to get unit file list: %s", strerror(-r));
603 n_units = hashmap_size(h);
604 units = new(UnitFileList, n_units);
606 unit_file_list_free(h);
610 HASHMAP_FOREACH(u, h, i) {
611 memcpy(units + c++, u, sizeof(UnitFileList));
617 r = bus_method_call_with_reply(
619 "org.freedesktop.systemd1",
620 "/org/freedesktop/systemd1",
621 "org.freedesktop.systemd1.Manager",
629 if (!dbus_message_iter_init(reply, &iter) ||
630 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
631 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
632 log_error("Failed to parse reply.");
636 dbus_message_iter_recurse(&iter, &sub);
638 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
642 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
647 n_units = MAX(2*c, 16);
648 w = realloc(units, sizeof(struct UnitFileList) * n_units);
657 dbus_message_iter_recurse(&sub, &sub2);
659 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
660 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
661 log_error("Failed to parse reply.");
665 u->state = unit_file_state_from_string(state);
667 dbus_message_iter_next(&sub);
673 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
674 output_unit_file_list(units, c);
680 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
682 _cleanup_free_ char *n = NULL;
684 size_t max_len = MAX(columns(),20);
686 for (i = level - 1; i >= 0; i--) {
688 if(len > max_len - 3 && !arg_full) {
689 printf("%s...\n",max_len % 2 ? "" : " ");
692 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
695 if(len > max_len - 3 && !arg_full) {
696 printf("%s...\n",max_len % 2 ? "" : " ");
699 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
702 printf("%s\n", name);
706 n = ellipsize(name, max_len-len, 100);
714 static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
715 static const char dependencies[] =
717 "RequiresOverridable\0"
719 "RequisiteOverridable\0"
722 _cleanup_free_ char *path;
723 const char *interface = "org.freedesktop.systemd1.Unit";
725 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
726 DBusMessageIter iter, sub, sub2, sub3;
735 path = unit_dbus_path_from_name(name);
741 r = bus_method_call_with_reply(
743 "org.freedesktop.systemd1",
745 "org.freedesktop.DBus.Properties",
749 DBUS_TYPE_STRING, &interface,
754 if (!dbus_message_iter_init(reply, &iter) ||
755 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
756 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
757 log_error("Failed to parse reply.");
762 dbus_message_iter_recurse(&iter, &sub);
764 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
767 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
768 dbus_message_iter_recurse(&sub, &sub2);
770 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
771 log_error("Failed to parse reply.");
776 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
777 log_error("Failed to parse reply.");
782 dbus_message_iter_recurse(&sub2, &sub3);
783 dbus_message_iter_next(&sub);
785 if (!nulstr_contains(dependencies, prop))
788 if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
789 if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
790 DBusMessageIter sub4;
791 dbus_message_iter_recurse(&sub3, &sub4);
793 while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
796 assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
797 dbus_message_iter_get_basic(&sub4, &s);
799 r = strv_extend(&ret, s);
805 dbus_message_iter_next(&sub4);
818 static int list_dependencies_compare(const void *_a, const void *_b) {
819 const char **a = (const char**) _a, **b = (const char**) _b;
820 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
822 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
824 return strcasecmp(*a, *b);
827 static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char **units, unsigned int branches) {
833 u = strv_append(units, name);
837 r = list_dependencies_get_dependencies(bus, name, &deps);
841 qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
843 STRV_FOREACH(c, deps) {
844 if (strv_contains(u, *c)) {
845 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
851 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
855 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
856 r = list_dependencies_one(bus, *c, level + 1, u, (branches << 1) | (c[1] == NULL ? 0 : 1));
869 static int list_dependencies(DBusConnection *bus, char **args) {
870 _cleanup_free_ char *unit = NULL;
876 unit = unit_name_mangle(args[1]);
881 u = SPECIAL_DEFAULT_TARGET;
883 pager_open_if_enabled();
887 return list_dependencies_one(bus, u, 0, NULL, 0);
890 static int list_jobs(DBusConnection *bus, char **args) {
891 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
892 DBusMessageIter iter, sub, sub2;
896 pager_open_if_enabled();
898 r = bus_method_call_with_reply(
900 "org.freedesktop.systemd1",
901 "/org/freedesktop/systemd1",
902 "org.freedesktop.systemd1.Manager",
910 if (!dbus_message_iter_init(reply, &iter) ||
911 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
912 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
913 log_error("Failed to parse reply.");
917 dbus_message_iter_recurse(&iter, &sub);
920 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
922 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
923 const char *name, *type, *state, *job_path, *unit_path;
927 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
928 log_error("Failed to parse reply.");
932 dbus_message_iter_recurse(&sub, &sub2);
934 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
935 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
936 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
937 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
938 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
939 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
940 log_error("Failed to parse reply.");
944 e = arg_full ? NULL : ellipsize(name, 25, 33);
945 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
950 dbus_message_iter_next(&sub);
954 printf("\n%u jobs listed.\n", k);
959 static int load_unit(DBusConnection *bus, char **args) {
964 STRV_FOREACH(name, args+1) {
965 _cleanup_free_ char *n = NULL;
968 n = unit_name_mangle(*name);
972 r = bus_method_call_with_reply(
974 "org.freedesktop.systemd1",
975 "/org/freedesktop/systemd1",
976 "org.freedesktop.systemd1.Manager",
980 DBUS_TYPE_STRING, &n,
989 static int cancel_job(DBusConnection *bus, char **args) {
994 if (strv_length(args) <= 1)
995 return daemon_reload(bus, args);
997 STRV_FOREACH(name, args+1) {
1001 r = safe_atou32(*name, &id);
1003 log_error("Failed to parse job id: %s", strerror(-r));
1007 r = bus_method_call_with_reply(
1009 "org.freedesktop.systemd1",
1010 "/org/freedesktop/systemd1",
1011 "org.freedesktop.systemd1.Manager",
1015 DBUS_TYPE_UINT32, &id,
1024 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1025 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1026 dbus_bool_t b = FALSE;
1027 DBusMessageIter iter, sub;
1029 *interface = "org.freedesktop.systemd1.Unit",
1030 *property = "NeedDaemonReload",
1032 _cleanup_free_ char *n = NULL;
1035 /* We ignore all errors here, since this is used to show a warning only */
1037 n = unit_name_mangle(unit);
1041 r = bus_method_call_with_reply (
1043 "org.freedesktop.systemd1",
1044 "/org/freedesktop/systemd1",
1045 "org.freedesktop.systemd1.Manager",
1049 DBUS_TYPE_STRING, &n,
1054 if (!dbus_message_get_args(reply, NULL,
1055 DBUS_TYPE_OBJECT_PATH, &path,
1059 dbus_message_unref(reply);
1062 r = bus_method_call_with_reply(
1064 "org.freedesktop.systemd1",
1066 "org.freedesktop.DBus.Properties",
1070 DBUS_TYPE_STRING, &interface,
1071 DBUS_TYPE_STRING, &property,
1076 if (!dbus_message_iter_init(reply, &iter) ||
1077 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1080 dbus_message_iter_recurse(&iter, &sub);
1081 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1084 dbus_message_iter_get_basic(&sub, &b);
1088 typedef struct WaitData {
1095 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1103 dbus_error_init(&error);
1105 log_debug("Got D-Bus request: %s.%s() on %s",
1106 dbus_message_get_interface(message),
1107 dbus_message_get_member(message),
1108 dbus_message_get_path(message));
1110 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1111 log_error("Warning! D-Bus connection terminated.");
1112 dbus_connection_close(connection);
1114 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1116 const char *path, *result, *unit;
1118 if (dbus_message_get_args(message, &error,
1119 DBUS_TYPE_UINT32, &id,
1120 DBUS_TYPE_OBJECT_PATH, &path,
1121 DBUS_TYPE_STRING, &unit,
1122 DBUS_TYPE_STRING, &result,
1123 DBUS_TYPE_INVALID)) {
1125 free(set_remove(d->set, (char*) path));
1127 if (!isempty(result))
1128 d->result = strdup(result);
1131 d->name = strdup(unit);
1136 dbus_error_free(&error);
1137 if (dbus_message_get_args(message, &error,
1138 DBUS_TYPE_UINT32, &id,
1139 DBUS_TYPE_OBJECT_PATH, &path,
1140 DBUS_TYPE_STRING, &result,
1141 DBUS_TYPE_INVALID)) {
1142 /* Compatibility with older systemd versions <
1143 * 183 during upgrades. This should be dropped
1145 free(set_remove(d->set, (char*) path));
1148 d->result = strdup(result);
1154 log_error("Failed to parse message: %s", bus_error_message(&error));
1158 dbus_error_free(&error);
1159 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1162 static int enable_wait_for_jobs(DBusConnection *bus) {
1170 dbus_error_init(&error);
1171 dbus_bus_add_match(bus,
1173 "sender='org.freedesktop.systemd1',"
1174 "interface='org.freedesktop.systemd1.Manager',"
1175 "member='JobRemoved',"
1176 "path='/org/freedesktop/systemd1'",
1179 if (dbus_error_is_set(&error)) {
1180 log_error("Failed to add match: %s", bus_error_message(&error));
1181 dbus_error_free(&error);
1185 /* This is slightly dirty, since we don't undo the match registrations. */
1189 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1199 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1202 while (!set_isempty(s)) {
1204 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1205 log_error("Disconnected from bus.");
1206 return -ECONNREFUSED;
1213 if (streq(d.result, "timeout"))
1214 log_error("Job for %s timed out.", strna(d.name));
1215 else if (streq(d.result, "canceled"))
1216 log_error("Job for %s canceled.", strna(d.name));
1217 else if (streq(d.result, "dependency"))
1218 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1219 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1220 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1223 if (streq_ptr(d.result, "timeout"))
1225 else if (streq_ptr(d.result, "canceled"))
1227 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1238 dbus_connection_remove_filter(bus, wait_filter, &d);
1242 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1243 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1244 _cleanup_free_ char *n = NULL;
1245 DBusMessageIter iter, sub;
1247 *interface = "org.freedesktop.systemd1.Unit",
1248 *property = "ActiveState";
1249 const char *state, *path;
1255 dbus_error_init(&error);
1257 n = unit_name_mangle(name);
1261 r = bus_method_call_with_reply (
1263 "org.freedesktop.systemd1",
1264 "/org/freedesktop/systemd1",
1265 "org.freedesktop.systemd1.Manager",
1269 DBUS_TYPE_STRING, &n,
1272 dbus_error_free(&error);
1279 if (!dbus_message_get_args(reply, NULL,
1280 DBUS_TYPE_OBJECT_PATH, &path,
1281 DBUS_TYPE_INVALID)) {
1282 log_error("Failed to parse reply.");
1286 dbus_message_unref(reply);
1289 r = bus_method_call_with_reply(
1291 "org.freedesktop.systemd1",
1293 "org.freedesktop.DBus.Properties",
1297 DBUS_TYPE_STRING, &interface,
1298 DBUS_TYPE_STRING, &property,
1306 if (!dbus_message_iter_init(reply, &iter) ||
1307 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1308 log_error("Failed to parse reply.");
1312 dbus_message_iter_recurse(&iter, &sub);
1314 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1315 log_error("Failed to parse reply.");
1319 dbus_message_iter_get_basic(&sub, &state);
1324 return strv_find(check_states, state) ? 1 : 0;
1327 static void check_triggering_units(
1328 DBusConnection *bus,
1329 const char *unit_name) {
1331 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1332 DBusMessageIter iter, sub;
1333 const char *interface = "org.freedesktop.systemd1.Unit",
1334 *triggered_by_property = "TriggeredBy";
1335 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1336 bool print_warning_label = true;
1339 n = unit_name_mangle(unit_name);
1345 unit_path = unit_dbus_path_from_name(n);
1351 r = bus_method_call_with_reply(
1353 "org.freedesktop.systemd1",
1355 "org.freedesktop.DBus.Properties",
1359 DBUS_TYPE_STRING, &interface,
1360 DBUS_TYPE_STRING, &triggered_by_property,
1365 if (!dbus_message_iter_init(reply, &iter) ||
1366 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1367 log_error("Failed to parse reply.");
1371 dbus_message_iter_recurse(&iter, &sub);
1372 dbus_message_iter_recurse(&sub, &iter);
1375 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1376 const char * const check_states[] = {
1381 const char *service_trigger;
1383 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1384 log_error("Failed to parse reply.");
1388 dbus_message_iter_get_basic(&sub, &service_trigger);
1390 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1394 if (print_warning_label) {
1395 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1396 print_warning_label = false;
1399 log_warning(" %s", service_trigger);
1402 dbus_message_iter_next(&sub);
1406 static int start_unit_one(
1407 DBusConnection *bus,
1414 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1415 _cleanup_free_ char *n;
1424 n = unit_name_mangle(name);
1428 r = bus_method_call_with_reply(
1430 "org.freedesktop.systemd1",
1431 "/org/freedesktop/systemd1",
1432 "org.freedesktop.systemd1.Manager",
1436 DBUS_TYPE_STRING, &n,
1437 DBUS_TYPE_STRING, &mode,
1440 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1441 /* There's always a fallback possible for
1442 * legacy actions. */
1445 log_error("Failed to issue method call: %s", bus_error_message(error));
1450 if (!dbus_message_get_args(reply, error,
1451 DBUS_TYPE_OBJECT_PATH, &path,
1452 DBUS_TYPE_INVALID)) {
1453 log_error("Failed to parse reply: %s", bus_error_message(error));
1457 if (need_daemon_reload(bus, n))
1458 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1459 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1471 log_error("Failed to add path to set.");
1479 static enum action verb_to_action(const char *verb) {
1480 if (streq(verb, "halt"))
1482 else if (streq(verb, "poweroff"))
1483 return ACTION_POWEROFF;
1484 else if (streq(verb, "reboot"))
1485 return ACTION_REBOOT;
1486 else if (streq(verb, "kexec"))
1487 return ACTION_KEXEC;
1488 else if (streq(verb, "rescue"))
1489 return ACTION_RESCUE;
1490 else if (streq(verb, "emergency"))
1491 return ACTION_EMERGENCY;
1492 else if (streq(verb, "default"))
1493 return ACTION_DEFAULT;
1494 else if (streq(verb, "exit"))
1496 else if (streq(verb, "suspend"))
1497 return ACTION_SUSPEND;
1498 else if (streq(verb, "hibernate"))
1499 return ACTION_HIBERNATE;
1500 else if (streq(verb, "hybrid-sleep"))
1501 return ACTION_HYBRID_SLEEP;
1503 return ACTION_INVALID;
1506 static int start_unit(DBusConnection *bus, char **args) {
1508 static const char * const table[_ACTION_MAX] = {
1509 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1510 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1511 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1512 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1513 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1514 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1515 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1516 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1517 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1518 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1519 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1520 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1521 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1522 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
1523 [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
1527 const char *method, *mode, *one_name;
1532 dbus_error_init(&error);
1536 ask_password_agent_open_if_enabled();
1538 if (arg_action == ACTION_SYSTEMCTL) {
1540 streq(args[0], "stop") ||
1541 streq(args[0], "condstop") ? "StopUnit" :
1542 streq(args[0], "reload") ? "ReloadUnit" :
1543 streq(args[0], "restart") ? "RestartUnit" :
1545 streq(args[0], "try-restart") ||
1546 streq(args[0], "condrestart") ? "TryRestartUnit" :
1548 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1550 streq(args[0], "reload-or-try-restart") ||
1551 streq(args[0], "condreload") ||
1553 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1557 (streq(args[0], "isolate") ||
1558 streq(args[0], "rescue") ||
1559 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1561 one_name = table[verb_to_action(args[0])];
1564 assert(arg_action < ELEMENTSOF(table));
1565 assert(table[arg_action]);
1567 method = "StartUnit";
1569 mode = (arg_action == ACTION_EMERGENCY ||
1570 arg_action == ACTION_RESCUE ||
1571 arg_action == ACTION_RUNLEVEL2 ||
1572 arg_action == ACTION_RUNLEVEL3 ||
1573 arg_action == ACTION_RUNLEVEL4 ||
1574 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1576 one_name = table[arg_action];
1579 if (!arg_no_block) {
1580 ret = enable_wait_for_jobs(bus);
1582 log_error("Could not watch jobs: %s", strerror(-ret));
1586 s = set_new(string_hash_func, string_compare_func);
1594 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1596 ret = translate_bus_error_to_exit_status(ret, &error);
1598 STRV_FOREACH(name, args+1) {
1599 r = start_unit_one(bus, method, *name, mode, &error, s);
1601 ret = translate_bus_error_to_exit_status(r, &error);
1602 dbus_error_free(&error);
1607 if (!arg_no_block) {
1608 r = wait_for_jobs(bus, s);
1614 /* When stopping units, warn if they can still be triggered by
1615 * another active unit (socket, path, timer) */
1616 if (!arg_quiet && streq(method, "StopUnit")) {
1618 check_triggering_units(bus, one_name);
1620 STRV_FOREACH(name, args+1)
1621 check_triggering_units(bus, *name);
1627 dbus_error_free(&error);
1632 /* Ask systemd-logind, which might grant access to unprivileged users
1633 * through PolicyKit */
1634 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1637 dbus_bool_t interactive = true;
1642 polkit_agent_open_if_enabled();
1650 case ACTION_POWEROFF:
1651 method = "PowerOff";
1654 case ACTION_SUSPEND:
1658 case ACTION_HIBERNATE:
1659 method = "Hibernate";
1662 case ACTION_HYBRID_SLEEP:
1663 method = "HybridSleep";
1670 return bus_method_call_with_reply(
1672 "org.freedesktop.login1",
1673 "/org/freedesktop/login1",
1674 "org.freedesktop.login1.Manager",
1678 DBUS_TYPE_BOOLEAN, &interactive,
1685 static int check_inhibitors(DBusConnection *bus, enum action a) {
1687 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1688 DBusMessageIter iter, sub, sub2;
1691 _cleanup_strv_free_ char **sessions = NULL;
1697 if (arg_ignore_inhibitors || arg_force > 0)
1709 r = bus_method_call_with_reply(
1711 "org.freedesktop.login1",
1712 "/org/freedesktop/login1",
1713 "org.freedesktop.login1.Manager",
1719 /* If logind is not around, then there are no inhibitors... */
1722 if (!dbus_message_iter_init(reply, &iter) ||
1723 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1724 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1725 log_error("Failed to parse reply.");
1729 dbus_message_iter_recurse(&iter, &sub);
1730 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1731 const char *what, *who, *why, *mode;
1733 _cleanup_strv_free_ char **sv = NULL;
1734 _cleanup_free_ char *comm = NULL, *user = NULL;
1736 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1737 log_error("Failed to parse reply.");
1741 dbus_message_iter_recurse(&sub, &sub2);
1743 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
1744 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
1745 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
1746 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
1747 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
1748 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
1749 log_error("Failed to parse reply.");
1753 if (!streq(mode, "block"))
1756 sv = strv_split(what, ":");
1760 if (!strv_contains(sv,
1762 a == ACTION_POWEROFF ||
1763 a == ACTION_REBOOT ||
1764 a == ACTION_KEXEC ? "shutdown" : "sleep"))
1767 get_process_comm(pid, &comm);
1768 user = uid_to_name(uid);
1769 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
1770 who, (unsigned long) pid, strna(comm), strna(user), why);
1774 dbus_message_iter_next(&sub);
1777 dbus_message_iter_recurse(&iter, &sub);
1779 /* Check for current sessions */
1780 sd_get_sessions(&sessions);
1781 STRV_FOREACH(s, sessions) {
1783 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
1785 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
1788 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
1791 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
1794 sd_session_get_tty(*s, &tty);
1795 sd_session_get_seat(*s, &seat);
1796 sd_session_get_service(*s, &service);
1797 user = uid_to_name(uid);
1799 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
1806 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
1807 a == ACTION_HALT ? "halt" :
1808 a == ACTION_POWEROFF ? "poweroff" :
1809 a == ACTION_REBOOT ? "reboot" :
1810 a == ACTION_KEXEC ? "kexec" :
1811 a == ACTION_SUSPEND ? "suspend" :
1812 a == ACTION_HIBERNATE ? "hibernate" : "hybrid-sleep");
1820 static int start_special(DBusConnection *bus, char **args) {
1826 a = verb_to_action(args[0]);
1828 r = check_inhibitors(bus, a);
1832 if (arg_force >= 2 && geteuid() != 0) {
1833 log_error("Must be root.");
1837 if (arg_force >= 2 &&
1838 (a == ACTION_HALT ||
1839 a == ACTION_POWEROFF ||
1840 a == ACTION_REBOOT))
1843 if (arg_force >= 1 &&
1844 (a == ACTION_HALT ||
1845 a == ACTION_POWEROFF ||
1846 a == ACTION_REBOOT ||
1847 a == ACTION_KEXEC ||
1849 return daemon_reload(bus, args);
1851 /* first try logind, to allow authentication with polkit */
1852 if (geteuid() != 0 &&
1853 (a == ACTION_POWEROFF ||
1854 a == ACTION_REBOOT ||
1855 a == ACTION_SUSPEND ||
1856 a == ACTION_HIBERNATE ||
1857 a == ACTION_HYBRID_SLEEP)) {
1858 r = reboot_with_logind(bus, a);
1863 r = start_unit(bus, args);
1870 static int check_unit_active(DBusConnection *bus, char **args) {
1871 const char * const check_states[] = {
1878 int r = 3; /* According to LSB: "program is not running" */
1883 STRV_FOREACH(name, args+1) {
1886 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1896 static int check_unit_failed(DBusConnection *bus, char **args) {
1897 const char * const check_states[] = {
1908 STRV_FOREACH(name, args+1) {
1911 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1921 static int kill_unit(DBusConnection *bus, char **args) {
1929 arg_kill_who = "all";
1931 STRV_FOREACH(name, args+1) {
1932 _cleanup_free_ char *n = NULL;
1934 n = unit_name_mangle(*name);
1938 r = bus_method_call_with_reply(
1940 "org.freedesktop.systemd1",
1941 "/org/freedesktop/systemd1",
1942 "org.freedesktop.systemd1.Manager",
1946 DBUS_TYPE_STRING, &n,
1947 DBUS_TYPE_STRING, &arg_kill_who,
1948 DBUS_TYPE_INT32, &arg_signal,
1956 static int set_cgroup(DBusConnection *bus, char **args) {
1957 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
1960 DBusMessageIter iter;
1962 _cleanup_free_ char *n = NULL;
1963 const char *runtime;
1968 dbus_error_init(&error);
1971 streq(args[0], "set-cgroup") ? "SetUnitControlGroups" :
1972 streq(args[0], "unset-group") ? "UnsetUnitControlGroups"
1973 : "UnsetUnitControlGroupAttributes";
1975 n = unit_name_mangle(args[1]);
1979 m = dbus_message_new_method_call(
1980 "org.freedesktop.systemd1",
1981 "/org/freedesktop/systemd1",
1982 "org.freedesktop.systemd1.Manager",
1987 dbus_message_iter_init_append(m, &iter);
1988 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
1991 r = bus_append_strv_iter(&iter, args + 2);
1995 runtime = arg_runtime ? "runtime" : "persistent";
1996 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
1999 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2001 log_error("Failed to issue method call: %s", bus_error_message(&error));
2002 dbus_error_free(&error);
2009 static int set_cgroup_attr(DBusConnection *bus, char **args) {
2010 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2012 DBusMessageIter iter, sub, sub2;
2014 _cleanup_free_ char *n = NULL;
2015 const char *runtime;
2020 dbus_error_init(&error);
2022 if (strv_length(args) % 2 != 0) {
2023 log_error("Expecting an uneven number of arguments!");
2027 n = unit_name_mangle(args[1]);
2031 m = dbus_message_new_method_call(
2032 "org.freedesktop.systemd1",
2033 "/org/freedesktop/systemd1",
2034 "org.freedesktop.systemd1.Manager",
2035 "SetUnitControlGroupAttributes");
2039 dbus_message_iter_init_append(m, &iter);
2040 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2041 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub))
2044 STRV_FOREACH_PAIR(x, y, args + 2) {
2045 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
2046 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, x) ||
2047 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, y) ||
2048 !dbus_message_iter_close_container(&sub, &sub2))
2052 runtime = arg_runtime ? "runtime" : "persistent";
2053 if (!dbus_message_iter_close_container(&iter, &sub) ||
2054 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2057 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2059 log_error("Failed to issue method call: %s", bus_error_message(&error));
2060 dbus_error_free(&error);
2067 static int get_cgroup_attr(DBusConnection *bus, char **args) {
2068 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2070 DBusMessageIter iter;
2072 _cleanup_free_ char *n = NULL;
2073 _cleanup_strv_free_ char **list = NULL;
2079 dbus_error_init(&error);
2081 n = unit_name_mangle(args[1]);
2085 m = dbus_message_new_method_call(
2086 "org.freedesktop.systemd1",
2087 "/org/freedesktop/systemd1",
2088 "org.freedesktop.systemd1.Manager",
2089 "GetUnitControlGroupAttributes");
2093 dbus_message_iter_init_append(m, &iter);
2094 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
2097 r = bus_append_strv_iter(&iter, args + 2);
2101 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2103 log_error("Failed to issue method call: %s", bus_error_message(&error));
2104 dbus_error_free(&error);
2108 dbus_message_iter_init(reply, &iter);
2109 r = bus_parse_strv_iter(&iter, &list);
2111 log_error("Failed to parse value list.");
2115 STRV_FOREACH(a, list) {
2116 if (endswith(*a, "\n"))
2125 typedef struct ExecStatusInfo {
2133 usec_t start_timestamp;
2134 usec_t exit_timestamp;
2139 LIST_FIELDS(struct ExecStatusInfo, exec);
2142 static void exec_status_info_free(ExecStatusInfo *i) {
2151 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2152 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2153 DBusMessageIter sub2, sub3;
2157 int32_t code, status;
2163 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2166 dbus_message_iter_recurse(sub, &sub2);
2168 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2171 i->path = strdup(path);
2175 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2176 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2180 dbus_message_iter_recurse(&sub2, &sub3);
2181 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2182 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2183 dbus_message_iter_next(&sub3);
2187 i->argv = new0(char*, n+1);
2192 dbus_message_iter_recurse(&sub2, &sub3);
2193 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2196 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2197 dbus_message_iter_get_basic(&sub3, &s);
2198 dbus_message_iter_next(&sub3);
2200 i->argv[n] = strdup(s);
2207 if (!dbus_message_iter_next(&sub2) ||
2208 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2209 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2210 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2211 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2212 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2213 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2214 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2215 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2219 i->start_timestamp = (usec_t) start_timestamp;
2220 i->exit_timestamp = (usec_t) exit_timestamp;
2221 i->pid = (pid_t) pid;
2228 typedef struct UnitStatusInfo {
2230 const char *load_state;
2231 const char *active_state;
2232 const char *sub_state;
2233 const char *unit_file_state;
2235 const char *description;
2236 const char *following;
2238 char **documentation;
2240 const char *fragment_path;
2241 const char *source_path;
2242 const char *default_control_group;
2244 const char *load_error;
2247 usec_t inactive_exit_timestamp;
2248 usec_t inactive_exit_timestamp_monotonic;
2249 usec_t active_enter_timestamp;
2250 usec_t active_exit_timestamp;
2251 usec_t inactive_enter_timestamp;
2253 bool need_daemon_reload;
2258 const char *status_text;
2261 usec_t start_timestamp;
2262 usec_t exit_timestamp;
2264 int exit_code, exit_status;
2266 usec_t condition_timestamp;
2267 bool condition_result;
2270 unsigned n_accepted;
2271 unsigned n_connections;
2275 const char *sysfs_path;
2277 /* Mount, Automount */
2283 LIST_HEAD(ExecStatusInfo, exec);
2286 static void print_status_info(UnitStatusInfo *i) {
2288 const char *on, *off, *ss;
2290 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2291 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2294 arg_all * OUTPUT_SHOW_ALL |
2295 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2296 on_tty() * OUTPUT_COLOR |
2297 !arg_quiet * OUTPUT_WARN_CUTOFF |
2298 arg_full * OUTPUT_FULL_WIDTH;
2302 /* This shows pretty information about a unit. See
2303 * print_property() for a low-level property printer */
2305 printf("%s", strna(i->id));
2307 if (i->description && !streq_ptr(i->id, i->description))
2308 printf(" - %s", i->description);
2313 printf("\t Follow: unit currently follows state of %s\n", i->following);
2315 if (streq_ptr(i->load_state, "error")) {
2316 on = ansi_highlight_red(true);
2317 off = ansi_highlight_red(false);
2321 path = i->source_path ? i->source_path : i->fragment_path;
2324 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2325 else if (path && i->unit_file_state)
2326 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2328 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2330 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2332 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2334 if (streq_ptr(i->active_state, "failed")) {
2335 on = ansi_highlight_red(true);
2336 off = ansi_highlight_red(false);
2337 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2338 on = ansi_highlight_green(true);
2339 off = ansi_highlight_green(false);
2344 printf("\t Active: %s%s (%s)%s",
2346 strna(i->active_state),
2350 printf("\t Active: %s%s%s",
2352 strna(i->active_state),
2355 if (!isempty(i->result) && !streq(i->result, "success"))
2356 printf(" (Result: %s)", i->result);
2358 timestamp = (streq_ptr(i->active_state, "active") ||
2359 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2360 (streq_ptr(i->active_state, "inactive") ||
2361 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2362 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2363 i->active_exit_timestamp;
2365 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2366 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2369 printf(" since %s; %s\n", s2, s1);
2371 printf(" since %s\n", s2);
2375 if (!i->condition_result && i->condition_timestamp > 0) {
2376 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2377 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2380 printf("\t start condition failed at %s; %s\n", s2, s1);
2382 printf("\t start condition failed at %s\n", s2);
2386 printf("\t Device: %s\n", i->sysfs_path);
2388 printf("\t Where: %s\n", i->where);
2390 printf("\t What: %s\n", i->what);
2392 if (!strv_isempty(i->documentation)) {
2396 STRV_FOREACH(t, i->documentation) {
2398 printf("\t Docs: %s\n", *t);
2401 printf("\t %s\n", *t);
2406 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2408 LIST_FOREACH(exec, p, i->exec) {
2409 _cleanup_free_ char *t = NULL;
2412 /* Only show exited processes here */
2416 t = strv_join(p->argv, " ");
2417 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2419 good = is_clean_exit_lsb(p->code, p->status, NULL);
2421 on = ansi_highlight_red(true);
2422 off = ansi_highlight_red(false);
2426 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2428 if (p->code == CLD_EXITED) {
2431 printf("status=%i", p->status);
2433 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2438 printf("signal=%s", signal_to_string(p->status));
2440 printf(")%s\n", off);
2442 if (i->main_pid == p->pid &&
2443 i->start_timestamp == p->start_timestamp &&
2444 i->exit_timestamp == p->start_timestamp)
2445 /* Let's not show this twice */
2448 if (p->pid == i->control_pid)
2452 if (i->main_pid > 0 || i->control_pid > 0) {
2455 if (i->main_pid > 0) {
2456 printf("Main PID: %u", (unsigned) i->main_pid);
2459 _cleanup_free_ char *t = NULL;
2460 get_process_comm(i->main_pid, &t);
2463 } else if (i->exit_code > 0) {
2464 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2466 if (i->exit_code == CLD_EXITED) {
2469 printf("status=%i", i->exit_status);
2471 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2476 printf("signal=%s", signal_to_string(i->exit_status));
2481 if (i->main_pid > 0 && i->control_pid > 0)
2484 if (i->control_pid > 0) {
2485 _cleanup_free_ char *t = NULL;
2487 printf(" Control: %u", (unsigned) i->control_pid);
2489 get_process_comm(i->control_pid, &t);
2498 printf("\t Status: \"%s\"\n", i->status_text);
2500 if (i->default_control_group &&
2501 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2504 printf("\t CGroup: %s\n", i->default_control_group);
2506 if (arg_transport != TRANSPORT_SSH) {
2516 if (i->main_pid > 0)
2517 extra[k++] = i->main_pid;
2519 if (i->control_pid > 0)
2520 extra[k++] = i->control_pid;
2522 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, extra, k, flags);
2526 if (i->id && arg_transport != TRANSPORT_SSH) {
2528 if(arg_scope == UNIT_FILE_SYSTEM)
2529 show_journal_by_unit(stdout,
2533 i->inactive_exit_timestamp_monotonic,
2537 show_journal_by_user_unit(stdout,
2541 i->inactive_exit_timestamp_monotonic,
2547 if (i->need_daemon_reload)
2548 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2549 ansi_highlight_red(true),
2550 ansi_highlight_red(false),
2551 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2554 static void show_unit_help(UnitStatusInfo *i) {
2559 if (!i->documentation) {
2560 log_info("Documentation for %s not known.", i->id);
2564 STRV_FOREACH(p, i->documentation) {
2566 if (startswith(*p, "man:")) {
2569 char *page = NULL, *section = NULL;
2570 const char *args[4] = { "man", NULL, NULL, NULL };
2575 if ((*p)[k-1] == ')')
2576 e = strrchr(*p, '(');
2579 page = strndup((*p) + 4, e - *p - 4);
2585 section = strndup(e + 1, *p + k - e - 2);
2599 log_error("Failed to fork: %m");
2607 execvp(args[0], (char**) args);
2608 log_error("Failed to execute man: %m");
2609 _exit(EXIT_FAILURE);
2615 wait_for_terminate(pid, NULL);
2617 log_info("Can't show: %s", *p);
2621 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2627 switch (dbus_message_iter_get_arg_type(iter)) {
2629 case DBUS_TYPE_STRING: {
2632 dbus_message_iter_get_basic(iter, &s);
2635 if (streq(name, "Id"))
2637 else if (streq(name, "LoadState"))
2639 else if (streq(name, "ActiveState"))
2640 i->active_state = s;
2641 else if (streq(name, "SubState"))
2643 else if (streq(name, "Description"))
2645 else if (streq(name, "FragmentPath"))
2646 i->fragment_path = s;
2647 else if (streq(name, "SourcePath"))
2649 else if (streq(name, "DefaultControlGroup"))
2650 i->default_control_group = s;
2651 else if (streq(name, "StatusText"))
2653 else if (streq(name, "SysFSPath"))
2655 else if (streq(name, "Where"))
2657 else if (streq(name, "What"))
2659 else if (streq(name, "Following"))
2661 else if (streq(name, "UnitFileState"))
2662 i->unit_file_state = s;
2663 else if (streq(name, "Result"))
2670 case DBUS_TYPE_BOOLEAN: {
2673 dbus_message_iter_get_basic(iter, &b);
2675 if (streq(name, "Accept"))
2677 else if (streq(name, "NeedDaemonReload"))
2678 i->need_daemon_reload = b;
2679 else if (streq(name, "ConditionResult"))
2680 i->condition_result = b;
2685 case DBUS_TYPE_UINT32: {
2688 dbus_message_iter_get_basic(iter, &u);
2690 if (streq(name, "MainPID")) {
2692 i->main_pid = (pid_t) u;
2695 } else if (streq(name, "ControlPID"))
2696 i->control_pid = (pid_t) u;
2697 else if (streq(name, "ExecMainPID")) {
2699 i->main_pid = (pid_t) u;
2700 } else if (streq(name, "NAccepted"))
2702 else if (streq(name, "NConnections"))
2703 i->n_connections = u;
2708 case DBUS_TYPE_INT32: {
2711 dbus_message_iter_get_basic(iter, &j);
2713 if (streq(name, "ExecMainCode"))
2714 i->exit_code = (int) j;
2715 else if (streq(name, "ExecMainStatus"))
2716 i->exit_status = (int) j;
2721 case DBUS_TYPE_UINT64: {
2724 dbus_message_iter_get_basic(iter, &u);
2726 if (streq(name, "ExecMainStartTimestamp"))
2727 i->start_timestamp = (usec_t) u;
2728 else if (streq(name, "ExecMainExitTimestamp"))
2729 i->exit_timestamp = (usec_t) u;
2730 else if (streq(name, "ActiveEnterTimestamp"))
2731 i->active_enter_timestamp = (usec_t) u;
2732 else if (streq(name, "InactiveEnterTimestamp"))
2733 i->inactive_enter_timestamp = (usec_t) u;
2734 else if (streq(name, "InactiveExitTimestamp"))
2735 i->inactive_exit_timestamp = (usec_t) u;
2736 else if (streq(name, "InactiveExitTimestampMonotonic"))
2737 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2738 else if (streq(name, "ActiveExitTimestamp"))
2739 i->active_exit_timestamp = (usec_t) u;
2740 else if (streq(name, "ConditionTimestamp"))
2741 i->condition_timestamp = (usec_t) u;
2746 case DBUS_TYPE_ARRAY: {
2748 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2749 startswith(name, "Exec")) {
2750 DBusMessageIter sub;
2752 dbus_message_iter_recurse(iter, &sub);
2753 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2754 ExecStatusInfo *info;
2757 if (!(info = new0(ExecStatusInfo, 1)))
2760 if (!(info->name = strdup(name))) {
2765 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2770 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2772 dbus_message_iter_next(&sub);
2774 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2775 streq(name, "Documentation")) {
2777 DBusMessageIter sub;
2779 dbus_message_iter_recurse(iter, &sub);
2780 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2784 dbus_message_iter_get_basic(&sub, &s);
2786 l = strv_append(i->documentation, s);
2790 strv_free(i->documentation);
2791 i->documentation = l;
2793 dbus_message_iter_next(&sub);
2800 case DBUS_TYPE_STRUCT: {
2802 if (streq(name, "LoadError")) {
2803 DBusMessageIter sub;
2804 const char *n, *message;
2807 dbus_message_iter_recurse(iter, &sub);
2809 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2813 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2817 if (!isempty(message))
2818 i->load_error = message;
2828 static int print_property(const char *name, DBusMessageIter *iter) {
2832 /* This is a low-level property printer, see
2833 * print_status_info() for the nicer output */
2835 if (arg_property && !strv_find(arg_property, name))
2838 switch (dbus_message_iter_get_arg_type(iter)) {
2840 case DBUS_TYPE_STRUCT: {
2841 DBusMessageIter sub;
2842 dbus_message_iter_recurse(iter, &sub);
2844 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2847 dbus_message_iter_get_basic(&sub, &u);
2850 printf("%s=%u\n", name, (unsigned) u);
2852 printf("%s=\n", name);
2855 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2858 dbus_message_iter_get_basic(&sub, &s);
2860 if (arg_all || s[0])
2861 printf("%s=%s\n", name, s);
2864 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2865 const char *a = NULL, *b = NULL;
2867 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2868 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2870 if (arg_all || !isempty(a) || !isempty(b))
2871 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2879 case DBUS_TYPE_ARRAY:
2881 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2882 DBusMessageIter sub, sub2;
2884 dbus_message_iter_recurse(iter, &sub);
2885 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2889 dbus_message_iter_recurse(&sub, &sub2);
2891 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2892 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2893 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2895 dbus_message_iter_next(&sub);
2900 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2901 DBusMessageIter sub, sub2;
2903 dbus_message_iter_recurse(iter, &sub);
2904 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2905 const char *type, *path;
2907 dbus_message_iter_recurse(&sub, &sub2);
2909 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2910 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2911 printf("%s=%s\n", type, path);
2913 dbus_message_iter_next(&sub);
2918 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2919 DBusMessageIter sub, sub2;
2921 dbus_message_iter_recurse(iter, &sub);
2922 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2924 uint64_t value, next_elapse;
2926 dbus_message_iter_recurse(&sub, &sub2);
2928 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2929 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2930 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2931 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2933 printf("%s={ value=%s ; next_elapse=%s }\n",
2935 format_timespan(timespan1, sizeof(timespan1), value),
2936 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2939 dbus_message_iter_next(&sub);
2944 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2945 DBusMessageIter sub, sub2;
2947 dbus_message_iter_recurse(iter, &sub);
2948 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2949 const char *controller, *attr, *value;
2951 dbus_message_iter_recurse(&sub, &sub2);
2953 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2954 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2955 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2957 printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2963 dbus_message_iter_next(&sub);
2968 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2969 DBusMessageIter sub;
2971 dbus_message_iter_recurse(iter, &sub);
2972 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2973 ExecStatusInfo info;
2976 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2977 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2980 t = strv_join(info.argv, " ");
2982 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2986 yes_no(info.ignore),
2987 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2988 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2989 (unsigned) info. pid,
2990 sigchld_code_to_string(info.code),
2992 info.code == CLD_EXITED ? "" : "/",
2993 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2999 strv_free(info.argv);
3001 dbus_message_iter_next(&sub);
3010 if (generic_print_property(name, iter, arg_all) > 0)
3014 printf("%s=[unprintable]\n", name);
3019 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3020 _cleanup_free_ DBusMessage *reply = NULL;
3021 const char *interface = "";
3023 DBusMessageIter iter, sub, sub2, sub3;
3024 UnitStatusInfo info;
3032 r = bus_method_call_with_reply(
3034 "org.freedesktop.systemd1",
3036 "org.freedesktop.DBus.Properties",
3040 DBUS_TYPE_STRING, &interface,
3045 if (!dbus_message_iter_init(reply, &iter) ||
3046 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3047 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3048 log_error("Failed to parse reply.");
3052 dbus_message_iter_recurse(&iter, &sub);
3059 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3062 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3063 dbus_message_iter_recurse(&sub, &sub2);
3065 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3066 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3067 log_error("Failed to parse reply.");
3071 dbus_message_iter_recurse(&sub2, &sub3);
3073 if (show_properties)
3074 r = print_property(name, &sub3);
3076 r = status_property(name, &sub3, &info);
3078 log_error("Failed to parse reply.");
3082 dbus_message_iter_next(&sub);
3087 if (!show_properties) {
3088 if (streq(verb, "help"))
3089 show_unit_help(&info);
3091 print_status_info(&info);
3094 strv_free(info.documentation);
3096 if (!streq_ptr(info.active_state, "active") &&
3097 !streq_ptr(info.active_state, "reloading") &&
3098 streq(verb, "status"))
3099 /* According to LSB: "program not running" */
3102 while ((p = info.exec)) {
3103 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3104 exec_status_info_free(p);
3110 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3111 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3112 const char *path = NULL;
3116 dbus_error_init(&error);
3118 r = bus_method_call_with_reply(
3120 "org.freedesktop.systemd1",
3121 "/org/freedesktop/systemd1",
3122 "org.freedesktop.systemd1.Manager",
3126 DBUS_TYPE_UINT32, &pid,
3131 if (!dbus_message_get_args(reply, &error,
3132 DBUS_TYPE_OBJECT_PATH, &path,
3133 DBUS_TYPE_INVALID)) {
3134 log_error("Failed to parse reply: %s", bus_error_message(&error));
3139 r = show_one(verb, bus, path, false, new_line);
3142 dbus_error_free(&error);
3147 static int show(DBusConnection *bus, char **args) {
3149 bool show_properties, new_line = false;
3155 show_properties = streq(args[0], "show");
3157 if (show_properties)
3158 pager_open_if_enabled();
3160 /* If no argument is specified inspect the manager itself */
3162 if (show_properties && strv_length(args) <= 1)
3163 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3165 STRV_FOREACH(name, args+1) {
3168 if (safe_atou32(*name, &id) < 0) {
3169 _cleanup_free_ char *p = NULL, *n = NULL;
3170 /* Interpret as unit name */
3172 n = unit_name_mangle(*name);
3176 p = unit_dbus_path_from_name(n);
3180 r = show_one(args[0], bus, p, show_properties, &new_line);
3184 } else if (show_properties) {
3185 _cleanup_free_ char *p = NULL;
3187 /* Interpret as job id */
3188 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3191 r = show_one(args[0], bus, p, show_properties, &new_line);
3196 /* Interpret as PID */
3197 r = show_one_by_pid(args[0], bus, id, &new_line);
3206 static int dump(DBusConnection *bus, char **args) {
3207 _cleanup_free_ DBusMessage *reply = NULL;
3212 dbus_error_init(&error);
3214 pager_open_if_enabled();
3216 r = bus_method_call_with_reply(
3218 "org.freedesktop.systemd1",
3219 "/org/freedesktop/systemd1",
3220 "org.freedesktop.systemd1.Manager",
3228 if (!dbus_message_get_args(reply, &error,
3229 DBUS_TYPE_STRING, &text,
3230 DBUS_TYPE_INVALID)) {
3231 log_error("Failed to parse reply: %s", bus_error_message(&error));
3232 dbus_error_free(&error);
3236 fputs(text, stdout);
3240 static int snapshot(DBusConnection *bus, char **args) {
3241 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3244 dbus_bool_t cleanup = FALSE;
3245 DBusMessageIter iter, sub;
3248 *interface = "org.freedesktop.systemd1.Unit",
3250 _cleanup_free_ char *n = NULL;
3252 dbus_error_init(&error);
3254 if (strv_length(args) > 1)
3255 n = snapshot_name_mangle(args[1]);
3261 r = bus_method_call_with_reply (
3263 "org.freedesktop.systemd1",
3264 "/org/freedesktop/systemd1",
3265 "org.freedesktop.systemd1.Manager",
3269 DBUS_TYPE_STRING, &n,
3270 DBUS_TYPE_BOOLEAN, &cleanup,
3275 if (!dbus_message_get_args(reply, &error,
3276 DBUS_TYPE_OBJECT_PATH, &path,
3277 DBUS_TYPE_INVALID)) {
3278 log_error("Failed to parse reply: %s", bus_error_message(&error));
3279 dbus_error_free(&error);
3283 dbus_message_unref(reply);
3286 r = bus_method_call_with_reply (
3288 "org.freedesktop.systemd1",
3290 "org.freedesktop.DBus.Properties",
3294 DBUS_TYPE_STRING, &interface,
3295 DBUS_TYPE_STRING, &property,
3300 if (!dbus_message_iter_init(reply, &iter) ||
3301 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3302 log_error("Failed to parse reply.");
3306 dbus_message_iter_recurse(&iter, &sub);
3308 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3309 log_error("Failed to parse reply.");
3313 dbus_message_iter_get_basic(&sub, &id);
3321 static int delete_snapshot(DBusConnection *bus, char **args) {
3326 STRV_FOREACH(name, args+1) {
3327 _cleanup_free_ char *n = NULL;
3330 n = snapshot_name_mangle(*name);
3334 r = bus_method_call_with_reply(
3336 "org.freedesktop.systemd1",
3337 "/org/freedesktop/systemd1",
3338 "org.freedesktop.systemd1.Manager",
3342 DBUS_TYPE_STRING, &n,
3351 static int daemon_reload(DBusConnection *bus, char **args) {
3356 if (arg_action == ACTION_RELOAD)
3358 else if (arg_action == ACTION_REEXEC)
3359 method = "Reexecute";
3361 assert(arg_action == ACTION_SYSTEMCTL);
3364 streq(args[0], "clear-jobs") ||
3365 streq(args[0], "cancel") ? "ClearJobs" :
3366 streq(args[0], "daemon-reexec") ? "Reexecute" :
3367 streq(args[0], "reset-failed") ? "ResetFailed" :
3368 streq(args[0], "halt") ? "Halt" :
3369 streq(args[0], "poweroff") ? "PowerOff" :
3370 streq(args[0], "reboot") ? "Reboot" :
3371 streq(args[0], "kexec") ? "KExec" :
3372 streq(args[0], "exit") ? "Exit" :
3373 /* "daemon-reload" */ "Reload";
3376 r = bus_method_call_with_reply(
3378 "org.freedesktop.systemd1",
3379 "/org/freedesktop/systemd1",
3380 "org.freedesktop.systemd1.Manager",
3386 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3387 /* There's always a fallback possible for
3388 * legacy actions. */
3390 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3391 /* On reexecution, we expect a disconnect, not
3395 log_error("Failed to issue method call: %s", bus_error_message(&error));
3397 dbus_error_free(&error);
3401 static int reset_failed(DBusConnection *bus, char **args) {
3405 if (strv_length(args) <= 1)
3406 return daemon_reload(bus, args);
3408 STRV_FOREACH(name, args+1) {
3409 _cleanup_free_ char *n;
3411 n = unit_name_mangle(*name);
3415 r = bus_method_call_with_reply(
3417 "org.freedesktop.systemd1",
3418 "/org/freedesktop/systemd1",
3419 "org.freedesktop.systemd1.Manager",
3423 DBUS_TYPE_STRING, &n,
3432 static int show_enviroment(DBusConnection *bus, char **args) {
3433 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3434 DBusMessageIter iter, sub, sub2;
3437 *interface = "org.freedesktop.systemd1.Manager",
3438 *property = "Environment";
3440 pager_open_if_enabled();
3442 r = bus_method_call_with_reply(
3444 "org.freedesktop.systemd1",
3445 "/org/freedesktop/systemd1",
3446 "org.freedesktop.DBus.Properties",
3450 DBUS_TYPE_STRING, &interface,
3451 DBUS_TYPE_STRING, &property,
3456 if (!dbus_message_iter_init(reply, &iter) ||
3457 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3458 log_error("Failed to parse reply.");
3462 dbus_message_iter_recurse(&iter, &sub);
3464 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3465 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3466 log_error("Failed to parse reply.");
3470 dbus_message_iter_recurse(&sub, &sub2);
3472 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3475 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3476 log_error("Failed to parse reply.");
3480 dbus_message_iter_get_basic(&sub2, &text);
3483 dbus_message_iter_next(&sub2);
3489 static int switch_root(DBusConnection *bus, char **args) {
3492 _cleanup_free_ char *init = NULL;
3494 l = strv_length(args);
3495 if (l < 2 || l > 3) {
3496 log_error("Wrong number of arguments.");
3503 init = strdup(args[2]);
3505 parse_env_file("/proc/cmdline", WHITESPACE,
3515 log_debug("switching root - root: %s; init: %s", root, init);
3517 return bus_method_call_with_reply(
3519 "org.freedesktop.systemd1",
3520 "/org/freedesktop/systemd1",
3521 "org.freedesktop.systemd1.Manager",
3525 DBUS_TYPE_STRING, &root,
3526 DBUS_TYPE_STRING, &init,
3530 static int set_environment(DBusConnection *bus, char **args) {
3531 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3534 DBusMessageIter iter;
3540 dbus_error_init(&error);
3542 method = streq(args[0], "set-environment")
3544 : "UnsetEnvironment";
3546 m = dbus_message_new_method_call(
3547 "org.freedesktop.systemd1",
3548 "/org/freedesktop/systemd1",
3549 "org.freedesktop.systemd1.Manager",
3554 dbus_message_iter_init_append(m, &iter);
3556 r = bus_append_strv_iter(&iter, args + 1);
3560 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3562 log_error("Failed to issue method call: %s", bus_error_message(&error));
3563 dbus_error_free(&error);
3570 static int enable_sysv_units(char **args) {
3573 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3574 const char *verb = args[0];
3575 unsigned f = 1, t = 1;
3578 if (arg_scope != UNIT_FILE_SYSTEM)
3581 if (!streq(verb, "enable") &&
3582 !streq(verb, "disable") &&
3583 !streq(verb, "is-enabled"))
3586 /* Processes all SysV units, and reshuffles the array so that
3587 * afterwards only the native units remain */
3590 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3595 for (f = 1; args[f]; f++) {
3598 bool found_native = false, found_sysv;
3600 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3601 char **k, *l, *q = NULL;
3608 if (!endswith(name, ".service"))
3611 if (path_is_absolute(name))
3614 STRV_FOREACH(k, paths.unit_path) {
3617 if (!isempty(arg_root))
3618 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3620 asprintf(&p, "%s/%s", *k, name);
3627 found_native = access(p, F_OK) >= 0;
3638 if (!isempty(arg_root))
3639 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3641 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3647 p[strlen(p) - sizeof(".service") + 1] = 0;
3648 found_sysv = access(p, F_OK) >= 0;
3655 /* Mark this entry, so that we don't try enabling it as native unit */
3656 args[f] = (char*) "";
3658 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3660 if (!isempty(arg_root))
3661 argv[c++] = q = strappend("--root=", arg_root);
3663 argv[c++] = path_get_file_name(p);
3665 streq(verb, "enable") ? "on" :
3666 streq(verb, "disable") ? "off" : "--level=5";
3669 l = strv_join((char**)argv, " ");
3677 log_info("Executing %s", l);
3682 log_error("Failed to fork: %m");
3687 } else if (pid == 0) {
3690 execv(argv[0], (char**) argv);
3691 _exit(EXIT_FAILURE);
3697 j = wait_for_terminate(pid, &status);
3699 log_error("Failed to wait for child: %s", strerror(-r));
3704 if (status.si_code == CLD_EXITED) {
3705 if (streq(verb, "is-enabled")) {
3706 if (status.si_status == 0) {
3715 } else if (status.si_status != 0) {
3726 lookup_paths_free(&paths);
3728 /* Drop all SysV units */
3729 for (f = 1, t = 1; args[f]; f++) {
3731 if (isempty(args[f]))
3734 args[t++] = args[f];
3743 static int mangle_names(char **original_names, char ***mangled_names) {
3744 char **i, **l, **name;
3746 l = new(char*, strv_length(original_names) + 1);
3751 STRV_FOREACH(name, original_names) {
3753 /* When enabling units qualified path names are OK,
3754 * too, hence allow them explicitly. */
3759 *i = unit_name_mangle(*name);
3775 static int enable_unit(DBusConnection *bus, char **args) {
3776 const char *verb = args[0];
3777 UnitFileChange *changes = NULL;
3778 unsigned n_changes = 0, i;
3779 int carries_install_info = -1;
3780 DBusMessage *m = NULL, *reply = NULL;
3783 char **mangled_names = NULL;
3785 r = enable_sysv_units(args);
3792 dbus_error_init(&error);
3794 if (!bus || avoid_bus()) {
3795 if (streq(verb, "enable")) {
3796 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3797 carries_install_info = r;
3798 } else if (streq(verb, "disable"))
3799 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3800 else if (streq(verb, "reenable")) {
3801 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3802 carries_install_info = r;
3803 } else if (streq(verb, "link"))
3804 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3805 else if (streq(verb, "preset")) {
3806 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3807 carries_install_info = r;
3808 } else if (streq(verb, "mask"))
3809 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3810 else if (streq(verb, "unmask"))
3811 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3813 assert_not_reached("Unknown verb");
3816 log_error("Operation failed: %s", strerror(-r));
3821 for (i = 0; i < n_changes; i++) {
3822 if (changes[i].type == UNIT_FILE_SYMLINK)
3823 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3825 log_info("rm '%s'", changes[i].path);
3832 bool send_force = true, expect_carries_install_info = false;
3834 DBusMessageIter iter, sub, sub2;
3836 if (streq(verb, "enable")) {
3837 method = "EnableUnitFiles";
3838 expect_carries_install_info = true;
3839 } else if (streq(verb, "disable")) {
3840 method = "DisableUnitFiles";
3842 } else if (streq(verb, "reenable")) {
3843 method = "ReenableUnitFiles";
3844 expect_carries_install_info = true;
3845 } else if (streq(verb, "link"))
3846 method = "LinkUnitFiles";
3847 else if (streq(verb, "preset")) {
3848 method = "PresetUnitFiles";
3849 expect_carries_install_info = true;
3850 } else if (streq(verb, "mask"))
3851 method = "MaskUnitFiles";
3852 else if (streq(verb, "unmask")) {
3853 method = "UnmaskUnitFiles";
3856 assert_not_reached("Unknown verb");
3858 m = dbus_message_new_method_call(
3859 "org.freedesktop.systemd1",
3860 "/org/freedesktop/systemd1",
3861 "org.freedesktop.systemd1.Manager",
3868 dbus_message_iter_init_append(m, &iter);
3870 r = mangle_names(args+1, &mangled_names);
3874 r = bus_append_strv_iter(&iter, mangled_names);
3876 log_error("Failed to append unit files.");
3881 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3882 log_error("Failed to append runtime boolean.");
3890 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3891 log_error("Failed to append force boolean.");
3897 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3899 log_error("Failed to issue method call: %s", bus_error_message(&error));
3904 if (!dbus_message_iter_init(reply, &iter)) {
3905 log_error("Failed to initialize iterator.");
3909 if (expect_carries_install_info) {
3910 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3912 log_error("Failed to parse reply.");
3916 carries_install_info = b;
3919 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3920 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3921 log_error("Failed to parse reply.");
3926 dbus_message_iter_recurse(&iter, &sub);
3927 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3928 const char *type, *path, *source;
3930 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3931 log_error("Failed to parse reply.");
3936 dbus_message_iter_recurse(&sub, &sub2);
3938 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3939 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3940 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3941 log_error("Failed to parse reply.");
3947 if (streq(type, "symlink"))
3948 log_info("ln -s '%s' '%s'", source, path);
3950 log_info("rm '%s'", path);
3953 dbus_message_iter_next(&sub);
3956 /* Try to reload if enabeld */
3958 r = daemon_reload(bus, args);
3961 if (carries_install_info == 0)
3963 "The unit files have no [Install] section. They are not meant to be enabled\n"
3964 "using systemctl.\n"
3965 "Possible reasons for having this kind of units are:\n"
3966 "1) A unit may be statically enabled by being symlinked from another unit's\n"
3967 " .wants/ or .requires/ directory.\n"
3968 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
3969 " a requirement dependency on it.\n"
3970 "3) A unit may be started when needed via activation (socket, path, timer,\n"
3971 " D-Bus, udev, scripted systemctl call, ...).\n");
3975 dbus_message_unref(m);
3978 dbus_message_unref(reply);
3980 unit_file_changes_free(changes, n_changes);
3982 dbus_error_free(&error);
3984 strv_free(mangled_names);
3989 static int unit_is_enabled(DBusConnection *bus, char **args) {
3992 DBusMessage *reply = NULL;
3996 dbus_error_init(&error);
3998 r = enable_sysv_units(args);
4004 if (!bus || avoid_bus()) {
4006 STRV_FOREACH(name, args+1) {
4007 UnitFileState state;
4009 state = unit_file_get_state(arg_scope, arg_root, *name);
4015 if (state == UNIT_FILE_ENABLED ||
4016 state == UNIT_FILE_ENABLED_RUNTIME ||
4017 state == UNIT_FILE_STATIC)
4021 puts(unit_file_state_to_string(state));
4025 STRV_FOREACH(name, args+1) {
4028 r = bus_method_call_with_reply (
4030 "org.freedesktop.systemd1",
4031 "/org/freedesktop/systemd1",
4032 "org.freedesktop.systemd1.Manager",
4036 DBUS_TYPE_STRING, name,
4041 if (!dbus_message_get_args(reply, &error,
4042 DBUS_TYPE_STRING, &s,
4043 DBUS_TYPE_INVALID)) {
4044 log_error("Failed to parse reply: %s", bus_error_message(&error));
4049 dbus_message_unref(reply);
4052 if (streq(s, "enabled") ||
4053 streq(s, "enabled-runtime") ||
4062 r = enabled ? 0 : 1;
4066 dbus_message_unref(reply);
4068 dbus_error_free(&error);
4072 static int systemctl_help(void) {
4074 pager_open_if_enabled();
4076 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4077 "Query or send control commands to the systemd manager.\n\n"
4078 " -h --help Show this help\n"
4079 " --version Show package version\n"
4080 " -t --type=TYPE List only units of a particular type\n"
4081 " -p --property=NAME Show only properties by this name\n"
4082 " -a --all Show all units/properties, including dead/empty ones\n"
4083 " --failed Show only failed units\n"
4084 " --full Don't ellipsize unit names on output\n"
4085 " --fail When queueing a new job, fail if conflicting jobs are\n"
4087 " --ignore-dependencies\n"
4088 " When queueing a new job, ignore all its dependencies\n"
4089 " -i --ignore-inhibitors\n"
4090 " When shutting down or sleeping, ignore inhibitors\n"
4091 " --kill-who=WHO Who to send signal to\n"
4092 " -s --signal=SIGNAL Which signal to send\n"
4093 " -H --host=[USER@]HOST\n"
4094 " Show information for remote host\n"
4095 " -P --privileged Acquire privileges before execution\n"
4096 " -q --quiet Suppress output\n"
4097 " --no-block Do not wait until operation finished\n"
4098 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4099 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4101 " --no-legend Do not print a legend (column headers and hints)\n"
4102 " --no-pager Do not pipe output into a pager\n"
4103 " --no-ask-password\n"
4104 " Do not ask for system passwords\n"
4105 " --system Connect to system manager\n"
4106 " --user Connect to user service manager\n"
4107 " --global Enable/disable unit files globally\n"
4108 " -f --force When enabling unit files, override existing symlinks\n"
4109 " When shutting down, execute action immediately\n"
4110 " --root=PATH Enable unit files in the specified root directory\n"
4111 " --runtime Enable unit files only temporarily until next reboot\n"
4112 " -n --lines=INTEGER Journal entries to show\n"
4113 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4114 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4116 " list-units List loaded units\n"
4117 " start [NAME...] Start (activate) one or more units\n"
4118 " stop [NAME...] Stop (deactivate) one or more units\n"
4119 " reload [NAME...] Reload one or more units\n"
4120 " restart [NAME...] Start or restart one or more units\n"
4121 " try-restart [NAME...] Restart one or more units if active\n"
4122 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4123 " otherwise start or restart\n"
4124 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4125 " otherwise restart if active\n"
4126 " isolate [NAME] Start one unit and stop all others\n"
4127 " kill [NAME...] Send signal to processes of a unit\n"
4128 " is-active [NAME...] Check whether units are active\n"
4129 " is-failed [NAME...] Check whether units are failed\n"
4130 " status [NAME...|PID...] Show runtime status of one or more units\n"
4131 " show [NAME...|JOB...] Show properties of one or more\n"
4132 " units/jobs or the manager\n"
4133 " help [NAME...|PID...] Show manual for one or more units\n"
4134 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4136 " get-cgroup-attr [NAME] [ATTR] ...\n"
4137 " Get control group attrubute\n"
4138 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4139 " Set control group attribute\n"
4140 " unset-cgroup-attr [NAME] [ATTR...]\n"
4141 " Unset control group attribute\n"
4142 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4143 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4144 " load [NAME...] Load one or more units\n"
4145 " list-dependencies [NAME] Recursively show units which are required\n"
4146 " or wanted by this unit\n\n"
4147 "Unit File Commands:\n"
4148 " list-unit-files List installed unit files\n"
4149 " enable [NAME...] Enable one or more unit files\n"
4150 " disable [NAME...] Disable one or more unit files\n"
4151 " reenable [NAME...] Reenable one or more unit files\n"
4152 " preset [NAME...] Enable/disable one or more unit files\n"
4153 " based on preset configuration\n"
4154 " mask [NAME...] Mask one or more units\n"
4155 " unmask [NAME...] Unmask one or more units\n"
4156 " link [PATH...] Link one or more units files into\n"
4157 " the search path\n"
4158 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4160 " list-jobs List jobs\n"
4161 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4162 "Status Commands:\n"
4163 " dump Dump server status\n"
4164 "Snapshot Commands:\n"
4165 " snapshot [NAME] Create a snapshot\n"
4166 " delete [NAME...] Remove one or more snapshots\n\n"
4167 "Environment Commands:\n"
4168 " show-environment Dump environment\n"
4169 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4170 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4171 "Manager Lifecycle Commands:\n"
4172 " daemon-reload Reload systemd manager configuration\n"
4173 " daemon-reexec Reexecute systemd manager\n\n"
4174 "System Commands:\n"
4175 " default Enter system default mode\n"
4176 " rescue Enter system rescue mode\n"
4177 " emergency Enter system emergency mode\n"
4178 " halt Shut down and halt the system\n"
4179 " poweroff Shut down and power-off the system\n"
4180 " reboot Shut down and reboot the system\n"
4181 " kexec Shut down and reboot the system with kexec\n"
4182 " exit Request user instance exit\n"
4183 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4184 " suspend Suspend the system\n"
4185 " hibernate Hibernate the system\n"
4186 " hybrid-sleep Hibernate and suspend the system\n",
4187 program_invocation_short_name);
4192 static int halt_help(void) {
4194 printf("%s [OPTIONS...]\n\n"
4195 "%s the system.\n\n"
4196 " --help Show this help\n"
4197 " --halt Halt the machine\n"
4198 " -p --poweroff Switch off the machine\n"
4199 " --reboot Reboot the machine\n"
4200 " -f --force Force immediate halt/power-off/reboot\n"
4201 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4202 " -d --no-wtmp Don't write wtmp record\n"
4203 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4204 program_invocation_short_name,
4205 arg_action == ACTION_REBOOT ? "Reboot" :
4206 arg_action == ACTION_POWEROFF ? "Power off" :
4212 static int shutdown_help(void) {
4214 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4215 "Shut down the system.\n\n"
4216 " --help Show this help\n"
4217 " -H --halt Halt the machine\n"
4218 " -P --poweroff Power-off the machine\n"
4219 " -r --reboot Reboot the machine\n"
4220 " -h Equivalent to --poweroff, overridden by --halt\n"
4221 " -k Don't halt/power-off/reboot, just send warnings\n"
4222 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4223 " -c Cancel a pending shutdown\n",
4224 program_invocation_short_name);
4229 static int telinit_help(void) {
4231 printf("%s [OPTIONS...] {COMMAND}\n\n"
4232 "Send control commands to the init daemon.\n\n"
4233 " --help Show this help\n"
4234 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4236 " 0 Power-off the machine\n"
4237 " 6 Reboot the machine\n"
4238 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4239 " 1, s, S Enter rescue mode\n"
4240 " q, Q Reload init daemon configuration\n"
4241 " u, U Reexecute init daemon\n",
4242 program_invocation_short_name);
4247 static int runlevel_help(void) {
4249 printf("%s [OPTIONS...]\n\n"
4250 "Prints the previous and current runlevel of the init system.\n\n"
4251 " --help Show this help\n",
4252 program_invocation_short_name);
4257 static int help_types(void) {
4260 puts("Available unit types:");
4261 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4262 if (unit_type_table[i])
4263 puts(unit_type_table[i]);
4265 puts("\nAvailable unit load states: ");
4266 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4267 if (unit_type_table[i])
4268 puts(unit_load_state_table[i]);
4273 static int systemctl_parse_argv(int argc, char *argv[]) {
4277 ARG_IGNORE_DEPENDENCIES,
4290 ARG_NO_ASK_PASSWORD,
4296 static const struct option options[] = {
4297 { "help", no_argument, NULL, 'h' },
4298 { "version", no_argument, NULL, ARG_VERSION },
4299 { "type", required_argument, NULL, 't' },
4300 { "property", required_argument, NULL, 'p' },
4301 { "all", no_argument, NULL, 'a' },
4302 { "failed", no_argument, NULL, ARG_FAILED },
4303 { "full", no_argument, NULL, ARG_FULL },
4304 { "fail", no_argument, NULL, ARG_FAIL },
4305 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4306 { "ignore-inhibitors", no_argument, NULL, 'i' },
4307 { "user", no_argument, NULL, ARG_USER },
4308 { "system", no_argument, NULL, ARG_SYSTEM },
4309 { "global", no_argument, NULL, ARG_GLOBAL },
4310 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4311 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4312 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4313 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4314 { "quiet", no_argument, NULL, 'q' },
4315 { "root", required_argument, NULL, ARG_ROOT },
4316 { "force", no_argument, NULL, ARG_FORCE },
4317 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4318 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4319 { "signal", required_argument, NULL, 's' },
4320 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4321 { "host", required_argument, NULL, 'H' },
4322 { "privileged",no_argument, NULL, 'P' },
4323 { "runtime", no_argument, NULL, ARG_RUNTIME },
4324 { "lines", required_argument, NULL, 'n' },
4325 { "output", required_argument, NULL, 'o' },
4326 { NULL, 0, NULL, 0 }
4334 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4343 puts(PACKAGE_STRING);
4344 puts(SYSTEMD_FEATURES);
4348 if (streq(optarg, "help")) {
4353 if (unit_type_from_string(optarg) >= 0) {
4357 if (unit_load_state_from_string(optarg) >= 0) {
4358 arg_load_state = optarg;
4361 log_error("Unkown unit type or load state '%s'.",
4363 log_info("Use -t help to see a list of allowed values.");
4368 if (!(l = strv_append(arg_property, optarg)))
4371 strv_free(arg_property);
4374 /* If the user asked for a particular
4375 * property, show it to him, even if it is
4386 arg_job_mode = "fail";
4389 case ARG_IGNORE_DEPENDENCIES:
4390 arg_job_mode = "ignore-dependencies";
4394 arg_scope = UNIT_FILE_USER;
4398 arg_scope = UNIT_FILE_SYSTEM;
4402 arg_scope = UNIT_FILE_GLOBAL;
4406 arg_no_block = true;
4410 arg_no_legend = true;
4414 arg_no_pager = true;
4446 arg_no_reload = true;
4450 arg_kill_who = optarg;
4454 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4455 log_error("Failed to parse signal string %s.", optarg);
4460 case ARG_NO_ASK_PASSWORD:
4461 arg_ask_password = false;
4465 arg_transport = TRANSPORT_POLKIT;
4469 arg_transport = TRANSPORT_SSH;
4478 if (safe_atou(optarg, &arg_lines) < 0) {
4479 log_error("Failed to parse lines '%s'", optarg);
4485 arg_output = output_mode_from_string(optarg);
4486 if (arg_output < 0) {
4487 log_error("Unknown output '%s'.", optarg);
4493 arg_ignore_inhibitors = true;
4500 log_error("Unknown option code '%c'.", c);
4505 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4506 log_error("Cannot access user instance remotely.");
4513 static int halt_parse_argv(int argc, char *argv[]) {
4522 static const struct option options[] = {
4523 { "help", no_argument, NULL, ARG_HELP },
4524 { "halt", no_argument, NULL, ARG_HALT },
4525 { "poweroff", no_argument, NULL, 'p' },
4526 { "reboot", no_argument, NULL, ARG_REBOOT },
4527 { "force", no_argument, NULL, 'f' },
4528 { "wtmp-only", no_argument, NULL, 'w' },
4529 { "no-wtmp", no_argument, NULL, 'd' },
4530 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4531 { NULL, 0, NULL, 0 }
4539 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4540 if (runlevel == '0' || runlevel == '6')
4543 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4551 arg_action = ACTION_HALT;
4555 if (arg_action != ACTION_REBOOT)
4556 arg_action = ACTION_POWEROFF;
4560 arg_action = ACTION_REBOOT;
4582 /* Compatibility nops */
4589 log_error("Unknown option code '%c'.", c);
4594 if (optind < argc) {
4595 log_error("Too many arguments.");
4602 static int parse_time_spec(const char *t, usec_t *_u) {
4606 if (streq(t, "now"))
4608 else if (!strchr(t, ':')) {
4611 if (safe_atou64(t, &u) < 0)
4614 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4623 hour = strtol(t, &e, 10);
4624 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4627 minute = strtol(e+1, &e, 10);
4628 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4631 n = now(CLOCK_REALTIME);
4632 s = (time_t) (n / USEC_PER_SEC);
4635 assert_se(localtime_r(&s, &tm));
4637 tm.tm_hour = (int) hour;
4638 tm.tm_min = (int) minute;
4641 assert_se(s = mktime(&tm));
4643 *_u = (usec_t) s * USEC_PER_SEC;
4646 *_u += USEC_PER_DAY;
4652 static int shutdown_parse_argv(int argc, char *argv[]) {
4659 static const struct option options[] = {
4660 { "help", no_argument, NULL, ARG_HELP },
4661 { "halt", no_argument, NULL, 'H' },
4662 { "poweroff", no_argument, NULL, 'P' },
4663 { "reboot", no_argument, NULL, 'r' },
4664 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4665 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4666 { NULL, 0, NULL, 0 }
4674 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4682 arg_action = ACTION_HALT;
4686 arg_action = ACTION_POWEROFF;
4691 arg_action = ACTION_KEXEC;
4693 arg_action = ACTION_REBOOT;
4697 arg_action = ACTION_KEXEC;
4701 if (arg_action != ACTION_HALT)
4702 arg_action = ACTION_POWEROFF;
4715 /* Compatibility nops */
4719 arg_action = ACTION_CANCEL_SHUTDOWN;
4726 log_error("Unknown option code '%c'.", c);
4731 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4732 r = parse_time_spec(argv[optind], &arg_when);
4734 log_error("Failed to parse time specification: %s", argv[optind]);
4738 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4740 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4741 /* No time argument for shutdown cancel */
4742 arg_wall = argv + optind;
4743 else if (argc > optind + 1)
4744 /* We skip the time argument */
4745 arg_wall = argv + optind + 1;
4752 static int telinit_parse_argv(int argc, char *argv[]) {
4759 static const struct option options[] = {
4760 { "help", no_argument, NULL, ARG_HELP },
4761 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4762 { NULL, 0, NULL, 0 }
4765 static const struct {
4769 { '0', ACTION_POWEROFF },
4770 { '6', ACTION_REBOOT },
4771 { '1', ACTION_RESCUE },
4772 { '2', ACTION_RUNLEVEL2 },
4773 { '3', ACTION_RUNLEVEL3 },
4774 { '4', ACTION_RUNLEVEL4 },
4775 { '5', ACTION_RUNLEVEL5 },
4776 { 's', ACTION_RESCUE },
4777 { 'S', ACTION_RESCUE },
4778 { 'q', ACTION_RELOAD },
4779 { 'Q', ACTION_RELOAD },
4780 { 'u', ACTION_REEXEC },
4781 { 'U', ACTION_REEXEC }
4790 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4805 log_error("Unknown option code '%c'.", c);
4810 if (optind >= argc) {
4815 if (optind + 1 < argc) {
4816 log_error("Too many arguments.");
4820 if (strlen(argv[optind]) != 1) {
4821 log_error("Expected single character argument.");
4825 for (i = 0; i < ELEMENTSOF(table); i++)
4826 if (table[i].from == argv[optind][0])
4829 if (i >= ELEMENTSOF(table)) {
4830 log_error("Unknown command '%s'.", argv[optind]);
4834 arg_action = table[i].to;
4841 static int runlevel_parse_argv(int argc, char *argv[]) {
4847 static const struct option options[] = {
4848 { "help", no_argument, NULL, ARG_HELP },
4849 { NULL, 0, NULL, 0 }
4857 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4868 log_error("Unknown option code '%c'.", c);
4873 if (optind < argc) {
4874 log_error("Too many arguments.");
4881 static int parse_argv(int argc, char *argv[]) {
4885 if (program_invocation_short_name) {
4887 if (strstr(program_invocation_short_name, "halt")) {
4888 arg_action = ACTION_HALT;
4889 return halt_parse_argv(argc, argv);
4890 } else if (strstr(program_invocation_short_name, "poweroff")) {
4891 arg_action = ACTION_POWEROFF;
4892 return halt_parse_argv(argc, argv);
4893 } else if (strstr(program_invocation_short_name, "reboot")) {
4895 arg_action = ACTION_KEXEC;
4897 arg_action = ACTION_REBOOT;
4898 return halt_parse_argv(argc, argv);
4899 } else if (strstr(program_invocation_short_name, "shutdown")) {
4900 arg_action = ACTION_POWEROFF;
4901 return shutdown_parse_argv(argc, argv);
4902 } else if (strstr(program_invocation_short_name, "init")) {
4904 if (sd_booted() > 0) {
4905 arg_action = ACTION_INVALID;
4906 return telinit_parse_argv(argc, argv);
4908 /* Hmm, so some other init system is
4909 * running, we need to forward this
4910 * request to it. For now we simply
4911 * guess that it is Upstart. */
4913 execv("/lib/upstart/telinit", argv);
4915 log_error("Couldn't find an alternative telinit implementation to spawn.");
4919 } else if (strstr(program_invocation_short_name, "runlevel")) {
4920 arg_action = ACTION_RUNLEVEL;
4921 return runlevel_parse_argv(argc, argv);
4925 arg_action = ACTION_SYSTEMCTL;
4926 return systemctl_parse_argv(argc, argv);
4929 static int action_to_runlevel(void) {
4931 static const char table[_ACTION_MAX] = {
4932 [ACTION_HALT] = '0',
4933 [ACTION_POWEROFF] = '0',
4934 [ACTION_REBOOT] = '6',
4935 [ACTION_RUNLEVEL2] = '2',
4936 [ACTION_RUNLEVEL3] = '3',
4937 [ACTION_RUNLEVEL4] = '4',
4938 [ACTION_RUNLEVEL5] = '5',
4939 [ACTION_RESCUE] = '1'
4942 assert(arg_action < _ACTION_MAX);
4944 return table[arg_action];
4947 static int talk_upstart(void) {
4948 DBusMessage *m = NULL, *reply = NULL;
4950 int previous, rl, r;
4952 env1_buf[] = "RUNLEVEL=X",
4953 env2_buf[] = "PREVLEVEL=X";
4954 char *env1 = env1_buf, *env2 = env2_buf;
4955 const char *emit = "runlevel";
4956 dbus_bool_t b_false = FALSE;
4957 DBusMessageIter iter, sub;
4958 DBusConnection *bus;
4960 dbus_error_init(&error);
4962 if (!(rl = action_to_runlevel()))
4965 if (utmp_get_runlevel(&previous, NULL) < 0)
4968 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4969 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4974 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4979 if ((r = bus_check_peercred(bus)) < 0) {
4980 log_error("Failed to verify owner of bus.");
4984 if (!(m = dbus_message_new_method_call(
4985 "com.ubuntu.Upstart",
4986 "/com/ubuntu/Upstart",
4987 "com.ubuntu.Upstart0_6",
4990 log_error("Could not allocate message.");
4995 dbus_message_iter_init_append(m, &iter);
4997 env1_buf[sizeof(env1_buf)-2] = rl;
4998 env2_buf[sizeof(env2_buf)-2] = previous;
5000 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5001 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5002 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5003 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5004 !dbus_message_iter_close_container(&iter, &sub) ||
5005 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5006 log_error("Could not append arguments to message.");
5011 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5013 if (bus_error_is_no_service(&error)) {
5018 log_error("Failed to issue method call: %s", bus_error_message(&error));
5027 dbus_message_unref(m);
5030 dbus_message_unref(reply);
5033 dbus_connection_flush(bus);
5034 dbus_connection_close(bus);
5035 dbus_connection_unref(bus);
5038 dbus_error_free(&error);
5043 static int talk_initctl(void) {
5044 struct init_request request;
5048 if (!(rl = action_to_runlevel()))
5052 request.magic = INIT_MAGIC;
5053 request.sleeptime = 0;
5054 request.cmd = INIT_CMD_RUNLVL;
5055 request.runlevel = rl;
5057 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5059 if (errno == ENOENT)
5062 log_error("Failed to open "INIT_FIFO": %m");
5067 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5068 close_nointr_nofail(fd);
5071 log_error("Failed to write to "INIT_FIFO": %m");
5072 return errno ? -errno : -EIO;
5078 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5080 static const struct {
5088 int (* const dispatch)(DBusConnection *bus, char **args);
5090 { "list-units", LESS, 1, list_units },
5091 { "list-unit-files", EQUAL, 1, list_unit_files },
5092 { "list-jobs", EQUAL, 1, list_jobs },
5093 { "clear-jobs", EQUAL, 1, daemon_reload },
5094 { "load", MORE, 2, load_unit },
5095 { "cancel", MORE, 2, cancel_job },
5096 { "start", MORE, 2, start_unit },
5097 { "stop", MORE, 2, start_unit },
5098 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5099 { "reload", MORE, 2, start_unit },
5100 { "restart", MORE, 2, start_unit },
5101 { "try-restart", MORE, 2, start_unit },
5102 { "reload-or-restart", MORE, 2, start_unit },
5103 { "reload-or-try-restart", MORE, 2, start_unit },
5104 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5105 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5106 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5107 { "isolate", EQUAL, 2, start_unit },
5108 { "set-cgroup", MORE, 2, set_cgroup },
5109 { "unset-cgroup", MORE, 2, set_cgroup },
5110 { "get-cgroup-attr", MORE, 2, get_cgroup_attr },
5111 { "set-cgroup-attr", MORE, 2, set_cgroup_attr },
5112 { "unset-cgroup-attr", MORE, 2, set_cgroup },
5113 { "kill", MORE, 2, kill_unit },
5114 { "is-active", MORE, 2, check_unit_active },
5115 { "check", MORE, 2, check_unit_active },
5116 { "is-failed", MORE, 2, check_unit_failed },
5117 { "show", MORE, 1, show },
5118 { "status", MORE, 2, show },
5119 { "help", MORE, 2, show },
5120 { "dump", EQUAL, 1, dump },
5121 { "snapshot", LESS, 2, snapshot },
5122 { "delete", MORE, 2, delete_snapshot },
5123 { "daemon-reload", EQUAL, 1, daemon_reload },
5124 { "daemon-reexec", EQUAL, 1, daemon_reload },
5125 { "show-environment", EQUAL, 1, show_enviroment },
5126 { "set-environment", MORE, 2, set_environment },
5127 { "unset-environment", MORE, 2, set_environment },
5128 { "halt", EQUAL, 1, start_special },
5129 { "poweroff", EQUAL, 1, start_special },
5130 { "reboot", EQUAL, 1, start_special },
5131 { "kexec", EQUAL, 1, start_special },
5132 { "suspend", EQUAL, 1, start_special },
5133 { "hibernate", EQUAL, 1, start_special },
5134 { "hybrid-sleep", EQUAL, 1, start_special },
5135 { "default", EQUAL, 1, start_special },
5136 { "rescue", EQUAL, 1, start_special },
5137 { "emergency", EQUAL, 1, start_special },
5138 { "exit", EQUAL, 1, start_special },
5139 { "reset-failed", MORE, 1, reset_failed },
5140 { "enable", MORE, 2, enable_unit },
5141 { "disable", MORE, 2, enable_unit },
5142 { "is-enabled", MORE, 2, unit_is_enabled },
5143 { "reenable", MORE, 2, enable_unit },
5144 { "preset", MORE, 2, enable_unit },
5145 { "mask", MORE, 2, enable_unit },
5146 { "unmask", MORE, 2, enable_unit },
5147 { "link", MORE, 2, enable_unit },
5148 { "switch-root", MORE, 2, switch_root },
5149 { "list-dependencies", LESS, 2, list_dependencies },
5159 left = argc - optind;
5162 /* Special rule: no arguments means "list-units" */
5165 if (streq(argv[optind], "help") && !argv[optind+1]) {
5166 log_error("This command expects one or more "
5167 "unit names. Did you mean --help?");
5171 for (i = 0; i < ELEMENTSOF(verbs); i++)
5172 if (streq(argv[optind], verbs[i].verb))
5175 if (i >= ELEMENTSOF(verbs)) {
5176 log_error("Unknown operation '%s'.", argv[optind]);
5181 switch (verbs[i].argc_cmp) {
5184 if (left != verbs[i].argc) {
5185 log_error("Invalid number of arguments.");
5192 if (left < verbs[i].argc) {
5193 log_error("Too few arguments.");
5200 if (left > verbs[i].argc) {
5201 log_error("Too many arguments.");
5208 assert_not_reached("Unknown comparison operator.");
5211 /* Require a bus connection for all operations but
5213 if (!streq(verbs[i].verb, "enable") &&
5214 !streq(verbs[i].verb, "disable") &&
5215 !streq(verbs[i].verb, "is-enabled") &&
5216 !streq(verbs[i].verb, "list-unit-files") &&
5217 !streq(verbs[i].verb, "reenable") &&
5218 !streq(verbs[i].verb, "preset") &&
5219 !streq(verbs[i].verb, "mask") &&
5220 !streq(verbs[i].verb, "unmask") &&
5221 !streq(verbs[i].verb, "link")) {
5223 if (running_in_chroot() > 0) {
5224 log_info("Running in chroot, ignoring request.");
5228 if (((!streq(verbs[i].verb, "reboot") &&
5229 !streq(verbs[i].verb, "halt") &&
5230 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5231 log_error("Failed to get D-Bus connection: %s",
5232 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5238 if (!bus && !avoid_bus()) {
5239 log_error("Failed to get D-Bus connection: %s",
5240 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5245 return verbs[i].dispatch(bus, argv + optind);
5248 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5250 struct msghdr msghdr;
5251 struct iovec iovec[2];
5252 union sockaddr_union sockaddr;
5253 struct sd_shutdown_command c;
5255 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5262 c.dry_run = dry_run;
5266 sockaddr.sa.sa_family = AF_UNIX;
5267 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5270 msghdr.msg_name = &sockaddr;
5271 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5274 iovec[0].iov_base = (char*) &c;
5275 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5277 if (isempty(message))
5278 msghdr.msg_iovlen = 1;
5280 iovec[1].iov_base = (char*) message;
5281 iovec[1].iov_len = strlen(message);
5282 msghdr.msg_iovlen = 2;
5284 msghdr.msg_iov = iovec;
5286 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5287 close_nointr_nofail(fd);
5291 close_nointr_nofail(fd);
5295 static int reload_with_fallback(DBusConnection *bus) {
5298 /* First, try systemd via D-Bus. */
5299 if (daemon_reload(bus, NULL) >= 0)
5303 /* Nothing else worked, so let's try signals */
5304 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5306 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5307 log_error("kill() failed: %m");
5314 static int start_with_fallback(DBusConnection *bus) {
5317 /* First, try systemd via D-Bus. */
5318 if (start_unit(bus, NULL) >= 0)
5322 /* Hmm, talking to systemd via D-Bus didn't work. Then
5323 * let's try to talk to Upstart via D-Bus. */
5324 if (talk_upstart() > 0)
5327 /* Nothing else worked, so let's try
5329 if (talk_initctl() > 0)
5332 log_error("Failed to talk to init daemon.");
5336 warn_wall(arg_action);
5340 static _noreturn_ void halt_now(enum action a) {
5342 /* Make sure C-A-D is handled by the kernel from this
5344 reboot(RB_ENABLE_CAD);
5349 log_info("Halting.");
5350 reboot(RB_HALT_SYSTEM);
5353 case ACTION_POWEROFF:
5354 log_info("Powering off.");
5355 reboot(RB_POWER_OFF);
5359 log_info("Rebooting.");
5360 reboot(RB_AUTOBOOT);
5364 assert_not_reached("Unknown halt action.");
5367 assert_not_reached("Uh? This shouldn't happen.");
5370 static int halt_main(DBusConnection *bus) {
5373 r = check_inhibitors(bus, arg_action);
5377 if (geteuid() != 0) {
5378 /* Try logind if we are a normal user and no special
5379 * mode applies. Maybe PolicyKit allows us to shutdown
5382 if (arg_when <= 0 &&
5385 (arg_action == ACTION_POWEROFF ||
5386 arg_action == ACTION_REBOOT)) {
5387 r = reboot_with_logind(bus, arg_action);
5392 log_error("Must be root.");
5399 m = strv_join(arg_wall, " ");
5400 r = send_shutdownd(arg_when,
5401 arg_action == ACTION_HALT ? 'H' :
5402 arg_action == ACTION_POWEROFF ? 'P' :
5403 arg_action == ACTION_KEXEC ? 'K' :
5411 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5413 char date[FORMAT_TIMESTAMP_MAX];
5415 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5416 format_timestamp(date, sizeof(date), arg_when));
5421 if (!arg_dry && !arg_force)
5422 return start_with_fallback(bus);
5425 if (sd_booted() > 0)
5426 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5428 r = utmp_put_shutdown();
5430 log_warning("Failed to write utmp record: %s", strerror(-r));
5437 halt_now(arg_action);
5438 /* We should never reach this. */
5442 static int runlevel_main(void) {
5443 int r, runlevel, previous;
5445 r = utmp_get_runlevel(&runlevel, &previous);
5452 previous <= 0 ? 'N' : previous,
5453 runlevel <= 0 ? 'N' : runlevel);
5458 int main(int argc, char*argv[]) {
5459 int r, retval = EXIT_FAILURE;
5460 DBusConnection *bus = NULL;
5463 dbus_error_init(&error);
5465 setlocale(LC_ALL, "");
5466 log_parse_environment();
5469 r = parse_argv(argc, argv);
5473 retval = EXIT_SUCCESS;
5477 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5478 * let's shortcut this */
5479 if (arg_action == ACTION_RUNLEVEL) {
5480 r = runlevel_main();
5481 retval = r < 0 ? EXIT_FAILURE : r;
5485 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5486 log_info("Running in chroot, ignoring request.");
5492 if (arg_transport == TRANSPORT_NORMAL)
5493 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5494 else if (arg_transport == TRANSPORT_POLKIT) {
5495 bus_connect_system_polkit(&bus, &error);
5496 private_bus = false;
5497 } else if (arg_transport == TRANSPORT_SSH) {
5498 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5499 private_bus = false;
5501 assert_not_reached("Uh, invalid transport...");
5504 switch (arg_action) {
5506 case ACTION_SYSTEMCTL:
5507 r = systemctl_main(bus, argc, argv, &error);
5511 case ACTION_POWEROFF:
5517 case ACTION_RUNLEVEL2:
5518 case ACTION_RUNLEVEL3:
5519 case ACTION_RUNLEVEL4:
5520 case ACTION_RUNLEVEL5:
5522 case ACTION_EMERGENCY:
5523 case ACTION_DEFAULT:
5524 r = start_with_fallback(bus);
5529 r = reload_with_fallback(bus);
5532 case ACTION_CANCEL_SHUTDOWN: {
5536 m = strv_join(arg_wall, " ");
5538 retval = EXIT_FAILURE;
5542 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5544 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5549 case ACTION_INVALID:
5550 case ACTION_RUNLEVEL:
5552 assert_not_reached("Unknown action");
5555 retval = r < 0 ? EXIT_FAILURE : r;
5559 dbus_connection_flush(bus);
5560 dbus_connection_close(bus);
5561 dbus_connection_unref(bus);
5564 dbus_error_free(&error);
5568 strv_free(arg_property);
5571 ask_password_agent_close();
5572 polkit_agent_close();