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"
70 static const char *arg_type = NULL;
71 static const char *arg_load_state = NULL;
72 static char **arg_property = NULL;
73 static bool arg_all = false;
74 static const char *arg_job_mode = "replace";
75 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
76 static bool arg_no_block = false;
77 static bool arg_no_legend = false;
78 static bool arg_no_pager = false;
79 static bool arg_no_wtmp = false;
80 static bool arg_no_wall = false;
81 static bool arg_no_reload = false;
82 static bool arg_ignore_inhibitors = false;
83 static bool arg_dry = false;
84 static bool arg_quiet = false;
85 static bool arg_full = false;
86 static int arg_force = 0;
87 static bool arg_ask_password = true;
88 static bool arg_failed = false;
89 static bool arg_runtime = false;
90 static char **arg_wall = NULL;
91 static const char *arg_kill_who = NULL;
92 static int arg_signal = SIGTERM;
93 static const char *arg_root = NULL;
94 static usec_t arg_when = 0;
116 ACTION_CANCEL_SHUTDOWN,
118 } arg_action = ACTION_SYSTEMCTL;
124 static enum transport {
128 } arg_transport = TRANSPORT_NORMAL;
129 static const char *arg_host = NULL;
130 static unsigned arg_lines = 10;
131 static OutputMode arg_output = OUTPUT_SHORT;
133 static bool private_bus = false;
135 static int daemon_reload(DBusConnection *bus, char **args);
136 static void halt_now(enum action a);
138 static void pager_open_if_enabled(void) {
146 static void ask_password_agent_open_if_enabled(void) {
148 /* Open the password agent as a child process if necessary */
150 if (!arg_ask_password)
153 if (arg_scope != UNIT_FILE_SYSTEM)
156 ask_password_agent_open();
160 static void polkit_agent_open_if_enabled(void) {
162 /* Open the polkit agent as a child process if necessary */
164 if (!arg_ask_password)
167 if (arg_scope != UNIT_FILE_SYSTEM)
174 static const char *ansi_highlight(bool b) {
179 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
182 static const char *ansi_highlight_red(bool b) {
187 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
190 static const char *ansi_highlight_green(bool b) {
195 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
198 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
201 if (!dbus_error_is_set(error))
204 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
205 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
206 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
207 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
208 return EXIT_NOPERMISSION;
210 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
211 return EXIT_NOTINSTALLED;
213 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
214 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
215 return EXIT_NOTIMPLEMENTED;
217 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
218 return EXIT_NOTCONFIGURED;
226 static void warn_wall(enum action a) {
227 static const char *table[_ACTION_MAX] = {
228 [ACTION_HALT] = "The system is going down for system halt NOW!",
229 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
230 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
231 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
232 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
233 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
234 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
241 _cleanup_free_ char *p;
243 p = strv_join(arg_wall, " ");
258 utmp_wall(table[a], NULL);
261 static bool avoid_bus(void) {
263 if (running_in_chroot() > 0)
266 if (sd_booted() <= 0)
269 if (!isempty(arg_root))
272 if (arg_scope == UNIT_FILE_GLOBAL)
278 static int compare_unit_info(const void *a, const void *b) {
280 const struct unit_info *u = a, *v = b;
282 d1 = strrchr(u->id, '.');
283 d2 = strrchr(v->id, '.');
288 r = strcasecmp(d1, d2);
293 return strcasecmp(u->id, v->id);
296 static bool output_show_unit(const struct unit_info *u) {
300 return streq(u->active_state, "failed");
302 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
303 streq(dot+1, arg_type))) &&
304 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
305 (arg_all || !(streq(u->active_state, "inactive")
306 || u->following[0]) || u->job_id > 0);
309 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
310 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
311 const struct unit_info *u;
314 max_id_len = sizeof("UNIT")-1;
315 active_len = sizeof("ACTIVE")-1;
316 sub_len = sizeof("SUB")-1;
317 job_len = sizeof("JOB")-1;
320 for (u = unit_infos; u < unit_infos + c; u++) {
321 if (!output_show_unit(u))
324 max_id_len = MAX(max_id_len, strlen(u->id));
325 active_len = MAX(active_len, strlen(u->active_state));
326 sub_len = MAX(sub_len, strlen(u->sub_state));
327 if (u->job_id != 0) {
328 job_len = MAX(job_len, strlen(u->job_type));
335 id_len = MIN(max_id_len, 25);
336 basic_len = 5 + id_len + 5 + active_len + sub_len;
338 basic_len += job_len + 1;
339 if (basic_len < (unsigned) columns()) {
340 unsigned extra_len, incr;
341 extra_len = columns() - basic_len;
342 /* Either UNIT already got 25, or is fully satisfied.
343 * Grant up to 25 to DESC now. */
344 incr = MIN(extra_len, 25);
347 /* split the remaining space between UNIT and DESC,
348 * but do not give UNIT more than it needs. */
350 incr = MIN(extra_len / 2, max_id_len - id_len);
352 desc_len += extra_len - incr;
358 for (u = unit_infos; u < unit_infos + c; u++) {
360 const char *on_loaded, *off_loaded;
361 const char *on_active, *off_active;
363 if (!output_show_unit(u))
366 if (!n_shown && !arg_no_legend) {
367 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
368 active_len, "ACTIVE", sub_len, "SUB");
370 printf("%-*s ", job_len, "JOB");
371 if (!arg_full && arg_no_pager)
372 printf("%.*s\n", desc_len, "DESCRIPTION");
374 printf("%s\n", "DESCRIPTION");
379 if (streq(u->load_state, "error")) {
380 on_loaded = ansi_highlight_red(true);
381 off_loaded = ansi_highlight_red(false);
383 on_loaded = off_loaded = "";
385 if (streq(u->active_state, "failed")) {
386 on_active = ansi_highlight_red(true);
387 off_active = ansi_highlight_red(false);
389 on_active = off_active = "";
391 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
393 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s",
394 id_len, e ? e : u->id,
395 on_loaded, u->load_state, off_loaded,
396 on_active, active_len, u->active_state,
397 sub_len, u->sub_state, off_active,
398 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
399 if (!arg_full && arg_no_pager)
400 printf("%.*s\n", desc_len, u->description);
402 printf("%s\n", u->description);
407 if (!arg_no_legend) {
408 const char *on, *off;
411 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
412 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
413 "SUB = The low-level unit activation state, values depend on unit type.\n");
415 printf("JOB = Pending job for the unit.\n");
417 on = ansi_highlight(true);
418 off = ansi_highlight(false);
420 on = ansi_highlight_red(true);
421 off = ansi_highlight_red(false);
425 printf("%s%u loaded units listed.%s\n"
426 "To show all installed unit files use 'systemctl list-unit-files'.\n",
429 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
430 "To show all installed unit files use 'systemctl list-unit-files'.\n",
435 static int list_units(DBusConnection *bus, char **args) {
436 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
437 _cleanup_free_ struct unit_info *unit_infos = NULL;
438 DBusMessageIter iter, sub, sub2;
439 unsigned c = 0, n_units = 0;
442 pager_open_if_enabled();
444 r = bus_method_call_with_reply(
446 "org.freedesktop.systemd1",
447 "/org/freedesktop/systemd1",
448 "org.freedesktop.systemd1.Manager",
456 if (!dbus_message_iter_init(reply, &iter) ||
457 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
458 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
459 log_error("Failed to parse reply.");
463 dbus_message_iter_recurse(&iter, &sub);
465 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
468 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
473 n_units = MAX(2*c, 16);
474 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
483 dbus_message_iter_recurse(&sub, &sub2);
485 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
486 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
487 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
488 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
489 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
490 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
491 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
492 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
493 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
494 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
495 log_error("Failed to parse reply.");
499 dbus_message_iter_next(&sub);
504 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
505 output_units_list(unit_infos, c);
511 static int compare_unit_file_list(const void *a, const void *b) {
513 const UnitFileList *u = a, *v = b;
515 d1 = strrchr(u->path, '.');
516 d2 = strrchr(v->path, '.');
521 r = strcasecmp(d1, d2);
526 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
529 static bool output_show_unit_file(const UnitFileList *u) {
532 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
535 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
536 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
537 const UnitFileList *u;
539 max_id_len = sizeof("UNIT FILE")-1;
540 state_cols = sizeof("STATE")-1;
541 for (u = units; u < units + c; u++) {
542 if (!output_show_unit_file(u))
545 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
546 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
551 id_cols = MIN(max_id_len, 25);
552 basic_cols = 1 + id_cols + state_cols;
553 if (basic_cols < (unsigned) columns())
554 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
556 id_cols = max_id_len;
559 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
561 for (u = units; u < units + c; u++) {
563 const char *on, *off;
566 if (!output_show_unit_file(u))
571 if (u->state == UNIT_FILE_MASKED ||
572 u->state == UNIT_FILE_MASKED_RUNTIME ||
573 u->state == UNIT_FILE_DISABLED ||
574 u->state == UNIT_FILE_INVALID) {
575 on = ansi_highlight_red(true);
576 off = ansi_highlight_red(false);
577 } else if (u->state == UNIT_FILE_ENABLED) {
578 on = ansi_highlight_green(true);
579 off = ansi_highlight_green(false);
583 id = path_get_file_name(u->path);
585 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
587 printf("%-*s %s%-*s%s\n",
589 on, state_cols, unit_file_state_to_string(u->state), off);
595 printf("\n%u unit files listed.\n", n_shown);
598 static int list_unit_files(DBusConnection *bus, char **args) {
599 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
600 _cleanup_free_ UnitFileList *units = NULL;
601 DBusMessageIter iter, sub, sub2;
602 unsigned c = 0, n_units = 0;
605 pager_open_if_enabled();
612 h = hashmap_new(string_hash_func, string_compare_func);
616 r = unit_file_get_list(arg_scope, arg_root, h);
618 unit_file_list_free(h);
619 log_error("Failed to get unit file list: %s", strerror(-r));
623 n_units = hashmap_size(h);
624 units = new(UnitFileList, n_units);
626 unit_file_list_free(h);
630 HASHMAP_FOREACH(u, h, i) {
631 memcpy(units + c++, u, sizeof(UnitFileList));
637 r = bus_method_call_with_reply(
639 "org.freedesktop.systemd1",
640 "/org/freedesktop/systemd1",
641 "org.freedesktop.systemd1.Manager",
649 if (!dbus_message_iter_init(reply, &iter) ||
650 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
651 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
652 log_error("Failed to parse reply.");
656 dbus_message_iter_recurse(&iter, &sub);
658 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
662 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
667 n_units = MAX(2*c, 16);
668 w = realloc(units, sizeof(struct UnitFileList) * n_units);
677 dbus_message_iter_recurse(&sub, &sub2);
679 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
680 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
681 log_error("Failed to parse reply.");
685 u->state = unit_file_state_from_string(state);
687 dbus_message_iter_next(&sub);
693 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
694 output_unit_file_list(units, c);
700 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
702 _cleanup_free_ char *n = NULL;
704 size_t max_len = MAX(columns(),20);
706 for (i = level - 1; i >= 0; i--) {
708 if(len > max_len - 3 && !arg_full) {
709 printf("%s...\n",max_len % 2 ? "" : " ");
712 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
715 if(len > max_len - 3 && !arg_full) {
716 printf("%s...\n",max_len % 2 ? "" : " ");
719 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
722 printf("%s\n", name);
726 n = ellipsize(name, max_len-len, 100);
734 static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
735 static const char dependencies[] =
737 "RequiresOverridable\0"
739 "RequisiteOverridable\0"
742 _cleanup_free_ char *path;
743 const char *interface = "org.freedesktop.systemd1.Unit";
745 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
746 DBusMessageIter iter, sub, sub2, sub3;
755 path = unit_dbus_path_from_name(name);
761 r = bus_method_call_with_reply(
763 "org.freedesktop.systemd1",
765 "org.freedesktop.DBus.Properties",
769 DBUS_TYPE_STRING, &interface,
774 if (!dbus_message_iter_init(reply, &iter) ||
775 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
776 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
777 log_error("Failed to parse reply.");
782 dbus_message_iter_recurse(&iter, &sub);
784 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
787 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
788 dbus_message_iter_recurse(&sub, &sub2);
790 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
791 log_error("Failed to parse reply.");
796 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
797 log_error("Failed to parse reply.");
802 dbus_message_iter_recurse(&sub2, &sub3);
803 dbus_message_iter_next(&sub);
805 if (!nulstr_contains(dependencies, prop))
808 if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
809 if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
810 DBusMessageIter sub4;
811 dbus_message_iter_recurse(&sub3, &sub4);
813 while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
816 assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
817 dbus_message_iter_get_basic(&sub4, &s);
819 r = strv_extend(&ret, s);
825 dbus_message_iter_next(&sub4);
838 static int list_dependencies_compare(const void *_a, const void *_b) {
839 const char **a = (const char**) _a, **b = (const char**) _b;
840 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
842 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
844 return strcasecmp(*a, *b);
847 static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char **units, unsigned int branches) {
853 u = strv_append(units, name);
857 r = list_dependencies_get_dependencies(bus, name, &deps);
861 qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
863 STRV_FOREACH(c, deps) {
864 if (strv_contains(u, *c)) {
865 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
871 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
875 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
876 r = list_dependencies_one(bus, *c, level + 1, u, (branches << 1) | (c[1] == NULL ? 0 : 1));
889 static int list_dependencies(DBusConnection *bus, char **args) {
890 _cleanup_free_ char *unit = NULL;
896 unit = unit_name_mangle(args[1]);
901 u = SPECIAL_DEFAULT_TARGET;
903 pager_open_if_enabled();
907 return list_dependencies_one(bus, u, 0, NULL, 0);
910 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
912 static const char * const colors[] = {
913 "Requires", "[color=\"black\"]",
914 "RequiresOverridable", "[color=\"black\"]",
915 "Requisite", "[color=\"darkblue\"]",
916 "RequisiteOverridable", "[color=\"darkblue\"]",
917 "Wants", "[color=\"grey66\"]",
918 "Conflicts", "[color=\"red\"]",
919 "ConflictedBy", "[color=\"red\"]",
920 "After", "[color=\"green\"]"
923 const char *c = NULL;
930 for (i = 0; i < ELEMENTSOF(colors); i += 2)
931 if (streq(colors[i], prop)) {
939 if (arg_dot != DOT_ALL)
940 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
943 switch (dbus_message_iter_get_arg_type(iter)) {
945 case DBUS_TYPE_ARRAY:
947 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
950 dbus_message_iter_recurse(iter, &sub);
952 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
955 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
956 dbus_message_iter_get_basic(&sub, &s);
957 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
959 dbus_message_iter_next(&sub);
969 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
970 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
971 const char *interface = "org.freedesktop.systemd1.Unit";
973 DBusMessageIter iter, sub, sub2, sub3;
978 r = bus_method_call_with_reply(
980 "org.freedesktop.systemd1",
982 "org.freedesktop.DBus.Properties",
986 DBUS_TYPE_STRING, &interface,
991 if (!dbus_message_iter_init(reply, &iter) ||
992 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
993 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
994 log_error("Failed to parse reply.");
998 dbus_message_iter_recurse(&iter, &sub);
1000 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1003 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
1004 dbus_message_iter_recurse(&sub, &sub2);
1006 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0 ||
1007 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
1008 log_error("Failed to parse reply.");
1012 dbus_message_iter_recurse(&sub2, &sub3);
1013 r = dot_one_property(name, prop, &sub3);
1017 dbus_message_iter_next(&sub);
1023 static int dot(DBusConnection *bus, char **args) {
1024 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1025 DBusMessageIter iter, sub, sub2;
1028 r = bus_method_call_with_reply(
1030 "org.freedesktop.systemd1",
1031 "/org/freedesktop/systemd1",
1032 "org.freedesktop.systemd1.Manager",
1040 if (!dbus_message_iter_init(reply, &iter) ||
1041 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1042 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1043 log_error("Failed to parse reply.");
1047 printf("digraph systemd {\n");
1049 dbus_message_iter_recurse(&iter, &sub);
1050 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1051 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
1053 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1054 log_error("Failed to parse reply.");
1058 dbus_message_iter_recurse(&sub, &sub2);
1060 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
1061 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
1062 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
1063 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
1064 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
1065 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
1066 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
1067 log_error("Failed to parse reply.");
1071 r = dot_one(bus, id, unit_path);
1075 /* printf("\t\"%s\";\n", id); */
1076 dbus_message_iter_next(&sub);
1081 log_info(" Color legend: black = Requires\n"
1082 " dark blue = Requisite\n"
1083 " dark grey = Wants\n"
1084 " red = Conflicts\n"
1085 " green = After\n");
1088 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
1089 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
1094 static int list_jobs(DBusConnection *bus, char **args) {
1095 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1096 DBusMessageIter iter, sub, sub2;
1100 pager_open_if_enabled();
1102 r = bus_method_call_with_reply(
1104 "org.freedesktop.systemd1",
1105 "/org/freedesktop/systemd1",
1106 "org.freedesktop.systemd1.Manager",
1114 if (!dbus_message_iter_init(reply, &iter) ||
1115 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1116 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1117 log_error("Failed to parse reply.");
1121 dbus_message_iter_recurse(&iter, &sub);
1124 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
1126 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1127 const char *name, *type, *state, *job_path, *unit_path;
1131 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1132 log_error("Failed to parse reply.");
1136 dbus_message_iter_recurse(&sub, &sub2);
1138 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1139 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1140 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1141 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1142 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1143 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1144 log_error("Failed to parse reply.");
1148 e = arg_full ? NULL : ellipsize(name, 25, 33);
1149 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1154 dbus_message_iter_next(&sub);
1158 printf("\n%u jobs listed.\n", k);
1163 static int load_unit(DBusConnection *bus, char **args) {
1168 STRV_FOREACH(name, args+1) {
1169 _cleanup_free_ char *n = NULL;
1172 n = unit_name_mangle(*name);
1176 r = bus_method_call_with_reply(
1178 "org.freedesktop.systemd1",
1179 "/org/freedesktop/systemd1",
1180 "org.freedesktop.systemd1.Manager",
1184 DBUS_TYPE_STRING, &n,
1193 static int cancel_job(DBusConnection *bus, char **args) {
1198 if (strv_length(args) <= 1)
1199 return daemon_reload(bus, args);
1201 STRV_FOREACH(name, args+1) {
1205 r = safe_atou32(*name, &id);
1207 log_error("Failed to parse job id: %s", strerror(-r));
1211 r = bus_method_call_with_reply(
1213 "org.freedesktop.systemd1",
1214 "/org/freedesktop/systemd1",
1215 "org.freedesktop.systemd1.Manager",
1219 DBUS_TYPE_UINT32, &id,
1228 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1229 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1230 dbus_bool_t b = FALSE;
1231 DBusMessageIter iter, sub;
1233 *interface = "org.freedesktop.systemd1.Unit",
1234 *property = "NeedDaemonReload",
1236 _cleanup_free_ char *n = NULL;
1239 /* We ignore all errors here, since this is used to show a warning only */
1241 n = unit_name_mangle(unit);
1245 r = bus_method_call_with_reply (
1247 "org.freedesktop.systemd1",
1248 "/org/freedesktop/systemd1",
1249 "org.freedesktop.systemd1.Manager",
1253 DBUS_TYPE_STRING, &n,
1258 if (!dbus_message_get_args(reply, NULL,
1259 DBUS_TYPE_OBJECT_PATH, &path,
1263 dbus_message_unref(reply);
1266 r = bus_method_call_with_reply(
1268 "org.freedesktop.systemd1",
1270 "org.freedesktop.DBus.Properties",
1274 DBUS_TYPE_STRING, &interface,
1275 DBUS_TYPE_STRING, &property,
1280 if (!dbus_message_iter_init(reply, &iter) ||
1281 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1284 dbus_message_iter_recurse(&iter, &sub);
1285 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1288 dbus_message_iter_get_basic(&sub, &b);
1292 typedef struct WaitData {
1299 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1307 dbus_error_init(&error);
1309 log_debug("Got D-Bus request: %s.%s() on %s",
1310 dbus_message_get_interface(message),
1311 dbus_message_get_member(message),
1312 dbus_message_get_path(message));
1314 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1315 log_error("Warning! D-Bus connection terminated.");
1316 dbus_connection_close(connection);
1318 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1320 const char *path, *result, *unit;
1322 if (dbus_message_get_args(message, &error,
1323 DBUS_TYPE_UINT32, &id,
1324 DBUS_TYPE_OBJECT_PATH, &path,
1325 DBUS_TYPE_STRING, &unit,
1326 DBUS_TYPE_STRING, &result,
1327 DBUS_TYPE_INVALID)) {
1329 free(set_remove(d->set, (char*) path));
1331 if (!isempty(result))
1332 d->result = strdup(result);
1335 d->name = strdup(unit);
1340 dbus_error_free(&error);
1341 if (dbus_message_get_args(message, &error,
1342 DBUS_TYPE_UINT32, &id,
1343 DBUS_TYPE_OBJECT_PATH, &path,
1344 DBUS_TYPE_STRING, &result,
1345 DBUS_TYPE_INVALID)) {
1346 /* Compatibility with older systemd versions <
1347 * 183 during upgrades. This should be dropped
1349 free(set_remove(d->set, (char*) path));
1352 d->result = strdup(result);
1358 log_error("Failed to parse message: %s", bus_error_message(&error));
1362 dbus_error_free(&error);
1363 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1366 static int enable_wait_for_jobs(DBusConnection *bus) {
1374 dbus_error_init(&error);
1375 dbus_bus_add_match(bus,
1377 "sender='org.freedesktop.systemd1',"
1378 "interface='org.freedesktop.systemd1.Manager',"
1379 "member='JobRemoved',"
1380 "path='/org/freedesktop/systemd1'",
1383 if (dbus_error_is_set(&error)) {
1384 log_error("Failed to add match: %s", bus_error_message(&error));
1385 dbus_error_free(&error);
1389 /* This is slightly dirty, since we don't undo the match registrations. */
1393 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1403 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1406 while (!set_isempty(s)) {
1408 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1409 log_error("Disconnected from bus.");
1410 return -ECONNREFUSED;
1417 if (streq(d.result, "timeout"))
1418 log_error("Job for %s timed out.", strna(d.name));
1419 else if (streq(d.result, "canceled"))
1420 log_error("Job for %s canceled.", strna(d.name));
1421 else if (streq(d.result, "dependency"))
1422 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1423 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1424 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1427 if (streq_ptr(d.result, "timeout"))
1429 else if (streq_ptr(d.result, "canceled"))
1431 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1442 dbus_connection_remove_filter(bus, wait_filter, &d);
1446 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1447 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1448 _cleanup_free_ char *n = NULL;
1449 DBusMessageIter iter, sub;
1451 *interface = "org.freedesktop.systemd1.Unit",
1452 *property = "ActiveState";
1453 const char *state, *path;
1459 dbus_error_init(&error);
1461 n = unit_name_mangle(name);
1465 r = bus_method_call_with_reply (
1467 "org.freedesktop.systemd1",
1468 "/org/freedesktop/systemd1",
1469 "org.freedesktop.systemd1.Manager",
1473 DBUS_TYPE_STRING, &n,
1476 dbus_error_free(&error);
1483 if (!dbus_message_get_args(reply, NULL,
1484 DBUS_TYPE_OBJECT_PATH, &path,
1485 DBUS_TYPE_INVALID)) {
1486 log_error("Failed to parse reply.");
1490 dbus_message_unref(reply);
1493 r = bus_method_call_with_reply(
1495 "org.freedesktop.systemd1",
1497 "org.freedesktop.DBus.Properties",
1501 DBUS_TYPE_STRING, &interface,
1502 DBUS_TYPE_STRING, &property,
1510 if (!dbus_message_iter_init(reply, &iter) ||
1511 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1512 log_error("Failed to parse reply.");
1516 dbus_message_iter_recurse(&iter, &sub);
1518 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1519 log_error("Failed to parse reply.");
1523 dbus_message_iter_get_basic(&sub, &state);
1528 return strv_find(check_states, state) ? 1 : 0;
1531 static void check_triggering_units(
1532 DBusConnection *bus,
1533 const char *unit_name) {
1535 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1536 DBusMessageIter iter, sub;
1537 const char *interface = "org.freedesktop.systemd1.Unit",
1538 *triggered_by_property = "TriggeredBy";
1539 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1540 bool print_warning_label = true;
1543 n = unit_name_mangle(unit_name);
1549 unit_path = unit_dbus_path_from_name(n);
1555 r = bus_method_call_with_reply(
1557 "org.freedesktop.systemd1",
1559 "org.freedesktop.DBus.Properties",
1563 DBUS_TYPE_STRING, &interface,
1564 DBUS_TYPE_STRING, &triggered_by_property,
1569 if (!dbus_message_iter_init(reply, &iter) ||
1570 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1571 log_error("Failed to parse reply.");
1575 dbus_message_iter_recurse(&iter, &sub);
1576 dbus_message_iter_recurse(&sub, &iter);
1579 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1580 const char * const check_states[] = {
1585 const char *service_trigger;
1587 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1588 log_error("Failed to parse reply.");
1592 dbus_message_iter_get_basic(&sub, &service_trigger);
1594 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1598 if (print_warning_label) {
1599 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1600 print_warning_label = false;
1603 log_warning(" %s", service_trigger);
1606 dbus_message_iter_next(&sub);
1610 static int start_unit_one(
1611 DBusConnection *bus,
1618 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1619 _cleanup_free_ char *n;
1628 n = unit_name_mangle(name);
1632 r = bus_method_call_with_reply(
1634 "org.freedesktop.systemd1",
1635 "/org/freedesktop/systemd1",
1636 "org.freedesktop.systemd1.Manager",
1640 DBUS_TYPE_STRING, &n,
1641 DBUS_TYPE_STRING, &mode,
1644 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1645 /* There's always a fallback possible for
1646 * legacy actions. */
1649 log_error("Failed to issue method call: %s", bus_error_message(error));
1654 if (!dbus_message_get_args(reply, error,
1655 DBUS_TYPE_OBJECT_PATH, &path,
1656 DBUS_TYPE_INVALID)) {
1657 log_error("Failed to parse reply: %s", bus_error_message(error));
1661 if (need_daemon_reload(bus, n))
1662 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1663 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1675 log_error("Failed to add path to set.");
1683 static enum action verb_to_action(const char *verb) {
1684 if (streq(verb, "halt"))
1686 else if (streq(verb, "poweroff"))
1687 return ACTION_POWEROFF;
1688 else if (streq(verb, "reboot"))
1689 return ACTION_REBOOT;
1690 else if (streq(verb, "kexec"))
1691 return ACTION_KEXEC;
1692 else if (streq(verb, "rescue"))
1693 return ACTION_RESCUE;
1694 else if (streq(verb, "emergency"))
1695 return ACTION_EMERGENCY;
1696 else if (streq(verb, "default"))
1697 return ACTION_DEFAULT;
1698 else if (streq(verb, "exit"))
1700 else if (streq(verb, "suspend"))
1701 return ACTION_SUSPEND;
1702 else if (streq(verb, "hibernate"))
1703 return ACTION_HIBERNATE;
1704 else if (streq(verb, "hybrid-sleep"))
1705 return ACTION_HYBRID_SLEEP;
1707 return ACTION_INVALID;
1710 static int start_unit(DBusConnection *bus, char **args) {
1712 static const char * const table[_ACTION_MAX] = {
1713 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1714 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1715 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1716 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1717 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1718 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1719 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1720 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1721 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1722 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1723 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1724 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1725 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1726 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
1727 [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
1731 const char *method, *mode, *one_name;
1736 dbus_error_init(&error);
1740 ask_password_agent_open_if_enabled();
1742 if (arg_action == ACTION_SYSTEMCTL) {
1744 streq(args[0], "stop") ||
1745 streq(args[0], "condstop") ? "StopUnit" :
1746 streq(args[0], "reload") ? "ReloadUnit" :
1747 streq(args[0], "restart") ? "RestartUnit" :
1749 streq(args[0], "try-restart") ||
1750 streq(args[0], "condrestart") ? "TryRestartUnit" :
1752 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1754 streq(args[0], "reload-or-try-restart") ||
1755 streq(args[0], "condreload") ||
1757 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1761 (streq(args[0], "isolate") ||
1762 streq(args[0], "rescue") ||
1763 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1765 one_name = table[verb_to_action(args[0])];
1768 assert(arg_action < ELEMENTSOF(table));
1769 assert(table[arg_action]);
1771 method = "StartUnit";
1773 mode = (arg_action == ACTION_EMERGENCY ||
1774 arg_action == ACTION_RESCUE ||
1775 arg_action == ACTION_RUNLEVEL2 ||
1776 arg_action == ACTION_RUNLEVEL3 ||
1777 arg_action == ACTION_RUNLEVEL4 ||
1778 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1780 one_name = table[arg_action];
1783 if (!arg_no_block) {
1784 ret = enable_wait_for_jobs(bus);
1786 log_error("Could not watch jobs: %s", strerror(-ret));
1790 s = set_new(string_hash_func, string_compare_func);
1798 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1800 ret = translate_bus_error_to_exit_status(ret, &error);
1802 STRV_FOREACH(name, args+1) {
1803 r = start_unit_one(bus, method, *name, mode, &error, s);
1805 ret = translate_bus_error_to_exit_status(r, &error);
1806 dbus_error_free(&error);
1811 if (!arg_no_block) {
1812 r = wait_for_jobs(bus, s);
1818 /* When stopping units, warn if they can still be triggered by
1819 * another active unit (socket, path, timer) */
1820 if (!arg_quiet && streq(method, "StopUnit")) {
1822 check_triggering_units(bus, one_name);
1824 STRV_FOREACH(name, args+1)
1825 check_triggering_units(bus, *name);
1831 dbus_error_free(&error);
1836 /* Ask systemd-logind, which might grant access to unprivileged users
1837 * through PolicyKit */
1838 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1841 dbus_bool_t interactive = true;
1846 polkit_agent_open_if_enabled();
1854 case ACTION_POWEROFF:
1855 method = "PowerOff";
1858 case ACTION_SUSPEND:
1862 case ACTION_HIBERNATE:
1863 method = "Hibernate";
1866 case ACTION_HYBRID_SLEEP:
1867 method = "HybridSleep";
1874 return bus_method_call_with_reply(
1876 "org.freedesktop.login1",
1877 "/org/freedesktop/login1",
1878 "org.freedesktop.login1.Manager",
1882 DBUS_TYPE_BOOLEAN, &interactive,
1889 static int check_inhibitors(DBusConnection *bus, enum action a) {
1891 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1892 DBusMessageIter iter, sub, sub2;
1895 _cleanup_strv_free_ char **sessions = NULL;
1901 if (arg_ignore_inhibitors || arg_force > 0)
1913 r = bus_method_call_with_reply(
1915 "org.freedesktop.login1",
1916 "/org/freedesktop/login1",
1917 "org.freedesktop.login1.Manager",
1923 /* If logind is not around, then there are no inhibitors... */
1926 if (!dbus_message_iter_init(reply, &iter) ||
1927 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1928 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1929 log_error("Failed to parse reply.");
1933 dbus_message_iter_recurse(&iter, &sub);
1934 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1935 const char *what, *who, *why, *mode;
1937 _cleanup_strv_free_ char **sv = NULL;
1938 _cleanup_free_ char *comm = NULL, *user = NULL;
1940 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1941 log_error("Failed to parse reply.");
1945 dbus_message_iter_recurse(&sub, &sub2);
1947 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
1948 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
1949 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
1950 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
1951 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
1952 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
1953 log_error("Failed to parse reply.");
1957 if (!streq(mode, "block"))
1960 sv = strv_split(what, ":");
1964 if (!strv_contains(sv,
1966 a == ACTION_POWEROFF ||
1967 a == ACTION_REBOOT ||
1968 a == ACTION_KEXEC ? "shutdown" : "sleep"))
1971 get_process_comm(pid, &comm);
1972 user = uid_to_name(uid);
1973 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
1974 who, (unsigned long) pid, strna(comm), strna(user), why);
1978 dbus_message_iter_next(&sub);
1981 dbus_message_iter_recurse(&iter, &sub);
1983 /* Check for current sessions */
1984 sd_get_sessions(&sessions);
1985 STRV_FOREACH(s, sessions) {
1987 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
1989 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
1992 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
1995 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
1998 sd_session_get_tty(*s, &tty);
1999 sd_session_get_seat(*s, &seat);
2000 sd_session_get_service(*s, &service);
2001 user = uid_to_name(uid);
2003 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2010 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2011 a == ACTION_HALT ? "halt" :
2012 a == ACTION_POWEROFF ? "poweroff" :
2013 a == ACTION_REBOOT ? "reboot" :
2014 a == ACTION_KEXEC ? "kexec" :
2015 a == ACTION_SUSPEND ? "suspend" :
2016 a == ACTION_HIBERNATE ? "hibernate" : "hybrid-sleep");
2024 static int start_special(DBusConnection *bus, char **args) {
2030 a = verb_to_action(args[0]);
2032 r = check_inhibitors(bus, a);
2036 if (arg_force >= 2 && geteuid() != 0) {
2037 log_error("Must be root.");
2041 if (arg_force >= 2 &&
2042 (a == ACTION_HALT ||
2043 a == ACTION_POWEROFF ||
2044 a == ACTION_REBOOT))
2047 if (arg_force >= 1 &&
2048 (a == ACTION_HALT ||
2049 a == ACTION_POWEROFF ||
2050 a == ACTION_REBOOT ||
2051 a == ACTION_KEXEC ||
2053 return daemon_reload(bus, args);
2055 /* first try logind, to allow authentication with polkit */
2056 if (geteuid() != 0 &&
2057 (a == ACTION_POWEROFF ||
2058 a == ACTION_REBOOT ||
2059 a == ACTION_SUSPEND ||
2060 a == ACTION_HIBERNATE ||
2061 a == ACTION_HYBRID_SLEEP)) {
2062 r = reboot_with_logind(bus, a);
2067 r = start_unit(bus, args);
2074 static int check_unit_active(DBusConnection *bus, char **args) {
2075 const char * const check_states[] = {
2082 int r = 3; /* According to LSB: "program is not running" */
2087 STRV_FOREACH(name, args+1) {
2090 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2100 static int check_unit_failed(DBusConnection *bus, char **args) {
2101 const char * const check_states[] = {
2112 STRV_FOREACH(name, args+1) {
2115 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2125 static int kill_unit(DBusConnection *bus, char **args) {
2133 arg_kill_who = "all";
2135 STRV_FOREACH(name, args+1) {
2136 _cleanup_free_ char *n = NULL;
2138 n = unit_name_mangle(*name);
2142 r = bus_method_call_with_reply(
2144 "org.freedesktop.systemd1",
2145 "/org/freedesktop/systemd1",
2146 "org.freedesktop.systemd1.Manager",
2150 DBUS_TYPE_STRING, &n,
2151 DBUS_TYPE_STRING, &arg_kill_who,
2152 DBUS_TYPE_INT32, &arg_signal,
2160 static int set_cgroup(DBusConnection *bus, char **args) {
2161 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2164 DBusMessageIter iter;
2166 _cleanup_free_ char *n = NULL;
2167 const char *runtime;
2172 dbus_error_init(&error);
2175 streq(args[0], "set-cgroup") ? "SetUnitControlGroups" :
2176 streq(args[0], "unset-group") ? "UnsetUnitControlGroups"
2177 : "UnsetUnitControlGroupAttributes";
2179 n = unit_name_mangle(args[1]);
2183 m = dbus_message_new_method_call(
2184 "org.freedesktop.systemd1",
2185 "/org/freedesktop/systemd1",
2186 "org.freedesktop.systemd1.Manager",
2191 dbus_message_iter_init_append(m, &iter);
2192 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
2195 r = bus_append_strv_iter(&iter, args + 2);
2199 runtime = arg_runtime ? "runtime" : "persistent";
2200 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2203 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2205 log_error("Failed to issue method call: %s", bus_error_message(&error));
2206 dbus_error_free(&error);
2213 static int set_cgroup_attr(DBusConnection *bus, char **args) {
2214 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2216 DBusMessageIter iter, sub, sub2;
2218 _cleanup_free_ char *n = NULL;
2219 const char *runtime;
2224 dbus_error_init(&error);
2226 if (strv_length(args) % 2 != 0) {
2227 log_error("Expecting an uneven number of arguments!");
2231 n = unit_name_mangle(args[1]);
2235 m = dbus_message_new_method_call(
2236 "org.freedesktop.systemd1",
2237 "/org/freedesktop/systemd1",
2238 "org.freedesktop.systemd1.Manager",
2239 "SetUnitControlGroupAttributes");
2243 dbus_message_iter_init_append(m, &iter);
2244 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2245 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub))
2248 STRV_FOREACH_PAIR(x, y, args + 2) {
2249 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
2250 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, x) ||
2251 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, y) ||
2252 !dbus_message_iter_close_container(&sub, &sub2))
2256 runtime = arg_runtime ? "runtime" : "persistent";
2257 if (!dbus_message_iter_close_container(&iter, &sub) ||
2258 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2261 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2263 log_error("Failed to issue method call: %s", bus_error_message(&error));
2264 dbus_error_free(&error);
2271 static int get_cgroup_attr(DBusConnection *bus, char **args) {
2272 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2274 DBusMessageIter iter;
2276 _cleanup_free_ char *n = NULL;
2277 _cleanup_strv_free_ char **list = NULL;
2283 dbus_error_init(&error);
2285 n = unit_name_mangle(args[1]);
2289 m = dbus_message_new_method_call(
2290 "org.freedesktop.systemd1",
2291 "/org/freedesktop/systemd1",
2292 "org.freedesktop.systemd1.Manager",
2293 "GetUnitControlGroupAttributes");
2297 dbus_message_iter_init_append(m, &iter);
2298 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
2301 r = bus_append_strv_iter(&iter, args + 2);
2305 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2307 log_error("Failed to issue method call: %s", bus_error_message(&error));
2308 dbus_error_free(&error);
2312 dbus_message_iter_init(reply, &iter);
2313 r = bus_parse_strv_iter(&iter, &list);
2315 log_error("Failed to parse value list.");
2319 STRV_FOREACH(a, list) {
2320 if (endswith(*a, "\n"))
2329 typedef struct ExecStatusInfo {
2337 usec_t start_timestamp;
2338 usec_t exit_timestamp;
2343 LIST_FIELDS(struct ExecStatusInfo, exec);
2346 static void exec_status_info_free(ExecStatusInfo *i) {
2355 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2356 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2357 DBusMessageIter sub2, sub3;
2361 int32_t code, status;
2367 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2370 dbus_message_iter_recurse(sub, &sub2);
2372 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2375 i->path = strdup(path);
2379 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2380 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2384 dbus_message_iter_recurse(&sub2, &sub3);
2385 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2386 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2387 dbus_message_iter_next(&sub3);
2391 i->argv = new0(char*, n+1);
2396 dbus_message_iter_recurse(&sub2, &sub3);
2397 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2400 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2401 dbus_message_iter_get_basic(&sub3, &s);
2402 dbus_message_iter_next(&sub3);
2404 i->argv[n] = strdup(s);
2411 if (!dbus_message_iter_next(&sub2) ||
2412 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2413 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2414 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2415 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2416 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2417 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2418 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2419 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2423 i->start_timestamp = (usec_t) start_timestamp;
2424 i->exit_timestamp = (usec_t) exit_timestamp;
2425 i->pid = (pid_t) pid;
2432 typedef struct UnitStatusInfo {
2434 const char *load_state;
2435 const char *active_state;
2436 const char *sub_state;
2437 const char *unit_file_state;
2439 const char *description;
2440 const char *following;
2442 char **documentation;
2444 const char *fragment_path;
2445 const char *source_path;
2446 const char *default_control_group;
2448 const char *load_error;
2451 usec_t inactive_exit_timestamp;
2452 usec_t inactive_exit_timestamp_monotonic;
2453 usec_t active_enter_timestamp;
2454 usec_t active_exit_timestamp;
2455 usec_t inactive_enter_timestamp;
2457 bool need_daemon_reload;
2462 const char *status_text;
2465 usec_t start_timestamp;
2466 usec_t exit_timestamp;
2468 int exit_code, exit_status;
2470 usec_t condition_timestamp;
2471 bool condition_result;
2474 unsigned n_accepted;
2475 unsigned n_connections;
2479 const char *sysfs_path;
2481 /* Mount, Automount */
2487 LIST_HEAD(ExecStatusInfo, exec);
2490 static void print_status_info(UnitStatusInfo *i) {
2492 const char *on, *off, *ss;
2494 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2495 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2498 arg_all * OUTPUT_SHOW_ALL |
2499 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2500 on_tty() * OUTPUT_COLOR |
2501 !arg_quiet * OUTPUT_WARN_CUTOFF |
2502 arg_full * OUTPUT_FULL_WIDTH;
2506 /* This shows pretty information about a unit. See
2507 * print_property() for a low-level property printer */
2509 printf("%s", strna(i->id));
2511 if (i->description && !streq_ptr(i->id, i->description))
2512 printf(" - %s", i->description);
2517 printf("\t Follow: unit currently follows state of %s\n", i->following);
2519 if (streq_ptr(i->load_state, "error")) {
2520 on = ansi_highlight_red(true);
2521 off = ansi_highlight_red(false);
2525 path = i->source_path ? i->source_path : i->fragment_path;
2528 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2529 else if (path && i->unit_file_state)
2530 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2532 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2534 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2536 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2538 if (streq_ptr(i->active_state, "failed")) {
2539 on = ansi_highlight_red(true);
2540 off = ansi_highlight_red(false);
2541 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2542 on = ansi_highlight_green(true);
2543 off = ansi_highlight_green(false);
2548 printf("\t Active: %s%s (%s)%s",
2550 strna(i->active_state),
2554 printf("\t Active: %s%s%s",
2556 strna(i->active_state),
2559 if (!isempty(i->result) && !streq(i->result, "success"))
2560 printf(" (Result: %s)", i->result);
2562 timestamp = (streq_ptr(i->active_state, "active") ||
2563 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2564 (streq_ptr(i->active_state, "inactive") ||
2565 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2566 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2567 i->active_exit_timestamp;
2569 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2570 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2573 printf(" since %s; %s\n", s2, s1);
2575 printf(" since %s\n", s2);
2579 if (!i->condition_result && i->condition_timestamp > 0) {
2580 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2581 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2584 printf("\t start condition failed at %s; %s\n", s2, s1);
2586 printf("\t start condition failed at %s\n", s2);
2590 printf("\t Device: %s\n", i->sysfs_path);
2592 printf("\t Where: %s\n", i->where);
2594 printf("\t What: %s\n", i->what);
2596 if (!strv_isempty(i->documentation)) {
2600 STRV_FOREACH(t, i->documentation) {
2602 printf("\t Docs: %s\n", *t);
2605 printf("\t %s\n", *t);
2610 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2612 LIST_FOREACH(exec, p, i->exec) {
2613 _cleanup_free_ char *t = NULL;
2616 /* Only show exited processes here */
2620 t = strv_join(p->argv, " ");
2621 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2623 good = is_clean_exit_lsb(p->code, p->status, NULL);
2625 on = ansi_highlight_red(true);
2626 off = ansi_highlight_red(false);
2630 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2632 if (p->code == CLD_EXITED) {
2635 printf("status=%i", p->status);
2637 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2642 printf("signal=%s", signal_to_string(p->status));
2644 printf(")%s\n", off);
2646 if (i->main_pid == p->pid &&
2647 i->start_timestamp == p->start_timestamp &&
2648 i->exit_timestamp == p->start_timestamp)
2649 /* Let's not show this twice */
2652 if (p->pid == i->control_pid)
2656 if (i->main_pid > 0 || i->control_pid > 0) {
2659 if (i->main_pid > 0) {
2660 printf("Main PID: %u", (unsigned) i->main_pid);
2663 _cleanup_free_ char *t = NULL;
2664 get_process_comm(i->main_pid, &t);
2667 } else if (i->exit_code > 0) {
2668 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2670 if (i->exit_code == CLD_EXITED) {
2673 printf("status=%i", i->exit_status);
2675 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2680 printf("signal=%s", signal_to_string(i->exit_status));
2685 if (i->main_pid > 0 && i->control_pid > 0)
2688 if (i->control_pid > 0) {
2689 _cleanup_free_ char *t = NULL;
2691 printf(" Control: %u", (unsigned) i->control_pid);
2693 get_process_comm(i->control_pid, &t);
2702 printf("\t Status: \"%s\"\n", i->status_text);
2704 if (i->default_control_group &&
2705 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2708 printf("\t CGroup: %s\n", i->default_control_group);
2710 if (arg_transport != TRANSPORT_SSH) {
2720 if (i->main_pid > 0)
2721 extra[k++] = i->main_pid;
2723 if (i->control_pid > 0)
2724 extra[k++] = i->control_pid;
2726 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, extra, k, flags);
2730 if (i->id && arg_transport != TRANSPORT_SSH) {
2732 if(arg_scope == UNIT_FILE_SYSTEM)
2733 show_journal_by_unit(stdout,
2737 i->inactive_exit_timestamp_monotonic,
2741 show_journal_by_user_unit(stdout,
2745 i->inactive_exit_timestamp_monotonic,
2751 if (i->need_daemon_reload)
2752 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2753 ansi_highlight_red(true),
2754 ansi_highlight_red(false),
2755 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2758 static void show_unit_help(UnitStatusInfo *i) {
2763 if (!i->documentation) {
2764 log_info("Documentation for %s not known.", i->id);
2768 STRV_FOREACH(p, i->documentation) {
2770 if (startswith(*p, "man:")) {
2773 char *page = NULL, *section = NULL;
2774 const char *args[4] = { "man", NULL, NULL, NULL };
2779 if ((*p)[k-1] == ')')
2780 e = strrchr(*p, '(');
2783 page = strndup((*p) + 4, e - *p - 4);
2789 section = strndup(e + 1, *p + k - e - 2);
2803 log_error("Failed to fork: %m");
2811 execvp(args[0], (char**) args);
2812 log_error("Failed to execute man: %m");
2813 _exit(EXIT_FAILURE);
2819 wait_for_terminate(pid, NULL);
2821 log_info("Can't show: %s", *p);
2825 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2831 switch (dbus_message_iter_get_arg_type(iter)) {
2833 case DBUS_TYPE_STRING: {
2836 dbus_message_iter_get_basic(iter, &s);
2839 if (streq(name, "Id"))
2841 else if (streq(name, "LoadState"))
2843 else if (streq(name, "ActiveState"))
2844 i->active_state = s;
2845 else if (streq(name, "SubState"))
2847 else if (streq(name, "Description"))
2849 else if (streq(name, "FragmentPath"))
2850 i->fragment_path = s;
2851 else if (streq(name, "SourcePath"))
2853 else if (streq(name, "DefaultControlGroup"))
2854 i->default_control_group = s;
2855 else if (streq(name, "StatusText"))
2857 else if (streq(name, "SysFSPath"))
2859 else if (streq(name, "Where"))
2861 else if (streq(name, "What"))
2863 else if (streq(name, "Following"))
2865 else if (streq(name, "UnitFileState"))
2866 i->unit_file_state = s;
2867 else if (streq(name, "Result"))
2874 case DBUS_TYPE_BOOLEAN: {
2877 dbus_message_iter_get_basic(iter, &b);
2879 if (streq(name, "Accept"))
2881 else if (streq(name, "NeedDaemonReload"))
2882 i->need_daemon_reload = b;
2883 else if (streq(name, "ConditionResult"))
2884 i->condition_result = b;
2889 case DBUS_TYPE_UINT32: {
2892 dbus_message_iter_get_basic(iter, &u);
2894 if (streq(name, "MainPID")) {
2896 i->main_pid = (pid_t) u;
2899 } else if (streq(name, "ControlPID"))
2900 i->control_pid = (pid_t) u;
2901 else if (streq(name, "ExecMainPID")) {
2903 i->main_pid = (pid_t) u;
2904 } else if (streq(name, "NAccepted"))
2906 else if (streq(name, "NConnections"))
2907 i->n_connections = u;
2912 case DBUS_TYPE_INT32: {
2915 dbus_message_iter_get_basic(iter, &j);
2917 if (streq(name, "ExecMainCode"))
2918 i->exit_code = (int) j;
2919 else if (streq(name, "ExecMainStatus"))
2920 i->exit_status = (int) j;
2925 case DBUS_TYPE_UINT64: {
2928 dbus_message_iter_get_basic(iter, &u);
2930 if (streq(name, "ExecMainStartTimestamp"))
2931 i->start_timestamp = (usec_t) u;
2932 else if (streq(name, "ExecMainExitTimestamp"))
2933 i->exit_timestamp = (usec_t) u;
2934 else if (streq(name, "ActiveEnterTimestamp"))
2935 i->active_enter_timestamp = (usec_t) u;
2936 else if (streq(name, "InactiveEnterTimestamp"))
2937 i->inactive_enter_timestamp = (usec_t) u;
2938 else if (streq(name, "InactiveExitTimestamp"))
2939 i->inactive_exit_timestamp = (usec_t) u;
2940 else if (streq(name, "InactiveExitTimestampMonotonic"))
2941 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2942 else if (streq(name, "ActiveExitTimestamp"))
2943 i->active_exit_timestamp = (usec_t) u;
2944 else if (streq(name, "ConditionTimestamp"))
2945 i->condition_timestamp = (usec_t) u;
2950 case DBUS_TYPE_ARRAY: {
2952 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2953 startswith(name, "Exec")) {
2954 DBusMessageIter sub;
2956 dbus_message_iter_recurse(iter, &sub);
2957 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2958 ExecStatusInfo *info;
2961 if (!(info = new0(ExecStatusInfo, 1)))
2964 if (!(info->name = strdup(name))) {
2969 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2974 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2976 dbus_message_iter_next(&sub);
2978 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2979 streq(name, "Documentation")) {
2981 DBusMessageIter sub;
2983 dbus_message_iter_recurse(iter, &sub);
2984 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2988 dbus_message_iter_get_basic(&sub, &s);
2990 l = strv_append(i->documentation, s);
2994 strv_free(i->documentation);
2995 i->documentation = l;
2997 dbus_message_iter_next(&sub);
3004 case DBUS_TYPE_STRUCT: {
3006 if (streq(name, "LoadError")) {
3007 DBusMessageIter sub;
3008 const char *n, *message;
3011 dbus_message_iter_recurse(iter, &sub);
3013 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
3017 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
3021 if (!isempty(message))
3022 i->load_error = message;
3032 static int print_property(const char *name, DBusMessageIter *iter) {
3036 /* This is a low-level property printer, see
3037 * print_status_info() for the nicer output */
3039 if (arg_property && !strv_find(arg_property, name))
3042 switch (dbus_message_iter_get_arg_type(iter)) {
3044 case DBUS_TYPE_STRUCT: {
3045 DBusMessageIter sub;
3046 dbus_message_iter_recurse(iter, &sub);
3048 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
3051 dbus_message_iter_get_basic(&sub, &u);
3054 printf("%s=%u\n", name, (unsigned) u);
3056 printf("%s=\n", name);
3059 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
3062 dbus_message_iter_get_basic(&sub, &s);
3064 if (arg_all || s[0])
3065 printf("%s=%s\n", name, s);
3068 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
3069 const char *a = NULL, *b = NULL;
3071 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
3072 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
3074 if (arg_all || !isempty(a) || !isempty(b))
3075 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3083 case DBUS_TYPE_ARRAY:
3085 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
3086 DBusMessageIter sub, sub2;
3088 dbus_message_iter_recurse(iter, &sub);
3089 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3093 dbus_message_iter_recurse(&sub, &sub2);
3095 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3096 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3097 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3099 dbus_message_iter_next(&sub);
3104 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3105 DBusMessageIter sub, sub2;
3107 dbus_message_iter_recurse(iter, &sub);
3108 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3109 const char *type, *path;
3111 dbus_message_iter_recurse(&sub, &sub2);
3113 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3114 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3115 printf("%s=%s\n", type, path);
3117 dbus_message_iter_next(&sub);
3122 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3123 DBusMessageIter sub, sub2;
3125 dbus_message_iter_recurse(iter, &sub);
3126 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3128 uint64_t value, next_elapse;
3130 dbus_message_iter_recurse(&sub, &sub2);
3132 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3133 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3134 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3135 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3137 printf("%s={ value=%s ; next_elapse=%s }\n",
3139 format_timespan(timespan1, sizeof(timespan1), value),
3140 format_timespan(timespan2, sizeof(timespan2), next_elapse));
3143 dbus_message_iter_next(&sub);
3148 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
3149 DBusMessageIter sub, sub2;
3151 dbus_message_iter_recurse(iter, &sub);
3152 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3153 const char *controller, *attr, *value;
3155 dbus_message_iter_recurse(&sub, &sub2);
3157 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
3158 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
3159 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
3161 printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
3167 dbus_message_iter_next(&sub);
3172 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3173 DBusMessageIter sub;
3175 dbus_message_iter_recurse(iter, &sub);
3176 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3177 ExecStatusInfo info;
3180 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3181 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3184 t = strv_join(info.argv, " ");
3186 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3190 yes_no(info.ignore),
3191 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3192 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3193 (unsigned) info. pid,
3194 sigchld_code_to_string(info.code),
3196 info.code == CLD_EXITED ? "" : "/",
3197 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3203 strv_free(info.argv);
3205 dbus_message_iter_next(&sub);
3214 if (generic_print_property(name, iter, arg_all) > 0)
3218 printf("%s=[unprintable]\n", name);
3223 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3224 _cleanup_free_ DBusMessage *reply = NULL;
3225 const char *interface = "";
3227 DBusMessageIter iter, sub, sub2, sub3;
3228 UnitStatusInfo info;
3236 r = bus_method_call_with_reply(
3238 "org.freedesktop.systemd1",
3240 "org.freedesktop.DBus.Properties",
3244 DBUS_TYPE_STRING, &interface,
3249 if (!dbus_message_iter_init(reply, &iter) ||
3250 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3251 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3252 log_error("Failed to parse reply.");
3256 dbus_message_iter_recurse(&iter, &sub);
3263 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3266 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3267 dbus_message_iter_recurse(&sub, &sub2);
3269 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3270 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3271 log_error("Failed to parse reply.");
3275 dbus_message_iter_recurse(&sub2, &sub3);
3277 if (show_properties)
3278 r = print_property(name, &sub3);
3280 r = status_property(name, &sub3, &info);
3282 log_error("Failed to parse reply.");
3286 dbus_message_iter_next(&sub);
3291 if (!show_properties) {
3292 if (streq(verb, "help"))
3293 show_unit_help(&info);
3295 print_status_info(&info);
3298 strv_free(info.documentation);
3300 if (!streq_ptr(info.active_state, "active") &&
3301 !streq_ptr(info.active_state, "reloading") &&
3302 streq(verb, "status"))
3303 /* According to LSB: "program not running" */
3306 while ((p = info.exec)) {
3307 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3308 exec_status_info_free(p);
3314 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3315 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3316 const char *path = NULL;
3320 dbus_error_init(&error);
3322 r = bus_method_call_with_reply(
3324 "org.freedesktop.systemd1",
3325 "/org/freedesktop/systemd1",
3326 "org.freedesktop.systemd1.Manager",
3330 DBUS_TYPE_UINT32, &pid,
3335 if (!dbus_message_get_args(reply, &error,
3336 DBUS_TYPE_OBJECT_PATH, &path,
3337 DBUS_TYPE_INVALID)) {
3338 log_error("Failed to parse reply: %s", bus_error_message(&error));
3343 r = show_one(verb, bus, path, false, new_line);
3346 dbus_error_free(&error);
3351 static int show(DBusConnection *bus, char **args) {
3353 bool show_properties, new_line = false;
3359 show_properties = streq(args[0], "show");
3361 if (show_properties)
3362 pager_open_if_enabled();
3364 /* If no argument is specified inspect the manager itself */
3366 if (show_properties && strv_length(args) <= 1)
3367 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3369 STRV_FOREACH(name, args+1) {
3372 if (safe_atou32(*name, &id) < 0) {
3373 _cleanup_free_ char *p = NULL, *n = NULL;
3374 /* Interpret as unit name */
3376 n = unit_name_mangle(*name);
3380 p = unit_dbus_path_from_name(n);
3384 r = show_one(args[0], bus, p, show_properties, &new_line);
3388 } else if (show_properties) {
3389 _cleanup_free_ char *p = NULL;
3391 /* Interpret as job id */
3392 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3395 r = show_one(args[0], bus, p, show_properties, &new_line);
3400 /* Interpret as PID */
3401 r = show_one_by_pid(args[0], bus, id, &new_line);
3410 static int dump(DBusConnection *bus, char **args) {
3411 _cleanup_free_ DBusMessage *reply = NULL;
3416 dbus_error_init(&error);
3418 pager_open_if_enabled();
3420 r = bus_method_call_with_reply(
3422 "org.freedesktop.systemd1",
3423 "/org/freedesktop/systemd1",
3424 "org.freedesktop.systemd1.Manager",
3432 if (!dbus_message_get_args(reply, &error,
3433 DBUS_TYPE_STRING, &text,
3434 DBUS_TYPE_INVALID)) {
3435 log_error("Failed to parse reply: %s", bus_error_message(&error));
3436 dbus_error_free(&error);
3440 fputs(text, stdout);
3444 static int snapshot(DBusConnection *bus, char **args) {
3445 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3448 dbus_bool_t cleanup = FALSE;
3449 DBusMessageIter iter, sub;
3452 *interface = "org.freedesktop.systemd1.Unit",
3454 _cleanup_free_ char *n = NULL;
3456 dbus_error_init(&error);
3458 if (strv_length(args) > 1)
3459 n = snapshot_name_mangle(args[1]);
3465 r = bus_method_call_with_reply (
3467 "org.freedesktop.systemd1",
3468 "/org/freedesktop/systemd1",
3469 "org.freedesktop.systemd1.Manager",
3473 DBUS_TYPE_STRING, &n,
3474 DBUS_TYPE_BOOLEAN, &cleanup,
3479 if (!dbus_message_get_args(reply, &error,
3480 DBUS_TYPE_OBJECT_PATH, &path,
3481 DBUS_TYPE_INVALID)) {
3482 log_error("Failed to parse reply: %s", bus_error_message(&error));
3483 dbus_error_free(&error);
3487 dbus_message_unref(reply);
3490 r = bus_method_call_with_reply (
3492 "org.freedesktop.systemd1",
3494 "org.freedesktop.DBus.Properties",
3498 DBUS_TYPE_STRING, &interface,
3499 DBUS_TYPE_STRING, &property,
3504 if (!dbus_message_iter_init(reply, &iter) ||
3505 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3506 log_error("Failed to parse reply.");
3510 dbus_message_iter_recurse(&iter, &sub);
3512 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3513 log_error("Failed to parse reply.");
3517 dbus_message_iter_get_basic(&sub, &id);
3525 static int delete_snapshot(DBusConnection *bus, char **args) {
3530 STRV_FOREACH(name, args+1) {
3531 _cleanup_free_ char *n = NULL;
3534 n = snapshot_name_mangle(*name);
3538 r = bus_method_call_with_reply(
3540 "org.freedesktop.systemd1",
3541 "/org/freedesktop/systemd1",
3542 "org.freedesktop.systemd1.Manager",
3546 DBUS_TYPE_STRING, &n,
3555 static int daemon_reload(DBusConnection *bus, char **args) {
3560 if (arg_action == ACTION_RELOAD)
3562 else if (arg_action == ACTION_REEXEC)
3563 method = "Reexecute";
3565 assert(arg_action == ACTION_SYSTEMCTL);
3568 streq(args[0], "clear-jobs") ||
3569 streq(args[0], "cancel") ? "ClearJobs" :
3570 streq(args[0], "daemon-reexec") ? "Reexecute" :
3571 streq(args[0], "reset-failed") ? "ResetFailed" :
3572 streq(args[0], "halt") ? "Halt" :
3573 streq(args[0], "poweroff") ? "PowerOff" :
3574 streq(args[0], "reboot") ? "Reboot" :
3575 streq(args[0], "kexec") ? "KExec" :
3576 streq(args[0], "exit") ? "Exit" :
3577 /* "daemon-reload" */ "Reload";
3580 r = bus_method_call_with_reply(
3582 "org.freedesktop.systemd1",
3583 "/org/freedesktop/systemd1",
3584 "org.freedesktop.systemd1.Manager",
3590 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3591 /* There's always a fallback possible for
3592 * legacy actions. */
3594 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3595 /* On reexecution, we expect a disconnect, not
3599 log_error("Failed to issue method call: %s", bus_error_message(&error));
3601 dbus_error_free(&error);
3605 static int reset_failed(DBusConnection *bus, char **args) {
3609 if (strv_length(args) <= 1)
3610 return daemon_reload(bus, args);
3612 STRV_FOREACH(name, args+1) {
3613 _cleanup_free_ char *n;
3615 n = unit_name_mangle(*name);
3619 r = bus_method_call_with_reply(
3621 "org.freedesktop.systemd1",
3622 "/org/freedesktop/systemd1",
3623 "org.freedesktop.systemd1.Manager",
3627 DBUS_TYPE_STRING, &n,
3636 static int show_enviroment(DBusConnection *bus, char **args) {
3637 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3638 DBusMessageIter iter, sub, sub2;
3641 *interface = "org.freedesktop.systemd1.Manager",
3642 *property = "Environment";
3644 pager_open_if_enabled();
3646 r = bus_method_call_with_reply(
3648 "org.freedesktop.systemd1",
3649 "/org/freedesktop/systemd1",
3650 "org.freedesktop.DBus.Properties",
3654 DBUS_TYPE_STRING, &interface,
3655 DBUS_TYPE_STRING, &property,
3660 if (!dbus_message_iter_init(reply, &iter) ||
3661 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3662 log_error("Failed to parse reply.");
3666 dbus_message_iter_recurse(&iter, &sub);
3668 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3669 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3670 log_error("Failed to parse reply.");
3674 dbus_message_iter_recurse(&sub, &sub2);
3676 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3679 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3680 log_error("Failed to parse reply.");
3684 dbus_message_iter_get_basic(&sub2, &text);
3687 dbus_message_iter_next(&sub2);
3693 static int switch_root(DBusConnection *bus, char **args) {
3696 _cleanup_free_ char *init = NULL;
3698 l = strv_length(args);
3699 if (l < 2 || l > 3) {
3700 log_error("Wrong number of arguments.");
3707 init = strdup(args[2]);
3709 parse_env_file("/proc/cmdline", WHITESPACE,
3719 log_debug("switching root - root: %s; init: %s", root, init);
3721 return bus_method_call_with_reply(
3723 "org.freedesktop.systemd1",
3724 "/org/freedesktop/systemd1",
3725 "org.freedesktop.systemd1.Manager",
3729 DBUS_TYPE_STRING, &root,
3730 DBUS_TYPE_STRING, &init,
3734 static int set_environment(DBusConnection *bus, char **args) {
3735 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3738 DBusMessageIter iter;
3744 dbus_error_init(&error);
3746 method = streq(args[0], "set-environment")
3748 : "UnsetEnvironment";
3750 m = dbus_message_new_method_call(
3751 "org.freedesktop.systemd1",
3752 "/org/freedesktop/systemd1",
3753 "org.freedesktop.systemd1.Manager",
3758 dbus_message_iter_init_append(m, &iter);
3760 r = bus_append_strv_iter(&iter, args + 1);
3764 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3766 log_error("Failed to issue method call: %s", bus_error_message(&error));
3767 dbus_error_free(&error);
3774 static int enable_sysv_units(char **args) {
3777 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3778 const char *verb = args[0];
3779 unsigned f = 1, t = 1;
3782 if (arg_scope != UNIT_FILE_SYSTEM)
3785 if (!streq(verb, "enable") &&
3786 !streq(verb, "disable") &&
3787 !streq(verb, "is-enabled"))
3790 /* Processes all SysV units, and reshuffles the array so that
3791 * afterwards only the native units remain */
3794 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3799 for (f = 1; args[f]; f++) {
3802 bool found_native = false, found_sysv;
3804 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3805 char **k, *l, *q = NULL;
3812 if (!endswith(name, ".service"))
3815 if (path_is_absolute(name))
3818 STRV_FOREACH(k, paths.unit_path) {
3821 if (!isempty(arg_root))
3822 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3824 asprintf(&p, "%s/%s", *k, name);
3831 found_native = access(p, F_OK) >= 0;
3842 if (!isempty(arg_root))
3843 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3845 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3851 p[strlen(p) - sizeof(".service") + 1] = 0;
3852 found_sysv = access(p, F_OK) >= 0;
3859 /* Mark this entry, so that we don't try enabling it as native unit */
3860 args[f] = (char*) "";
3862 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3864 if (!isempty(arg_root))
3865 argv[c++] = q = strappend("--root=", arg_root);
3867 argv[c++] = path_get_file_name(p);
3869 streq(verb, "enable") ? "on" :
3870 streq(verb, "disable") ? "off" : "--level=5";
3873 l = strv_join((char**)argv, " ");
3881 log_info("Executing %s", l);
3886 log_error("Failed to fork: %m");
3891 } else if (pid == 0) {
3894 execv(argv[0], (char**) argv);
3895 _exit(EXIT_FAILURE);
3901 j = wait_for_terminate(pid, &status);
3903 log_error("Failed to wait for child: %s", strerror(-r));
3908 if (status.si_code == CLD_EXITED) {
3909 if (streq(verb, "is-enabled")) {
3910 if (status.si_status == 0) {
3919 } else if (status.si_status != 0) {
3930 lookup_paths_free(&paths);
3932 /* Drop all SysV units */
3933 for (f = 1, t = 1; args[f]; f++) {
3935 if (isempty(args[f]))
3938 args[t++] = args[f];
3947 static int mangle_names(char **original_names, char ***mangled_names) {
3948 char **i, **l, **name;
3950 l = new(char*, strv_length(original_names) + 1);
3955 STRV_FOREACH(name, original_names) {
3957 /* When enabling units qualified path names are OK,
3958 * too, hence allow them explicitly. */
3963 *i = unit_name_mangle(*name);
3979 static int enable_unit(DBusConnection *bus, char **args) {
3980 const char *verb = args[0];
3981 UnitFileChange *changes = NULL;
3982 unsigned n_changes = 0, i;
3983 int carries_install_info = -1;
3984 DBusMessage *m = NULL, *reply = NULL;
3987 char **mangled_names = NULL;
3989 r = enable_sysv_units(args);
3996 dbus_error_init(&error);
3998 if (!bus || avoid_bus()) {
3999 if (streq(verb, "enable")) {
4000 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4001 carries_install_info = r;
4002 } else if (streq(verb, "disable"))
4003 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
4004 else if (streq(verb, "reenable")) {
4005 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4006 carries_install_info = r;
4007 } else if (streq(verb, "link"))
4008 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4009 else if (streq(verb, "preset")) {
4010 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4011 carries_install_info = r;
4012 } else if (streq(verb, "mask"))
4013 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
4014 else if (streq(verb, "unmask"))
4015 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
4017 assert_not_reached("Unknown verb");
4020 log_error("Operation failed: %s", strerror(-r));
4025 for (i = 0; i < n_changes; i++) {
4026 if (changes[i].type == UNIT_FILE_SYMLINK)
4027 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
4029 log_info("rm '%s'", changes[i].path);
4036 bool send_force = true, expect_carries_install_info = false;
4038 DBusMessageIter iter, sub, sub2;
4040 if (streq(verb, "enable")) {
4041 method = "EnableUnitFiles";
4042 expect_carries_install_info = true;
4043 } else if (streq(verb, "disable")) {
4044 method = "DisableUnitFiles";
4046 } else if (streq(verb, "reenable")) {
4047 method = "ReenableUnitFiles";
4048 expect_carries_install_info = true;
4049 } else if (streq(verb, "link"))
4050 method = "LinkUnitFiles";
4051 else if (streq(verb, "preset")) {
4052 method = "PresetUnitFiles";
4053 expect_carries_install_info = true;
4054 } else if (streq(verb, "mask"))
4055 method = "MaskUnitFiles";
4056 else if (streq(verb, "unmask")) {
4057 method = "UnmaskUnitFiles";
4060 assert_not_reached("Unknown verb");
4062 m = dbus_message_new_method_call(
4063 "org.freedesktop.systemd1",
4064 "/org/freedesktop/systemd1",
4065 "org.freedesktop.systemd1.Manager",
4072 dbus_message_iter_init_append(m, &iter);
4074 r = mangle_names(args+1, &mangled_names);
4078 r = bus_append_strv_iter(&iter, mangled_names);
4080 log_error("Failed to append unit files.");
4085 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4086 log_error("Failed to append runtime boolean.");
4094 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4095 log_error("Failed to append force boolean.");
4101 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4103 log_error("Failed to issue method call: %s", bus_error_message(&error));
4108 if (!dbus_message_iter_init(reply, &iter)) {
4109 log_error("Failed to initialize iterator.");
4113 if (expect_carries_install_info) {
4114 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4116 log_error("Failed to parse reply.");
4120 carries_install_info = b;
4123 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4124 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4125 log_error("Failed to parse reply.");
4130 dbus_message_iter_recurse(&iter, &sub);
4131 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4132 const char *type, *path, *source;
4134 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4135 log_error("Failed to parse reply.");
4140 dbus_message_iter_recurse(&sub, &sub2);
4142 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4143 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4144 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4145 log_error("Failed to parse reply.");
4151 if (streq(type, "symlink"))
4152 log_info("ln -s '%s' '%s'", source, path);
4154 log_info("rm '%s'", path);
4157 dbus_message_iter_next(&sub);
4160 /* Try to reload if enabeld */
4162 r = daemon_reload(bus, args);
4165 if (carries_install_info == 0)
4167 "The unit files have no [Install] section. They are not meant to be enabled\n"
4168 "using systemctl.\n"
4169 "Possible reasons for having this kind of units are:\n"
4170 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4171 " .wants/ or .requires/ directory.\n"
4172 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4173 " a requirement dependency on it.\n"
4174 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4175 " D-Bus, udev, scripted systemctl call, ...).\n");
4179 dbus_message_unref(m);
4182 dbus_message_unref(reply);
4184 unit_file_changes_free(changes, n_changes);
4186 dbus_error_free(&error);
4188 strv_free(mangled_names);
4193 static int unit_is_enabled(DBusConnection *bus, char **args) {
4196 DBusMessage *reply = NULL;
4200 dbus_error_init(&error);
4202 r = enable_sysv_units(args);
4208 if (!bus || avoid_bus()) {
4210 STRV_FOREACH(name, args+1) {
4211 UnitFileState state;
4213 state = unit_file_get_state(arg_scope, arg_root, *name);
4219 if (state == UNIT_FILE_ENABLED ||
4220 state == UNIT_FILE_ENABLED_RUNTIME ||
4221 state == UNIT_FILE_STATIC)
4225 puts(unit_file_state_to_string(state));
4229 STRV_FOREACH(name, args+1) {
4232 r = bus_method_call_with_reply (
4234 "org.freedesktop.systemd1",
4235 "/org/freedesktop/systemd1",
4236 "org.freedesktop.systemd1.Manager",
4240 DBUS_TYPE_STRING, name,
4245 if (!dbus_message_get_args(reply, &error,
4246 DBUS_TYPE_STRING, &s,
4247 DBUS_TYPE_INVALID)) {
4248 log_error("Failed to parse reply: %s", bus_error_message(&error));
4253 dbus_message_unref(reply);
4256 if (streq(s, "enabled") ||
4257 streq(s, "enabled-runtime") ||
4266 r = enabled ? 0 : 1;
4270 dbus_message_unref(reply);
4272 dbus_error_free(&error);
4276 static int systemctl_help(void) {
4278 pager_open_if_enabled();
4280 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4281 "Query or send control commands to the systemd manager.\n\n"
4282 " -h --help Show this help\n"
4283 " --version Show package version\n"
4284 " -t --type=TYPE List only units of a particular type\n"
4285 " -p --property=NAME Show only properties by this name\n"
4286 " -a --all Show all units/properties, including dead/empty ones\n"
4287 " --failed Show only failed units\n"
4288 " --full Don't ellipsize unit names on output\n"
4289 " --fail When queueing a new job, fail if conflicting jobs are\n"
4291 " --ignore-dependencies\n"
4292 " When queueing a new job, ignore all its dependencies\n"
4293 " -i --ignore-inhibitors\n"
4294 " When shutting down or sleeping, ignore inhibitors\n"
4295 " --kill-who=WHO Who to send signal to\n"
4296 " -s --signal=SIGNAL Which signal to send\n"
4297 " -H --host=[USER@]HOST\n"
4298 " Show information for remote host\n"
4299 " -P --privileged Acquire privileges before execution\n"
4300 " -q --quiet Suppress output\n"
4301 " --no-block Do not wait until operation finished\n"
4302 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4303 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4305 " --no-legend Do not print a legend (column headers and hints)\n"
4306 " --no-pager Do not pipe output into a pager\n"
4307 " --no-ask-password\n"
4308 " Do not ask for system passwords\n"
4309 " --order When generating graph for dot, show only order\n"
4310 " --require When generating graph for dot, show only requirement\n"
4311 " --system Connect to system manager\n"
4312 " --user Connect to user service manager\n"
4313 " --global Enable/disable unit files globally\n"
4314 " -f --force When enabling unit files, override existing symlinks\n"
4315 " When shutting down, execute action immediately\n"
4316 " --root=PATH Enable unit files in the specified root directory\n"
4317 " --runtime Enable unit files only temporarily until next reboot\n"
4318 " -n --lines=INTEGER Journal entries to show\n"
4319 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4320 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4322 " list-units List loaded units\n"
4323 " start [NAME...] Start (activate) one or more units\n"
4324 " stop [NAME...] Stop (deactivate) one or more units\n"
4325 " reload [NAME...] Reload one or more units\n"
4326 " restart [NAME...] Start or restart one or more units\n"
4327 " try-restart [NAME...] Restart one or more units if active\n"
4328 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4329 " otherwise start or restart\n"
4330 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4331 " otherwise restart if active\n"
4332 " isolate [NAME] Start one unit and stop all others\n"
4333 " kill [NAME...] Send signal to processes of a unit\n"
4334 " is-active [NAME...] Check whether units are active\n"
4335 " is-failed [NAME...] Check whether units are failed\n"
4336 " status [NAME...|PID...] Show runtime status of one or more units\n"
4337 " show [NAME...|JOB...] Show properties of one or more\n"
4338 " units/jobs or the manager\n"
4339 " help [NAME...|PID...] Show manual for one or more units\n"
4340 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4342 " get-cgroup-attr [NAME] [ATTR] ...\n"
4343 " Get control group attrubute\n"
4344 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4345 " Set control group attribute\n"
4346 " unset-cgroup-attr [NAME] [ATTR...]\n"
4347 " Unset control group attribute\n"
4348 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4349 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4350 " load [NAME...] Load one or more units\n"
4351 " list-dependencies [NAME] Recursively show units which are required\n"
4352 " or wanted by this unit\n\n"
4353 "Unit File Commands:\n"
4354 " list-unit-files List installed unit files\n"
4355 " enable [NAME...] Enable one or more unit files\n"
4356 " disable [NAME...] Disable one or more unit files\n"
4357 " reenable [NAME...] Reenable one or more unit files\n"
4358 " preset [NAME...] Enable/disable one or more unit files\n"
4359 " based on preset configuration\n"
4360 " mask [NAME...] Mask one or more units\n"
4361 " unmask [NAME...] Unmask one or more units\n"
4362 " link [PATH...] Link one or more units files into\n"
4363 " the search path\n"
4364 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4366 " list-jobs List jobs\n"
4367 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4368 "Status Commands:\n"
4369 " dump Dump server status\n"
4370 " dot Dump dependency graph for dot(1)\n\n"
4371 "Snapshot Commands:\n"
4372 " snapshot [NAME] Create a snapshot\n"
4373 " delete [NAME...] Remove one or more snapshots\n\n"
4374 "Environment Commands:\n"
4375 " show-environment Dump environment\n"
4376 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4377 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4378 "Manager Lifecycle Commands:\n"
4379 " daemon-reload Reload systemd manager configuration\n"
4380 " daemon-reexec Reexecute systemd manager\n\n"
4381 "System Commands:\n"
4382 " default Enter system default mode\n"
4383 " rescue Enter system rescue mode\n"
4384 " emergency Enter system emergency mode\n"
4385 " halt Shut down and halt the system\n"
4386 " poweroff Shut down and power-off the system\n"
4387 " reboot Shut down and reboot the system\n"
4388 " kexec Shut down and reboot the system with kexec\n"
4389 " exit Request user instance exit\n"
4390 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4391 " suspend Suspend the system\n"
4392 " hibernate Hibernate the system\n"
4393 " hybrid-sleep Hibernate and suspend the system\n",
4394 program_invocation_short_name);
4399 static int halt_help(void) {
4401 printf("%s [OPTIONS...]\n\n"
4402 "%s the system.\n\n"
4403 " --help Show this help\n"
4404 " --halt Halt the machine\n"
4405 " -p --poweroff Switch off the machine\n"
4406 " --reboot Reboot the machine\n"
4407 " -f --force Force immediate halt/power-off/reboot\n"
4408 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4409 " -d --no-wtmp Don't write wtmp record\n"
4410 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4411 program_invocation_short_name,
4412 arg_action == ACTION_REBOOT ? "Reboot" :
4413 arg_action == ACTION_POWEROFF ? "Power off" :
4419 static int shutdown_help(void) {
4421 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4422 "Shut down the system.\n\n"
4423 " --help Show this help\n"
4424 " -H --halt Halt the machine\n"
4425 " -P --poweroff Power-off the machine\n"
4426 " -r --reboot Reboot the machine\n"
4427 " -h Equivalent to --poweroff, overridden by --halt\n"
4428 " -k Don't halt/power-off/reboot, just send warnings\n"
4429 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4430 " -c Cancel a pending shutdown\n",
4431 program_invocation_short_name);
4436 static int telinit_help(void) {
4438 printf("%s [OPTIONS...] {COMMAND}\n\n"
4439 "Send control commands to the init daemon.\n\n"
4440 " --help Show this help\n"
4441 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4443 " 0 Power-off the machine\n"
4444 " 6 Reboot the machine\n"
4445 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4446 " 1, s, S Enter rescue mode\n"
4447 " q, Q Reload init daemon configuration\n"
4448 " u, U Reexecute init daemon\n",
4449 program_invocation_short_name);
4454 static int runlevel_help(void) {
4456 printf("%s [OPTIONS...]\n\n"
4457 "Prints the previous and current runlevel of the init system.\n\n"
4458 " --help Show this help\n",
4459 program_invocation_short_name);
4464 static int help_types(void) {
4467 puts("Available unit types:");
4468 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4469 if (unit_type_table[i])
4470 puts(unit_type_table[i]);
4472 puts("\nAvailable unit load states: ");
4473 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4474 if (unit_type_table[i])
4475 puts(unit_load_state_table[i]);
4480 static int systemctl_parse_argv(int argc, char *argv[]) {
4484 ARG_IGNORE_DEPENDENCIES,
4499 ARG_NO_ASK_PASSWORD,
4505 static const struct option options[] = {
4506 { "help", no_argument, NULL, 'h' },
4507 { "version", no_argument, NULL, ARG_VERSION },
4508 { "type", required_argument, NULL, 't' },
4509 { "property", required_argument, NULL, 'p' },
4510 { "all", no_argument, NULL, 'a' },
4511 { "failed", no_argument, NULL, ARG_FAILED },
4512 { "full", no_argument, NULL, ARG_FULL },
4513 { "fail", no_argument, NULL, ARG_FAIL },
4514 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4515 { "ignore-inhibitors", no_argument, NULL, 'i' },
4516 { "user", no_argument, NULL, ARG_USER },
4517 { "system", no_argument, NULL, ARG_SYSTEM },
4518 { "global", no_argument, NULL, ARG_GLOBAL },
4519 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4520 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4521 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4522 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4523 { "quiet", no_argument, NULL, 'q' },
4524 { "order", no_argument, NULL, ARG_ORDER },
4525 { "require", no_argument, NULL, ARG_REQUIRE },
4526 { "root", required_argument, NULL, ARG_ROOT },
4527 { "force", no_argument, NULL, ARG_FORCE },
4528 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4529 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4530 { "signal", required_argument, NULL, 's' },
4531 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4532 { "host", required_argument, NULL, 'H' },
4533 { "privileged",no_argument, NULL, 'P' },
4534 { "runtime", no_argument, NULL, ARG_RUNTIME },
4535 { "lines", required_argument, NULL, 'n' },
4536 { "output", required_argument, NULL, 'o' },
4537 { NULL, 0, NULL, 0 }
4545 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4554 puts(PACKAGE_STRING);
4555 puts(SYSTEMD_FEATURES);
4559 if (streq(optarg, "help")) {
4564 if (unit_type_from_string(optarg) >= 0) {
4568 if (unit_load_state_from_string(optarg) >= 0) {
4569 arg_load_state = optarg;
4572 log_error("Unkown unit type or load state '%s'.",
4574 log_info("Use -t help to see a list of allowed values.");
4579 if (!(l = strv_append(arg_property, optarg)))
4582 strv_free(arg_property);
4585 /* If the user asked for a particular
4586 * property, show it to him, even if it is
4597 arg_job_mode = "fail";
4600 case ARG_IGNORE_DEPENDENCIES:
4601 arg_job_mode = "ignore-dependencies";
4605 arg_scope = UNIT_FILE_USER;
4609 arg_scope = UNIT_FILE_SYSTEM;
4613 arg_scope = UNIT_FILE_GLOBAL;
4617 arg_no_block = true;
4621 arg_no_legend = true;
4625 arg_no_pager = true;
4633 arg_dot = DOT_ORDER;
4637 arg_dot = DOT_REQUIRE;
4665 arg_no_reload = true;
4669 arg_kill_who = optarg;
4673 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4674 log_error("Failed to parse signal string %s.", optarg);
4679 case ARG_NO_ASK_PASSWORD:
4680 arg_ask_password = false;
4684 arg_transport = TRANSPORT_POLKIT;
4688 arg_transport = TRANSPORT_SSH;
4697 if (safe_atou(optarg, &arg_lines) < 0) {
4698 log_error("Failed to parse lines '%s'", optarg);
4704 arg_output = output_mode_from_string(optarg);
4705 if (arg_output < 0) {
4706 log_error("Unknown output '%s'.", optarg);
4712 arg_ignore_inhibitors = true;
4719 log_error("Unknown option code '%c'.", c);
4724 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4725 log_error("Cannot access user instance remotely.");
4732 static int halt_parse_argv(int argc, char *argv[]) {
4741 static const struct option options[] = {
4742 { "help", no_argument, NULL, ARG_HELP },
4743 { "halt", no_argument, NULL, ARG_HALT },
4744 { "poweroff", no_argument, NULL, 'p' },
4745 { "reboot", no_argument, NULL, ARG_REBOOT },
4746 { "force", no_argument, NULL, 'f' },
4747 { "wtmp-only", no_argument, NULL, 'w' },
4748 { "no-wtmp", no_argument, NULL, 'd' },
4749 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4750 { NULL, 0, NULL, 0 }
4758 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4759 if (runlevel == '0' || runlevel == '6')
4762 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4770 arg_action = ACTION_HALT;
4774 if (arg_action != ACTION_REBOOT)
4775 arg_action = ACTION_POWEROFF;
4779 arg_action = ACTION_REBOOT;
4801 /* Compatibility nops */
4808 log_error("Unknown option code '%c'.", c);
4813 if (optind < argc) {
4814 log_error("Too many arguments.");
4821 static int parse_time_spec(const char *t, usec_t *_u) {
4825 if (streq(t, "now"))
4827 else if (!strchr(t, ':')) {
4830 if (safe_atou64(t, &u) < 0)
4833 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4842 hour = strtol(t, &e, 10);
4843 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4846 minute = strtol(e+1, &e, 10);
4847 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4850 n = now(CLOCK_REALTIME);
4851 s = (time_t) (n / USEC_PER_SEC);
4854 assert_se(localtime_r(&s, &tm));
4856 tm.tm_hour = (int) hour;
4857 tm.tm_min = (int) minute;
4860 assert_se(s = mktime(&tm));
4862 *_u = (usec_t) s * USEC_PER_SEC;
4865 *_u += USEC_PER_DAY;
4871 static int shutdown_parse_argv(int argc, char *argv[]) {
4878 static const struct option options[] = {
4879 { "help", no_argument, NULL, ARG_HELP },
4880 { "halt", no_argument, NULL, 'H' },
4881 { "poweroff", no_argument, NULL, 'P' },
4882 { "reboot", no_argument, NULL, 'r' },
4883 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4884 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4885 { NULL, 0, NULL, 0 }
4893 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4901 arg_action = ACTION_HALT;
4905 arg_action = ACTION_POWEROFF;
4910 arg_action = ACTION_KEXEC;
4912 arg_action = ACTION_REBOOT;
4916 arg_action = ACTION_KEXEC;
4920 if (arg_action != ACTION_HALT)
4921 arg_action = ACTION_POWEROFF;
4934 /* Compatibility nops */
4938 arg_action = ACTION_CANCEL_SHUTDOWN;
4945 log_error("Unknown option code '%c'.", c);
4950 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4951 r = parse_time_spec(argv[optind], &arg_when);
4953 log_error("Failed to parse time specification: %s", argv[optind]);
4957 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4959 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4960 /* No time argument for shutdown cancel */
4961 arg_wall = argv + optind;
4962 else if (argc > optind + 1)
4963 /* We skip the time argument */
4964 arg_wall = argv + optind + 1;
4971 static int telinit_parse_argv(int argc, char *argv[]) {
4978 static const struct option options[] = {
4979 { "help", no_argument, NULL, ARG_HELP },
4980 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4981 { NULL, 0, NULL, 0 }
4984 static const struct {
4988 { '0', ACTION_POWEROFF },
4989 { '6', ACTION_REBOOT },
4990 { '1', ACTION_RESCUE },
4991 { '2', ACTION_RUNLEVEL2 },
4992 { '3', ACTION_RUNLEVEL3 },
4993 { '4', ACTION_RUNLEVEL4 },
4994 { '5', ACTION_RUNLEVEL5 },
4995 { 's', ACTION_RESCUE },
4996 { 'S', ACTION_RESCUE },
4997 { 'q', ACTION_RELOAD },
4998 { 'Q', ACTION_RELOAD },
4999 { 'u', ACTION_REEXEC },
5000 { 'U', ACTION_REEXEC }
5009 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5024 log_error("Unknown option code '%c'.", c);
5029 if (optind >= argc) {
5034 if (optind + 1 < argc) {
5035 log_error("Too many arguments.");
5039 if (strlen(argv[optind]) != 1) {
5040 log_error("Expected single character argument.");
5044 for (i = 0; i < ELEMENTSOF(table); i++)
5045 if (table[i].from == argv[optind][0])
5048 if (i >= ELEMENTSOF(table)) {
5049 log_error("Unknown command '%s'.", argv[optind]);
5053 arg_action = table[i].to;
5060 static int runlevel_parse_argv(int argc, char *argv[]) {
5066 static const struct option options[] = {
5067 { "help", no_argument, NULL, ARG_HELP },
5068 { NULL, 0, NULL, 0 }
5076 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5087 log_error("Unknown option code '%c'.", c);
5092 if (optind < argc) {
5093 log_error("Too many arguments.");
5100 static int parse_argv(int argc, char *argv[]) {
5104 if (program_invocation_short_name) {
5106 if (strstr(program_invocation_short_name, "halt")) {
5107 arg_action = ACTION_HALT;
5108 return halt_parse_argv(argc, argv);
5109 } else if (strstr(program_invocation_short_name, "poweroff")) {
5110 arg_action = ACTION_POWEROFF;
5111 return halt_parse_argv(argc, argv);
5112 } else if (strstr(program_invocation_short_name, "reboot")) {
5114 arg_action = ACTION_KEXEC;
5116 arg_action = ACTION_REBOOT;
5117 return halt_parse_argv(argc, argv);
5118 } else if (strstr(program_invocation_short_name, "shutdown")) {
5119 arg_action = ACTION_POWEROFF;
5120 return shutdown_parse_argv(argc, argv);
5121 } else if (strstr(program_invocation_short_name, "init")) {
5123 if (sd_booted() > 0) {
5124 arg_action = ACTION_INVALID;
5125 return telinit_parse_argv(argc, argv);
5127 /* Hmm, so some other init system is
5128 * running, we need to forward this
5129 * request to it. For now we simply
5130 * guess that it is Upstart. */
5132 execv("/lib/upstart/telinit", argv);
5134 log_error("Couldn't find an alternative telinit implementation to spawn.");
5138 } else if (strstr(program_invocation_short_name, "runlevel")) {
5139 arg_action = ACTION_RUNLEVEL;
5140 return runlevel_parse_argv(argc, argv);
5144 arg_action = ACTION_SYSTEMCTL;
5145 return systemctl_parse_argv(argc, argv);
5148 static int action_to_runlevel(void) {
5150 static const char table[_ACTION_MAX] = {
5151 [ACTION_HALT] = '0',
5152 [ACTION_POWEROFF] = '0',
5153 [ACTION_REBOOT] = '6',
5154 [ACTION_RUNLEVEL2] = '2',
5155 [ACTION_RUNLEVEL3] = '3',
5156 [ACTION_RUNLEVEL4] = '4',
5157 [ACTION_RUNLEVEL5] = '5',
5158 [ACTION_RESCUE] = '1'
5161 assert(arg_action < _ACTION_MAX);
5163 return table[arg_action];
5166 static int talk_upstart(void) {
5167 DBusMessage *m = NULL, *reply = NULL;
5169 int previous, rl, r;
5171 env1_buf[] = "RUNLEVEL=X",
5172 env2_buf[] = "PREVLEVEL=X";
5173 char *env1 = env1_buf, *env2 = env2_buf;
5174 const char *emit = "runlevel";
5175 dbus_bool_t b_false = FALSE;
5176 DBusMessageIter iter, sub;
5177 DBusConnection *bus;
5179 dbus_error_init(&error);
5181 if (!(rl = action_to_runlevel()))
5184 if (utmp_get_runlevel(&previous, NULL) < 0)
5187 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5188 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5193 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5198 if ((r = bus_check_peercred(bus)) < 0) {
5199 log_error("Failed to verify owner of bus.");
5203 if (!(m = dbus_message_new_method_call(
5204 "com.ubuntu.Upstart",
5205 "/com/ubuntu/Upstart",
5206 "com.ubuntu.Upstart0_6",
5209 log_error("Could not allocate message.");
5214 dbus_message_iter_init_append(m, &iter);
5216 env1_buf[sizeof(env1_buf)-2] = rl;
5217 env2_buf[sizeof(env2_buf)-2] = previous;
5219 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5220 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5221 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5222 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5223 !dbus_message_iter_close_container(&iter, &sub) ||
5224 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5225 log_error("Could not append arguments to message.");
5230 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5232 if (bus_error_is_no_service(&error)) {
5237 log_error("Failed to issue method call: %s", bus_error_message(&error));
5246 dbus_message_unref(m);
5249 dbus_message_unref(reply);
5252 dbus_connection_flush(bus);
5253 dbus_connection_close(bus);
5254 dbus_connection_unref(bus);
5257 dbus_error_free(&error);
5262 static int talk_initctl(void) {
5263 struct init_request request;
5267 if (!(rl = action_to_runlevel()))
5271 request.magic = INIT_MAGIC;
5272 request.sleeptime = 0;
5273 request.cmd = INIT_CMD_RUNLVL;
5274 request.runlevel = rl;
5276 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5278 if (errno == ENOENT)
5281 log_error("Failed to open "INIT_FIFO": %m");
5286 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5287 close_nointr_nofail(fd);
5290 log_error("Failed to write to "INIT_FIFO": %m");
5291 return errno ? -errno : -EIO;
5297 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5299 static const struct {
5307 int (* const dispatch)(DBusConnection *bus, char **args);
5309 { "list-units", LESS, 1, list_units },
5310 { "list-unit-files", EQUAL, 1, list_unit_files },
5311 { "list-jobs", EQUAL, 1, list_jobs },
5312 { "clear-jobs", EQUAL, 1, daemon_reload },
5313 { "load", MORE, 2, load_unit },
5314 { "cancel", MORE, 2, cancel_job },
5315 { "start", MORE, 2, start_unit },
5316 { "stop", MORE, 2, start_unit },
5317 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5318 { "reload", MORE, 2, start_unit },
5319 { "restart", MORE, 2, start_unit },
5320 { "try-restart", MORE, 2, start_unit },
5321 { "reload-or-restart", MORE, 2, start_unit },
5322 { "reload-or-try-restart", MORE, 2, start_unit },
5323 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5324 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5325 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5326 { "isolate", EQUAL, 2, start_unit },
5327 { "set-cgroup", MORE, 2, set_cgroup },
5328 { "unset-cgroup", MORE, 2, set_cgroup },
5329 { "get-cgroup-attr", MORE, 2, get_cgroup_attr },
5330 { "set-cgroup-attr", MORE, 2, set_cgroup_attr },
5331 { "unset-cgroup-attr", MORE, 2, set_cgroup },
5332 { "kill", MORE, 2, kill_unit },
5333 { "is-active", MORE, 2, check_unit_active },
5334 { "check", MORE, 2, check_unit_active },
5335 { "is-failed", MORE, 2, check_unit_failed },
5336 { "show", MORE, 1, show },
5337 { "status", MORE, 2, show },
5338 { "help", MORE, 2, show },
5339 { "dump", EQUAL, 1, dump },
5340 { "dot", EQUAL, 1, dot },
5341 { "snapshot", LESS, 2, snapshot },
5342 { "delete", MORE, 2, delete_snapshot },
5343 { "daemon-reload", EQUAL, 1, daemon_reload },
5344 { "daemon-reexec", EQUAL, 1, daemon_reload },
5345 { "show-environment", EQUAL, 1, show_enviroment },
5346 { "set-environment", MORE, 2, set_environment },
5347 { "unset-environment", MORE, 2, set_environment },
5348 { "halt", EQUAL, 1, start_special },
5349 { "poweroff", EQUAL, 1, start_special },
5350 { "reboot", EQUAL, 1, start_special },
5351 { "kexec", EQUAL, 1, start_special },
5352 { "suspend", EQUAL, 1, start_special },
5353 { "hibernate", EQUAL, 1, start_special },
5354 { "hybrid-sleep", EQUAL, 1, start_special },
5355 { "default", EQUAL, 1, start_special },
5356 { "rescue", EQUAL, 1, start_special },
5357 { "emergency", EQUAL, 1, start_special },
5358 { "exit", EQUAL, 1, start_special },
5359 { "reset-failed", MORE, 1, reset_failed },
5360 { "enable", MORE, 2, enable_unit },
5361 { "disable", MORE, 2, enable_unit },
5362 { "is-enabled", MORE, 2, unit_is_enabled },
5363 { "reenable", MORE, 2, enable_unit },
5364 { "preset", MORE, 2, enable_unit },
5365 { "mask", MORE, 2, enable_unit },
5366 { "unmask", MORE, 2, enable_unit },
5367 { "link", MORE, 2, enable_unit },
5368 { "switch-root", MORE, 2, switch_root },
5369 { "list-dependencies", LESS, 2, list_dependencies },
5379 left = argc - optind;
5382 /* Special rule: no arguments means "list-units" */
5385 if (streq(argv[optind], "help") && !argv[optind+1]) {
5386 log_error("This command expects one or more "
5387 "unit names. Did you mean --help?");
5391 for (i = 0; i < ELEMENTSOF(verbs); i++)
5392 if (streq(argv[optind], verbs[i].verb))
5395 if (i >= ELEMENTSOF(verbs)) {
5396 log_error("Unknown operation '%s'.", argv[optind]);
5401 switch (verbs[i].argc_cmp) {
5404 if (left != verbs[i].argc) {
5405 log_error("Invalid number of arguments.");
5412 if (left < verbs[i].argc) {
5413 log_error("Too few arguments.");
5420 if (left > verbs[i].argc) {
5421 log_error("Too many arguments.");
5428 assert_not_reached("Unknown comparison operator.");
5431 /* Require a bus connection for all operations but
5433 if (!streq(verbs[i].verb, "enable") &&
5434 !streq(verbs[i].verb, "disable") &&
5435 !streq(verbs[i].verb, "is-enabled") &&
5436 !streq(verbs[i].verb, "list-unit-files") &&
5437 !streq(verbs[i].verb, "reenable") &&
5438 !streq(verbs[i].verb, "preset") &&
5439 !streq(verbs[i].verb, "mask") &&
5440 !streq(verbs[i].verb, "unmask") &&
5441 !streq(verbs[i].verb, "link")) {
5443 if (running_in_chroot() > 0) {
5444 log_info("Running in chroot, ignoring request.");
5448 if (((!streq(verbs[i].verb, "reboot") &&
5449 !streq(verbs[i].verb, "halt") &&
5450 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5451 log_error("Failed to get D-Bus connection: %s",
5452 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5458 if (!bus && !avoid_bus()) {
5459 log_error("Failed to get D-Bus connection: %s",
5460 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5465 return verbs[i].dispatch(bus, argv + optind);
5468 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5470 struct msghdr msghdr;
5471 struct iovec iovec[2];
5472 union sockaddr_union sockaddr;
5473 struct sd_shutdown_command c;
5475 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5482 c.dry_run = dry_run;
5486 sockaddr.sa.sa_family = AF_UNIX;
5487 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5490 msghdr.msg_name = &sockaddr;
5491 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5494 iovec[0].iov_base = (char*) &c;
5495 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5497 if (isempty(message))
5498 msghdr.msg_iovlen = 1;
5500 iovec[1].iov_base = (char*) message;
5501 iovec[1].iov_len = strlen(message);
5502 msghdr.msg_iovlen = 2;
5504 msghdr.msg_iov = iovec;
5506 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5507 close_nointr_nofail(fd);
5511 close_nointr_nofail(fd);
5515 static int reload_with_fallback(DBusConnection *bus) {
5518 /* First, try systemd via D-Bus. */
5519 if (daemon_reload(bus, NULL) >= 0)
5523 /* Nothing else worked, so let's try signals */
5524 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5526 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5527 log_error("kill() failed: %m");
5534 static int start_with_fallback(DBusConnection *bus) {
5537 /* First, try systemd via D-Bus. */
5538 if (start_unit(bus, NULL) >= 0)
5542 /* Hmm, talking to systemd via D-Bus didn't work. Then
5543 * let's try to talk to Upstart via D-Bus. */
5544 if (talk_upstart() > 0)
5547 /* Nothing else worked, so let's try
5549 if (talk_initctl() > 0)
5552 log_error("Failed to talk to init daemon.");
5556 warn_wall(arg_action);
5560 static _noreturn_ void halt_now(enum action a) {
5562 /* Make sure C-A-D is handled by the kernel from this
5564 reboot(RB_ENABLE_CAD);
5569 log_info("Halting.");
5570 reboot(RB_HALT_SYSTEM);
5573 case ACTION_POWEROFF:
5574 log_info("Powering off.");
5575 reboot(RB_POWER_OFF);
5579 log_info("Rebooting.");
5580 reboot(RB_AUTOBOOT);
5584 assert_not_reached("Unknown halt action.");
5587 assert_not_reached("Uh? This shouldn't happen.");
5590 static int halt_main(DBusConnection *bus) {
5593 r = check_inhibitors(bus, arg_action);
5597 if (geteuid() != 0) {
5598 /* Try logind if we are a normal user and no special
5599 * mode applies. Maybe PolicyKit allows us to shutdown
5602 if (arg_when <= 0 &&
5605 (arg_action == ACTION_POWEROFF ||
5606 arg_action == ACTION_REBOOT)) {
5607 r = reboot_with_logind(bus, arg_action);
5612 log_error("Must be root.");
5619 m = strv_join(arg_wall, " ");
5620 r = send_shutdownd(arg_when,
5621 arg_action == ACTION_HALT ? 'H' :
5622 arg_action == ACTION_POWEROFF ? 'P' :
5623 arg_action == ACTION_KEXEC ? 'K' :
5631 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5633 char date[FORMAT_TIMESTAMP_MAX];
5635 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5636 format_timestamp(date, sizeof(date), arg_when));
5641 if (!arg_dry && !arg_force)
5642 return start_with_fallback(bus);
5645 if (sd_booted() > 0)
5646 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5648 r = utmp_put_shutdown();
5650 log_warning("Failed to write utmp record: %s", strerror(-r));
5657 halt_now(arg_action);
5658 /* We should never reach this. */
5662 static int runlevel_main(void) {
5663 int r, runlevel, previous;
5665 r = utmp_get_runlevel(&runlevel, &previous);
5672 previous <= 0 ? 'N' : previous,
5673 runlevel <= 0 ? 'N' : runlevel);
5678 int main(int argc, char*argv[]) {
5679 int r, retval = EXIT_FAILURE;
5680 DBusConnection *bus = NULL;
5683 dbus_error_init(&error);
5685 setlocale(LC_ALL, "");
5686 log_parse_environment();
5689 r = parse_argv(argc, argv);
5693 retval = EXIT_SUCCESS;
5697 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5698 * let's shortcut this */
5699 if (arg_action == ACTION_RUNLEVEL) {
5700 r = runlevel_main();
5701 retval = r < 0 ? EXIT_FAILURE : r;
5705 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5706 log_info("Running in chroot, ignoring request.");
5712 if (arg_transport == TRANSPORT_NORMAL)
5713 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5714 else if (arg_transport == TRANSPORT_POLKIT) {
5715 bus_connect_system_polkit(&bus, &error);
5716 private_bus = false;
5717 } else if (arg_transport == TRANSPORT_SSH) {
5718 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5719 private_bus = false;
5721 assert_not_reached("Uh, invalid transport...");
5724 switch (arg_action) {
5726 case ACTION_SYSTEMCTL:
5727 r = systemctl_main(bus, argc, argv, &error);
5731 case ACTION_POWEROFF:
5737 case ACTION_RUNLEVEL2:
5738 case ACTION_RUNLEVEL3:
5739 case ACTION_RUNLEVEL4:
5740 case ACTION_RUNLEVEL5:
5742 case ACTION_EMERGENCY:
5743 case ACTION_DEFAULT:
5744 r = start_with_fallback(bus);
5749 r = reload_with_fallback(bus);
5752 case ACTION_CANCEL_SHUTDOWN: {
5756 m = strv_join(arg_wall, " ");
5758 retval = EXIT_FAILURE;
5762 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5764 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5769 case ACTION_INVALID:
5770 case ACTION_RUNLEVEL:
5772 assert_not_reached("Unknown action");
5775 retval = r < 0 ? EXIT_FAILURE : r;
5779 dbus_connection_flush(bus);
5780 dbus_connection_close(bus);
5781 dbus_connection_unref(bus);
5784 dbus_error_free(&error);
5788 strv_free(arg_property);
5791 ask_password_agent_close();
5792 polkit_agent_close();