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)
280 const char *description;
281 const char *load_state;
282 const char *active_state;
283 const char *sub_state;
284 const char *following;
285 const char *unit_path;
287 const char *job_type;
288 const char *job_path;
291 static int compare_unit_info(const void *a, const void *b) {
293 const struct unit_info *u = a, *v = b;
295 d1 = strrchr(u->id, '.');
296 d2 = strrchr(v->id, '.');
301 r = strcasecmp(d1, d2);
306 return strcasecmp(u->id, v->id);
309 static bool output_show_unit(const struct unit_info *u) {
313 return streq(u->active_state, "failed");
315 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
316 streq(dot+1, arg_type))) &&
317 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
318 (arg_all || !(streq(u->active_state, "inactive")
319 || u->following[0]) || u->job_id > 0);
322 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
323 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
324 const struct unit_info *u;
327 max_id_len = sizeof("UNIT")-1;
328 active_len = sizeof("ACTIVE")-1;
329 sub_len = sizeof("SUB")-1;
330 job_len = sizeof("JOB")-1;
333 for (u = unit_infos; u < unit_infos + c; u++) {
334 if (!output_show_unit(u))
337 max_id_len = MAX(max_id_len, strlen(u->id));
338 active_len = MAX(active_len, strlen(u->active_state));
339 sub_len = MAX(sub_len, strlen(u->sub_state));
340 if (u->job_id != 0) {
341 job_len = MAX(job_len, strlen(u->job_type));
348 id_len = MIN(max_id_len, 25);
349 basic_len = 5 + id_len + 5 + active_len + sub_len;
351 basic_len += job_len + 1;
352 if (basic_len < (unsigned) columns()) {
353 unsigned extra_len, incr;
354 extra_len = columns() - basic_len;
355 /* Either UNIT already got 25, or is fully satisfied.
356 * Grant up to 25 to DESC now. */
357 incr = MIN(extra_len, 25);
360 /* split the remaining space between UNIT and DESC,
361 * but do not give UNIT more than it needs. */
363 incr = MIN(extra_len / 2, max_id_len - id_len);
365 desc_len += extra_len - incr;
371 for (u = unit_infos; u < unit_infos + c; u++) {
373 const char *on_loaded, *off_loaded;
374 const char *on_active, *off_active;
376 if (!output_show_unit(u))
379 if (!n_shown && !arg_no_legend) {
380 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
381 active_len, "ACTIVE", sub_len, "SUB");
383 printf("%-*s ", job_len, "JOB");
384 if (!arg_full && arg_no_pager)
385 printf("%.*s\n", desc_len, "DESCRIPTION");
387 printf("%s\n", "DESCRIPTION");
392 if (streq(u->load_state, "error")) {
393 on_loaded = ansi_highlight_red(true);
394 off_loaded = ansi_highlight_red(false);
396 on_loaded = off_loaded = "";
398 if (streq(u->active_state, "failed")) {
399 on_active = ansi_highlight_red(true);
400 off_active = ansi_highlight_red(false);
402 on_active = off_active = "";
404 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
406 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s",
407 id_len, e ? e : u->id,
408 on_loaded, u->load_state, off_loaded,
409 on_active, active_len, u->active_state,
410 sub_len, u->sub_state, off_active,
411 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
412 if (!arg_full && arg_no_pager)
413 printf("%.*s\n", desc_len, u->description);
415 printf("%s\n", u->description);
420 if (!arg_no_legend) {
421 const char *on, *off;
424 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
425 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
426 "SUB = The low-level unit activation state, values depend on unit type.\n");
428 printf("JOB = Pending job for the unit.\n");
430 on = ansi_highlight(true);
431 off = ansi_highlight(false);
433 on = ansi_highlight_red(true);
434 off = ansi_highlight_red(false);
438 printf("%s%u loaded units listed.%s\n"
439 "To show all installed unit files use 'systemctl list-unit-files'.\n",
442 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
443 "To show all installed unit files use 'systemctl list-unit-files'.\n",
448 static int list_units(DBusConnection *bus, char **args) {
449 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
450 _cleanup_free_ struct unit_info *unit_infos = NULL;
451 DBusMessageIter iter, sub, sub2;
452 unsigned c = 0, n_units = 0;
455 pager_open_if_enabled();
457 r = bus_method_call_with_reply(
459 "org.freedesktop.systemd1",
460 "/org/freedesktop/systemd1",
461 "org.freedesktop.systemd1.Manager",
469 if (!dbus_message_iter_init(reply, &iter) ||
470 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
471 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
472 log_error("Failed to parse reply.");
476 dbus_message_iter_recurse(&iter, &sub);
478 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
481 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
486 n_units = MAX(2*c, 16);
487 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
496 dbus_message_iter_recurse(&sub, &sub2);
498 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
499 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
500 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
501 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
502 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
503 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
504 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
505 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
506 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
507 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
508 log_error("Failed to parse reply.");
512 dbus_message_iter_next(&sub);
517 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
518 output_units_list(unit_infos, c);
524 static int compare_unit_file_list(const void *a, const void *b) {
526 const UnitFileList *u = a, *v = b;
528 d1 = strrchr(u->path, '.');
529 d2 = strrchr(v->path, '.');
534 r = strcasecmp(d1, d2);
539 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
542 static bool output_show_unit_file(const UnitFileList *u) {
545 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
548 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
549 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
550 const UnitFileList *u;
552 max_id_len = sizeof("UNIT FILE")-1;
553 state_cols = sizeof("STATE")-1;
554 for (u = units; u < units + c; u++) {
555 if (!output_show_unit_file(u))
558 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
559 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
564 id_cols = MIN(max_id_len, 25);
565 basic_cols = 1 + id_cols + state_cols;
566 if (basic_cols < (unsigned) columns())
567 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
569 id_cols = max_id_len;
572 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
574 for (u = units; u < units + c; u++) {
576 const char *on, *off;
579 if (!output_show_unit_file(u))
584 if (u->state == UNIT_FILE_MASKED ||
585 u->state == UNIT_FILE_MASKED_RUNTIME ||
586 u->state == UNIT_FILE_DISABLED ||
587 u->state == UNIT_FILE_INVALID) {
588 on = ansi_highlight_red(true);
589 off = ansi_highlight_red(false);
590 } else if (u->state == UNIT_FILE_ENABLED) {
591 on = ansi_highlight_green(true);
592 off = ansi_highlight_green(false);
596 id = path_get_file_name(u->path);
598 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
600 printf("%-*s %s%-*s%s\n",
602 on, state_cols, unit_file_state_to_string(u->state), off);
608 printf("\n%u unit files listed.\n", n_shown);
611 static int list_unit_files(DBusConnection *bus, char **args) {
612 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
613 _cleanup_free_ UnitFileList *units = NULL;
614 DBusMessageIter iter, sub, sub2;
615 unsigned c = 0, n_units = 0;
618 pager_open_if_enabled();
625 h = hashmap_new(string_hash_func, string_compare_func);
629 r = unit_file_get_list(arg_scope, arg_root, h);
631 unit_file_list_free(h);
632 log_error("Failed to get unit file list: %s", strerror(-r));
636 n_units = hashmap_size(h);
637 units = new(UnitFileList, n_units);
639 unit_file_list_free(h);
643 HASHMAP_FOREACH(u, h, i) {
644 memcpy(units + c++, u, sizeof(UnitFileList));
650 r = bus_method_call_with_reply(
652 "org.freedesktop.systemd1",
653 "/org/freedesktop/systemd1",
654 "org.freedesktop.systemd1.Manager",
662 if (!dbus_message_iter_init(reply, &iter) ||
663 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
664 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
665 log_error("Failed to parse reply.");
669 dbus_message_iter_recurse(&iter, &sub);
671 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
675 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
680 n_units = MAX(2*c, 16);
681 w = realloc(units, sizeof(struct UnitFileList) * n_units);
690 dbus_message_iter_recurse(&sub, &sub2);
692 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
693 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
694 log_error("Failed to parse reply.");
698 u->state = unit_file_state_from_string(state);
700 dbus_message_iter_next(&sub);
706 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
707 output_unit_file_list(units, c);
713 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
715 _cleanup_free_ char *n = NULL;
717 size_t max_len = MAX(columns(),20);
719 for (i = level - 1; i >= 0; i--) {
721 if(len > max_len - 3 && !arg_full) {
722 printf("%s...\n",max_len % 2 ? "" : " ");
725 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
728 if(len > max_len - 3 && !arg_full) {
729 printf("%s...\n",max_len % 2 ? "" : " ");
732 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
735 printf("%s\n", name);
739 n = ellipsize(name, max_len-len, 100);
747 static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
748 static const char dependencies[] =
750 "RequiresOverridable\0"
752 "RequisiteOverridable\0"
755 _cleanup_free_ char *path;
756 const char *interface = "org.freedesktop.systemd1.Unit";
758 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
759 DBusMessageIter iter, sub, sub2, sub3;
769 path = unit_dbus_path_from_name(name);
775 r = bus_method_call_with_reply(
777 "org.freedesktop.systemd1",
779 "org.freedesktop.DBus.Properties",
783 DBUS_TYPE_STRING, &interface,
788 if (!dbus_message_iter_init(reply, &iter) ||
789 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
790 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
791 log_error("Failed to parse reply.");
796 dbus_message_iter_recurse(&iter, &sub);
798 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
801 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
802 log_error("Failed to parse reply.");
807 dbus_message_iter_recurse(&sub, &sub2);
809 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
810 log_error("Failed to parse reply.");
815 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
816 log_error("Failed to parse reply.");
821 dbus_message_iter_recurse(&sub2, &sub3);
822 dbus_message_iter_next(&sub);
824 if (!nulstr_contains(dependencies, prop))
827 if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
828 if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
829 DBusMessageIter sub4;
830 dbus_message_iter_recurse(&sub3, &sub4);
832 while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
835 assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
836 dbus_message_iter_get_basic(&sub4, &s);
837 c = strv_append(ret, s);
844 dbus_message_iter_next(&sub4);
856 static int list_dependencies_compare(const void *_a, const void *_b) {
857 const char **a = (const char**) _a, **b = (const char**) _b;
858 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
860 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
862 return strcasecmp(*a, *b);
865 static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char **units, unsigned int branches) {
871 u = strv_append(units, name);
875 r = list_dependencies_get_dependencies(bus, name, &deps);
879 qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
881 STRV_FOREACH(c, deps) {
882 if (strv_contains(u, *c)) {
883 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
889 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
893 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
894 r = list_dependencies_one(bus, *c, level + 1, u, (branches << 1) | (c[1] == NULL ? 0 : 1));
907 static int list_dependencies(DBusConnection *bus, char **args) {
909 _cleanup_free_ char *unit = NULL;
914 unit = unit_name_mangle(args[1]);
918 pager_open_if_enabled();
919 printf("%s\n", unit);
920 r = list_dependencies_one(bus, unit, 0, NULL, 0);
924 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
926 static const char * const colors[] = {
927 "Requires", "[color=\"black\"]",
928 "RequiresOverridable", "[color=\"black\"]",
929 "Requisite", "[color=\"darkblue\"]",
930 "RequisiteOverridable", "[color=\"darkblue\"]",
931 "Wants", "[color=\"grey66\"]",
932 "Conflicts", "[color=\"red\"]",
933 "ConflictedBy", "[color=\"red\"]",
934 "After", "[color=\"green\"]"
937 const char *c = NULL;
944 for (i = 0; i < ELEMENTSOF(colors); i += 2)
945 if (streq(colors[i], prop)) {
953 if (arg_dot != DOT_ALL)
954 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
957 switch (dbus_message_iter_get_arg_type(iter)) {
959 case DBUS_TYPE_ARRAY:
961 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
964 dbus_message_iter_recurse(iter, &sub);
966 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
969 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
970 dbus_message_iter_get_basic(&sub, &s);
971 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
973 dbus_message_iter_next(&sub);
983 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
984 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
985 const char *interface = "org.freedesktop.systemd1.Unit";
987 DBusMessageIter iter, sub, sub2, sub3;
992 r = bus_method_call_with_reply(
994 "org.freedesktop.systemd1",
996 "org.freedesktop.DBus.Properties",
1000 DBUS_TYPE_STRING, &interface,
1005 if (!dbus_message_iter_init(reply, &iter) ||
1006 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1007 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
1008 log_error("Failed to parse reply.");
1012 dbus_message_iter_recurse(&iter, &sub);
1014 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1017 assert(dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY);
1018 dbus_message_iter_recurse(&sub, &sub2);
1020 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0 ||
1021 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
1022 log_error("Failed to parse reply.");
1026 dbus_message_iter_recurse(&sub2, &sub3);
1027 r = dot_one_property(name, prop, &sub3);
1031 dbus_message_iter_next(&sub);
1037 static int dot(DBusConnection *bus, char **args) {
1038 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1039 DBusMessageIter iter, sub, sub2;
1042 r = bus_method_call_with_reply(
1044 "org.freedesktop.systemd1",
1045 "/org/freedesktop/systemd1",
1046 "org.freedesktop.systemd1.Manager",
1054 if (!dbus_message_iter_init(reply, &iter) ||
1055 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1056 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1057 log_error("Failed to parse reply.");
1061 printf("digraph systemd {\n");
1063 dbus_message_iter_recurse(&iter, &sub);
1064 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1065 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
1067 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1068 log_error("Failed to parse reply.");
1072 dbus_message_iter_recurse(&sub, &sub2);
1074 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
1075 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
1076 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
1077 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
1078 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
1079 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
1080 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
1081 log_error("Failed to parse reply.");
1085 r = dot_one(bus, id, unit_path);
1089 /* printf("\t\"%s\";\n", id); */
1090 dbus_message_iter_next(&sub);
1095 log_info(" Color legend: black = Requires\n"
1096 " dark blue = Requisite\n"
1097 " dark grey = Wants\n"
1098 " red = Conflicts\n"
1099 " green = After\n");
1102 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
1103 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
1108 static int list_jobs(DBusConnection *bus, char **args) {
1109 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1110 DBusMessageIter iter, sub, sub2;
1114 pager_open_if_enabled();
1116 r = bus_method_call_with_reply(
1118 "org.freedesktop.systemd1",
1119 "/org/freedesktop/systemd1",
1120 "org.freedesktop.systemd1.Manager",
1128 if (!dbus_message_iter_init(reply, &iter) ||
1129 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1130 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1131 log_error("Failed to parse reply.");
1135 dbus_message_iter_recurse(&iter, &sub);
1138 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
1140 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1141 const char *name, *type, *state, *job_path, *unit_path;
1145 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1146 log_error("Failed to parse reply.");
1150 dbus_message_iter_recurse(&sub, &sub2);
1152 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1153 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1154 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1155 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1156 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1157 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1158 log_error("Failed to parse reply.");
1162 e = arg_full ? NULL : ellipsize(name, 25, 33);
1163 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1168 dbus_message_iter_next(&sub);
1172 printf("\n%u jobs listed.\n", k);
1177 static int load_unit(DBusConnection *bus, char **args) {
1182 STRV_FOREACH(name, args+1) {
1183 _cleanup_free_ char *n = NULL;
1186 n = unit_name_mangle(*name);
1190 r = bus_method_call_with_reply(
1192 "org.freedesktop.systemd1",
1193 "/org/freedesktop/systemd1",
1194 "org.freedesktop.systemd1.Manager",
1198 DBUS_TYPE_STRING, &n,
1207 static int cancel_job(DBusConnection *bus, char **args) {
1212 if (strv_length(args) <= 1)
1213 return daemon_reload(bus, args);
1215 STRV_FOREACH(name, args+1) {
1219 r = safe_atou32(*name, &id);
1221 log_error("Failed to parse job id: %s", strerror(-r));
1225 r = bus_method_call_with_reply(
1227 "org.freedesktop.systemd1",
1228 "/org/freedesktop/systemd1",
1229 "org.freedesktop.systemd1.Manager",
1233 DBUS_TYPE_UINT32, &id,
1242 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1243 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1244 dbus_bool_t b = FALSE;
1245 DBusMessageIter iter, sub;
1247 *interface = "org.freedesktop.systemd1.Unit",
1248 *property = "NeedDaemonReload",
1250 _cleanup_free_ char *n = NULL;
1253 /* We ignore all errors here, since this is used to show a warning only */
1255 n = unit_name_mangle(unit);
1259 r = bus_method_call_with_reply (
1261 "org.freedesktop.systemd1",
1262 "/org/freedesktop/systemd1",
1263 "org.freedesktop.systemd1.Manager",
1267 DBUS_TYPE_STRING, &n,
1272 if (!dbus_message_get_args(reply, NULL,
1273 DBUS_TYPE_OBJECT_PATH, &path,
1277 dbus_message_unref(reply);
1280 r = bus_method_call_with_reply(
1282 "org.freedesktop.systemd1",
1284 "org.freedesktop.DBus.Properties",
1288 DBUS_TYPE_STRING, &interface,
1289 DBUS_TYPE_STRING, &property,
1294 if (!dbus_message_iter_init(reply, &iter) ||
1295 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1298 dbus_message_iter_recurse(&iter, &sub);
1299 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1302 dbus_message_iter_get_basic(&sub, &b);
1306 typedef struct WaitData {
1313 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1321 dbus_error_init(&error);
1323 log_debug("Got D-Bus request: %s.%s() on %s",
1324 dbus_message_get_interface(message),
1325 dbus_message_get_member(message),
1326 dbus_message_get_path(message));
1328 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1329 log_error("Warning! D-Bus connection terminated.");
1330 dbus_connection_close(connection);
1332 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1334 const char *path, *result, *unit;
1336 if (dbus_message_get_args(message, &error,
1337 DBUS_TYPE_UINT32, &id,
1338 DBUS_TYPE_OBJECT_PATH, &path,
1339 DBUS_TYPE_STRING, &unit,
1340 DBUS_TYPE_STRING, &result,
1341 DBUS_TYPE_INVALID)) {
1343 free(set_remove(d->set, (char*) path));
1345 if (!isempty(result))
1346 d->result = strdup(result);
1349 d->name = strdup(unit);
1354 dbus_error_free(&error);
1355 if (dbus_message_get_args(message, &error,
1356 DBUS_TYPE_UINT32, &id,
1357 DBUS_TYPE_OBJECT_PATH, &path,
1358 DBUS_TYPE_STRING, &result,
1359 DBUS_TYPE_INVALID)) {
1360 /* Compatibility with older systemd versions <
1361 * 183 during upgrades. This should be dropped
1363 free(set_remove(d->set, (char*) path));
1366 d->result = strdup(result);
1372 log_error("Failed to parse message: %s", bus_error_message(&error));
1376 dbus_error_free(&error);
1377 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1380 static int enable_wait_for_jobs(DBusConnection *bus) {
1388 dbus_error_init(&error);
1389 dbus_bus_add_match(bus,
1391 "sender='org.freedesktop.systemd1',"
1392 "interface='org.freedesktop.systemd1.Manager',"
1393 "member='JobRemoved',"
1394 "path='/org/freedesktop/systemd1'",
1397 if (dbus_error_is_set(&error)) {
1398 log_error("Failed to add match: %s", bus_error_message(&error));
1399 dbus_error_free(&error);
1403 /* This is slightly dirty, since we don't undo the match registrations. */
1407 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1417 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1420 while (!set_isempty(s)) {
1422 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1423 log_error("Disconnected from bus.");
1424 return -ECONNREFUSED;
1431 if (streq(d.result, "timeout"))
1432 log_error("Job for %s timed out.", strna(d.name));
1433 else if (streq(d.result, "canceled"))
1434 log_error("Job for %s canceled.", strna(d.name));
1435 else if (streq(d.result, "dependency"))
1436 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1437 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1438 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1441 if (streq_ptr(d.result, "timeout"))
1443 else if (streq_ptr(d.result, "canceled"))
1445 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1456 dbus_connection_remove_filter(bus, wait_filter, &d);
1460 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1461 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1462 _cleanup_free_ char *n = NULL;
1463 DBusMessageIter iter, sub;
1465 *interface = "org.freedesktop.systemd1.Unit",
1466 *property = "ActiveState";
1467 const char *state, *path;
1473 dbus_error_init(&error);
1475 n = unit_name_mangle(name);
1479 r = bus_method_call_with_reply (
1481 "org.freedesktop.systemd1",
1482 "/org/freedesktop/systemd1",
1483 "org.freedesktop.systemd1.Manager",
1487 DBUS_TYPE_STRING, &n,
1490 dbus_error_free(&error);
1497 if (!dbus_message_get_args(reply, NULL,
1498 DBUS_TYPE_OBJECT_PATH, &path,
1499 DBUS_TYPE_INVALID)) {
1500 log_error("Failed to parse reply.");
1504 dbus_message_unref(reply);
1507 r = bus_method_call_with_reply(
1509 "org.freedesktop.systemd1",
1511 "org.freedesktop.DBus.Properties",
1515 DBUS_TYPE_STRING, &interface,
1516 DBUS_TYPE_STRING, &property,
1524 if (!dbus_message_iter_init(reply, &iter) ||
1525 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1526 log_error("Failed to parse reply.");
1530 dbus_message_iter_recurse(&iter, &sub);
1532 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1533 log_error("Failed to parse reply.");
1537 dbus_message_iter_get_basic(&sub, &state);
1542 return strv_find(check_states, state) ? 1 : 0;
1545 static void check_triggering_units(
1546 DBusConnection *bus,
1547 const char *unit_name) {
1549 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1550 DBusMessageIter iter, sub;
1551 const char *interface = "org.freedesktop.systemd1.Unit",
1552 *triggered_by_property = "TriggeredBy";
1553 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1554 bool print_warning_label = true;
1557 n = unit_name_mangle(unit_name);
1563 unit_path = unit_dbus_path_from_name(n);
1569 r = bus_method_call_with_reply(
1571 "org.freedesktop.systemd1",
1573 "org.freedesktop.DBus.Properties",
1577 DBUS_TYPE_STRING, &interface,
1578 DBUS_TYPE_STRING, &triggered_by_property,
1583 if (!dbus_message_iter_init(reply, &iter) ||
1584 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1585 log_error("Failed to parse reply.");
1589 dbus_message_iter_recurse(&iter, &sub);
1590 dbus_message_iter_recurse(&sub, &iter);
1593 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1594 const char * const check_states[] = {
1599 const char *service_trigger;
1601 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1602 log_error("Failed to parse reply.");
1606 dbus_message_iter_get_basic(&sub, &service_trigger);
1608 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1612 if (print_warning_label) {
1613 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1614 print_warning_label = false;
1617 log_warning(" %s", service_trigger);
1620 dbus_message_iter_next(&sub);
1624 static int start_unit_one(
1625 DBusConnection *bus,
1632 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1633 _cleanup_free_ char *n;
1642 n = unit_name_mangle(name);
1646 r = bus_method_call_with_reply(
1648 "org.freedesktop.systemd1",
1649 "/org/freedesktop/systemd1",
1650 "org.freedesktop.systemd1.Manager",
1654 DBUS_TYPE_STRING, &n,
1655 DBUS_TYPE_STRING, &mode,
1658 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1659 /* There's always a fallback possible for
1660 * legacy actions. */
1663 log_error("Failed to issue method call: %s", bus_error_message(error));
1668 if (!dbus_message_get_args(reply, error,
1669 DBUS_TYPE_OBJECT_PATH, &path,
1670 DBUS_TYPE_INVALID)) {
1671 log_error("Failed to parse reply: %s", bus_error_message(error));
1675 if (need_daemon_reload(bus, n))
1676 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1677 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1689 log_error("Failed to add path to set.");
1697 static enum action verb_to_action(const char *verb) {
1698 if (streq(verb, "halt"))
1700 else if (streq(verb, "poweroff"))
1701 return ACTION_POWEROFF;
1702 else if (streq(verb, "reboot"))
1703 return ACTION_REBOOT;
1704 else if (streq(verb, "kexec"))
1705 return ACTION_KEXEC;
1706 else if (streq(verb, "rescue"))
1707 return ACTION_RESCUE;
1708 else if (streq(verb, "emergency"))
1709 return ACTION_EMERGENCY;
1710 else if (streq(verb, "default"))
1711 return ACTION_DEFAULT;
1712 else if (streq(verb, "exit"))
1714 else if (streq(verb, "suspend"))
1715 return ACTION_SUSPEND;
1716 else if (streq(verb, "hibernate"))
1717 return ACTION_HIBERNATE;
1718 else if (streq(verb, "hybrid-sleep"))
1719 return ACTION_HYBRID_SLEEP;
1721 return ACTION_INVALID;
1724 static int start_unit(DBusConnection *bus, char **args) {
1726 static const char * const table[_ACTION_MAX] = {
1727 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1728 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1729 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1730 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1731 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1732 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1733 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1734 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1735 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1736 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1737 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1738 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1739 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1740 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
1741 [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
1745 const char *method, *mode, *one_name;
1750 dbus_error_init(&error);
1754 ask_password_agent_open_if_enabled();
1756 if (arg_action == ACTION_SYSTEMCTL) {
1758 streq(args[0], "stop") ||
1759 streq(args[0], "condstop") ? "StopUnit" :
1760 streq(args[0], "reload") ? "ReloadUnit" :
1761 streq(args[0], "restart") ? "RestartUnit" :
1763 streq(args[0], "try-restart") ||
1764 streq(args[0], "condrestart") ? "TryRestartUnit" :
1766 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1768 streq(args[0], "reload-or-try-restart") ||
1769 streq(args[0], "condreload") ||
1771 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1775 (streq(args[0], "isolate") ||
1776 streq(args[0], "rescue") ||
1777 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1779 one_name = table[verb_to_action(args[0])];
1782 assert(arg_action < ELEMENTSOF(table));
1783 assert(table[arg_action]);
1785 method = "StartUnit";
1787 mode = (arg_action == ACTION_EMERGENCY ||
1788 arg_action == ACTION_RESCUE ||
1789 arg_action == ACTION_RUNLEVEL2 ||
1790 arg_action == ACTION_RUNLEVEL3 ||
1791 arg_action == ACTION_RUNLEVEL4 ||
1792 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1794 one_name = table[arg_action];
1797 if (!arg_no_block) {
1798 ret = enable_wait_for_jobs(bus);
1800 log_error("Could not watch jobs: %s", strerror(-ret));
1804 s = set_new(string_hash_func, string_compare_func);
1812 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1814 ret = translate_bus_error_to_exit_status(ret, &error);
1816 STRV_FOREACH(name, args+1) {
1817 r = start_unit_one(bus, method, *name, mode, &error, s);
1819 ret = translate_bus_error_to_exit_status(r, &error);
1820 dbus_error_free(&error);
1825 if (!arg_no_block) {
1826 r = wait_for_jobs(bus, s);
1832 /* When stopping units, warn if they can still be triggered by
1833 * another active unit (socket, path, timer) */
1834 if (!arg_quiet && streq(method, "StopUnit")) {
1836 check_triggering_units(bus, one_name);
1838 STRV_FOREACH(name, args+1)
1839 check_triggering_units(bus, *name);
1845 dbus_error_free(&error);
1850 /* Ask systemd-logind, which might grant access to unprivileged users
1851 * through PolicyKit */
1852 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1855 dbus_bool_t interactive = true;
1860 polkit_agent_open_if_enabled();
1868 case ACTION_POWEROFF:
1869 method = "PowerOff";
1872 case ACTION_SUSPEND:
1876 case ACTION_HIBERNATE:
1877 method = "Hibernate";
1880 case ACTION_HYBRID_SLEEP:
1881 method = "HybridSleep";
1888 return bus_method_call_with_reply(
1890 "org.freedesktop.login1",
1891 "/org/freedesktop/login1",
1892 "org.freedesktop.login1.Manager",
1896 DBUS_TYPE_BOOLEAN, &interactive,
1903 static int check_inhibitors(DBusConnection *bus, enum action a) {
1905 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1906 DBusMessageIter iter, sub, sub2;
1909 _cleanup_strv_free_ char **sessions = NULL;
1915 if (arg_ignore_inhibitors || arg_force > 0)
1927 r = bus_method_call_with_reply(
1929 "org.freedesktop.login1",
1930 "/org/freedesktop/login1",
1931 "org.freedesktop.login1.Manager",
1937 /* If logind is not around, then there are no inhibitors... */
1940 if (!dbus_message_iter_init(reply, &iter) ||
1941 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1942 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1943 log_error("Failed to parse reply.");
1947 dbus_message_iter_recurse(&iter, &sub);
1948 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1949 const char *what, *who, *why, *mode;
1951 _cleanup_strv_free_ char **sv = NULL;
1952 _cleanup_free_ char *comm = NULL, *user = NULL;
1954 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1955 log_error("Failed to parse reply.");
1959 dbus_message_iter_recurse(&sub, &sub2);
1961 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
1962 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
1963 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
1964 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
1965 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
1966 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
1967 log_error("Failed to parse reply.");
1971 if (!streq(mode, "block"))
1974 sv = strv_split(what, ":");
1978 if (!strv_contains(sv,
1980 a == ACTION_POWEROFF ||
1981 a == ACTION_REBOOT ||
1982 a == ACTION_KEXEC ? "shutdown" : "sleep"))
1985 get_process_comm(pid, &comm);
1986 user = uid_to_name(uid);
1987 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
1988 who, (unsigned long) pid, strna(comm), strna(user), why);
1992 dbus_message_iter_next(&sub);
1995 dbus_message_iter_recurse(&iter, &sub);
1997 /* Check for current sessions */
1998 sd_get_sessions(&sessions);
1999 STRV_FOREACH(s, sessions) {
2001 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2003 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2006 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2009 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2012 sd_session_get_tty(*s, &tty);
2013 sd_session_get_seat(*s, &seat);
2014 sd_session_get_service(*s, &service);
2015 user = uid_to_name(uid);
2017 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2024 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2025 a == ACTION_HALT ? "halt" :
2026 a == ACTION_POWEROFF ? "poweroff" :
2027 a == ACTION_REBOOT ? "reboot" :
2028 a == ACTION_KEXEC ? "kexec" :
2029 a == ACTION_SUSPEND ? "suspend" :
2030 a == ACTION_HIBERNATE ? "hibernate" : "hybrid-sleep");
2038 static int start_special(DBusConnection *bus, char **args) {
2044 a = verb_to_action(args[0]);
2046 r = check_inhibitors(bus, a);
2050 if (arg_force >= 2 && geteuid() != 0) {
2051 log_error("Must be root.");
2055 if (arg_force >= 2 &&
2056 (a == ACTION_HALT ||
2057 a == ACTION_POWEROFF ||
2058 a == ACTION_REBOOT))
2061 if (arg_force >= 1 &&
2062 (a == ACTION_HALT ||
2063 a == ACTION_POWEROFF ||
2064 a == ACTION_REBOOT ||
2065 a == ACTION_KEXEC ||
2067 return daemon_reload(bus, args);
2069 /* first try logind, to allow authentication with polkit */
2070 if (geteuid() != 0 &&
2071 (a == ACTION_POWEROFF ||
2072 a == ACTION_REBOOT ||
2073 a == ACTION_SUSPEND ||
2074 a == ACTION_HIBERNATE ||
2075 a == ACTION_HYBRID_SLEEP)) {
2076 r = reboot_with_logind(bus, a);
2081 r = start_unit(bus, args);
2088 static int check_unit_active(DBusConnection *bus, char **args) {
2089 const char * const check_states[] = {
2096 int r = 3; /* According to LSB: "program is not running" */
2101 STRV_FOREACH(name, args+1) {
2104 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2114 static int check_unit_failed(DBusConnection *bus, char **args) {
2115 const char * const check_states[] = {
2126 STRV_FOREACH(name, args+1) {
2129 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2139 static int kill_unit(DBusConnection *bus, char **args) {
2147 arg_kill_who = "all";
2149 STRV_FOREACH(name, args+1) {
2150 _cleanup_free_ char *n = NULL;
2152 n = unit_name_mangle(*name);
2156 r = bus_method_call_with_reply(
2158 "org.freedesktop.systemd1",
2159 "/org/freedesktop/systemd1",
2160 "org.freedesktop.systemd1.Manager",
2164 DBUS_TYPE_STRING, &n,
2165 DBUS_TYPE_STRING, &arg_kill_who,
2166 DBUS_TYPE_INT32, &arg_signal,
2174 static int set_cgroup(DBusConnection *bus, char **args) {
2175 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2178 DBusMessageIter iter;
2180 _cleanup_free_ char *n = NULL;
2185 dbus_error_init(&error);
2188 streq(args[0], "set-cgroup") ? "SetUnitControlGroups" :
2189 streq(args[0], "unset-group") ? "UnsetUnitControlGroups"
2190 : "UnsetUnitControlGroupAttributes";
2192 n = unit_name_mangle(args[1]);
2196 m = dbus_message_new_method_call(
2197 "org.freedesktop.systemd1",
2198 "/org/freedesktop/systemd1",
2199 "org.freedesktop.systemd1.Manager",
2204 dbus_message_iter_init_append(m, &iter);
2205 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
2208 r = bus_append_strv_iter(&iter, args + 2);
2212 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2214 log_error("Failed to issue method call: %s", bus_error_message(&error));
2215 dbus_error_free(&error);
2222 static int set_cgroup_attr(DBusConnection *bus, char **args) {
2223 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2225 DBusMessageIter iter, sub, sub2;
2227 _cleanup_free_ char *n = NULL;
2232 dbus_error_init(&error);
2234 if (strv_length(args) % 2 != 0) {
2235 log_error("Expecting an uneven number of arguments!");
2239 n = unit_name_mangle(args[1]);
2243 m = dbus_message_new_method_call(
2244 "org.freedesktop.systemd1",
2245 "/org/freedesktop/systemd1",
2246 "org.freedesktop.systemd1.Manager",
2247 "SetUnitControlGroupAttributes");
2251 dbus_message_iter_init_append(m, &iter);
2252 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2253 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub))
2256 STRV_FOREACH_PAIR(x, y, args + 2) {
2257 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
2258 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, x) ||
2259 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, y) ||
2260 !dbus_message_iter_close_container(&sub, &sub2))
2264 if (!dbus_message_iter_close_container(&iter, &sub))
2267 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2269 log_error("Failed to issue method call: %s", bus_error_message(&error));
2270 dbus_error_free(&error);
2277 typedef struct ExecStatusInfo {
2285 usec_t start_timestamp;
2286 usec_t exit_timestamp;
2291 LIST_FIELDS(struct ExecStatusInfo, exec);
2294 static void exec_status_info_free(ExecStatusInfo *i) {
2303 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2304 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2305 DBusMessageIter sub2, sub3;
2309 int32_t code, status;
2315 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2318 dbus_message_iter_recurse(sub, &sub2);
2320 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2323 i->path = strdup(path);
2327 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2328 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2332 dbus_message_iter_recurse(&sub2, &sub3);
2333 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2334 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2335 dbus_message_iter_next(&sub3);
2339 i->argv = new0(char*, n+1);
2344 dbus_message_iter_recurse(&sub2, &sub3);
2345 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2348 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2349 dbus_message_iter_get_basic(&sub3, &s);
2350 dbus_message_iter_next(&sub3);
2352 i->argv[n] = strdup(s);
2359 if (!dbus_message_iter_next(&sub2) ||
2360 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2361 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2362 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2363 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2364 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2365 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2366 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2367 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2371 i->start_timestamp = (usec_t) start_timestamp;
2372 i->exit_timestamp = (usec_t) exit_timestamp;
2373 i->pid = (pid_t) pid;
2380 typedef struct UnitStatusInfo {
2382 const char *load_state;
2383 const char *active_state;
2384 const char *sub_state;
2385 const char *unit_file_state;
2387 const char *description;
2388 const char *following;
2390 char **documentation;
2392 const char *fragment_path;
2393 const char *source_path;
2394 const char *default_control_group;
2396 const char *load_error;
2399 usec_t inactive_exit_timestamp;
2400 usec_t inactive_exit_timestamp_monotonic;
2401 usec_t active_enter_timestamp;
2402 usec_t active_exit_timestamp;
2403 usec_t inactive_enter_timestamp;
2405 bool need_daemon_reload;
2410 const char *status_text;
2413 usec_t start_timestamp;
2414 usec_t exit_timestamp;
2416 int exit_code, exit_status;
2418 usec_t condition_timestamp;
2419 bool condition_result;
2422 unsigned n_accepted;
2423 unsigned n_connections;
2427 const char *sysfs_path;
2429 /* Mount, Automount */
2435 LIST_HEAD(ExecStatusInfo, exec);
2438 static void print_status_info(UnitStatusInfo *i) {
2440 const char *on, *off, *ss;
2442 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2443 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2446 arg_all * OUTPUT_SHOW_ALL |
2447 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2448 on_tty() * OUTPUT_COLOR |
2449 !arg_quiet * OUTPUT_WARN_CUTOFF |
2450 arg_full * OUTPUT_FULL_WIDTH;
2454 /* This shows pretty information about a unit. See
2455 * print_property() for a low-level property printer */
2457 printf("%s", strna(i->id));
2459 if (i->description && !streq_ptr(i->id, i->description))
2460 printf(" - %s", i->description);
2465 printf("\t Follow: unit currently follows state of %s\n", i->following);
2467 if (streq_ptr(i->load_state, "error")) {
2468 on = ansi_highlight_red(true);
2469 off = ansi_highlight_red(false);
2473 path = i->source_path ? i->source_path : i->fragment_path;
2476 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2477 else if (path && i->unit_file_state)
2478 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2480 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2482 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2484 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2486 if (streq_ptr(i->active_state, "failed")) {
2487 on = ansi_highlight_red(true);
2488 off = ansi_highlight_red(false);
2489 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2490 on = ansi_highlight_green(true);
2491 off = ansi_highlight_green(false);
2496 printf("\t Active: %s%s (%s)%s",
2498 strna(i->active_state),
2502 printf("\t Active: %s%s%s",
2504 strna(i->active_state),
2507 if (!isempty(i->result) && !streq(i->result, "success"))
2508 printf(" (Result: %s)", i->result);
2510 timestamp = (streq_ptr(i->active_state, "active") ||
2511 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2512 (streq_ptr(i->active_state, "inactive") ||
2513 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2514 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2515 i->active_exit_timestamp;
2517 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2518 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2521 printf(" since %s; %s\n", s2, s1);
2523 printf(" since %s\n", s2);
2527 if (!i->condition_result && i->condition_timestamp > 0) {
2528 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2529 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2532 printf("\t start condition failed at %s; %s\n", s2, s1);
2534 printf("\t start condition failed at %s\n", s2);
2538 printf("\t Device: %s\n", i->sysfs_path);
2540 printf("\t Where: %s\n", i->where);
2542 printf("\t What: %s\n", i->what);
2544 if (!strv_isempty(i->documentation)) {
2548 STRV_FOREACH(t, i->documentation) {
2550 printf("\t Docs: %s\n", *t);
2553 printf("\t %s\n", *t);
2558 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2560 LIST_FOREACH(exec, p, i->exec) {
2561 _cleanup_free_ char *t = NULL;
2564 /* Only show exited processes here */
2568 t = strv_join(p->argv, " ");
2569 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2571 good = is_clean_exit_lsb(p->code, p->status, NULL);
2573 on = ansi_highlight_red(true);
2574 off = ansi_highlight_red(false);
2578 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2580 if (p->code == CLD_EXITED) {
2583 printf("status=%i", p->status);
2585 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2590 printf("signal=%s", signal_to_string(p->status));
2592 printf(")%s\n", off);
2594 if (i->main_pid == p->pid &&
2595 i->start_timestamp == p->start_timestamp &&
2596 i->exit_timestamp == p->start_timestamp)
2597 /* Let's not show this twice */
2600 if (p->pid == i->control_pid)
2604 if (i->main_pid > 0 || i->control_pid > 0) {
2607 if (i->main_pid > 0) {
2608 printf("Main PID: %u", (unsigned) i->main_pid);
2611 _cleanup_free_ char *t = NULL;
2612 get_process_comm(i->main_pid, &t);
2615 } else if (i->exit_code > 0) {
2616 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2618 if (i->exit_code == CLD_EXITED) {
2621 printf("status=%i", i->exit_status);
2623 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2628 printf("signal=%s", signal_to_string(i->exit_status));
2633 if (i->main_pid > 0 && i->control_pid > 0)
2636 if (i->control_pid > 0) {
2637 _cleanup_free_ char *t = NULL;
2639 printf(" Control: %u", (unsigned) i->control_pid);
2641 get_process_comm(i->control_pid, &t);
2650 printf("\t Status: \"%s\"\n", i->status_text);
2652 if (i->default_control_group &&
2653 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2656 printf("\t CGroup: %s\n", i->default_control_group);
2658 if (arg_transport != TRANSPORT_SSH) {
2668 if (i->main_pid > 0)
2669 extra[k++] = i->main_pid;
2671 if (i->control_pid > 0)
2672 extra[k++] = i->control_pid;
2674 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, extra, k, flags);
2678 if (i->id && arg_transport != TRANSPORT_SSH) {
2680 show_journal_by_unit(stdout,
2684 i->inactive_exit_timestamp_monotonic,
2689 if (i->need_daemon_reload)
2690 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2691 ansi_highlight_red(true),
2692 ansi_highlight_red(false),
2693 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2696 static void show_unit_help(UnitStatusInfo *i) {
2701 if (!i->documentation) {
2702 log_info("Documentation for %s not known.", i->id);
2706 STRV_FOREACH(p, i->documentation) {
2708 if (startswith(*p, "man:")) {
2711 char *page = NULL, *section = NULL;
2712 const char *args[4] = { "man", NULL, NULL, NULL };
2717 if ((*p)[k-1] == ')')
2718 e = strrchr(*p, '(');
2721 page = strndup((*p) + 4, e - *p - 4);
2727 section = strndup(e + 1, *p + k - e - 2);
2741 log_error("Failed to fork: %m");
2749 execvp(args[0], (char**) args);
2750 log_error("Failed to execute man: %m");
2751 _exit(EXIT_FAILURE);
2757 wait_for_terminate(pid, NULL);
2759 log_info("Can't show: %s", *p);
2763 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2769 switch (dbus_message_iter_get_arg_type(iter)) {
2771 case DBUS_TYPE_STRING: {
2774 dbus_message_iter_get_basic(iter, &s);
2777 if (streq(name, "Id"))
2779 else if (streq(name, "LoadState"))
2781 else if (streq(name, "ActiveState"))
2782 i->active_state = s;
2783 else if (streq(name, "SubState"))
2785 else if (streq(name, "Description"))
2787 else if (streq(name, "FragmentPath"))
2788 i->fragment_path = s;
2789 else if (streq(name, "SourcePath"))
2791 else if (streq(name, "DefaultControlGroup"))
2792 i->default_control_group = s;
2793 else if (streq(name, "StatusText"))
2795 else if (streq(name, "SysFSPath"))
2797 else if (streq(name, "Where"))
2799 else if (streq(name, "What"))
2801 else if (streq(name, "Following"))
2803 else if (streq(name, "UnitFileState"))
2804 i->unit_file_state = s;
2805 else if (streq(name, "Result"))
2812 case DBUS_TYPE_BOOLEAN: {
2815 dbus_message_iter_get_basic(iter, &b);
2817 if (streq(name, "Accept"))
2819 else if (streq(name, "NeedDaemonReload"))
2820 i->need_daemon_reload = b;
2821 else if (streq(name, "ConditionResult"))
2822 i->condition_result = b;
2827 case DBUS_TYPE_UINT32: {
2830 dbus_message_iter_get_basic(iter, &u);
2832 if (streq(name, "MainPID")) {
2834 i->main_pid = (pid_t) u;
2837 } else if (streq(name, "ControlPID"))
2838 i->control_pid = (pid_t) u;
2839 else if (streq(name, "ExecMainPID")) {
2841 i->main_pid = (pid_t) u;
2842 } else if (streq(name, "NAccepted"))
2844 else if (streq(name, "NConnections"))
2845 i->n_connections = u;
2850 case DBUS_TYPE_INT32: {
2853 dbus_message_iter_get_basic(iter, &j);
2855 if (streq(name, "ExecMainCode"))
2856 i->exit_code = (int) j;
2857 else if (streq(name, "ExecMainStatus"))
2858 i->exit_status = (int) j;
2863 case DBUS_TYPE_UINT64: {
2866 dbus_message_iter_get_basic(iter, &u);
2868 if (streq(name, "ExecMainStartTimestamp"))
2869 i->start_timestamp = (usec_t) u;
2870 else if (streq(name, "ExecMainExitTimestamp"))
2871 i->exit_timestamp = (usec_t) u;
2872 else if (streq(name, "ActiveEnterTimestamp"))
2873 i->active_enter_timestamp = (usec_t) u;
2874 else if (streq(name, "InactiveEnterTimestamp"))
2875 i->inactive_enter_timestamp = (usec_t) u;
2876 else if (streq(name, "InactiveExitTimestamp"))
2877 i->inactive_exit_timestamp = (usec_t) u;
2878 else if (streq(name, "InactiveExitTimestampMonotonic"))
2879 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2880 else if (streq(name, "ActiveExitTimestamp"))
2881 i->active_exit_timestamp = (usec_t) u;
2882 else if (streq(name, "ConditionTimestamp"))
2883 i->condition_timestamp = (usec_t) u;
2888 case DBUS_TYPE_ARRAY: {
2890 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2891 startswith(name, "Exec")) {
2892 DBusMessageIter sub;
2894 dbus_message_iter_recurse(iter, &sub);
2895 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2896 ExecStatusInfo *info;
2899 if (!(info = new0(ExecStatusInfo, 1)))
2902 if (!(info->name = strdup(name))) {
2907 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2912 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2914 dbus_message_iter_next(&sub);
2916 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2917 streq(name, "Documentation")) {
2919 DBusMessageIter sub;
2921 dbus_message_iter_recurse(iter, &sub);
2922 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2926 dbus_message_iter_get_basic(&sub, &s);
2928 l = strv_append(i->documentation, s);
2932 strv_free(i->documentation);
2933 i->documentation = l;
2935 dbus_message_iter_next(&sub);
2942 case DBUS_TYPE_STRUCT: {
2944 if (streq(name, "LoadError")) {
2945 DBusMessageIter sub;
2946 const char *n, *message;
2949 dbus_message_iter_recurse(iter, &sub);
2951 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2955 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2959 if (!isempty(message))
2960 i->load_error = message;
2970 static int print_property(const char *name, DBusMessageIter *iter) {
2974 /* This is a low-level property printer, see
2975 * print_status_info() for the nicer output */
2977 if (arg_property && !strv_find(arg_property, name))
2980 switch (dbus_message_iter_get_arg_type(iter)) {
2982 case DBUS_TYPE_STRUCT: {
2983 DBusMessageIter sub;
2984 dbus_message_iter_recurse(iter, &sub);
2986 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2989 dbus_message_iter_get_basic(&sub, &u);
2992 printf("%s=%u\n", name, (unsigned) u);
2994 printf("%s=\n", name);
2997 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
3000 dbus_message_iter_get_basic(&sub, &s);
3002 if (arg_all || s[0])
3003 printf("%s=%s\n", name, s);
3006 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
3007 const char *a = NULL, *b = NULL;
3009 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
3010 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
3012 if (arg_all || !isempty(a) || !isempty(b))
3013 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3021 case DBUS_TYPE_ARRAY:
3023 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
3024 DBusMessageIter sub, sub2;
3026 dbus_message_iter_recurse(iter, &sub);
3027 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3031 dbus_message_iter_recurse(&sub, &sub2);
3033 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3034 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3035 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3037 dbus_message_iter_next(&sub);
3042 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3043 DBusMessageIter sub, sub2;
3045 dbus_message_iter_recurse(iter, &sub);
3046 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3047 const char *type, *path;
3049 dbus_message_iter_recurse(&sub, &sub2);
3051 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3052 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3053 printf("%s=%s\n", type, path);
3055 dbus_message_iter_next(&sub);
3060 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3061 DBusMessageIter sub, sub2;
3063 dbus_message_iter_recurse(iter, &sub);
3064 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3066 uint64_t value, next_elapse;
3068 dbus_message_iter_recurse(&sub, &sub2);
3070 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3071 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3072 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3073 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3075 printf("%s={ value=%s ; next_elapse=%s }\n",
3077 format_timespan(timespan1, sizeof(timespan1), value),
3078 format_timespan(timespan2, sizeof(timespan2), next_elapse));
3081 dbus_message_iter_next(&sub);
3086 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
3087 DBusMessageIter sub, sub2;
3089 dbus_message_iter_recurse(iter, &sub);
3090 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3091 const char *controller, *attr, *value;
3093 dbus_message_iter_recurse(&sub, &sub2);
3095 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
3096 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
3097 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
3099 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
3105 dbus_message_iter_next(&sub);
3110 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3111 DBusMessageIter sub;
3113 dbus_message_iter_recurse(iter, &sub);
3114 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3115 ExecStatusInfo info;
3118 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3119 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3122 t = strv_join(info.argv, " ");
3124 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3128 yes_no(info.ignore),
3129 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3130 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3131 (unsigned) info. pid,
3132 sigchld_code_to_string(info.code),
3134 info.code == CLD_EXITED ? "" : "/",
3135 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3141 strv_free(info.argv);
3143 dbus_message_iter_next(&sub);
3152 if (generic_print_property(name, iter, arg_all) > 0)
3156 printf("%s=[unprintable]\n", name);
3161 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3162 _cleanup_free_ DBusMessage *reply = NULL;
3163 const char *interface = "";
3165 DBusMessageIter iter, sub, sub2, sub3;
3166 UnitStatusInfo info;
3174 r = bus_method_call_with_reply(
3176 "org.freedesktop.systemd1",
3178 "org.freedesktop.DBus.Properties",
3182 DBUS_TYPE_STRING, &interface,
3187 if (!dbus_message_iter_init(reply, &iter) ||
3188 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3189 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3190 log_error("Failed to parse reply.");
3194 dbus_message_iter_recurse(&iter, &sub);
3201 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3204 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3205 dbus_message_iter_recurse(&sub, &sub2);
3207 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3208 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3209 log_error("Failed to parse reply.");
3213 dbus_message_iter_recurse(&sub2, &sub3);
3215 if (show_properties)
3216 r = print_property(name, &sub3);
3218 r = status_property(name, &sub3, &info);
3220 log_error("Failed to parse reply.");
3224 dbus_message_iter_next(&sub);
3229 if (!show_properties) {
3230 if (streq(verb, "help"))
3231 show_unit_help(&info);
3233 print_status_info(&info);
3236 strv_free(info.documentation);
3238 if (!streq_ptr(info.active_state, "active") &&
3239 !streq_ptr(info.active_state, "reloading") &&
3240 streq(verb, "status"))
3241 /* According to LSB: "program not running" */
3244 while ((p = info.exec)) {
3245 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3246 exec_status_info_free(p);
3252 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3253 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3254 const char *path = NULL;
3258 dbus_error_init(&error);
3260 r = bus_method_call_with_reply(
3262 "org.freedesktop.systemd1",
3263 "/org/freedesktop/systemd1",
3264 "org.freedesktop.systemd1.Manager",
3268 DBUS_TYPE_UINT32, &pid,
3273 if (!dbus_message_get_args(reply, &error,
3274 DBUS_TYPE_OBJECT_PATH, &path,
3275 DBUS_TYPE_INVALID)) {
3276 log_error("Failed to parse reply: %s", bus_error_message(&error));
3281 r = show_one(verb, bus, path, false, new_line);
3284 dbus_error_free(&error);
3289 static int show(DBusConnection *bus, char **args) {
3291 bool show_properties, new_line = false;
3297 show_properties = streq(args[0], "show");
3299 if (show_properties)
3300 pager_open_if_enabled();
3302 /* If no argument is specified inspect the manager itself */
3304 if (show_properties && strv_length(args) <= 1)
3305 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3307 STRV_FOREACH(name, args+1) {
3310 if (safe_atou32(*name, &id) < 0) {
3311 _cleanup_free_ char *p = NULL, *n = NULL;
3312 /* Interpret as unit name */
3314 n = unit_name_mangle(*name);
3318 p = unit_dbus_path_from_name(n);
3322 r = show_one(args[0], bus, p, show_properties, &new_line);
3326 } else if (show_properties) {
3327 _cleanup_free_ char *p = NULL;
3329 /* Interpret as job id */
3330 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3333 r = show_one(args[0], bus, p, show_properties, &new_line);
3338 /* Interpret as PID */
3339 r = show_one_by_pid(args[0], bus, id, &new_line);
3348 static int dump(DBusConnection *bus, char **args) {
3349 _cleanup_free_ DBusMessage *reply = NULL;
3354 dbus_error_init(&error);
3356 pager_open_if_enabled();
3358 r = bus_method_call_with_reply(
3360 "org.freedesktop.systemd1",
3361 "/org/freedesktop/systemd1",
3362 "org.freedesktop.systemd1.Manager",
3370 if (!dbus_message_get_args(reply, &error,
3371 DBUS_TYPE_STRING, &text,
3372 DBUS_TYPE_INVALID)) {
3373 log_error("Failed to parse reply: %s", bus_error_message(&error));
3374 dbus_error_free(&error);
3378 fputs(text, stdout);
3382 static int snapshot(DBusConnection *bus, char **args) {
3383 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3386 dbus_bool_t cleanup = FALSE;
3387 DBusMessageIter iter, sub;
3390 *interface = "org.freedesktop.systemd1.Unit",
3392 _cleanup_free_ char *n = NULL;
3394 dbus_error_init(&error);
3396 if (strv_length(args) > 1)
3397 n = snapshot_name_mangle(args[1]);
3403 r = bus_method_call_with_reply (
3405 "org.freedesktop.systemd1",
3406 "/org/freedesktop/systemd1",
3407 "org.freedesktop.systemd1.Manager",
3411 DBUS_TYPE_STRING, &n,
3412 DBUS_TYPE_BOOLEAN, &cleanup,
3417 if (!dbus_message_get_args(reply, &error,
3418 DBUS_TYPE_OBJECT_PATH, &path,
3419 DBUS_TYPE_INVALID)) {
3420 log_error("Failed to parse reply: %s", bus_error_message(&error));
3421 dbus_error_free(&error);
3425 dbus_message_unref(reply);
3428 r = bus_method_call_with_reply (
3430 "org.freedesktop.systemd1",
3432 "org.freedesktop.DBus.Properties",
3436 DBUS_TYPE_STRING, &interface,
3437 DBUS_TYPE_STRING, &property,
3442 if (!dbus_message_iter_init(reply, &iter) ||
3443 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3444 log_error("Failed to parse reply.");
3448 dbus_message_iter_recurse(&iter, &sub);
3450 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3451 log_error("Failed to parse reply.");
3455 dbus_message_iter_get_basic(&sub, &id);
3463 static int delete_snapshot(DBusConnection *bus, char **args) {
3468 STRV_FOREACH(name, args+1) {
3469 _cleanup_free_ char *n = NULL;
3472 n = snapshot_name_mangle(*name);
3476 r = bus_method_call_with_reply(
3478 "org.freedesktop.systemd1",
3479 "/org/freedesktop/systemd1",
3480 "org.freedesktop.systemd1.Manager",
3484 DBUS_TYPE_STRING, &n,
3493 static int daemon_reload(DBusConnection *bus, char **args) {
3498 if (arg_action == ACTION_RELOAD)
3500 else if (arg_action == ACTION_REEXEC)
3501 method = "Reexecute";
3503 assert(arg_action == ACTION_SYSTEMCTL);
3506 streq(args[0], "clear-jobs") ||
3507 streq(args[0], "cancel") ? "ClearJobs" :
3508 streq(args[0], "daemon-reexec") ? "Reexecute" :
3509 streq(args[0], "reset-failed") ? "ResetFailed" :
3510 streq(args[0], "halt") ? "Halt" :
3511 streq(args[0], "poweroff") ? "PowerOff" :
3512 streq(args[0], "reboot") ? "Reboot" :
3513 streq(args[0], "kexec") ? "KExec" :
3514 streq(args[0], "exit") ? "Exit" :
3515 /* "daemon-reload" */ "Reload";
3518 r = bus_method_call_with_reply(
3520 "org.freedesktop.systemd1",
3521 "/org/freedesktop/systemd1",
3522 "org.freedesktop.systemd1.Manager",
3528 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3529 /* There's always a fallback possible for
3530 * legacy actions. */
3532 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3533 /* On reexecution, we expect a disconnect, not
3537 log_error("Failed to issue method call: %s", bus_error_message(&error));
3539 dbus_error_free(&error);
3543 static int reset_failed(DBusConnection *bus, char **args) {
3547 if (strv_length(args) <= 1)
3548 return daemon_reload(bus, args);
3550 STRV_FOREACH(name, args+1) {
3551 _cleanup_free_ char *n;
3553 n = unit_name_mangle(*name);
3557 r = bus_method_call_with_reply(
3559 "org.freedesktop.systemd1",
3560 "/org/freedesktop/systemd1",
3561 "org.freedesktop.systemd1.Manager",
3565 DBUS_TYPE_STRING, &n,
3574 static int show_enviroment(DBusConnection *bus, char **args) {
3575 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3576 DBusMessageIter iter, sub, sub2;
3579 *interface = "org.freedesktop.systemd1.Manager",
3580 *property = "Environment";
3582 pager_open_if_enabled();
3584 r = bus_method_call_with_reply(
3586 "org.freedesktop.systemd1",
3587 "/org/freedesktop/systemd1",
3588 "org.freedesktop.DBus.Properties",
3592 DBUS_TYPE_STRING, &interface,
3593 DBUS_TYPE_STRING, &property,
3598 if (!dbus_message_iter_init(reply, &iter) ||
3599 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3600 log_error("Failed to parse reply.");
3604 dbus_message_iter_recurse(&iter, &sub);
3606 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3607 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3608 log_error("Failed to parse reply.");
3612 dbus_message_iter_recurse(&sub, &sub2);
3614 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3617 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3618 log_error("Failed to parse reply.");
3622 dbus_message_iter_get_basic(&sub2, &text);
3625 dbus_message_iter_next(&sub2);
3631 static int switch_root(DBusConnection *bus, char **args) {
3634 _cleanup_free_ char *init = NULL;
3636 l = strv_length(args);
3637 if (l < 2 || l > 3) {
3638 log_error("Wrong number of arguments.");
3645 init = strdup(args[2]);
3647 parse_env_file("/proc/cmdline", WHITESPACE,
3657 log_debug("switching root - root: %s; init: %s", root, init);
3659 return bus_method_call_with_reply(
3661 "org.freedesktop.systemd1",
3662 "/org/freedesktop/systemd1",
3663 "org.freedesktop.systemd1.Manager",
3667 DBUS_TYPE_STRING, &root,
3668 DBUS_TYPE_STRING, &init,
3672 static int set_environment(DBusConnection *bus, char **args) {
3673 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3676 DBusMessageIter iter;
3682 dbus_error_init(&error);
3684 method = streq(args[0], "set-environment")
3686 : "UnsetEnvironment";
3688 m = dbus_message_new_method_call(
3689 "org.freedesktop.systemd1",
3690 "/org/freedesktop/systemd1",
3691 "org.freedesktop.systemd1.Manager",
3696 dbus_message_iter_init_append(m, &iter);
3698 r = bus_append_strv_iter(&iter, args + 1);
3702 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3704 log_error("Failed to issue method call: %s", bus_error_message(&error));
3705 dbus_error_free(&error);
3712 static int enable_sysv_units(char **args) {
3715 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3716 const char *verb = args[0];
3717 unsigned f = 1, t = 1;
3720 if (arg_scope != UNIT_FILE_SYSTEM)
3723 if (!streq(verb, "enable") &&
3724 !streq(verb, "disable") &&
3725 !streq(verb, "is-enabled"))
3728 /* Processes all SysV units, and reshuffles the array so that
3729 * afterwards only the native units remain */
3732 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3737 for (f = 1; args[f]; f++) {
3740 bool found_native = false, found_sysv;
3742 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3743 char **k, *l, *q = NULL;
3750 if (!endswith(name, ".service"))
3753 if (path_is_absolute(name))
3756 STRV_FOREACH(k, paths.unit_path) {
3759 if (!isempty(arg_root))
3760 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3762 asprintf(&p, "%s/%s", *k, name);
3769 found_native = access(p, F_OK) >= 0;
3780 if (!isempty(arg_root))
3781 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3783 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3789 p[strlen(p) - sizeof(".service") + 1] = 0;
3790 found_sysv = access(p, F_OK) >= 0;
3797 /* Mark this entry, so that we don't try enabling it as native unit */
3798 args[f] = (char*) "";
3800 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3802 if (!isempty(arg_root))
3803 argv[c++] = q = strappend("--root=", arg_root);
3805 argv[c++] = path_get_file_name(p);
3807 streq(verb, "enable") ? "on" :
3808 streq(verb, "disable") ? "off" : "--level=5";
3811 l = strv_join((char**)argv, " ");
3819 log_info("Executing %s", l);
3824 log_error("Failed to fork: %m");
3829 } else if (pid == 0) {
3832 execv(argv[0], (char**) argv);
3833 _exit(EXIT_FAILURE);
3839 j = wait_for_terminate(pid, &status);
3841 log_error("Failed to wait for child: %s", strerror(-r));
3846 if (status.si_code == CLD_EXITED) {
3847 if (streq(verb, "is-enabled")) {
3848 if (status.si_status == 0) {
3857 } else if (status.si_status != 0) {
3868 lookup_paths_free(&paths);
3870 /* Drop all SysV units */
3871 for (f = 1, t = 1; args[f]; f++) {
3873 if (isempty(args[f]))
3876 args[t++] = args[f];
3885 static int mangle_names(char **original_names, char ***mangled_names) {
3886 char **i, **l, **name;
3888 l = new(char*, strv_length(original_names) + 1);
3893 STRV_FOREACH(name, original_names) {
3895 /* When enabling units qualified path names are OK,
3896 * too, hence allow them explicitly. */
3901 *i = unit_name_mangle(*name);
3917 static int enable_unit(DBusConnection *bus, char **args) {
3918 const char *verb = args[0];
3919 UnitFileChange *changes = NULL;
3920 unsigned n_changes = 0, i;
3921 int carries_install_info = -1;
3922 DBusMessage *m = NULL, *reply = NULL;
3925 char **mangled_names = NULL;
3927 r = enable_sysv_units(args);
3934 dbus_error_init(&error);
3936 if (!bus || avoid_bus()) {
3937 if (streq(verb, "enable")) {
3938 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3939 carries_install_info = r;
3940 } else if (streq(verb, "disable"))
3941 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3942 else if (streq(verb, "reenable")) {
3943 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3944 carries_install_info = r;
3945 } else if (streq(verb, "link"))
3946 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3947 else if (streq(verb, "preset")) {
3948 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3949 carries_install_info = r;
3950 } else if (streq(verb, "mask"))
3951 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3952 else if (streq(verb, "unmask"))
3953 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3955 assert_not_reached("Unknown verb");
3958 log_error("Operation failed: %s", strerror(-r));
3963 for (i = 0; i < n_changes; i++) {
3964 if (changes[i].type == UNIT_FILE_SYMLINK)
3965 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3967 log_info("rm '%s'", changes[i].path);
3974 bool send_force = true, expect_carries_install_info = false;
3976 DBusMessageIter iter, sub, sub2;
3978 if (streq(verb, "enable")) {
3979 method = "EnableUnitFiles";
3980 expect_carries_install_info = true;
3981 } else if (streq(verb, "disable")) {
3982 method = "DisableUnitFiles";
3984 } else if (streq(verb, "reenable")) {
3985 method = "ReenableUnitFiles";
3986 expect_carries_install_info = true;
3987 } else if (streq(verb, "link"))
3988 method = "LinkUnitFiles";
3989 else if (streq(verb, "preset")) {
3990 method = "PresetUnitFiles";
3991 expect_carries_install_info = true;
3992 } else if (streq(verb, "mask"))
3993 method = "MaskUnitFiles";
3994 else if (streq(verb, "unmask")) {
3995 method = "UnmaskUnitFiles";
3998 assert_not_reached("Unknown verb");
4000 m = dbus_message_new_method_call(
4001 "org.freedesktop.systemd1",
4002 "/org/freedesktop/systemd1",
4003 "org.freedesktop.systemd1.Manager",
4010 dbus_message_iter_init_append(m, &iter);
4012 r = mangle_names(args+1, &mangled_names);
4016 r = bus_append_strv_iter(&iter, mangled_names);
4018 log_error("Failed to append unit files.");
4023 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4024 log_error("Failed to append runtime boolean.");
4032 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4033 log_error("Failed to append force boolean.");
4039 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4041 log_error("Failed to issue method call: %s", bus_error_message(&error));
4046 if (!dbus_message_iter_init(reply, &iter)) {
4047 log_error("Failed to initialize iterator.");
4051 if (expect_carries_install_info) {
4052 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4054 log_error("Failed to parse reply.");
4058 carries_install_info = b;
4061 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4062 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4063 log_error("Failed to parse reply.");
4068 dbus_message_iter_recurse(&iter, &sub);
4069 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4070 const char *type, *path, *source;
4072 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4073 log_error("Failed to parse reply.");
4078 dbus_message_iter_recurse(&sub, &sub2);
4080 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4081 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4082 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4083 log_error("Failed to parse reply.");
4089 if (streq(type, "symlink"))
4090 log_info("ln -s '%s' '%s'", source, path);
4092 log_info("rm '%s'", path);
4095 dbus_message_iter_next(&sub);
4098 /* Try to reload if enabeld */
4100 r = daemon_reload(bus, args);
4103 if (carries_install_info == 0)
4105 "The unit files have no [Install] section. They are not meant to be enabled\n"
4106 "using systemctl.\n"
4107 "Possible reasons for having this kind of units are:\n"
4108 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4109 " .wants/ or .requires/ directory.\n"
4110 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4111 " a requirement dependency on it.\n"
4112 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4113 " D-Bus, udev, scripted systemctl call, ...).\n");
4117 dbus_message_unref(m);
4120 dbus_message_unref(reply);
4122 unit_file_changes_free(changes, n_changes);
4124 dbus_error_free(&error);
4126 strv_free(mangled_names);
4131 static int unit_is_enabled(DBusConnection *bus, char **args) {
4134 DBusMessage *reply = NULL;
4138 dbus_error_init(&error);
4140 r = enable_sysv_units(args);
4146 if (!bus || avoid_bus()) {
4148 STRV_FOREACH(name, args+1) {
4149 UnitFileState state;
4151 state = unit_file_get_state(arg_scope, arg_root, *name);
4157 if (state == UNIT_FILE_ENABLED ||
4158 state == UNIT_FILE_ENABLED_RUNTIME ||
4159 state == UNIT_FILE_STATIC)
4163 puts(unit_file_state_to_string(state));
4167 STRV_FOREACH(name, args+1) {
4170 r = bus_method_call_with_reply (
4172 "org.freedesktop.systemd1",
4173 "/org/freedesktop/systemd1",
4174 "org.freedesktop.systemd1.Manager",
4178 DBUS_TYPE_STRING, name,
4183 if (!dbus_message_get_args(reply, &error,
4184 DBUS_TYPE_STRING, &s,
4185 DBUS_TYPE_INVALID)) {
4186 log_error("Failed to parse reply: %s", bus_error_message(&error));
4191 dbus_message_unref(reply);
4194 if (streq(s, "enabled") ||
4195 streq(s, "enabled-runtime") ||
4204 r = enabled ? 0 : 1;
4208 dbus_message_unref(reply);
4210 dbus_error_free(&error);
4214 static int systemctl_help(void) {
4216 pager_open_if_enabled();
4218 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4219 "Query or send control commands to the systemd manager.\n\n"
4220 " -h --help Show this help\n"
4221 " --version Show package version\n"
4222 " -t --type=TYPE List only units of a particular type\n"
4223 " -p --property=NAME Show only properties by this name\n"
4224 " -a --all Show all units/properties, including dead/empty ones\n"
4225 " --failed Show only failed units\n"
4226 " --full Don't ellipsize unit names on output\n"
4227 " --fail When queueing a new job, fail if conflicting jobs are\n"
4229 " --ignore-dependencies\n"
4230 " When queueing a new job, ignore all its dependencies\n"
4231 " -i --ignore-inhibitors\n"
4232 " When shutting down or sleeping, ignore inhibitors\n"
4233 " --kill-who=WHO Who to send signal to\n"
4234 " -s --signal=SIGNAL Which signal to send\n"
4235 " -H --host=[USER@]HOST\n"
4236 " Show information for remote host\n"
4237 " -P --privileged Acquire privileges before execution\n"
4238 " -q --quiet Suppress output\n"
4239 " --no-block Do not wait until operation finished\n"
4240 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4241 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4243 " --no-legend Do not print a legend (column headers and hints)\n"
4244 " --no-pager Do not pipe output into a pager\n"
4245 " --no-ask-password\n"
4246 " Do not ask for system passwords\n"
4247 " --order When generating graph for dot, show only order\n"
4248 " --require When generating graph for dot, show only requirement\n"
4249 " --system Connect to system manager\n"
4250 " --user Connect to user service manager\n"
4251 " --global Enable/disable unit files globally\n"
4252 " -f --force When enabling unit files, override existing symlinks\n"
4253 " When shutting down, execute action immediately\n"
4254 " --root=PATH Enable unit files in the specified root directory\n"
4255 " --runtime Enable unit files only temporarily until next reboot\n"
4256 " -n --lines=INTEGER Journal entries to show\n"
4257 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4258 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4260 " list-units List loaded units\n"
4261 " start [NAME...] Start (activate) one or more units\n"
4262 " stop [NAME...] Stop (deactivate) one or more units\n"
4263 " reload [NAME...] Reload one or more units\n"
4264 " restart [NAME...] Start or restart one or more units\n"
4265 " try-restart [NAME...] Restart one or more units if active\n"
4266 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4267 " otherwise start or restart\n"
4268 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4269 " otherwise restart if active\n"
4270 " isolate [NAME] Start one unit and stop all others\n"
4271 " kill [NAME...] Send signal to processes of a unit\n"
4272 " is-active [NAME...] Check whether units are active\n"
4273 " is-failed [NAME...] Check whether units are failed\n"
4274 " status [NAME...|PID...] Show runtime status of one or more units\n"
4275 " show [NAME...|JOB...] Show properties of one or more\n"
4276 " units/jobs or the manager\n"
4277 " help [NAME...|PID...] Show manual for one or more units\n"
4278 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4280 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4281 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4282 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4283 " Set control group attribute\n"
4284 " unset-cgroup-attr [NAME] [ATTR...]\n"
4285 " Unset control group attribute\n"
4286 " load [NAME...] Load one or more units\n"
4287 " list-dependencies [NAME] Recursively show units which are required\n"
4288 " or wanted by this unit\n\n"
4289 "Unit File Commands:\n"
4290 " list-unit-files List installed unit files\n"
4291 " enable [NAME...] Enable one or more unit files\n"
4292 " disable [NAME...] Disable one or more unit files\n"
4293 " reenable [NAME...] Reenable one or more unit files\n"
4294 " preset [NAME...] Enable/disable one or more unit files\n"
4295 " based on preset configuration\n"
4296 " mask [NAME...] Mask one or more units\n"
4297 " unmask [NAME...] Unmask one or more units\n"
4298 " link [PATH...] Link one or more units files into\n"
4299 " the search path\n"
4300 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4302 " list-jobs List jobs\n"
4303 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4304 "Status Commands:\n"
4305 " dump Dump server status\n"
4306 " dot Dump dependency graph for dot(1)\n\n"
4307 "Snapshot Commands:\n"
4308 " snapshot [NAME] Create a snapshot\n"
4309 " delete [NAME...] Remove one or more snapshots\n\n"
4310 "Environment Commands:\n"
4311 " show-environment Dump environment\n"
4312 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4313 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4314 "Manager Lifecycle Commands:\n"
4315 " daemon-reload Reload systemd manager configuration\n"
4316 " daemon-reexec Reexecute systemd manager\n\n"
4317 "System Commands:\n"
4318 " default Enter system default mode\n"
4319 " rescue Enter system rescue mode\n"
4320 " emergency Enter system emergency mode\n"
4321 " halt Shut down and halt the system\n"
4322 " poweroff Shut down and power-off the system\n"
4323 " reboot Shut down and reboot the system\n"
4324 " kexec Shut down and reboot the system with kexec\n"
4325 " exit Request user instance exit\n"
4326 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4327 " suspend Suspend the system\n"
4328 " hibernate Hibernate the system\n"
4329 " hybrid-sleep Hibernate and suspend the system\n",
4330 program_invocation_short_name);
4335 static int halt_help(void) {
4337 printf("%s [OPTIONS...]\n\n"
4338 "%s the system.\n\n"
4339 " --help Show this help\n"
4340 " --halt Halt the machine\n"
4341 " -p --poweroff Switch off the machine\n"
4342 " --reboot Reboot the machine\n"
4343 " -f --force Force immediate halt/power-off/reboot\n"
4344 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4345 " -d --no-wtmp Don't write wtmp record\n"
4346 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4347 program_invocation_short_name,
4348 arg_action == ACTION_REBOOT ? "Reboot" :
4349 arg_action == ACTION_POWEROFF ? "Power off" :
4355 static int shutdown_help(void) {
4357 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4358 "Shut down the system.\n\n"
4359 " --help Show this help\n"
4360 " -H --halt Halt the machine\n"
4361 " -P --poweroff Power-off the machine\n"
4362 " -r --reboot Reboot the machine\n"
4363 " -h Equivalent to --poweroff, overridden by --halt\n"
4364 " -k Don't halt/power-off/reboot, just send warnings\n"
4365 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4366 " -c Cancel a pending shutdown\n",
4367 program_invocation_short_name);
4372 static int telinit_help(void) {
4374 printf("%s [OPTIONS...] {COMMAND}\n\n"
4375 "Send control commands to the init daemon.\n\n"
4376 " --help Show this help\n"
4377 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4379 " 0 Power-off the machine\n"
4380 " 6 Reboot the machine\n"
4381 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4382 " 1, s, S Enter rescue mode\n"
4383 " q, Q Reload init daemon configuration\n"
4384 " u, U Reexecute init daemon\n",
4385 program_invocation_short_name);
4390 static int runlevel_help(void) {
4392 printf("%s [OPTIONS...]\n\n"
4393 "Prints the previous and current runlevel of the init system.\n\n"
4394 " --help Show this help\n",
4395 program_invocation_short_name);
4400 static int help_types(void) {
4403 puts("Available unit types:");
4404 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4405 if (unit_type_table[i])
4406 puts(unit_type_table[i]);
4408 puts("\nAvailable unit load states: ");
4409 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4410 if (unit_type_table[i])
4411 puts(unit_load_state_table[i]);
4416 static int systemctl_parse_argv(int argc, char *argv[]) {
4420 ARG_IGNORE_DEPENDENCIES,
4435 ARG_NO_ASK_PASSWORD,
4441 static const struct option options[] = {
4442 { "help", no_argument, NULL, 'h' },
4443 { "version", no_argument, NULL, ARG_VERSION },
4444 { "type", required_argument, NULL, 't' },
4445 { "property", required_argument, NULL, 'p' },
4446 { "all", no_argument, NULL, 'a' },
4447 { "failed", no_argument, NULL, ARG_FAILED },
4448 { "full", no_argument, NULL, ARG_FULL },
4449 { "fail", no_argument, NULL, ARG_FAIL },
4450 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4451 { "ignore-inhibitors", no_argument, NULL, 'i' },
4452 { "user", no_argument, NULL, ARG_USER },
4453 { "system", no_argument, NULL, ARG_SYSTEM },
4454 { "global", no_argument, NULL, ARG_GLOBAL },
4455 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4456 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4457 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4458 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4459 { "quiet", no_argument, NULL, 'q' },
4460 { "order", no_argument, NULL, ARG_ORDER },
4461 { "require", no_argument, NULL, ARG_REQUIRE },
4462 { "root", required_argument, NULL, ARG_ROOT },
4463 { "force", no_argument, NULL, ARG_FORCE },
4464 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4465 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4466 { "signal", required_argument, NULL, 's' },
4467 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4468 { "host", required_argument, NULL, 'H' },
4469 { "privileged",no_argument, NULL, 'P' },
4470 { "runtime", no_argument, NULL, ARG_RUNTIME },
4471 { "lines", required_argument, NULL, 'n' },
4472 { "output", required_argument, NULL, 'o' },
4473 { NULL, 0, NULL, 0 }
4481 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4490 puts(PACKAGE_STRING);
4491 puts(SYSTEMD_FEATURES);
4495 if (streq(optarg, "help")) {
4500 if (unit_type_from_string(optarg) >= 0) {
4504 if (unit_load_state_from_string(optarg) >= 0) {
4505 arg_load_state = optarg;
4508 log_error("Unkown unit type or load state '%s'.",
4510 log_info("Use -t help to see a list of allowed values.");
4515 if (!(l = strv_append(arg_property, optarg)))
4518 strv_free(arg_property);
4521 /* If the user asked for a particular
4522 * property, show it to him, even if it is
4533 arg_job_mode = "fail";
4536 case ARG_IGNORE_DEPENDENCIES:
4537 arg_job_mode = "ignore-dependencies";
4541 arg_scope = UNIT_FILE_USER;
4545 arg_scope = UNIT_FILE_SYSTEM;
4549 arg_scope = UNIT_FILE_GLOBAL;
4553 arg_no_block = true;
4557 arg_no_legend = true;
4561 arg_no_pager = true;
4569 arg_dot = DOT_ORDER;
4573 arg_dot = DOT_REQUIRE;
4601 arg_no_reload = true;
4605 arg_kill_who = optarg;
4609 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4610 log_error("Failed to parse signal string %s.", optarg);
4615 case ARG_NO_ASK_PASSWORD:
4616 arg_ask_password = false;
4620 arg_transport = TRANSPORT_POLKIT;
4624 arg_transport = TRANSPORT_SSH;
4633 if (safe_atou(optarg, &arg_lines) < 0) {
4634 log_error("Failed to parse lines '%s'", optarg);
4640 arg_output = output_mode_from_string(optarg);
4641 if (arg_output < 0) {
4642 log_error("Unknown output '%s'.", optarg);
4648 arg_ignore_inhibitors = true;
4655 log_error("Unknown option code '%c'.", c);
4660 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4661 log_error("Cannot access user instance remotely.");
4668 static int halt_parse_argv(int argc, char *argv[]) {
4677 static const struct option options[] = {
4678 { "help", no_argument, NULL, ARG_HELP },
4679 { "halt", no_argument, NULL, ARG_HALT },
4680 { "poweroff", no_argument, NULL, 'p' },
4681 { "reboot", no_argument, NULL, ARG_REBOOT },
4682 { "force", no_argument, NULL, 'f' },
4683 { "wtmp-only", no_argument, NULL, 'w' },
4684 { "no-wtmp", no_argument, NULL, 'd' },
4685 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4686 { NULL, 0, NULL, 0 }
4694 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4695 if (runlevel == '0' || runlevel == '6')
4698 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4706 arg_action = ACTION_HALT;
4710 if (arg_action != ACTION_REBOOT)
4711 arg_action = ACTION_POWEROFF;
4715 arg_action = ACTION_REBOOT;
4737 /* Compatibility nops */
4744 log_error("Unknown option code '%c'.", c);
4749 if (optind < argc) {
4750 log_error("Too many arguments.");
4757 static int parse_time_spec(const char *t, usec_t *_u) {
4761 if (streq(t, "now"))
4763 else if (!strchr(t, ':')) {
4766 if (safe_atou64(t, &u) < 0)
4769 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4778 hour = strtol(t, &e, 10);
4779 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4782 minute = strtol(e+1, &e, 10);
4783 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4786 n = now(CLOCK_REALTIME);
4787 s = (time_t) (n / USEC_PER_SEC);
4790 assert_se(localtime_r(&s, &tm));
4792 tm.tm_hour = (int) hour;
4793 tm.tm_min = (int) minute;
4796 assert_se(s = mktime(&tm));
4798 *_u = (usec_t) s * USEC_PER_SEC;
4801 *_u += USEC_PER_DAY;
4807 static int shutdown_parse_argv(int argc, char *argv[]) {
4814 static const struct option options[] = {
4815 { "help", no_argument, NULL, ARG_HELP },
4816 { "halt", no_argument, NULL, 'H' },
4817 { "poweroff", no_argument, NULL, 'P' },
4818 { "reboot", no_argument, NULL, 'r' },
4819 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4820 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4821 { NULL, 0, NULL, 0 }
4829 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4837 arg_action = ACTION_HALT;
4841 arg_action = ACTION_POWEROFF;
4846 arg_action = ACTION_KEXEC;
4848 arg_action = ACTION_REBOOT;
4852 arg_action = ACTION_KEXEC;
4856 if (arg_action != ACTION_HALT)
4857 arg_action = ACTION_POWEROFF;
4870 /* Compatibility nops */
4874 arg_action = ACTION_CANCEL_SHUTDOWN;
4881 log_error("Unknown option code '%c'.", c);
4886 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4887 r = parse_time_spec(argv[optind], &arg_when);
4889 log_error("Failed to parse time specification: %s", argv[optind]);
4893 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4895 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4896 /* No time argument for shutdown cancel */
4897 arg_wall = argv + optind;
4898 else if (argc > optind + 1)
4899 /* We skip the time argument */
4900 arg_wall = argv + optind + 1;
4907 static int telinit_parse_argv(int argc, char *argv[]) {
4914 static const struct option options[] = {
4915 { "help", no_argument, NULL, ARG_HELP },
4916 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4917 { NULL, 0, NULL, 0 }
4920 static const struct {
4924 { '0', ACTION_POWEROFF },
4925 { '6', ACTION_REBOOT },
4926 { '1', ACTION_RESCUE },
4927 { '2', ACTION_RUNLEVEL2 },
4928 { '3', ACTION_RUNLEVEL3 },
4929 { '4', ACTION_RUNLEVEL4 },
4930 { '5', ACTION_RUNLEVEL5 },
4931 { 's', ACTION_RESCUE },
4932 { 'S', ACTION_RESCUE },
4933 { 'q', ACTION_RELOAD },
4934 { 'Q', ACTION_RELOAD },
4935 { 'u', ACTION_REEXEC },
4936 { 'U', ACTION_REEXEC }
4945 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4960 log_error("Unknown option code '%c'.", c);
4965 if (optind >= argc) {
4970 if (optind + 1 < argc) {
4971 log_error("Too many arguments.");
4975 if (strlen(argv[optind]) != 1) {
4976 log_error("Expected single character argument.");
4980 for (i = 0; i < ELEMENTSOF(table); i++)
4981 if (table[i].from == argv[optind][0])
4984 if (i >= ELEMENTSOF(table)) {
4985 log_error("Unknown command '%s'.", argv[optind]);
4989 arg_action = table[i].to;
4996 static int runlevel_parse_argv(int argc, char *argv[]) {
5002 static const struct option options[] = {
5003 { "help", no_argument, NULL, ARG_HELP },
5004 { NULL, 0, NULL, 0 }
5012 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5023 log_error("Unknown option code '%c'.", c);
5028 if (optind < argc) {
5029 log_error("Too many arguments.");
5036 static int parse_argv(int argc, char *argv[]) {
5040 if (program_invocation_short_name) {
5042 if (strstr(program_invocation_short_name, "halt")) {
5043 arg_action = ACTION_HALT;
5044 return halt_parse_argv(argc, argv);
5045 } else if (strstr(program_invocation_short_name, "poweroff")) {
5046 arg_action = ACTION_POWEROFF;
5047 return halt_parse_argv(argc, argv);
5048 } else if (strstr(program_invocation_short_name, "reboot")) {
5050 arg_action = ACTION_KEXEC;
5052 arg_action = ACTION_REBOOT;
5053 return halt_parse_argv(argc, argv);
5054 } else if (strstr(program_invocation_short_name, "shutdown")) {
5055 arg_action = ACTION_POWEROFF;
5056 return shutdown_parse_argv(argc, argv);
5057 } else if (strstr(program_invocation_short_name, "init")) {
5059 if (sd_booted() > 0) {
5060 arg_action = ACTION_INVALID;
5061 return telinit_parse_argv(argc, argv);
5063 /* Hmm, so some other init system is
5064 * running, we need to forward this
5065 * request to it. For now we simply
5066 * guess that it is Upstart. */
5068 execv("/lib/upstart/telinit", argv);
5070 log_error("Couldn't find an alternative telinit implementation to spawn.");
5074 } else if (strstr(program_invocation_short_name, "runlevel")) {
5075 arg_action = ACTION_RUNLEVEL;
5076 return runlevel_parse_argv(argc, argv);
5080 arg_action = ACTION_SYSTEMCTL;
5081 return systemctl_parse_argv(argc, argv);
5084 static int action_to_runlevel(void) {
5086 static const char table[_ACTION_MAX] = {
5087 [ACTION_HALT] = '0',
5088 [ACTION_POWEROFF] = '0',
5089 [ACTION_REBOOT] = '6',
5090 [ACTION_RUNLEVEL2] = '2',
5091 [ACTION_RUNLEVEL3] = '3',
5092 [ACTION_RUNLEVEL4] = '4',
5093 [ACTION_RUNLEVEL5] = '5',
5094 [ACTION_RESCUE] = '1'
5097 assert(arg_action < _ACTION_MAX);
5099 return table[arg_action];
5102 static int talk_upstart(void) {
5103 DBusMessage *m = NULL, *reply = NULL;
5105 int previous, rl, r;
5107 env1_buf[] = "RUNLEVEL=X",
5108 env2_buf[] = "PREVLEVEL=X";
5109 char *env1 = env1_buf, *env2 = env2_buf;
5110 const char *emit = "runlevel";
5111 dbus_bool_t b_false = FALSE;
5112 DBusMessageIter iter, sub;
5113 DBusConnection *bus;
5115 dbus_error_init(&error);
5117 if (!(rl = action_to_runlevel()))
5120 if (utmp_get_runlevel(&previous, NULL) < 0)
5123 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5124 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5129 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5134 if ((r = bus_check_peercred(bus)) < 0) {
5135 log_error("Failed to verify owner of bus.");
5139 if (!(m = dbus_message_new_method_call(
5140 "com.ubuntu.Upstart",
5141 "/com/ubuntu/Upstart",
5142 "com.ubuntu.Upstart0_6",
5145 log_error("Could not allocate message.");
5150 dbus_message_iter_init_append(m, &iter);
5152 env1_buf[sizeof(env1_buf)-2] = rl;
5153 env2_buf[sizeof(env2_buf)-2] = previous;
5155 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5156 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5157 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5158 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5159 !dbus_message_iter_close_container(&iter, &sub) ||
5160 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5161 log_error("Could not append arguments to message.");
5166 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5168 if (bus_error_is_no_service(&error)) {
5173 log_error("Failed to issue method call: %s", bus_error_message(&error));
5182 dbus_message_unref(m);
5185 dbus_message_unref(reply);
5188 dbus_connection_flush(bus);
5189 dbus_connection_close(bus);
5190 dbus_connection_unref(bus);
5193 dbus_error_free(&error);
5198 static int talk_initctl(void) {
5199 struct init_request request;
5203 if (!(rl = action_to_runlevel()))
5207 request.magic = INIT_MAGIC;
5208 request.sleeptime = 0;
5209 request.cmd = INIT_CMD_RUNLVL;
5210 request.runlevel = rl;
5212 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5214 if (errno == ENOENT)
5217 log_error("Failed to open "INIT_FIFO": %m");
5222 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5223 close_nointr_nofail(fd);
5226 log_error("Failed to write to "INIT_FIFO": %m");
5227 return errno ? -errno : -EIO;
5233 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5235 static const struct {
5243 int (* const dispatch)(DBusConnection *bus, char **args);
5245 { "list-units", LESS, 1, list_units },
5246 { "list-unit-files", EQUAL, 1, list_unit_files },
5247 { "list-jobs", EQUAL, 1, list_jobs },
5248 { "clear-jobs", EQUAL, 1, daemon_reload },
5249 { "load", MORE, 2, load_unit },
5250 { "cancel", MORE, 2, cancel_job },
5251 { "start", MORE, 2, start_unit },
5252 { "stop", MORE, 2, start_unit },
5253 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5254 { "reload", MORE, 2, start_unit },
5255 { "restart", MORE, 2, start_unit },
5256 { "try-restart", MORE, 2, start_unit },
5257 { "reload-or-restart", MORE, 2, start_unit },
5258 { "reload-or-try-restart", MORE, 2, start_unit },
5259 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5260 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5261 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5262 { "isolate", EQUAL, 2, start_unit },
5263 { "set-cgroup", MORE, 2, set_cgroup },
5264 { "unset-cgroup", MORE, 2, set_cgroup },
5265 { "set-cgroup-attr", MORE, 2, set_cgroup_attr },
5266 { "unset-cgroup-attr", MORE, 2, set_cgroup },
5267 { "kill", MORE, 2, kill_unit },
5268 { "is-active", MORE, 2, check_unit_active },
5269 { "check", MORE, 2, check_unit_active },
5270 { "is-failed", MORE, 2, check_unit_failed },
5271 { "show", MORE, 1, show },
5272 { "status", MORE, 2, show },
5273 { "help", MORE, 2, show },
5274 { "dump", EQUAL, 1, dump },
5275 { "dot", EQUAL, 1, dot },
5276 { "snapshot", LESS, 2, snapshot },
5277 { "delete", MORE, 2, delete_snapshot },
5278 { "daemon-reload", EQUAL, 1, daemon_reload },
5279 { "daemon-reexec", EQUAL, 1, daemon_reload },
5280 { "show-environment", EQUAL, 1, show_enviroment },
5281 { "set-environment", MORE, 2, set_environment },
5282 { "unset-environment", MORE, 2, set_environment },
5283 { "halt", EQUAL, 1, start_special },
5284 { "poweroff", EQUAL, 1, start_special },
5285 { "reboot", EQUAL, 1, start_special },
5286 { "kexec", EQUAL, 1, start_special },
5287 { "suspend", EQUAL, 1, start_special },
5288 { "hibernate", EQUAL, 1, start_special },
5289 { "hybrid-sleep", EQUAL, 1, start_special },
5290 { "default", EQUAL, 1, start_special },
5291 { "rescue", EQUAL, 1, start_special },
5292 { "emergency", EQUAL, 1, start_special },
5293 { "exit", EQUAL, 1, start_special },
5294 { "reset-failed", MORE, 1, reset_failed },
5295 { "enable", MORE, 2, enable_unit },
5296 { "disable", MORE, 2, enable_unit },
5297 { "is-enabled", MORE, 2, unit_is_enabled },
5298 { "reenable", MORE, 2, enable_unit },
5299 { "preset", MORE, 2, enable_unit },
5300 { "mask", MORE, 2, enable_unit },
5301 { "unmask", MORE, 2, enable_unit },
5302 { "link", MORE, 2, enable_unit },
5303 { "switch-root", MORE, 2, switch_root },
5304 { "list-dependencies", EQUAL, 2, list_dependencies },
5314 left = argc - optind;
5317 /* Special rule: no arguments means "list-units" */
5320 if (streq(argv[optind], "help") && !argv[optind+1]) {
5321 log_error("This command expects one or more "
5322 "unit names. Did you mean --help?");
5326 for (i = 0; i < ELEMENTSOF(verbs); i++)
5327 if (streq(argv[optind], verbs[i].verb))
5330 if (i >= ELEMENTSOF(verbs)) {
5331 log_error("Unknown operation '%s'.", argv[optind]);
5336 switch (verbs[i].argc_cmp) {
5339 if (left != verbs[i].argc) {
5340 log_error("Invalid number of arguments.");
5347 if (left < verbs[i].argc) {
5348 log_error("Too few arguments.");
5355 if (left > verbs[i].argc) {
5356 log_error("Too many arguments.");
5363 assert_not_reached("Unknown comparison operator.");
5366 /* Require a bus connection for all operations but
5368 if (!streq(verbs[i].verb, "enable") &&
5369 !streq(verbs[i].verb, "disable") &&
5370 !streq(verbs[i].verb, "is-enabled") &&
5371 !streq(verbs[i].verb, "list-unit-files") &&
5372 !streq(verbs[i].verb, "reenable") &&
5373 !streq(verbs[i].verb, "preset") &&
5374 !streq(verbs[i].verb, "mask") &&
5375 !streq(verbs[i].verb, "unmask") &&
5376 !streq(verbs[i].verb, "link")) {
5378 if (running_in_chroot() > 0) {
5379 log_info("Running in chroot, ignoring request.");
5383 if (((!streq(verbs[i].verb, "reboot") &&
5384 !streq(verbs[i].verb, "halt") &&
5385 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5386 log_error("Failed to get D-Bus connection: %s",
5387 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5393 if (!bus && !avoid_bus()) {
5394 log_error("Failed to get D-Bus connection: %s",
5395 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5400 return verbs[i].dispatch(bus, argv + optind);
5403 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5405 struct msghdr msghdr;
5406 struct iovec iovec[2];
5407 union sockaddr_union sockaddr;
5408 struct sd_shutdown_command c;
5410 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5417 c.dry_run = dry_run;
5421 sockaddr.sa.sa_family = AF_UNIX;
5422 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5425 msghdr.msg_name = &sockaddr;
5426 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5429 iovec[0].iov_base = (char*) &c;
5430 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5432 if (isempty(message))
5433 msghdr.msg_iovlen = 1;
5435 iovec[1].iov_base = (char*) message;
5436 iovec[1].iov_len = strlen(message);
5437 msghdr.msg_iovlen = 2;
5439 msghdr.msg_iov = iovec;
5441 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5442 close_nointr_nofail(fd);
5446 close_nointr_nofail(fd);
5450 static int reload_with_fallback(DBusConnection *bus) {
5453 /* First, try systemd via D-Bus. */
5454 if (daemon_reload(bus, NULL) >= 0)
5458 /* Nothing else worked, so let's try signals */
5459 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5461 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5462 log_error("kill() failed: %m");
5469 static int start_with_fallback(DBusConnection *bus) {
5472 /* First, try systemd via D-Bus. */
5473 if (start_unit(bus, NULL) >= 0)
5477 /* Hmm, talking to systemd via D-Bus didn't work. Then
5478 * let's try to talk to Upstart via D-Bus. */
5479 if (talk_upstart() > 0)
5482 /* Nothing else worked, so let's try
5484 if (talk_initctl() > 0)
5487 log_error("Failed to talk to init daemon.");
5491 warn_wall(arg_action);
5495 static _noreturn_ void halt_now(enum action a) {
5497 /* Make sure C-A-D is handled by the kernel from this
5499 reboot(RB_ENABLE_CAD);
5504 log_info("Halting.");
5505 reboot(RB_HALT_SYSTEM);
5508 case ACTION_POWEROFF:
5509 log_info("Powering off.");
5510 reboot(RB_POWER_OFF);
5514 log_info("Rebooting.");
5515 reboot(RB_AUTOBOOT);
5519 assert_not_reached("Unknown halt action.");
5522 assert_not_reached("Uh? This shouldn't happen.");
5525 static int halt_main(DBusConnection *bus) {
5528 r = check_inhibitors(bus, arg_action);
5532 if (geteuid() != 0) {
5533 /* Try logind if we are a normal user and no special
5534 * mode applies. Maybe PolicyKit allows us to shutdown
5537 if (arg_when <= 0 &&
5540 (arg_action == ACTION_POWEROFF ||
5541 arg_action == ACTION_REBOOT)) {
5542 r = reboot_with_logind(bus, arg_action);
5547 log_error("Must be root.");
5554 m = strv_join(arg_wall, " ");
5555 r = send_shutdownd(arg_when,
5556 arg_action == ACTION_HALT ? 'H' :
5557 arg_action == ACTION_POWEROFF ? 'P' :
5558 arg_action == ACTION_KEXEC ? 'K' :
5566 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5568 char date[FORMAT_TIMESTAMP_MAX];
5570 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5571 format_timestamp(date, sizeof(date), arg_when));
5576 if (!arg_dry && !arg_force)
5577 return start_with_fallback(bus);
5580 if (sd_booted() > 0)
5581 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5583 r = utmp_put_shutdown();
5585 log_warning("Failed to write utmp record: %s", strerror(-r));
5592 halt_now(arg_action);
5593 /* We should never reach this. */
5597 static int runlevel_main(void) {
5598 int r, runlevel, previous;
5600 r = utmp_get_runlevel(&runlevel, &previous);
5607 previous <= 0 ? 'N' : previous,
5608 runlevel <= 0 ? 'N' : runlevel);
5613 int main(int argc, char*argv[]) {
5614 int r, retval = EXIT_FAILURE;
5615 DBusConnection *bus = NULL;
5618 dbus_error_init(&error);
5620 setlocale(LC_ALL, "");
5621 log_parse_environment();
5624 r = parse_argv(argc, argv);
5628 retval = EXIT_SUCCESS;
5632 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5633 * let's shortcut this */
5634 if (arg_action == ACTION_RUNLEVEL) {
5635 r = runlevel_main();
5636 retval = r < 0 ? EXIT_FAILURE : r;
5640 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5641 log_info("Running in chroot, ignoring request.");
5647 if (arg_transport == TRANSPORT_NORMAL)
5648 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5649 else if (arg_transport == TRANSPORT_POLKIT) {
5650 bus_connect_system_polkit(&bus, &error);
5651 private_bus = false;
5652 } else if (arg_transport == TRANSPORT_SSH) {
5653 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5654 private_bus = false;
5656 assert_not_reached("Uh, invalid transport...");
5659 switch (arg_action) {
5661 case ACTION_SYSTEMCTL:
5662 r = systemctl_main(bus, argc, argv, &error);
5666 case ACTION_POWEROFF:
5672 case ACTION_RUNLEVEL2:
5673 case ACTION_RUNLEVEL3:
5674 case ACTION_RUNLEVEL4:
5675 case ACTION_RUNLEVEL5:
5677 case ACTION_EMERGENCY:
5678 case ACTION_DEFAULT:
5679 r = start_with_fallback(bus);
5684 r = reload_with_fallback(bus);
5687 case ACTION_CANCEL_SHUTDOWN: {
5691 m = strv_join(arg_wall, " ");
5693 retval = EXIT_FAILURE;
5697 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5699 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5704 case ACTION_INVALID:
5705 case ACTION_RUNLEVEL:
5707 assert_not_reached("Unknown action");
5710 retval = r < 0 ? EXIT_FAILURE : r;
5714 dbus_connection_flush(bus);
5715 dbus_connection_close(bus);
5716 dbus_connection_unref(bus);
5719 dbus_error_free(&error);
5723 strv_free(arg_property);
5726 ask_password_agent_close();
5727 polkit_agent_close();