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;
768 path = unit_dbus_path_from_name(name);
774 r = bus_method_call_with_reply(
776 "org.freedesktop.systemd1",
778 "org.freedesktop.DBus.Properties",
782 DBUS_TYPE_STRING, &interface,
787 if (!dbus_message_iter_init(reply, &iter) ||
788 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
789 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
790 log_error("Failed to parse reply.");
795 dbus_message_iter_recurse(&iter, &sub);
797 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
800 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
801 log_error("Failed to parse reply.");
806 dbus_message_iter_recurse(&sub, &sub2);
808 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
809 log_error("Failed to parse reply.");
814 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
815 log_error("Failed to parse reply.");
820 dbus_message_iter_recurse(&sub2, &sub3);
821 dbus_message_iter_next(&sub);
823 if (!nulstr_contains(dependencies, prop))
826 if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
827 if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
828 DBusMessageIter sub4;
829 dbus_message_iter_recurse(&sub3, &sub4);
831 while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
834 assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
835 dbus_message_iter_get_basic(&sub4, &s);
837 r = strv_extend(&ret, s);
843 dbus_message_iter_next(&sub4);
855 static int list_dependencies_compare(const void *_a, const void *_b) {
856 const char **a = (const char**) _a, **b = (const char**) _b;
857 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
859 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
861 return strcasecmp(*a, *b);
864 static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char **units, unsigned int branches) {
870 u = strv_append(units, name);
874 r = list_dependencies_get_dependencies(bus, name, &deps);
878 qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
880 STRV_FOREACH(c, deps) {
881 if (strv_contains(u, *c)) {
882 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
888 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
892 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
893 r = list_dependencies_one(bus, *c, level + 1, u, (branches << 1) | (c[1] == NULL ? 0 : 1));
906 static int list_dependencies(DBusConnection *bus, char **args) {
907 _cleanup_free_ char *unit = NULL;
913 unit = unit_name_mangle(args[1]);
918 u = SPECIAL_DEFAULT_TARGET;
920 pager_open_if_enabled();
924 return list_dependencies_one(bus, u, 0, NULL, 0);
927 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
929 static const char * const colors[] = {
930 "Requires", "[color=\"black\"]",
931 "RequiresOverridable", "[color=\"black\"]",
932 "Requisite", "[color=\"darkblue\"]",
933 "RequisiteOverridable", "[color=\"darkblue\"]",
934 "Wants", "[color=\"grey66\"]",
935 "Conflicts", "[color=\"red\"]",
936 "ConflictedBy", "[color=\"red\"]",
937 "After", "[color=\"green\"]"
940 const char *c = NULL;
947 for (i = 0; i < ELEMENTSOF(colors); i += 2)
948 if (streq(colors[i], prop)) {
956 if (arg_dot != DOT_ALL)
957 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
960 switch (dbus_message_iter_get_arg_type(iter)) {
962 case DBUS_TYPE_ARRAY:
964 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
967 dbus_message_iter_recurse(iter, &sub);
969 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
972 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
973 dbus_message_iter_get_basic(&sub, &s);
974 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
976 dbus_message_iter_next(&sub);
986 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
987 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
988 const char *interface = "org.freedesktop.systemd1.Unit";
990 DBusMessageIter iter, sub, sub2, sub3;
995 r = bus_method_call_with_reply(
997 "org.freedesktop.systemd1",
999 "org.freedesktop.DBus.Properties",
1003 DBUS_TYPE_STRING, &interface,
1008 if (!dbus_message_iter_init(reply, &iter) ||
1009 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1010 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
1011 log_error("Failed to parse reply.");
1015 dbus_message_iter_recurse(&iter, &sub);
1017 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1020 assert(dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY);
1021 dbus_message_iter_recurse(&sub, &sub2);
1023 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0 ||
1024 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
1025 log_error("Failed to parse reply.");
1029 dbus_message_iter_recurse(&sub2, &sub3);
1030 r = dot_one_property(name, prop, &sub3);
1034 dbus_message_iter_next(&sub);
1040 static int dot(DBusConnection *bus, char **args) {
1041 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1042 DBusMessageIter iter, sub, sub2;
1045 r = bus_method_call_with_reply(
1047 "org.freedesktop.systemd1",
1048 "/org/freedesktop/systemd1",
1049 "org.freedesktop.systemd1.Manager",
1057 if (!dbus_message_iter_init(reply, &iter) ||
1058 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1059 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1060 log_error("Failed to parse reply.");
1064 printf("digraph systemd {\n");
1066 dbus_message_iter_recurse(&iter, &sub);
1067 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1068 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
1070 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1071 log_error("Failed to parse reply.");
1075 dbus_message_iter_recurse(&sub, &sub2);
1077 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
1078 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
1079 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
1080 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
1081 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
1082 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
1083 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
1084 log_error("Failed to parse reply.");
1088 r = dot_one(bus, id, unit_path);
1092 /* printf("\t\"%s\";\n", id); */
1093 dbus_message_iter_next(&sub);
1098 log_info(" Color legend: black = Requires\n"
1099 " dark blue = Requisite\n"
1100 " dark grey = Wants\n"
1101 " red = Conflicts\n"
1102 " green = After\n");
1105 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
1106 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
1111 static int list_jobs(DBusConnection *bus, char **args) {
1112 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1113 DBusMessageIter iter, sub, sub2;
1117 pager_open_if_enabled();
1119 r = bus_method_call_with_reply(
1121 "org.freedesktop.systemd1",
1122 "/org/freedesktop/systemd1",
1123 "org.freedesktop.systemd1.Manager",
1131 if (!dbus_message_iter_init(reply, &iter) ||
1132 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1133 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1134 log_error("Failed to parse reply.");
1138 dbus_message_iter_recurse(&iter, &sub);
1141 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
1143 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1144 const char *name, *type, *state, *job_path, *unit_path;
1148 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1149 log_error("Failed to parse reply.");
1153 dbus_message_iter_recurse(&sub, &sub2);
1155 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1156 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1157 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1158 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1159 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1160 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1161 log_error("Failed to parse reply.");
1165 e = arg_full ? NULL : ellipsize(name, 25, 33);
1166 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1171 dbus_message_iter_next(&sub);
1175 printf("\n%u jobs listed.\n", k);
1180 static int load_unit(DBusConnection *bus, char **args) {
1185 STRV_FOREACH(name, args+1) {
1186 _cleanup_free_ char *n = NULL;
1189 n = unit_name_mangle(*name);
1193 r = bus_method_call_with_reply(
1195 "org.freedesktop.systemd1",
1196 "/org/freedesktop/systemd1",
1197 "org.freedesktop.systemd1.Manager",
1201 DBUS_TYPE_STRING, &n,
1210 static int cancel_job(DBusConnection *bus, char **args) {
1215 if (strv_length(args) <= 1)
1216 return daemon_reload(bus, args);
1218 STRV_FOREACH(name, args+1) {
1222 r = safe_atou32(*name, &id);
1224 log_error("Failed to parse job id: %s", strerror(-r));
1228 r = bus_method_call_with_reply(
1230 "org.freedesktop.systemd1",
1231 "/org/freedesktop/systemd1",
1232 "org.freedesktop.systemd1.Manager",
1236 DBUS_TYPE_UINT32, &id,
1245 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1246 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1247 dbus_bool_t b = FALSE;
1248 DBusMessageIter iter, sub;
1250 *interface = "org.freedesktop.systemd1.Unit",
1251 *property = "NeedDaemonReload",
1253 _cleanup_free_ char *n = NULL;
1256 /* We ignore all errors here, since this is used to show a warning only */
1258 n = unit_name_mangle(unit);
1262 r = bus_method_call_with_reply (
1264 "org.freedesktop.systemd1",
1265 "/org/freedesktop/systemd1",
1266 "org.freedesktop.systemd1.Manager",
1270 DBUS_TYPE_STRING, &n,
1275 if (!dbus_message_get_args(reply, NULL,
1276 DBUS_TYPE_OBJECT_PATH, &path,
1280 dbus_message_unref(reply);
1283 r = bus_method_call_with_reply(
1285 "org.freedesktop.systemd1",
1287 "org.freedesktop.DBus.Properties",
1291 DBUS_TYPE_STRING, &interface,
1292 DBUS_TYPE_STRING, &property,
1297 if (!dbus_message_iter_init(reply, &iter) ||
1298 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1301 dbus_message_iter_recurse(&iter, &sub);
1302 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1305 dbus_message_iter_get_basic(&sub, &b);
1309 typedef struct WaitData {
1316 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1324 dbus_error_init(&error);
1326 log_debug("Got D-Bus request: %s.%s() on %s",
1327 dbus_message_get_interface(message),
1328 dbus_message_get_member(message),
1329 dbus_message_get_path(message));
1331 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1332 log_error("Warning! D-Bus connection terminated.");
1333 dbus_connection_close(connection);
1335 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1337 const char *path, *result, *unit;
1339 if (dbus_message_get_args(message, &error,
1340 DBUS_TYPE_UINT32, &id,
1341 DBUS_TYPE_OBJECT_PATH, &path,
1342 DBUS_TYPE_STRING, &unit,
1343 DBUS_TYPE_STRING, &result,
1344 DBUS_TYPE_INVALID)) {
1346 free(set_remove(d->set, (char*) path));
1348 if (!isempty(result))
1349 d->result = strdup(result);
1352 d->name = strdup(unit);
1357 dbus_error_free(&error);
1358 if (dbus_message_get_args(message, &error,
1359 DBUS_TYPE_UINT32, &id,
1360 DBUS_TYPE_OBJECT_PATH, &path,
1361 DBUS_TYPE_STRING, &result,
1362 DBUS_TYPE_INVALID)) {
1363 /* Compatibility with older systemd versions <
1364 * 183 during upgrades. This should be dropped
1366 free(set_remove(d->set, (char*) path));
1369 d->result = strdup(result);
1375 log_error("Failed to parse message: %s", bus_error_message(&error));
1379 dbus_error_free(&error);
1380 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1383 static int enable_wait_for_jobs(DBusConnection *bus) {
1391 dbus_error_init(&error);
1392 dbus_bus_add_match(bus,
1394 "sender='org.freedesktop.systemd1',"
1395 "interface='org.freedesktop.systemd1.Manager',"
1396 "member='JobRemoved',"
1397 "path='/org/freedesktop/systemd1'",
1400 if (dbus_error_is_set(&error)) {
1401 log_error("Failed to add match: %s", bus_error_message(&error));
1402 dbus_error_free(&error);
1406 /* This is slightly dirty, since we don't undo the match registrations. */
1410 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1420 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1423 while (!set_isempty(s)) {
1425 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1426 log_error("Disconnected from bus.");
1427 return -ECONNREFUSED;
1434 if (streq(d.result, "timeout"))
1435 log_error("Job for %s timed out.", strna(d.name));
1436 else if (streq(d.result, "canceled"))
1437 log_error("Job for %s canceled.", strna(d.name));
1438 else if (streq(d.result, "dependency"))
1439 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1440 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1441 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1444 if (streq_ptr(d.result, "timeout"))
1446 else if (streq_ptr(d.result, "canceled"))
1448 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1459 dbus_connection_remove_filter(bus, wait_filter, &d);
1463 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1464 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1465 _cleanup_free_ char *n = NULL;
1466 DBusMessageIter iter, sub;
1468 *interface = "org.freedesktop.systemd1.Unit",
1469 *property = "ActiveState";
1470 const char *state, *path;
1476 dbus_error_init(&error);
1478 n = unit_name_mangle(name);
1482 r = bus_method_call_with_reply (
1484 "org.freedesktop.systemd1",
1485 "/org/freedesktop/systemd1",
1486 "org.freedesktop.systemd1.Manager",
1490 DBUS_TYPE_STRING, &n,
1493 dbus_error_free(&error);
1500 if (!dbus_message_get_args(reply, NULL,
1501 DBUS_TYPE_OBJECT_PATH, &path,
1502 DBUS_TYPE_INVALID)) {
1503 log_error("Failed to parse reply.");
1507 dbus_message_unref(reply);
1510 r = bus_method_call_with_reply(
1512 "org.freedesktop.systemd1",
1514 "org.freedesktop.DBus.Properties",
1518 DBUS_TYPE_STRING, &interface,
1519 DBUS_TYPE_STRING, &property,
1527 if (!dbus_message_iter_init(reply, &iter) ||
1528 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1529 log_error("Failed to parse reply.");
1533 dbus_message_iter_recurse(&iter, &sub);
1535 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1536 log_error("Failed to parse reply.");
1540 dbus_message_iter_get_basic(&sub, &state);
1545 return strv_find(check_states, state) ? 1 : 0;
1548 static void check_triggering_units(
1549 DBusConnection *bus,
1550 const char *unit_name) {
1552 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1553 DBusMessageIter iter, sub;
1554 const char *interface = "org.freedesktop.systemd1.Unit",
1555 *triggered_by_property = "TriggeredBy";
1556 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1557 bool print_warning_label = true;
1560 n = unit_name_mangle(unit_name);
1566 unit_path = unit_dbus_path_from_name(n);
1572 r = bus_method_call_with_reply(
1574 "org.freedesktop.systemd1",
1576 "org.freedesktop.DBus.Properties",
1580 DBUS_TYPE_STRING, &interface,
1581 DBUS_TYPE_STRING, &triggered_by_property,
1586 if (!dbus_message_iter_init(reply, &iter) ||
1587 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1588 log_error("Failed to parse reply.");
1592 dbus_message_iter_recurse(&iter, &sub);
1593 dbus_message_iter_recurse(&sub, &iter);
1596 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1597 const char * const check_states[] = {
1602 const char *service_trigger;
1604 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1605 log_error("Failed to parse reply.");
1609 dbus_message_iter_get_basic(&sub, &service_trigger);
1611 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1615 if (print_warning_label) {
1616 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1617 print_warning_label = false;
1620 log_warning(" %s", service_trigger);
1623 dbus_message_iter_next(&sub);
1627 static int start_unit_one(
1628 DBusConnection *bus,
1635 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1636 _cleanup_free_ char *n;
1645 n = unit_name_mangle(name);
1649 r = bus_method_call_with_reply(
1651 "org.freedesktop.systemd1",
1652 "/org/freedesktop/systemd1",
1653 "org.freedesktop.systemd1.Manager",
1657 DBUS_TYPE_STRING, &n,
1658 DBUS_TYPE_STRING, &mode,
1661 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1662 /* There's always a fallback possible for
1663 * legacy actions. */
1666 log_error("Failed to issue method call: %s", bus_error_message(error));
1671 if (!dbus_message_get_args(reply, error,
1672 DBUS_TYPE_OBJECT_PATH, &path,
1673 DBUS_TYPE_INVALID)) {
1674 log_error("Failed to parse reply: %s", bus_error_message(error));
1678 if (need_daemon_reload(bus, n))
1679 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1680 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1692 log_error("Failed to add path to set.");
1700 static enum action verb_to_action(const char *verb) {
1701 if (streq(verb, "halt"))
1703 else if (streq(verb, "poweroff"))
1704 return ACTION_POWEROFF;
1705 else if (streq(verb, "reboot"))
1706 return ACTION_REBOOT;
1707 else if (streq(verb, "kexec"))
1708 return ACTION_KEXEC;
1709 else if (streq(verb, "rescue"))
1710 return ACTION_RESCUE;
1711 else if (streq(verb, "emergency"))
1712 return ACTION_EMERGENCY;
1713 else if (streq(verb, "default"))
1714 return ACTION_DEFAULT;
1715 else if (streq(verb, "exit"))
1717 else if (streq(verb, "suspend"))
1718 return ACTION_SUSPEND;
1719 else if (streq(verb, "hibernate"))
1720 return ACTION_HIBERNATE;
1721 else if (streq(verb, "hybrid-sleep"))
1722 return ACTION_HYBRID_SLEEP;
1724 return ACTION_INVALID;
1727 static int start_unit(DBusConnection *bus, char **args) {
1729 static const char * const table[_ACTION_MAX] = {
1730 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1731 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1732 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1733 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1734 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1735 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1736 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1737 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1738 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1739 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1740 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1741 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1742 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1743 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
1744 [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
1748 const char *method, *mode, *one_name;
1753 dbus_error_init(&error);
1757 ask_password_agent_open_if_enabled();
1759 if (arg_action == ACTION_SYSTEMCTL) {
1761 streq(args[0], "stop") ||
1762 streq(args[0], "condstop") ? "StopUnit" :
1763 streq(args[0], "reload") ? "ReloadUnit" :
1764 streq(args[0], "restart") ? "RestartUnit" :
1766 streq(args[0], "try-restart") ||
1767 streq(args[0], "condrestart") ? "TryRestartUnit" :
1769 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1771 streq(args[0], "reload-or-try-restart") ||
1772 streq(args[0], "condreload") ||
1774 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1778 (streq(args[0], "isolate") ||
1779 streq(args[0], "rescue") ||
1780 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1782 one_name = table[verb_to_action(args[0])];
1785 assert(arg_action < ELEMENTSOF(table));
1786 assert(table[arg_action]);
1788 method = "StartUnit";
1790 mode = (arg_action == ACTION_EMERGENCY ||
1791 arg_action == ACTION_RESCUE ||
1792 arg_action == ACTION_RUNLEVEL2 ||
1793 arg_action == ACTION_RUNLEVEL3 ||
1794 arg_action == ACTION_RUNLEVEL4 ||
1795 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1797 one_name = table[arg_action];
1800 if (!arg_no_block) {
1801 ret = enable_wait_for_jobs(bus);
1803 log_error("Could not watch jobs: %s", strerror(-ret));
1807 s = set_new(string_hash_func, string_compare_func);
1815 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1817 ret = translate_bus_error_to_exit_status(ret, &error);
1819 STRV_FOREACH(name, args+1) {
1820 r = start_unit_one(bus, method, *name, mode, &error, s);
1822 ret = translate_bus_error_to_exit_status(r, &error);
1823 dbus_error_free(&error);
1828 if (!arg_no_block) {
1829 r = wait_for_jobs(bus, s);
1835 /* When stopping units, warn if they can still be triggered by
1836 * another active unit (socket, path, timer) */
1837 if (!arg_quiet && streq(method, "StopUnit")) {
1839 check_triggering_units(bus, one_name);
1841 STRV_FOREACH(name, args+1)
1842 check_triggering_units(bus, *name);
1848 dbus_error_free(&error);
1853 /* Ask systemd-logind, which might grant access to unprivileged users
1854 * through PolicyKit */
1855 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1858 dbus_bool_t interactive = true;
1863 polkit_agent_open_if_enabled();
1871 case ACTION_POWEROFF:
1872 method = "PowerOff";
1875 case ACTION_SUSPEND:
1879 case ACTION_HIBERNATE:
1880 method = "Hibernate";
1883 case ACTION_HYBRID_SLEEP:
1884 method = "HybridSleep";
1891 return bus_method_call_with_reply(
1893 "org.freedesktop.login1",
1894 "/org/freedesktop/login1",
1895 "org.freedesktop.login1.Manager",
1899 DBUS_TYPE_BOOLEAN, &interactive,
1906 static int check_inhibitors(DBusConnection *bus, enum action a) {
1908 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1909 DBusMessageIter iter, sub, sub2;
1912 _cleanup_strv_free_ char **sessions = NULL;
1918 if (arg_ignore_inhibitors || arg_force > 0)
1930 r = bus_method_call_with_reply(
1932 "org.freedesktop.login1",
1933 "/org/freedesktop/login1",
1934 "org.freedesktop.login1.Manager",
1940 /* If logind is not around, then there are no inhibitors... */
1943 if (!dbus_message_iter_init(reply, &iter) ||
1944 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1945 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1946 log_error("Failed to parse reply.");
1950 dbus_message_iter_recurse(&iter, &sub);
1951 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1952 const char *what, *who, *why, *mode;
1954 _cleanup_strv_free_ char **sv = NULL;
1955 _cleanup_free_ char *comm = NULL, *user = NULL;
1957 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1958 log_error("Failed to parse reply.");
1962 dbus_message_iter_recurse(&sub, &sub2);
1964 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
1965 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
1966 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
1967 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
1968 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
1969 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
1970 log_error("Failed to parse reply.");
1974 if (!streq(mode, "block"))
1977 sv = strv_split(what, ":");
1981 if (!strv_contains(sv,
1983 a == ACTION_POWEROFF ||
1984 a == ACTION_REBOOT ||
1985 a == ACTION_KEXEC ? "shutdown" : "sleep"))
1988 get_process_comm(pid, &comm);
1989 user = uid_to_name(uid);
1990 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
1991 who, (unsigned long) pid, strna(comm), strna(user), why);
1995 dbus_message_iter_next(&sub);
1998 dbus_message_iter_recurse(&iter, &sub);
2000 /* Check for current sessions */
2001 sd_get_sessions(&sessions);
2002 STRV_FOREACH(s, sessions) {
2004 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
2006 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
2009 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
2012 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
2015 sd_session_get_tty(*s, &tty);
2016 sd_session_get_seat(*s, &seat);
2017 sd_session_get_service(*s, &service);
2018 user = uid_to_name(uid);
2020 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
2027 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
2028 a == ACTION_HALT ? "halt" :
2029 a == ACTION_POWEROFF ? "poweroff" :
2030 a == ACTION_REBOOT ? "reboot" :
2031 a == ACTION_KEXEC ? "kexec" :
2032 a == ACTION_SUSPEND ? "suspend" :
2033 a == ACTION_HIBERNATE ? "hibernate" : "hybrid-sleep");
2041 static int start_special(DBusConnection *bus, char **args) {
2047 a = verb_to_action(args[0]);
2049 r = check_inhibitors(bus, a);
2053 if (arg_force >= 2 && geteuid() != 0) {
2054 log_error("Must be root.");
2058 if (arg_force >= 2 &&
2059 (a == ACTION_HALT ||
2060 a == ACTION_POWEROFF ||
2061 a == ACTION_REBOOT))
2064 if (arg_force >= 1 &&
2065 (a == ACTION_HALT ||
2066 a == ACTION_POWEROFF ||
2067 a == ACTION_REBOOT ||
2068 a == ACTION_KEXEC ||
2070 return daemon_reload(bus, args);
2072 /* first try logind, to allow authentication with polkit */
2073 if (geteuid() != 0 &&
2074 (a == ACTION_POWEROFF ||
2075 a == ACTION_REBOOT ||
2076 a == ACTION_SUSPEND ||
2077 a == ACTION_HIBERNATE ||
2078 a == ACTION_HYBRID_SLEEP)) {
2079 r = reboot_with_logind(bus, a);
2084 r = start_unit(bus, args);
2091 static int check_unit_active(DBusConnection *bus, char **args) {
2092 const char * const check_states[] = {
2099 int r = 3; /* According to LSB: "program is not running" */
2104 STRV_FOREACH(name, args+1) {
2107 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2117 static int check_unit_failed(DBusConnection *bus, char **args) {
2118 const char * const check_states[] = {
2129 STRV_FOREACH(name, args+1) {
2132 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2142 static int kill_unit(DBusConnection *bus, char **args) {
2150 arg_kill_who = "all";
2152 STRV_FOREACH(name, args+1) {
2153 _cleanup_free_ char *n = NULL;
2155 n = unit_name_mangle(*name);
2159 r = bus_method_call_with_reply(
2161 "org.freedesktop.systemd1",
2162 "/org/freedesktop/systemd1",
2163 "org.freedesktop.systemd1.Manager",
2167 DBUS_TYPE_STRING, &n,
2168 DBUS_TYPE_STRING, &arg_kill_who,
2169 DBUS_TYPE_INT32, &arg_signal,
2177 static int set_cgroup(DBusConnection *bus, char **args) {
2178 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2181 DBusMessageIter iter;
2183 _cleanup_free_ char *n = NULL;
2188 dbus_error_init(&error);
2191 streq(args[0], "set-cgroup") ? "SetUnitControlGroups" :
2192 streq(args[0], "unset-group") ? "UnsetUnitControlGroups"
2193 : "UnsetUnitControlGroupAttributes";
2195 n = unit_name_mangle(args[1]);
2199 m = dbus_message_new_method_call(
2200 "org.freedesktop.systemd1",
2201 "/org/freedesktop/systemd1",
2202 "org.freedesktop.systemd1.Manager",
2207 dbus_message_iter_init_append(m, &iter);
2208 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
2211 r = bus_append_strv_iter(&iter, args + 2);
2215 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2217 log_error("Failed to issue method call: %s", bus_error_message(&error));
2218 dbus_error_free(&error);
2225 static int set_cgroup_attr(DBusConnection *bus, char **args) {
2226 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2228 DBusMessageIter iter, sub, sub2;
2230 _cleanup_free_ char *n = NULL;
2235 dbus_error_init(&error);
2237 if (strv_length(args) % 2 != 0) {
2238 log_error("Expecting an uneven number of arguments!");
2242 n = unit_name_mangle(args[1]);
2246 m = dbus_message_new_method_call(
2247 "org.freedesktop.systemd1",
2248 "/org/freedesktop/systemd1",
2249 "org.freedesktop.systemd1.Manager",
2250 "SetUnitControlGroupAttributes");
2254 dbus_message_iter_init_append(m, &iter);
2255 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2256 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub))
2259 STRV_FOREACH_PAIR(x, y, args + 2) {
2260 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
2261 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, x) ||
2262 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, y) ||
2263 !dbus_message_iter_close_container(&sub, &sub2))
2267 if (!dbus_message_iter_close_container(&iter, &sub))
2270 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2272 log_error("Failed to issue method call: %s", bus_error_message(&error));
2273 dbus_error_free(&error);
2280 typedef struct ExecStatusInfo {
2288 usec_t start_timestamp;
2289 usec_t exit_timestamp;
2294 LIST_FIELDS(struct ExecStatusInfo, exec);
2297 static void exec_status_info_free(ExecStatusInfo *i) {
2306 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2307 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2308 DBusMessageIter sub2, sub3;
2312 int32_t code, status;
2318 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2321 dbus_message_iter_recurse(sub, &sub2);
2323 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2326 i->path = strdup(path);
2330 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2331 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2335 dbus_message_iter_recurse(&sub2, &sub3);
2336 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2337 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2338 dbus_message_iter_next(&sub3);
2342 i->argv = new0(char*, n+1);
2347 dbus_message_iter_recurse(&sub2, &sub3);
2348 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2351 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2352 dbus_message_iter_get_basic(&sub3, &s);
2353 dbus_message_iter_next(&sub3);
2355 i->argv[n] = strdup(s);
2362 if (!dbus_message_iter_next(&sub2) ||
2363 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2364 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2365 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2366 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2367 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2368 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2369 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2370 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2374 i->start_timestamp = (usec_t) start_timestamp;
2375 i->exit_timestamp = (usec_t) exit_timestamp;
2376 i->pid = (pid_t) pid;
2383 typedef struct UnitStatusInfo {
2385 const char *load_state;
2386 const char *active_state;
2387 const char *sub_state;
2388 const char *unit_file_state;
2390 const char *description;
2391 const char *following;
2393 char **documentation;
2395 const char *fragment_path;
2396 const char *source_path;
2397 const char *default_control_group;
2399 const char *load_error;
2402 usec_t inactive_exit_timestamp;
2403 usec_t inactive_exit_timestamp_monotonic;
2404 usec_t active_enter_timestamp;
2405 usec_t active_exit_timestamp;
2406 usec_t inactive_enter_timestamp;
2408 bool need_daemon_reload;
2413 const char *status_text;
2416 usec_t start_timestamp;
2417 usec_t exit_timestamp;
2419 int exit_code, exit_status;
2421 usec_t condition_timestamp;
2422 bool condition_result;
2425 unsigned n_accepted;
2426 unsigned n_connections;
2430 const char *sysfs_path;
2432 /* Mount, Automount */
2438 LIST_HEAD(ExecStatusInfo, exec);
2441 static void print_status_info(UnitStatusInfo *i) {
2443 const char *on, *off, *ss;
2445 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2446 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2449 arg_all * OUTPUT_SHOW_ALL |
2450 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2451 on_tty() * OUTPUT_COLOR |
2452 !arg_quiet * OUTPUT_WARN_CUTOFF |
2453 arg_full * OUTPUT_FULL_WIDTH;
2457 /* This shows pretty information about a unit. See
2458 * print_property() for a low-level property printer */
2460 printf("%s", strna(i->id));
2462 if (i->description && !streq_ptr(i->id, i->description))
2463 printf(" - %s", i->description);
2468 printf("\t Follow: unit currently follows state of %s\n", i->following);
2470 if (streq_ptr(i->load_state, "error")) {
2471 on = ansi_highlight_red(true);
2472 off = ansi_highlight_red(false);
2476 path = i->source_path ? i->source_path : i->fragment_path;
2479 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2480 else if (path && i->unit_file_state)
2481 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2483 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2485 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2487 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2489 if (streq_ptr(i->active_state, "failed")) {
2490 on = ansi_highlight_red(true);
2491 off = ansi_highlight_red(false);
2492 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2493 on = ansi_highlight_green(true);
2494 off = ansi_highlight_green(false);
2499 printf("\t Active: %s%s (%s)%s",
2501 strna(i->active_state),
2505 printf("\t Active: %s%s%s",
2507 strna(i->active_state),
2510 if (!isempty(i->result) && !streq(i->result, "success"))
2511 printf(" (Result: %s)", i->result);
2513 timestamp = (streq_ptr(i->active_state, "active") ||
2514 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2515 (streq_ptr(i->active_state, "inactive") ||
2516 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2517 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2518 i->active_exit_timestamp;
2520 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2521 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2524 printf(" since %s; %s\n", s2, s1);
2526 printf(" since %s\n", s2);
2530 if (!i->condition_result && i->condition_timestamp > 0) {
2531 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2532 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2535 printf("\t start condition failed at %s; %s\n", s2, s1);
2537 printf("\t start condition failed at %s\n", s2);
2541 printf("\t Device: %s\n", i->sysfs_path);
2543 printf("\t Where: %s\n", i->where);
2545 printf("\t What: %s\n", i->what);
2547 if (!strv_isempty(i->documentation)) {
2551 STRV_FOREACH(t, i->documentation) {
2553 printf("\t Docs: %s\n", *t);
2556 printf("\t %s\n", *t);
2561 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2563 LIST_FOREACH(exec, p, i->exec) {
2564 _cleanup_free_ char *t = NULL;
2567 /* Only show exited processes here */
2571 t = strv_join(p->argv, " ");
2572 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2574 good = is_clean_exit_lsb(p->code, p->status, NULL);
2576 on = ansi_highlight_red(true);
2577 off = ansi_highlight_red(false);
2581 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2583 if (p->code == CLD_EXITED) {
2586 printf("status=%i", p->status);
2588 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2593 printf("signal=%s", signal_to_string(p->status));
2595 printf(")%s\n", off);
2597 if (i->main_pid == p->pid &&
2598 i->start_timestamp == p->start_timestamp &&
2599 i->exit_timestamp == p->start_timestamp)
2600 /* Let's not show this twice */
2603 if (p->pid == i->control_pid)
2607 if (i->main_pid > 0 || i->control_pid > 0) {
2610 if (i->main_pid > 0) {
2611 printf("Main PID: %u", (unsigned) i->main_pid);
2614 _cleanup_free_ char *t = NULL;
2615 get_process_comm(i->main_pid, &t);
2618 } else if (i->exit_code > 0) {
2619 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2621 if (i->exit_code == CLD_EXITED) {
2624 printf("status=%i", i->exit_status);
2626 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2631 printf("signal=%s", signal_to_string(i->exit_status));
2636 if (i->main_pid > 0 && i->control_pid > 0)
2639 if (i->control_pid > 0) {
2640 _cleanup_free_ char *t = NULL;
2642 printf(" Control: %u", (unsigned) i->control_pid);
2644 get_process_comm(i->control_pid, &t);
2653 printf("\t Status: \"%s\"\n", i->status_text);
2655 if (i->default_control_group &&
2656 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2659 printf("\t CGroup: %s\n", i->default_control_group);
2661 if (arg_transport != TRANSPORT_SSH) {
2671 if (i->main_pid > 0)
2672 extra[k++] = i->main_pid;
2674 if (i->control_pid > 0)
2675 extra[k++] = i->control_pid;
2677 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, extra, k, flags);
2681 if (i->id && arg_transport != TRANSPORT_SSH) {
2683 show_journal_by_unit(stdout,
2687 i->inactive_exit_timestamp_monotonic,
2692 if (i->need_daemon_reload)
2693 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2694 ansi_highlight_red(true),
2695 ansi_highlight_red(false),
2696 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2699 static void show_unit_help(UnitStatusInfo *i) {
2704 if (!i->documentation) {
2705 log_info("Documentation for %s not known.", i->id);
2709 STRV_FOREACH(p, i->documentation) {
2711 if (startswith(*p, "man:")) {
2714 char *page = NULL, *section = NULL;
2715 const char *args[4] = { "man", NULL, NULL, NULL };
2720 if ((*p)[k-1] == ')')
2721 e = strrchr(*p, '(');
2724 page = strndup((*p) + 4, e - *p - 4);
2730 section = strndup(e + 1, *p + k - e - 2);
2744 log_error("Failed to fork: %m");
2752 execvp(args[0], (char**) args);
2753 log_error("Failed to execute man: %m");
2754 _exit(EXIT_FAILURE);
2760 wait_for_terminate(pid, NULL);
2762 log_info("Can't show: %s", *p);
2766 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2772 switch (dbus_message_iter_get_arg_type(iter)) {
2774 case DBUS_TYPE_STRING: {
2777 dbus_message_iter_get_basic(iter, &s);
2780 if (streq(name, "Id"))
2782 else if (streq(name, "LoadState"))
2784 else if (streq(name, "ActiveState"))
2785 i->active_state = s;
2786 else if (streq(name, "SubState"))
2788 else if (streq(name, "Description"))
2790 else if (streq(name, "FragmentPath"))
2791 i->fragment_path = s;
2792 else if (streq(name, "SourcePath"))
2794 else if (streq(name, "DefaultControlGroup"))
2795 i->default_control_group = s;
2796 else if (streq(name, "StatusText"))
2798 else if (streq(name, "SysFSPath"))
2800 else if (streq(name, "Where"))
2802 else if (streq(name, "What"))
2804 else if (streq(name, "Following"))
2806 else if (streq(name, "UnitFileState"))
2807 i->unit_file_state = s;
2808 else if (streq(name, "Result"))
2815 case DBUS_TYPE_BOOLEAN: {
2818 dbus_message_iter_get_basic(iter, &b);
2820 if (streq(name, "Accept"))
2822 else if (streq(name, "NeedDaemonReload"))
2823 i->need_daemon_reload = b;
2824 else if (streq(name, "ConditionResult"))
2825 i->condition_result = b;
2830 case DBUS_TYPE_UINT32: {
2833 dbus_message_iter_get_basic(iter, &u);
2835 if (streq(name, "MainPID")) {
2837 i->main_pid = (pid_t) u;
2840 } else if (streq(name, "ControlPID"))
2841 i->control_pid = (pid_t) u;
2842 else if (streq(name, "ExecMainPID")) {
2844 i->main_pid = (pid_t) u;
2845 } else if (streq(name, "NAccepted"))
2847 else if (streq(name, "NConnections"))
2848 i->n_connections = u;
2853 case DBUS_TYPE_INT32: {
2856 dbus_message_iter_get_basic(iter, &j);
2858 if (streq(name, "ExecMainCode"))
2859 i->exit_code = (int) j;
2860 else if (streq(name, "ExecMainStatus"))
2861 i->exit_status = (int) j;
2866 case DBUS_TYPE_UINT64: {
2869 dbus_message_iter_get_basic(iter, &u);
2871 if (streq(name, "ExecMainStartTimestamp"))
2872 i->start_timestamp = (usec_t) u;
2873 else if (streq(name, "ExecMainExitTimestamp"))
2874 i->exit_timestamp = (usec_t) u;
2875 else if (streq(name, "ActiveEnterTimestamp"))
2876 i->active_enter_timestamp = (usec_t) u;
2877 else if (streq(name, "InactiveEnterTimestamp"))
2878 i->inactive_enter_timestamp = (usec_t) u;
2879 else if (streq(name, "InactiveExitTimestamp"))
2880 i->inactive_exit_timestamp = (usec_t) u;
2881 else if (streq(name, "InactiveExitTimestampMonotonic"))
2882 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2883 else if (streq(name, "ActiveExitTimestamp"))
2884 i->active_exit_timestamp = (usec_t) u;
2885 else if (streq(name, "ConditionTimestamp"))
2886 i->condition_timestamp = (usec_t) u;
2891 case DBUS_TYPE_ARRAY: {
2893 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2894 startswith(name, "Exec")) {
2895 DBusMessageIter sub;
2897 dbus_message_iter_recurse(iter, &sub);
2898 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2899 ExecStatusInfo *info;
2902 if (!(info = new0(ExecStatusInfo, 1)))
2905 if (!(info->name = strdup(name))) {
2910 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2915 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2917 dbus_message_iter_next(&sub);
2919 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2920 streq(name, "Documentation")) {
2922 DBusMessageIter sub;
2924 dbus_message_iter_recurse(iter, &sub);
2925 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2929 dbus_message_iter_get_basic(&sub, &s);
2931 l = strv_append(i->documentation, s);
2935 strv_free(i->documentation);
2936 i->documentation = l;
2938 dbus_message_iter_next(&sub);
2945 case DBUS_TYPE_STRUCT: {
2947 if (streq(name, "LoadError")) {
2948 DBusMessageIter sub;
2949 const char *n, *message;
2952 dbus_message_iter_recurse(iter, &sub);
2954 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2958 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2962 if (!isempty(message))
2963 i->load_error = message;
2973 static int print_property(const char *name, DBusMessageIter *iter) {
2977 /* This is a low-level property printer, see
2978 * print_status_info() for the nicer output */
2980 if (arg_property && !strv_find(arg_property, name))
2983 switch (dbus_message_iter_get_arg_type(iter)) {
2985 case DBUS_TYPE_STRUCT: {
2986 DBusMessageIter sub;
2987 dbus_message_iter_recurse(iter, &sub);
2989 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2992 dbus_message_iter_get_basic(&sub, &u);
2995 printf("%s=%u\n", name, (unsigned) u);
2997 printf("%s=\n", name);
3000 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
3003 dbus_message_iter_get_basic(&sub, &s);
3005 if (arg_all || s[0])
3006 printf("%s=%s\n", name, s);
3009 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
3010 const char *a = NULL, *b = NULL;
3012 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
3013 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
3015 if (arg_all || !isempty(a) || !isempty(b))
3016 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3024 case DBUS_TYPE_ARRAY:
3026 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
3027 DBusMessageIter sub, sub2;
3029 dbus_message_iter_recurse(iter, &sub);
3030 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3034 dbus_message_iter_recurse(&sub, &sub2);
3036 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3037 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3038 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3040 dbus_message_iter_next(&sub);
3045 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3046 DBusMessageIter sub, sub2;
3048 dbus_message_iter_recurse(iter, &sub);
3049 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3050 const char *type, *path;
3052 dbus_message_iter_recurse(&sub, &sub2);
3054 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3055 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3056 printf("%s=%s\n", type, path);
3058 dbus_message_iter_next(&sub);
3063 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3064 DBusMessageIter sub, sub2;
3066 dbus_message_iter_recurse(iter, &sub);
3067 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3069 uint64_t value, next_elapse;
3071 dbus_message_iter_recurse(&sub, &sub2);
3073 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3074 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3075 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3076 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3078 printf("%s={ value=%s ; next_elapse=%s }\n",
3080 format_timespan(timespan1, sizeof(timespan1), value),
3081 format_timespan(timespan2, sizeof(timespan2), next_elapse));
3084 dbus_message_iter_next(&sub);
3089 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
3090 DBusMessageIter sub, sub2;
3092 dbus_message_iter_recurse(iter, &sub);
3093 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3094 const char *controller, *attr, *value;
3096 dbus_message_iter_recurse(&sub, &sub2);
3098 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
3099 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
3100 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
3102 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
3108 dbus_message_iter_next(&sub);
3113 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3114 DBusMessageIter sub;
3116 dbus_message_iter_recurse(iter, &sub);
3117 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3118 ExecStatusInfo info;
3121 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3122 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3125 t = strv_join(info.argv, " ");
3127 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3131 yes_no(info.ignore),
3132 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3133 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3134 (unsigned) info. pid,
3135 sigchld_code_to_string(info.code),
3137 info.code == CLD_EXITED ? "" : "/",
3138 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3144 strv_free(info.argv);
3146 dbus_message_iter_next(&sub);
3155 if (generic_print_property(name, iter, arg_all) > 0)
3159 printf("%s=[unprintable]\n", name);
3164 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3165 _cleanup_free_ DBusMessage *reply = NULL;
3166 const char *interface = "";
3168 DBusMessageIter iter, sub, sub2, sub3;
3169 UnitStatusInfo info;
3177 r = bus_method_call_with_reply(
3179 "org.freedesktop.systemd1",
3181 "org.freedesktop.DBus.Properties",
3185 DBUS_TYPE_STRING, &interface,
3190 if (!dbus_message_iter_init(reply, &iter) ||
3191 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3192 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3193 log_error("Failed to parse reply.");
3197 dbus_message_iter_recurse(&iter, &sub);
3204 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3207 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3208 dbus_message_iter_recurse(&sub, &sub2);
3210 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3211 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3212 log_error("Failed to parse reply.");
3216 dbus_message_iter_recurse(&sub2, &sub3);
3218 if (show_properties)
3219 r = print_property(name, &sub3);
3221 r = status_property(name, &sub3, &info);
3223 log_error("Failed to parse reply.");
3227 dbus_message_iter_next(&sub);
3232 if (!show_properties) {
3233 if (streq(verb, "help"))
3234 show_unit_help(&info);
3236 print_status_info(&info);
3239 strv_free(info.documentation);
3241 if (!streq_ptr(info.active_state, "active") &&
3242 !streq_ptr(info.active_state, "reloading") &&
3243 streq(verb, "status"))
3244 /* According to LSB: "program not running" */
3247 while ((p = info.exec)) {
3248 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3249 exec_status_info_free(p);
3255 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3256 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3257 const char *path = NULL;
3261 dbus_error_init(&error);
3263 r = bus_method_call_with_reply(
3265 "org.freedesktop.systemd1",
3266 "/org/freedesktop/systemd1",
3267 "org.freedesktop.systemd1.Manager",
3271 DBUS_TYPE_UINT32, &pid,
3276 if (!dbus_message_get_args(reply, &error,
3277 DBUS_TYPE_OBJECT_PATH, &path,
3278 DBUS_TYPE_INVALID)) {
3279 log_error("Failed to parse reply: %s", bus_error_message(&error));
3284 r = show_one(verb, bus, path, false, new_line);
3287 dbus_error_free(&error);
3292 static int show(DBusConnection *bus, char **args) {
3294 bool show_properties, new_line = false;
3300 show_properties = streq(args[0], "show");
3302 if (show_properties)
3303 pager_open_if_enabled();
3305 /* If no argument is specified inspect the manager itself */
3307 if (show_properties && strv_length(args) <= 1)
3308 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3310 STRV_FOREACH(name, args+1) {
3313 if (safe_atou32(*name, &id) < 0) {
3314 _cleanup_free_ char *p = NULL, *n = NULL;
3315 /* Interpret as unit name */
3317 n = unit_name_mangle(*name);
3321 p = unit_dbus_path_from_name(n);
3325 r = show_one(args[0], bus, p, show_properties, &new_line);
3329 } else if (show_properties) {
3330 _cleanup_free_ char *p = NULL;
3332 /* Interpret as job id */
3333 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3336 r = show_one(args[0], bus, p, show_properties, &new_line);
3341 /* Interpret as PID */
3342 r = show_one_by_pid(args[0], bus, id, &new_line);
3351 static int dump(DBusConnection *bus, char **args) {
3352 _cleanup_free_ DBusMessage *reply = NULL;
3357 dbus_error_init(&error);
3359 pager_open_if_enabled();
3361 r = bus_method_call_with_reply(
3363 "org.freedesktop.systemd1",
3364 "/org/freedesktop/systemd1",
3365 "org.freedesktop.systemd1.Manager",
3373 if (!dbus_message_get_args(reply, &error,
3374 DBUS_TYPE_STRING, &text,
3375 DBUS_TYPE_INVALID)) {
3376 log_error("Failed to parse reply: %s", bus_error_message(&error));
3377 dbus_error_free(&error);
3381 fputs(text, stdout);
3385 static int snapshot(DBusConnection *bus, char **args) {
3386 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3389 dbus_bool_t cleanup = FALSE;
3390 DBusMessageIter iter, sub;
3393 *interface = "org.freedesktop.systemd1.Unit",
3395 _cleanup_free_ char *n = NULL;
3397 dbus_error_init(&error);
3399 if (strv_length(args) > 1)
3400 n = snapshot_name_mangle(args[1]);
3406 r = bus_method_call_with_reply (
3408 "org.freedesktop.systemd1",
3409 "/org/freedesktop/systemd1",
3410 "org.freedesktop.systemd1.Manager",
3414 DBUS_TYPE_STRING, &n,
3415 DBUS_TYPE_BOOLEAN, &cleanup,
3420 if (!dbus_message_get_args(reply, &error,
3421 DBUS_TYPE_OBJECT_PATH, &path,
3422 DBUS_TYPE_INVALID)) {
3423 log_error("Failed to parse reply: %s", bus_error_message(&error));
3424 dbus_error_free(&error);
3428 dbus_message_unref(reply);
3431 r = bus_method_call_with_reply (
3433 "org.freedesktop.systemd1",
3435 "org.freedesktop.DBus.Properties",
3439 DBUS_TYPE_STRING, &interface,
3440 DBUS_TYPE_STRING, &property,
3445 if (!dbus_message_iter_init(reply, &iter) ||
3446 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3447 log_error("Failed to parse reply.");
3451 dbus_message_iter_recurse(&iter, &sub);
3453 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3454 log_error("Failed to parse reply.");
3458 dbus_message_iter_get_basic(&sub, &id);
3466 static int delete_snapshot(DBusConnection *bus, char **args) {
3471 STRV_FOREACH(name, args+1) {
3472 _cleanup_free_ char *n = NULL;
3475 n = snapshot_name_mangle(*name);
3479 r = bus_method_call_with_reply(
3481 "org.freedesktop.systemd1",
3482 "/org/freedesktop/systemd1",
3483 "org.freedesktop.systemd1.Manager",
3487 DBUS_TYPE_STRING, &n,
3496 static int daemon_reload(DBusConnection *bus, char **args) {
3501 if (arg_action == ACTION_RELOAD)
3503 else if (arg_action == ACTION_REEXEC)
3504 method = "Reexecute";
3506 assert(arg_action == ACTION_SYSTEMCTL);
3509 streq(args[0], "clear-jobs") ||
3510 streq(args[0], "cancel") ? "ClearJobs" :
3511 streq(args[0], "daemon-reexec") ? "Reexecute" :
3512 streq(args[0], "reset-failed") ? "ResetFailed" :
3513 streq(args[0], "halt") ? "Halt" :
3514 streq(args[0], "poweroff") ? "PowerOff" :
3515 streq(args[0], "reboot") ? "Reboot" :
3516 streq(args[0], "kexec") ? "KExec" :
3517 streq(args[0], "exit") ? "Exit" :
3518 /* "daemon-reload" */ "Reload";
3521 r = bus_method_call_with_reply(
3523 "org.freedesktop.systemd1",
3524 "/org/freedesktop/systemd1",
3525 "org.freedesktop.systemd1.Manager",
3531 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3532 /* There's always a fallback possible for
3533 * legacy actions. */
3535 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3536 /* On reexecution, we expect a disconnect, not
3540 log_error("Failed to issue method call: %s", bus_error_message(&error));
3542 dbus_error_free(&error);
3546 static int reset_failed(DBusConnection *bus, char **args) {
3550 if (strv_length(args) <= 1)
3551 return daemon_reload(bus, args);
3553 STRV_FOREACH(name, args+1) {
3554 _cleanup_free_ char *n;
3556 n = unit_name_mangle(*name);
3560 r = bus_method_call_with_reply(
3562 "org.freedesktop.systemd1",
3563 "/org/freedesktop/systemd1",
3564 "org.freedesktop.systemd1.Manager",
3568 DBUS_TYPE_STRING, &n,
3577 static int show_enviroment(DBusConnection *bus, char **args) {
3578 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3579 DBusMessageIter iter, sub, sub2;
3582 *interface = "org.freedesktop.systemd1.Manager",
3583 *property = "Environment";
3585 pager_open_if_enabled();
3587 r = bus_method_call_with_reply(
3589 "org.freedesktop.systemd1",
3590 "/org/freedesktop/systemd1",
3591 "org.freedesktop.DBus.Properties",
3595 DBUS_TYPE_STRING, &interface,
3596 DBUS_TYPE_STRING, &property,
3601 if (!dbus_message_iter_init(reply, &iter) ||
3602 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3603 log_error("Failed to parse reply.");
3607 dbus_message_iter_recurse(&iter, &sub);
3609 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3610 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3611 log_error("Failed to parse reply.");
3615 dbus_message_iter_recurse(&sub, &sub2);
3617 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3620 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3621 log_error("Failed to parse reply.");
3625 dbus_message_iter_get_basic(&sub2, &text);
3628 dbus_message_iter_next(&sub2);
3634 static int switch_root(DBusConnection *bus, char **args) {
3637 _cleanup_free_ char *init = NULL;
3639 l = strv_length(args);
3640 if (l < 2 || l > 3) {
3641 log_error("Wrong number of arguments.");
3648 init = strdup(args[2]);
3650 parse_env_file("/proc/cmdline", WHITESPACE,
3660 log_debug("switching root - root: %s; init: %s", root, init);
3662 return bus_method_call_with_reply(
3664 "org.freedesktop.systemd1",
3665 "/org/freedesktop/systemd1",
3666 "org.freedesktop.systemd1.Manager",
3670 DBUS_TYPE_STRING, &root,
3671 DBUS_TYPE_STRING, &init,
3675 static int set_environment(DBusConnection *bus, char **args) {
3676 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3679 DBusMessageIter iter;
3685 dbus_error_init(&error);
3687 method = streq(args[0], "set-environment")
3689 : "UnsetEnvironment";
3691 m = dbus_message_new_method_call(
3692 "org.freedesktop.systemd1",
3693 "/org/freedesktop/systemd1",
3694 "org.freedesktop.systemd1.Manager",
3699 dbus_message_iter_init_append(m, &iter);
3701 r = bus_append_strv_iter(&iter, args + 1);
3705 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3707 log_error("Failed to issue method call: %s", bus_error_message(&error));
3708 dbus_error_free(&error);
3715 static int enable_sysv_units(char **args) {
3718 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3719 const char *verb = args[0];
3720 unsigned f = 1, t = 1;
3723 if (arg_scope != UNIT_FILE_SYSTEM)
3726 if (!streq(verb, "enable") &&
3727 !streq(verb, "disable") &&
3728 !streq(verb, "is-enabled"))
3731 /* Processes all SysV units, and reshuffles the array so that
3732 * afterwards only the native units remain */
3735 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3740 for (f = 1; args[f]; f++) {
3743 bool found_native = false, found_sysv;
3745 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3746 char **k, *l, *q = NULL;
3753 if (!endswith(name, ".service"))
3756 if (path_is_absolute(name))
3759 STRV_FOREACH(k, paths.unit_path) {
3762 if (!isempty(arg_root))
3763 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3765 asprintf(&p, "%s/%s", *k, name);
3772 found_native = access(p, F_OK) >= 0;
3783 if (!isempty(arg_root))
3784 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3786 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3792 p[strlen(p) - sizeof(".service") + 1] = 0;
3793 found_sysv = access(p, F_OK) >= 0;
3800 /* Mark this entry, so that we don't try enabling it as native unit */
3801 args[f] = (char*) "";
3803 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3805 if (!isempty(arg_root))
3806 argv[c++] = q = strappend("--root=", arg_root);
3808 argv[c++] = path_get_file_name(p);
3810 streq(verb, "enable") ? "on" :
3811 streq(verb, "disable") ? "off" : "--level=5";
3814 l = strv_join((char**)argv, " ");
3822 log_info("Executing %s", l);
3827 log_error("Failed to fork: %m");
3832 } else if (pid == 0) {
3835 execv(argv[0], (char**) argv);
3836 _exit(EXIT_FAILURE);
3842 j = wait_for_terminate(pid, &status);
3844 log_error("Failed to wait for child: %s", strerror(-r));
3849 if (status.si_code == CLD_EXITED) {
3850 if (streq(verb, "is-enabled")) {
3851 if (status.si_status == 0) {
3860 } else if (status.si_status != 0) {
3871 lookup_paths_free(&paths);
3873 /* Drop all SysV units */
3874 for (f = 1, t = 1; args[f]; f++) {
3876 if (isempty(args[f]))
3879 args[t++] = args[f];
3888 static int mangle_names(char **original_names, char ***mangled_names) {
3889 char **i, **l, **name;
3891 l = new(char*, strv_length(original_names) + 1);
3896 STRV_FOREACH(name, original_names) {
3898 /* When enabling units qualified path names are OK,
3899 * too, hence allow them explicitly. */
3904 *i = unit_name_mangle(*name);
3920 static int enable_unit(DBusConnection *bus, char **args) {
3921 const char *verb = args[0];
3922 UnitFileChange *changes = NULL;
3923 unsigned n_changes = 0, i;
3924 int carries_install_info = -1;
3925 DBusMessage *m = NULL, *reply = NULL;
3928 char **mangled_names = NULL;
3930 r = enable_sysv_units(args);
3937 dbus_error_init(&error);
3939 if (!bus || avoid_bus()) {
3940 if (streq(verb, "enable")) {
3941 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3942 carries_install_info = r;
3943 } else if (streq(verb, "disable"))
3944 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3945 else if (streq(verb, "reenable")) {
3946 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3947 carries_install_info = r;
3948 } else if (streq(verb, "link"))
3949 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3950 else if (streq(verb, "preset")) {
3951 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3952 carries_install_info = r;
3953 } else if (streq(verb, "mask"))
3954 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3955 else if (streq(verb, "unmask"))
3956 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3958 assert_not_reached("Unknown verb");
3961 log_error("Operation failed: %s", strerror(-r));
3966 for (i = 0; i < n_changes; i++) {
3967 if (changes[i].type == UNIT_FILE_SYMLINK)
3968 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3970 log_info("rm '%s'", changes[i].path);
3977 bool send_force = true, expect_carries_install_info = false;
3979 DBusMessageIter iter, sub, sub2;
3981 if (streq(verb, "enable")) {
3982 method = "EnableUnitFiles";
3983 expect_carries_install_info = true;
3984 } else if (streq(verb, "disable")) {
3985 method = "DisableUnitFiles";
3987 } else if (streq(verb, "reenable")) {
3988 method = "ReenableUnitFiles";
3989 expect_carries_install_info = true;
3990 } else if (streq(verb, "link"))
3991 method = "LinkUnitFiles";
3992 else if (streq(verb, "preset")) {
3993 method = "PresetUnitFiles";
3994 expect_carries_install_info = true;
3995 } else if (streq(verb, "mask"))
3996 method = "MaskUnitFiles";
3997 else if (streq(verb, "unmask")) {
3998 method = "UnmaskUnitFiles";
4001 assert_not_reached("Unknown verb");
4003 m = dbus_message_new_method_call(
4004 "org.freedesktop.systemd1",
4005 "/org/freedesktop/systemd1",
4006 "org.freedesktop.systemd1.Manager",
4013 dbus_message_iter_init_append(m, &iter);
4015 r = mangle_names(args+1, &mangled_names);
4019 r = bus_append_strv_iter(&iter, mangled_names);
4021 log_error("Failed to append unit files.");
4026 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4027 log_error("Failed to append runtime boolean.");
4035 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4036 log_error("Failed to append force boolean.");
4042 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4044 log_error("Failed to issue method call: %s", bus_error_message(&error));
4049 if (!dbus_message_iter_init(reply, &iter)) {
4050 log_error("Failed to initialize iterator.");
4054 if (expect_carries_install_info) {
4055 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4057 log_error("Failed to parse reply.");
4061 carries_install_info = b;
4064 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4065 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4066 log_error("Failed to parse reply.");
4071 dbus_message_iter_recurse(&iter, &sub);
4072 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4073 const char *type, *path, *source;
4075 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4076 log_error("Failed to parse reply.");
4081 dbus_message_iter_recurse(&sub, &sub2);
4083 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4084 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4085 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4086 log_error("Failed to parse reply.");
4092 if (streq(type, "symlink"))
4093 log_info("ln -s '%s' '%s'", source, path);
4095 log_info("rm '%s'", path);
4098 dbus_message_iter_next(&sub);
4101 /* Try to reload if enabeld */
4103 r = daemon_reload(bus, args);
4106 if (carries_install_info == 0)
4108 "The unit files have no [Install] section. They are not meant to be enabled\n"
4109 "using systemctl.\n"
4110 "Possible reasons for having this kind of units are:\n"
4111 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4112 " .wants/ or .requires/ directory.\n"
4113 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4114 " a requirement dependency on it.\n"
4115 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4116 " D-Bus, udev, scripted systemctl call, ...).\n");
4120 dbus_message_unref(m);
4123 dbus_message_unref(reply);
4125 unit_file_changes_free(changes, n_changes);
4127 dbus_error_free(&error);
4129 strv_free(mangled_names);
4134 static int unit_is_enabled(DBusConnection *bus, char **args) {
4137 DBusMessage *reply = NULL;
4141 dbus_error_init(&error);
4143 r = enable_sysv_units(args);
4149 if (!bus || avoid_bus()) {
4151 STRV_FOREACH(name, args+1) {
4152 UnitFileState state;
4154 state = unit_file_get_state(arg_scope, arg_root, *name);
4160 if (state == UNIT_FILE_ENABLED ||
4161 state == UNIT_FILE_ENABLED_RUNTIME ||
4162 state == UNIT_FILE_STATIC)
4166 puts(unit_file_state_to_string(state));
4170 STRV_FOREACH(name, args+1) {
4173 r = bus_method_call_with_reply (
4175 "org.freedesktop.systemd1",
4176 "/org/freedesktop/systemd1",
4177 "org.freedesktop.systemd1.Manager",
4181 DBUS_TYPE_STRING, name,
4186 if (!dbus_message_get_args(reply, &error,
4187 DBUS_TYPE_STRING, &s,
4188 DBUS_TYPE_INVALID)) {
4189 log_error("Failed to parse reply: %s", bus_error_message(&error));
4194 dbus_message_unref(reply);
4197 if (streq(s, "enabled") ||
4198 streq(s, "enabled-runtime") ||
4207 r = enabled ? 0 : 1;
4211 dbus_message_unref(reply);
4213 dbus_error_free(&error);
4217 static int systemctl_help(void) {
4219 pager_open_if_enabled();
4221 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4222 "Query or send control commands to the systemd manager.\n\n"
4223 " -h --help Show this help\n"
4224 " --version Show package version\n"
4225 " -t --type=TYPE List only units of a particular type\n"
4226 " -p --property=NAME Show only properties by this name\n"
4227 " -a --all Show all units/properties, including dead/empty ones\n"
4228 " --failed Show only failed units\n"
4229 " --full Don't ellipsize unit names on output\n"
4230 " --fail When queueing a new job, fail if conflicting jobs are\n"
4232 " --ignore-dependencies\n"
4233 " When queueing a new job, ignore all its dependencies\n"
4234 " -i --ignore-inhibitors\n"
4235 " When shutting down or sleeping, ignore inhibitors\n"
4236 " --kill-who=WHO Who to send signal to\n"
4237 " -s --signal=SIGNAL Which signal to send\n"
4238 " -H --host=[USER@]HOST\n"
4239 " Show information for remote host\n"
4240 " -P --privileged Acquire privileges before execution\n"
4241 " -q --quiet Suppress output\n"
4242 " --no-block Do not wait until operation finished\n"
4243 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4244 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4246 " --no-legend Do not print a legend (column headers and hints)\n"
4247 " --no-pager Do not pipe output into a pager\n"
4248 " --no-ask-password\n"
4249 " Do not ask for system passwords\n"
4250 " --order When generating graph for dot, show only order\n"
4251 " --require When generating graph for dot, show only requirement\n"
4252 " --system Connect to system manager\n"
4253 " --user Connect to user service manager\n"
4254 " --global Enable/disable unit files globally\n"
4255 " -f --force When enabling unit files, override existing symlinks\n"
4256 " When shutting down, execute action immediately\n"
4257 " --root=PATH Enable unit files in the specified root directory\n"
4258 " --runtime Enable unit files only temporarily until next reboot\n"
4259 " -n --lines=INTEGER Journal entries to show\n"
4260 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4261 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4263 " list-units List loaded units\n"
4264 " start [NAME...] Start (activate) one or more units\n"
4265 " stop [NAME...] Stop (deactivate) one or more units\n"
4266 " reload [NAME...] Reload one or more units\n"
4267 " restart [NAME...] Start or restart one or more units\n"
4268 " try-restart [NAME...] Restart one or more units if active\n"
4269 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4270 " otherwise start or restart\n"
4271 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4272 " otherwise restart if active\n"
4273 " isolate [NAME] Start one unit and stop all others\n"
4274 " kill [NAME...] Send signal to processes of a unit\n"
4275 " is-active [NAME...] Check whether units are active\n"
4276 " is-failed [NAME...] Check whether units are failed\n"
4277 " status [NAME...|PID...] Show runtime status of one or more units\n"
4278 " show [NAME...|JOB...] Show properties of one or more\n"
4279 " units/jobs or the manager\n"
4280 " help [NAME...|PID...] Show manual for one or more units\n"
4281 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4283 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4284 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4285 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4286 " Set control group attribute\n"
4287 " unset-cgroup-attr [NAME] [ATTR...]\n"
4288 " Unset control group attribute\n"
4289 " load [NAME...] Load one or more units\n"
4290 " list-dependencies [NAME] Recursively show units which are required\n"
4291 " or wanted by this unit\n\n"
4292 "Unit File Commands:\n"
4293 " list-unit-files List installed unit files\n"
4294 " enable [NAME...] Enable one or more unit files\n"
4295 " disable [NAME...] Disable one or more unit files\n"
4296 " reenable [NAME...] Reenable one or more unit files\n"
4297 " preset [NAME...] Enable/disable one or more unit files\n"
4298 " based on preset configuration\n"
4299 " mask [NAME...] Mask one or more units\n"
4300 " unmask [NAME...] Unmask one or more units\n"
4301 " link [PATH...] Link one or more units files into\n"
4302 " the search path\n"
4303 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4305 " list-jobs List jobs\n"
4306 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4307 "Status Commands:\n"
4308 " dump Dump server status\n"
4309 " dot Dump dependency graph for dot(1)\n\n"
4310 "Snapshot Commands:\n"
4311 " snapshot [NAME] Create a snapshot\n"
4312 " delete [NAME...] Remove one or more snapshots\n\n"
4313 "Environment Commands:\n"
4314 " show-environment Dump environment\n"
4315 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4316 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4317 "Manager Lifecycle Commands:\n"
4318 " daemon-reload Reload systemd manager configuration\n"
4319 " daemon-reexec Reexecute systemd manager\n\n"
4320 "System Commands:\n"
4321 " default Enter system default mode\n"
4322 " rescue Enter system rescue mode\n"
4323 " emergency Enter system emergency mode\n"
4324 " halt Shut down and halt the system\n"
4325 " poweroff Shut down and power-off the system\n"
4326 " reboot Shut down and reboot the system\n"
4327 " kexec Shut down and reboot the system with kexec\n"
4328 " exit Request user instance exit\n"
4329 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4330 " suspend Suspend the system\n"
4331 " hibernate Hibernate the system\n"
4332 " hybrid-sleep Hibernate and suspend the system\n",
4333 program_invocation_short_name);
4338 static int halt_help(void) {
4340 printf("%s [OPTIONS...]\n\n"
4341 "%s the system.\n\n"
4342 " --help Show this help\n"
4343 " --halt Halt the machine\n"
4344 " -p --poweroff Switch off the machine\n"
4345 " --reboot Reboot the machine\n"
4346 " -f --force Force immediate halt/power-off/reboot\n"
4347 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4348 " -d --no-wtmp Don't write wtmp record\n"
4349 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4350 program_invocation_short_name,
4351 arg_action == ACTION_REBOOT ? "Reboot" :
4352 arg_action == ACTION_POWEROFF ? "Power off" :
4358 static int shutdown_help(void) {
4360 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4361 "Shut down the system.\n\n"
4362 " --help Show this help\n"
4363 " -H --halt Halt the machine\n"
4364 " -P --poweroff Power-off the machine\n"
4365 " -r --reboot Reboot the machine\n"
4366 " -h Equivalent to --poweroff, overridden by --halt\n"
4367 " -k Don't halt/power-off/reboot, just send warnings\n"
4368 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4369 " -c Cancel a pending shutdown\n",
4370 program_invocation_short_name);
4375 static int telinit_help(void) {
4377 printf("%s [OPTIONS...] {COMMAND}\n\n"
4378 "Send control commands to the init daemon.\n\n"
4379 " --help Show this help\n"
4380 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4382 " 0 Power-off the machine\n"
4383 " 6 Reboot the machine\n"
4384 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4385 " 1, s, S Enter rescue mode\n"
4386 " q, Q Reload init daemon configuration\n"
4387 " u, U Reexecute init daemon\n",
4388 program_invocation_short_name);
4393 static int runlevel_help(void) {
4395 printf("%s [OPTIONS...]\n\n"
4396 "Prints the previous and current runlevel of the init system.\n\n"
4397 " --help Show this help\n",
4398 program_invocation_short_name);
4403 static int help_types(void) {
4406 puts("Available unit types:");
4407 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4408 if (unit_type_table[i])
4409 puts(unit_type_table[i]);
4411 puts("\nAvailable unit load states: ");
4412 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4413 if (unit_type_table[i])
4414 puts(unit_load_state_table[i]);
4419 static int systemctl_parse_argv(int argc, char *argv[]) {
4423 ARG_IGNORE_DEPENDENCIES,
4438 ARG_NO_ASK_PASSWORD,
4444 static const struct option options[] = {
4445 { "help", no_argument, NULL, 'h' },
4446 { "version", no_argument, NULL, ARG_VERSION },
4447 { "type", required_argument, NULL, 't' },
4448 { "property", required_argument, NULL, 'p' },
4449 { "all", no_argument, NULL, 'a' },
4450 { "failed", no_argument, NULL, ARG_FAILED },
4451 { "full", no_argument, NULL, ARG_FULL },
4452 { "fail", no_argument, NULL, ARG_FAIL },
4453 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4454 { "ignore-inhibitors", no_argument, NULL, 'i' },
4455 { "user", no_argument, NULL, ARG_USER },
4456 { "system", no_argument, NULL, ARG_SYSTEM },
4457 { "global", no_argument, NULL, ARG_GLOBAL },
4458 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4459 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4460 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4461 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4462 { "quiet", no_argument, NULL, 'q' },
4463 { "order", no_argument, NULL, ARG_ORDER },
4464 { "require", no_argument, NULL, ARG_REQUIRE },
4465 { "root", required_argument, NULL, ARG_ROOT },
4466 { "force", no_argument, NULL, ARG_FORCE },
4467 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4468 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4469 { "signal", required_argument, NULL, 's' },
4470 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4471 { "host", required_argument, NULL, 'H' },
4472 { "privileged",no_argument, NULL, 'P' },
4473 { "runtime", no_argument, NULL, ARG_RUNTIME },
4474 { "lines", required_argument, NULL, 'n' },
4475 { "output", required_argument, NULL, 'o' },
4476 { NULL, 0, NULL, 0 }
4484 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4493 puts(PACKAGE_STRING);
4494 puts(SYSTEMD_FEATURES);
4498 if (streq(optarg, "help")) {
4503 if (unit_type_from_string(optarg) >= 0) {
4507 if (unit_load_state_from_string(optarg) >= 0) {
4508 arg_load_state = optarg;
4511 log_error("Unkown unit type or load state '%s'.",
4513 log_info("Use -t help to see a list of allowed values.");
4518 if (!(l = strv_append(arg_property, optarg)))
4521 strv_free(arg_property);
4524 /* If the user asked for a particular
4525 * property, show it to him, even if it is
4536 arg_job_mode = "fail";
4539 case ARG_IGNORE_DEPENDENCIES:
4540 arg_job_mode = "ignore-dependencies";
4544 arg_scope = UNIT_FILE_USER;
4548 arg_scope = UNIT_FILE_SYSTEM;
4552 arg_scope = UNIT_FILE_GLOBAL;
4556 arg_no_block = true;
4560 arg_no_legend = true;
4564 arg_no_pager = true;
4572 arg_dot = DOT_ORDER;
4576 arg_dot = DOT_REQUIRE;
4604 arg_no_reload = true;
4608 arg_kill_who = optarg;
4612 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4613 log_error("Failed to parse signal string %s.", optarg);
4618 case ARG_NO_ASK_PASSWORD:
4619 arg_ask_password = false;
4623 arg_transport = TRANSPORT_POLKIT;
4627 arg_transport = TRANSPORT_SSH;
4636 if (safe_atou(optarg, &arg_lines) < 0) {
4637 log_error("Failed to parse lines '%s'", optarg);
4643 arg_output = output_mode_from_string(optarg);
4644 if (arg_output < 0) {
4645 log_error("Unknown output '%s'.", optarg);
4651 arg_ignore_inhibitors = true;
4658 log_error("Unknown option code '%c'.", c);
4663 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4664 log_error("Cannot access user instance remotely.");
4671 static int halt_parse_argv(int argc, char *argv[]) {
4680 static const struct option options[] = {
4681 { "help", no_argument, NULL, ARG_HELP },
4682 { "halt", no_argument, NULL, ARG_HALT },
4683 { "poweroff", no_argument, NULL, 'p' },
4684 { "reboot", no_argument, NULL, ARG_REBOOT },
4685 { "force", no_argument, NULL, 'f' },
4686 { "wtmp-only", no_argument, NULL, 'w' },
4687 { "no-wtmp", no_argument, NULL, 'd' },
4688 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4689 { NULL, 0, NULL, 0 }
4697 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4698 if (runlevel == '0' || runlevel == '6')
4701 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4709 arg_action = ACTION_HALT;
4713 if (arg_action != ACTION_REBOOT)
4714 arg_action = ACTION_POWEROFF;
4718 arg_action = ACTION_REBOOT;
4740 /* Compatibility nops */
4747 log_error("Unknown option code '%c'.", c);
4752 if (optind < argc) {
4753 log_error("Too many arguments.");
4760 static int parse_time_spec(const char *t, usec_t *_u) {
4764 if (streq(t, "now"))
4766 else if (!strchr(t, ':')) {
4769 if (safe_atou64(t, &u) < 0)
4772 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4781 hour = strtol(t, &e, 10);
4782 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4785 minute = strtol(e+1, &e, 10);
4786 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4789 n = now(CLOCK_REALTIME);
4790 s = (time_t) (n / USEC_PER_SEC);
4793 assert_se(localtime_r(&s, &tm));
4795 tm.tm_hour = (int) hour;
4796 tm.tm_min = (int) minute;
4799 assert_se(s = mktime(&tm));
4801 *_u = (usec_t) s * USEC_PER_SEC;
4804 *_u += USEC_PER_DAY;
4810 static int shutdown_parse_argv(int argc, char *argv[]) {
4817 static const struct option options[] = {
4818 { "help", no_argument, NULL, ARG_HELP },
4819 { "halt", no_argument, NULL, 'H' },
4820 { "poweroff", no_argument, NULL, 'P' },
4821 { "reboot", no_argument, NULL, 'r' },
4822 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4823 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4824 { NULL, 0, NULL, 0 }
4832 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4840 arg_action = ACTION_HALT;
4844 arg_action = ACTION_POWEROFF;
4849 arg_action = ACTION_KEXEC;
4851 arg_action = ACTION_REBOOT;
4855 arg_action = ACTION_KEXEC;
4859 if (arg_action != ACTION_HALT)
4860 arg_action = ACTION_POWEROFF;
4873 /* Compatibility nops */
4877 arg_action = ACTION_CANCEL_SHUTDOWN;
4884 log_error("Unknown option code '%c'.", c);
4889 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4890 r = parse_time_spec(argv[optind], &arg_when);
4892 log_error("Failed to parse time specification: %s", argv[optind]);
4896 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4898 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4899 /* No time argument for shutdown cancel */
4900 arg_wall = argv + optind;
4901 else if (argc > optind + 1)
4902 /* We skip the time argument */
4903 arg_wall = argv + optind + 1;
4910 static int telinit_parse_argv(int argc, char *argv[]) {
4917 static const struct option options[] = {
4918 { "help", no_argument, NULL, ARG_HELP },
4919 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4920 { NULL, 0, NULL, 0 }
4923 static const struct {
4927 { '0', ACTION_POWEROFF },
4928 { '6', ACTION_REBOOT },
4929 { '1', ACTION_RESCUE },
4930 { '2', ACTION_RUNLEVEL2 },
4931 { '3', ACTION_RUNLEVEL3 },
4932 { '4', ACTION_RUNLEVEL4 },
4933 { '5', ACTION_RUNLEVEL5 },
4934 { 's', ACTION_RESCUE },
4935 { 'S', ACTION_RESCUE },
4936 { 'q', ACTION_RELOAD },
4937 { 'Q', ACTION_RELOAD },
4938 { 'u', ACTION_REEXEC },
4939 { 'U', ACTION_REEXEC }
4948 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4963 log_error("Unknown option code '%c'.", c);
4968 if (optind >= argc) {
4973 if (optind + 1 < argc) {
4974 log_error("Too many arguments.");
4978 if (strlen(argv[optind]) != 1) {
4979 log_error("Expected single character argument.");
4983 for (i = 0; i < ELEMENTSOF(table); i++)
4984 if (table[i].from == argv[optind][0])
4987 if (i >= ELEMENTSOF(table)) {
4988 log_error("Unknown command '%s'.", argv[optind]);
4992 arg_action = table[i].to;
4999 static int runlevel_parse_argv(int argc, char *argv[]) {
5005 static const struct option options[] = {
5006 { "help", no_argument, NULL, ARG_HELP },
5007 { NULL, 0, NULL, 0 }
5015 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5026 log_error("Unknown option code '%c'.", c);
5031 if (optind < argc) {
5032 log_error("Too many arguments.");
5039 static int parse_argv(int argc, char *argv[]) {
5043 if (program_invocation_short_name) {
5045 if (strstr(program_invocation_short_name, "halt")) {
5046 arg_action = ACTION_HALT;
5047 return halt_parse_argv(argc, argv);
5048 } else if (strstr(program_invocation_short_name, "poweroff")) {
5049 arg_action = ACTION_POWEROFF;
5050 return halt_parse_argv(argc, argv);
5051 } else if (strstr(program_invocation_short_name, "reboot")) {
5053 arg_action = ACTION_KEXEC;
5055 arg_action = ACTION_REBOOT;
5056 return halt_parse_argv(argc, argv);
5057 } else if (strstr(program_invocation_short_name, "shutdown")) {
5058 arg_action = ACTION_POWEROFF;
5059 return shutdown_parse_argv(argc, argv);
5060 } else if (strstr(program_invocation_short_name, "init")) {
5062 if (sd_booted() > 0) {
5063 arg_action = ACTION_INVALID;
5064 return telinit_parse_argv(argc, argv);
5066 /* Hmm, so some other init system is
5067 * running, we need to forward this
5068 * request to it. For now we simply
5069 * guess that it is Upstart. */
5071 execv("/lib/upstart/telinit", argv);
5073 log_error("Couldn't find an alternative telinit implementation to spawn.");
5077 } else if (strstr(program_invocation_short_name, "runlevel")) {
5078 arg_action = ACTION_RUNLEVEL;
5079 return runlevel_parse_argv(argc, argv);
5083 arg_action = ACTION_SYSTEMCTL;
5084 return systemctl_parse_argv(argc, argv);
5087 static int action_to_runlevel(void) {
5089 static const char table[_ACTION_MAX] = {
5090 [ACTION_HALT] = '0',
5091 [ACTION_POWEROFF] = '0',
5092 [ACTION_REBOOT] = '6',
5093 [ACTION_RUNLEVEL2] = '2',
5094 [ACTION_RUNLEVEL3] = '3',
5095 [ACTION_RUNLEVEL4] = '4',
5096 [ACTION_RUNLEVEL5] = '5',
5097 [ACTION_RESCUE] = '1'
5100 assert(arg_action < _ACTION_MAX);
5102 return table[arg_action];
5105 static int talk_upstart(void) {
5106 DBusMessage *m = NULL, *reply = NULL;
5108 int previous, rl, r;
5110 env1_buf[] = "RUNLEVEL=X",
5111 env2_buf[] = "PREVLEVEL=X";
5112 char *env1 = env1_buf, *env2 = env2_buf;
5113 const char *emit = "runlevel";
5114 dbus_bool_t b_false = FALSE;
5115 DBusMessageIter iter, sub;
5116 DBusConnection *bus;
5118 dbus_error_init(&error);
5120 if (!(rl = action_to_runlevel()))
5123 if (utmp_get_runlevel(&previous, NULL) < 0)
5126 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5127 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5132 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5137 if ((r = bus_check_peercred(bus)) < 0) {
5138 log_error("Failed to verify owner of bus.");
5142 if (!(m = dbus_message_new_method_call(
5143 "com.ubuntu.Upstart",
5144 "/com/ubuntu/Upstart",
5145 "com.ubuntu.Upstart0_6",
5148 log_error("Could not allocate message.");
5153 dbus_message_iter_init_append(m, &iter);
5155 env1_buf[sizeof(env1_buf)-2] = rl;
5156 env2_buf[sizeof(env2_buf)-2] = previous;
5158 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5159 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5160 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5161 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5162 !dbus_message_iter_close_container(&iter, &sub) ||
5163 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5164 log_error("Could not append arguments to message.");
5169 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5171 if (bus_error_is_no_service(&error)) {
5176 log_error("Failed to issue method call: %s", bus_error_message(&error));
5185 dbus_message_unref(m);
5188 dbus_message_unref(reply);
5191 dbus_connection_flush(bus);
5192 dbus_connection_close(bus);
5193 dbus_connection_unref(bus);
5196 dbus_error_free(&error);
5201 static int talk_initctl(void) {
5202 struct init_request request;
5206 if (!(rl = action_to_runlevel()))
5210 request.magic = INIT_MAGIC;
5211 request.sleeptime = 0;
5212 request.cmd = INIT_CMD_RUNLVL;
5213 request.runlevel = rl;
5215 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5217 if (errno == ENOENT)
5220 log_error("Failed to open "INIT_FIFO": %m");
5225 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5226 close_nointr_nofail(fd);
5229 log_error("Failed to write to "INIT_FIFO": %m");
5230 return errno ? -errno : -EIO;
5236 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5238 static const struct {
5246 int (* const dispatch)(DBusConnection *bus, char **args);
5248 { "list-units", LESS, 1, list_units },
5249 { "list-unit-files", EQUAL, 1, list_unit_files },
5250 { "list-jobs", EQUAL, 1, list_jobs },
5251 { "clear-jobs", EQUAL, 1, daemon_reload },
5252 { "load", MORE, 2, load_unit },
5253 { "cancel", MORE, 2, cancel_job },
5254 { "start", MORE, 2, start_unit },
5255 { "stop", MORE, 2, start_unit },
5256 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5257 { "reload", MORE, 2, start_unit },
5258 { "restart", MORE, 2, start_unit },
5259 { "try-restart", MORE, 2, start_unit },
5260 { "reload-or-restart", MORE, 2, start_unit },
5261 { "reload-or-try-restart", MORE, 2, start_unit },
5262 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5263 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5264 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5265 { "isolate", EQUAL, 2, start_unit },
5266 { "set-cgroup", MORE, 2, set_cgroup },
5267 { "unset-cgroup", MORE, 2, set_cgroup },
5268 { "set-cgroup-attr", MORE, 2, set_cgroup_attr },
5269 { "unset-cgroup-attr", MORE, 2, set_cgroup },
5270 { "kill", MORE, 2, kill_unit },
5271 { "is-active", MORE, 2, check_unit_active },
5272 { "check", MORE, 2, check_unit_active },
5273 { "is-failed", MORE, 2, check_unit_failed },
5274 { "show", MORE, 1, show },
5275 { "status", MORE, 2, show },
5276 { "help", MORE, 2, show },
5277 { "dump", EQUAL, 1, dump },
5278 { "dot", EQUAL, 1, dot },
5279 { "snapshot", LESS, 2, snapshot },
5280 { "delete", MORE, 2, delete_snapshot },
5281 { "daemon-reload", EQUAL, 1, daemon_reload },
5282 { "daemon-reexec", EQUAL, 1, daemon_reload },
5283 { "show-environment", EQUAL, 1, show_enviroment },
5284 { "set-environment", MORE, 2, set_environment },
5285 { "unset-environment", MORE, 2, set_environment },
5286 { "halt", EQUAL, 1, start_special },
5287 { "poweroff", EQUAL, 1, start_special },
5288 { "reboot", EQUAL, 1, start_special },
5289 { "kexec", EQUAL, 1, start_special },
5290 { "suspend", EQUAL, 1, start_special },
5291 { "hibernate", EQUAL, 1, start_special },
5292 { "hybrid-sleep", EQUAL, 1, start_special },
5293 { "default", EQUAL, 1, start_special },
5294 { "rescue", EQUAL, 1, start_special },
5295 { "emergency", EQUAL, 1, start_special },
5296 { "exit", EQUAL, 1, start_special },
5297 { "reset-failed", MORE, 1, reset_failed },
5298 { "enable", MORE, 2, enable_unit },
5299 { "disable", MORE, 2, enable_unit },
5300 { "is-enabled", MORE, 2, unit_is_enabled },
5301 { "reenable", MORE, 2, enable_unit },
5302 { "preset", MORE, 2, enable_unit },
5303 { "mask", MORE, 2, enable_unit },
5304 { "unmask", MORE, 2, enable_unit },
5305 { "link", MORE, 2, enable_unit },
5306 { "switch-root", MORE, 2, switch_root },
5307 { "list-dependencies", LESS, 2, list_dependencies },
5317 left = argc - optind;
5320 /* Special rule: no arguments means "list-units" */
5323 if (streq(argv[optind], "help") && !argv[optind+1]) {
5324 log_error("This command expects one or more "
5325 "unit names. Did you mean --help?");
5329 for (i = 0; i < ELEMENTSOF(verbs); i++)
5330 if (streq(argv[optind], verbs[i].verb))
5333 if (i >= ELEMENTSOF(verbs)) {
5334 log_error("Unknown operation '%s'.", argv[optind]);
5339 switch (verbs[i].argc_cmp) {
5342 if (left != verbs[i].argc) {
5343 log_error("Invalid number of arguments.");
5350 if (left < verbs[i].argc) {
5351 log_error("Too few arguments.");
5358 if (left > verbs[i].argc) {
5359 log_error("Too many arguments.");
5366 assert_not_reached("Unknown comparison operator.");
5369 /* Require a bus connection for all operations but
5371 if (!streq(verbs[i].verb, "enable") &&
5372 !streq(verbs[i].verb, "disable") &&
5373 !streq(verbs[i].verb, "is-enabled") &&
5374 !streq(verbs[i].verb, "list-unit-files") &&
5375 !streq(verbs[i].verb, "reenable") &&
5376 !streq(verbs[i].verb, "preset") &&
5377 !streq(verbs[i].verb, "mask") &&
5378 !streq(verbs[i].verb, "unmask") &&
5379 !streq(verbs[i].verb, "link")) {
5381 if (running_in_chroot() > 0) {
5382 log_info("Running in chroot, ignoring request.");
5386 if (((!streq(verbs[i].verb, "reboot") &&
5387 !streq(verbs[i].verb, "halt") &&
5388 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5389 log_error("Failed to get D-Bus connection: %s",
5390 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5396 if (!bus && !avoid_bus()) {
5397 log_error("Failed to get D-Bus connection: %s",
5398 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5403 return verbs[i].dispatch(bus, argv + optind);
5406 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5408 struct msghdr msghdr;
5409 struct iovec iovec[2];
5410 union sockaddr_union sockaddr;
5411 struct sd_shutdown_command c;
5413 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5420 c.dry_run = dry_run;
5424 sockaddr.sa.sa_family = AF_UNIX;
5425 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5428 msghdr.msg_name = &sockaddr;
5429 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5432 iovec[0].iov_base = (char*) &c;
5433 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5435 if (isempty(message))
5436 msghdr.msg_iovlen = 1;
5438 iovec[1].iov_base = (char*) message;
5439 iovec[1].iov_len = strlen(message);
5440 msghdr.msg_iovlen = 2;
5442 msghdr.msg_iov = iovec;
5444 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5445 close_nointr_nofail(fd);
5449 close_nointr_nofail(fd);
5453 static int reload_with_fallback(DBusConnection *bus) {
5456 /* First, try systemd via D-Bus. */
5457 if (daemon_reload(bus, NULL) >= 0)
5461 /* Nothing else worked, so let's try signals */
5462 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5464 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5465 log_error("kill() failed: %m");
5472 static int start_with_fallback(DBusConnection *bus) {
5475 /* First, try systemd via D-Bus. */
5476 if (start_unit(bus, NULL) >= 0)
5480 /* Hmm, talking to systemd via D-Bus didn't work. Then
5481 * let's try to talk to Upstart via D-Bus. */
5482 if (talk_upstart() > 0)
5485 /* Nothing else worked, so let's try
5487 if (talk_initctl() > 0)
5490 log_error("Failed to talk to init daemon.");
5494 warn_wall(arg_action);
5498 static _noreturn_ void halt_now(enum action a) {
5500 /* Make sure C-A-D is handled by the kernel from this
5502 reboot(RB_ENABLE_CAD);
5507 log_info("Halting.");
5508 reboot(RB_HALT_SYSTEM);
5511 case ACTION_POWEROFF:
5512 log_info("Powering off.");
5513 reboot(RB_POWER_OFF);
5517 log_info("Rebooting.");
5518 reboot(RB_AUTOBOOT);
5522 assert_not_reached("Unknown halt action.");
5525 assert_not_reached("Uh? This shouldn't happen.");
5528 static int halt_main(DBusConnection *bus) {
5531 r = check_inhibitors(bus, arg_action);
5535 if (geteuid() != 0) {
5536 /* Try logind if we are a normal user and no special
5537 * mode applies. Maybe PolicyKit allows us to shutdown
5540 if (arg_when <= 0 &&
5543 (arg_action == ACTION_POWEROFF ||
5544 arg_action == ACTION_REBOOT)) {
5545 r = reboot_with_logind(bus, arg_action);
5550 log_error("Must be root.");
5557 m = strv_join(arg_wall, " ");
5558 r = send_shutdownd(arg_when,
5559 arg_action == ACTION_HALT ? 'H' :
5560 arg_action == ACTION_POWEROFF ? 'P' :
5561 arg_action == ACTION_KEXEC ? 'K' :
5569 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5571 char date[FORMAT_TIMESTAMP_MAX];
5573 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5574 format_timestamp(date, sizeof(date), arg_when));
5579 if (!arg_dry && !arg_force)
5580 return start_with_fallback(bus);
5583 if (sd_booted() > 0)
5584 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5586 r = utmp_put_shutdown();
5588 log_warning("Failed to write utmp record: %s", strerror(-r));
5595 halt_now(arg_action);
5596 /* We should never reach this. */
5600 static int runlevel_main(void) {
5601 int r, runlevel, previous;
5603 r = utmp_get_runlevel(&runlevel, &previous);
5610 previous <= 0 ? 'N' : previous,
5611 runlevel <= 0 ? 'N' : runlevel);
5616 int main(int argc, char*argv[]) {
5617 int r, retval = EXIT_FAILURE;
5618 DBusConnection *bus = NULL;
5621 dbus_error_init(&error);
5623 setlocale(LC_ALL, "");
5624 log_parse_environment();
5627 r = parse_argv(argc, argv);
5631 retval = EXIT_SUCCESS;
5635 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5636 * let's shortcut this */
5637 if (arg_action == ACTION_RUNLEVEL) {
5638 r = runlevel_main();
5639 retval = r < 0 ? EXIT_FAILURE : r;
5643 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5644 log_info("Running in chroot, ignoring request.");
5650 if (arg_transport == TRANSPORT_NORMAL)
5651 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5652 else if (arg_transport == TRANSPORT_POLKIT) {
5653 bus_connect_system_polkit(&bus, &error);
5654 private_bus = false;
5655 } else if (arg_transport == TRANSPORT_SSH) {
5656 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5657 private_bus = false;
5659 assert_not_reached("Uh, invalid transport...");
5662 switch (arg_action) {
5664 case ACTION_SYSTEMCTL:
5665 r = systemctl_main(bus, argc, argv, &error);
5669 case ACTION_POWEROFF:
5675 case ACTION_RUNLEVEL2:
5676 case ACTION_RUNLEVEL3:
5677 case ACTION_RUNLEVEL4:
5678 case ACTION_RUNLEVEL5:
5680 case ACTION_EMERGENCY:
5681 case ACTION_DEFAULT:
5682 r = start_with_fallback(bus);
5687 r = reload_with_fallback(bus);
5690 case ACTION_CANCEL_SHUTDOWN: {
5694 m = strv_join(arg_wall, " ");
5696 retval = EXIT_FAILURE;
5700 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5702 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5707 case ACTION_INVALID:
5708 case ACTION_RUNLEVEL:
5710 assert_not_reached("Unknown action");
5713 retval = r < 0 ? EXIT_FAILURE : r;
5717 dbus_connection_flush(bus);
5718 dbus_connection_close(bus);
5719 dbus_connection_unref(bus);
5722 dbus_error_free(&error);
5726 strv_free(arg_property);
5729 ask_password_agent_close();
5730 polkit_agent_close();