1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/reboot.h>
29 #include <sys/ioctl.h>
33 #include <sys/socket.h>
36 #include <sys/prctl.h>
37 #include <dbus/dbus.h>
39 #include <systemd/sd-daemon.h>
40 #include <systemd/sd-shutdown.h>
41 #include <systemd/sd-login.h>
47 #include "utmp-wtmp.h"
50 #include "path-util.h"
52 #include "dbus-common.h"
53 #include "cgroup-show.h"
54 #include "cgroup-util.h"
56 #include "path-lookup.h"
57 #include "conf-parser.h"
58 #include "exit-status.h"
59 #include "bus-errors.h"
61 #include "unit-name.h"
63 #include "spawn-ask-password-agent.h"
64 #include "spawn-polkit-agent.h"
66 #include "logs-show.h"
67 #include "path-util.h"
68 #include "socket-util.h"
70 static const char *arg_type = NULL;
71 static const char *arg_load_state = NULL;
72 static char **arg_property = NULL;
73 static bool arg_all = false;
74 static const char *arg_job_mode = "replace";
75 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
76 static bool arg_no_block = false;
77 static bool arg_no_legend = false;
78 static bool arg_no_pager = false;
79 static bool arg_no_wtmp = false;
80 static bool arg_no_wall = false;
81 static bool arg_no_reload = false;
82 static bool arg_ignore_inhibitors = false;
83 static bool arg_dry = false;
84 static bool arg_quiet = false;
85 static bool arg_full = false;
86 static int arg_force = 0;
87 static bool arg_ask_password = true;
88 static bool arg_failed = false;
89 static bool arg_runtime = false;
90 static char **arg_wall = NULL;
91 static const char *arg_kill_who = NULL;
92 static int arg_signal = SIGTERM;
93 static const char *arg_root = NULL;
94 static usec_t arg_when = 0;
116 ACTION_CANCEL_SHUTDOWN,
118 } arg_action = ACTION_SYSTEMCTL;
124 static enum transport {
128 } arg_transport = TRANSPORT_NORMAL;
129 static const char *arg_host = NULL;
130 static unsigned arg_lines = 10;
131 static OutputMode arg_output = OUTPUT_SHORT;
133 static bool private_bus = false;
135 static int daemon_reload(DBusConnection *bus, char **args);
136 static void halt_now(enum action a);
138 static void pager_open_if_enabled(void) {
146 static void ask_password_agent_open_if_enabled(void) {
148 /* Open the password agent as a child process if necessary */
150 if (!arg_ask_password)
153 if (arg_scope != UNIT_FILE_SYSTEM)
156 ask_password_agent_open();
160 static void polkit_agent_open_if_enabled(void) {
162 /* Open the polkit agent as a child process if necessary */
164 if (!arg_ask_password)
167 if (arg_scope != UNIT_FILE_SYSTEM)
174 static const char *ansi_highlight(bool b) {
179 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
182 static const char *ansi_highlight_red(bool b) {
187 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
190 static const char *ansi_highlight_green(bool b) {
195 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
198 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
201 if (!dbus_error_is_set(error))
204 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
205 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
206 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
207 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
208 return EXIT_NOPERMISSION;
210 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
211 return EXIT_NOTINSTALLED;
213 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
214 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
215 return EXIT_NOTIMPLEMENTED;
217 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
218 return EXIT_NOTCONFIGURED;
226 static void warn_wall(enum action a) {
227 static const char *table[_ACTION_MAX] = {
228 [ACTION_HALT] = "The system is going down for system halt NOW!",
229 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
230 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
231 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
232 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
233 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
234 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
241 _cleanup_free_ char *p;
243 p = strv_join(arg_wall, " ");
258 utmp_wall(table[a], NULL);
261 static bool avoid_bus(void) {
263 if (running_in_chroot() > 0)
266 if (sd_booted() <= 0)
269 if (!isempty(arg_root))
272 if (arg_scope == UNIT_FILE_GLOBAL)
278 static int compare_unit_info(const void *a, const void *b) {
280 const struct unit_info *u = a, *v = b;
282 d1 = strrchr(u->id, '.');
283 d2 = strrchr(v->id, '.');
288 r = strcasecmp(d1, d2);
293 return strcasecmp(u->id, v->id);
296 static bool output_show_unit(const struct unit_info *u) {
300 return streq(u->active_state, "failed");
302 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
303 streq(dot+1, arg_type))) &&
304 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
305 (arg_all || !(streq(u->active_state, "inactive")
306 || u->following[0]) || u->job_id > 0);
309 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
310 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
311 const struct unit_info *u;
314 max_id_len = sizeof("UNIT")-1;
315 active_len = sizeof("ACTIVE")-1;
316 sub_len = sizeof("SUB")-1;
317 job_len = sizeof("JOB")-1;
320 for (u = unit_infos; u < unit_infos + c; u++) {
321 if (!output_show_unit(u))
324 max_id_len = MAX(max_id_len, strlen(u->id));
325 active_len = MAX(active_len, strlen(u->active_state));
326 sub_len = MAX(sub_len, strlen(u->sub_state));
327 if (u->job_id != 0) {
328 job_len = MAX(job_len, strlen(u->job_type));
335 id_len = MIN(max_id_len, 25);
336 basic_len = 5 + id_len + 5 + active_len + sub_len;
338 basic_len += job_len + 1;
339 if (basic_len < (unsigned) columns()) {
340 unsigned extra_len, incr;
341 extra_len = columns() - basic_len;
342 /* Either UNIT already got 25, or is fully satisfied.
343 * Grant up to 25 to DESC now. */
344 incr = MIN(extra_len, 25);
347 /* split the remaining space between UNIT and DESC,
348 * but do not give UNIT more than it needs. */
350 incr = MIN(extra_len / 2, max_id_len - id_len);
352 desc_len += extra_len - incr;
358 for (u = unit_infos; u < unit_infos + c; u++) {
360 const char *on_loaded, *off_loaded;
361 const char *on_active, *off_active;
363 if (!output_show_unit(u))
366 if (!n_shown && !arg_no_legend) {
367 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
368 active_len, "ACTIVE", sub_len, "SUB");
370 printf("%-*s ", job_len, "JOB");
371 if (!arg_full && arg_no_pager)
372 printf("%.*s\n", desc_len, "DESCRIPTION");
374 printf("%s\n", "DESCRIPTION");
379 if (streq(u->load_state, "error")) {
380 on_loaded = ansi_highlight_red(true);
381 off_loaded = ansi_highlight_red(false);
383 on_loaded = off_loaded = "";
385 if (streq(u->active_state, "failed")) {
386 on_active = ansi_highlight_red(true);
387 off_active = ansi_highlight_red(false);
389 on_active = off_active = "";
391 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
393 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s",
394 id_len, e ? e : u->id,
395 on_loaded, u->load_state, off_loaded,
396 on_active, active_len, u->active_state,
397 sub_len, u->sub_state, off_active,
398 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
399 if (!arg_full && arg_no_pager)
400 printf("%.*s\n", desc_len, u->description);
402 printf("%s\n", u->description);
407 if (!arg_no_legend) {
408 const char *on, *off;
411 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
412 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
413 "SUB = The low-level unit activation state, values depend on unit type.\n");
415 printf("JOB = Pending job for the unit.\n");
417 on = ansi_highlight(true);
418 off = ansi_highlight(false);
420 on = ansi_highlight_red(true);
421 off = ansi_highlight_red(false);
425 printf("%s%u loaded units listed.%s\n"
426 "To show all installed unit files use 'systemctl list-unit-files'.\n",
429 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
430 "To show all installed unit files use 'systemctl list-unit-files'.\n",
435 static int list_units(DBusConnection *bus, char **args) {
436 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
437 _cleanup_free_ struct unit_info *unit_infos = NULL;
438 DBusMessageIter iter, sub;
439 unsigned c = 0, n_units = 0;
442 pager_open_if_enabled();
444 r = bus_method_call_with_reply(
446 "org.freedesktop.systemd1",
447 "/org/freedesktop/systemd1",
448 "org.freedesktop.systemd1.Manager",
456 if (!dbus_message_iter_init(reply, &iter) ||
457 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
458 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
459 log_error("Failed to parse reply.");
463 dbus_message_iter_recurse(&iter, &sub);
465 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
471 n_units = MAX(2*c, 16);
472 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
481 bus_parse_unit_info(&sub, u);
483 dbus_message_iter_next(&sub);
488 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
489 output_units_list(unit_infos, c);
495 static int compare_unit_file_list(const void *a, const void *b) {
497 const UnitFileList *u = a, *v = b;
499 d1 = strrchr(u->path, '.');
500 d2 = strrchr(v->path, '.');
505 r = strcasecmp(d1, d2);
510 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
513 static bool output_show_unit_file(const UnitFileList *u) {
516 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
519 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
520 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
521 const UnitFileList *u;
523 max_id_len = sizeof("UNIT FILE")-1;
524 state_cols = sizeof("STATE")-1;
525 for (u = units; u < units + c; u++) {
526 if (!output_show_unit_file(u))
529 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
530 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
535 id_cols = MIN(max_id_len, 25);
536 basic_cols = 1 + id_cols + state_cols;
537 if (basic_cols < (unsigned) columns())
538 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
540 id_cols = max_id_len;
543 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
545 for (u = units; u < units + c; u++) {
547 const char *on, *off;
550 if (!output_show_unit_file(u))
555 if (u->state == UNIT_FILE_MASKED ||
556 u->state == UNIT_FILE_MASKED_RUNTIME ||
557 u->state == UNIT_FILE_DISABLED ||
558 u->state == UNIT_FILE_INVALID) {
559 on = ansi_highlight_red(true);
560 off = ansi_highlight_red(false);
561 } else if (u->state == UNIT_FILE_ENABLED) {
562 on = ansi_highlight_green(true);
563 off = ansi_highlight_green(false);
567 id = path_get_file_name(u->path);
569 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
571 printf("%-*s %s%-*s%s\n",
573 on, state_cols, unit_file_state_to_string(u->state), off);
579 printf("\n%u unit files listed.\n", n_shown);
582 static int list_unit_files(DBusConnection *bus, char **args) {
583 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
584 _cleanup_free_ UnitFileList *units = NULL;
585 DBusMessageIter iter, sub, sub2;
586 unsigned c = 0, n_units = 0;
589 pager_open_if_enabled();
596 h = hashmap_new(string_hash_func, string_compare_func);
600 r = unit_file_get_list(arg_scope, arg_root, h);
602 unit_file_list_free(h);
603 log_error("Failed to get unit file list: %s", strerror(-r));
607 n_units = hashmap_size(h);
608 units = new(UnitFileList, n_units);
610 unit_file_list_free(h);
614 HASHMAP_FOREACH(u, h, i) {
615 memcpy(units + c++, u, sizeof(UnitFileList));
621 r = bus_method_call_with_reply(
623 "org.freedesktop.systemd1",
624 "/org/freedesktop/systemd1",
625 "org.freedesktop.systemd1.Manager",
633 if (!dbus_message_iter_init(reply, &iter) ||
634 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
635 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
636 log_error("Failed to parse reply.");
640 dbus_message_iter_recurse(&iter, &sub);
642 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
646 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
651 n_units = MAX(2*c, 16);
652 w = realloc(units, sizeof(struct UnitFileList) * n_units);
661 dbus_message_iter_recurse(&sub, &sub2);
663 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
664 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
665 log_error("Failed to parse reply.");
669 u->state = unit_file_state_from_string(state);
671 dbus_message_iter_next(&sub);
677 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
678 output_unit_file_list(units, c);
684 static int list_dependencies_print(const char *name, int level, unsigned int branches, bool last) {
686 _cleanup_free_ char *n = NULL;
688 size_t max_len = MAX(columns(),20);
690 for (i = level - 1; i >= 0; i--) {
692 if(len > max_len - 3 && !arg_full) {
693 printf("%s...\n",max_len % 2 ? "" : " ");
696 printf("%s", draw_special_char(branches & (1 << i) ? DRAW_TREE_VERT : DRAW_TREE_SPACE));
699 if(len > max_len - 3 && !arg_full) {
700 printf("%s...\n",max_len % 2 ? "" : " ");
703 printf("%s", draw_special_char(last ? DRAW_TREE_RIGHT : DRAW_TREE_BRANCH));
706 printf("%s\n", name);
710 n = ellipsize(name, max_len-len, 100);
718 static int list_dependencies_get_dependencies(DBusConnection *bus, const char *name, char ***deps) {
719 static const char dependencies[] =
721 "RequiresOverridable\0"
723 "RequisiteOverridable\0"
726 _cleanup_free_ char *path;
727 const char *interface = "org.freedesktop.systemd1.Unit";
729 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
730 DBusMessageIter iter, sub, sub2, sub3;
739 path = unit_dbus_path_from_name(name);
745 r = bus_method_call_with_reply(
747 "org.freedesktop.systemd1",
749 "org.freedesktop.DBus.Properties",
753 DBUS_TYPE_STRING, &interface,
758 if (!dbus_message_iter_init(reply, &iter) ||
759 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
760 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
761 log_error("Failed to parse reply.");
766 dbus_message_iter_recurse(&iter, &sub);
768 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
771 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
772 dbus_message_iter_recurse(&sub, &sub2);
774 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
775 log_error("Failed to parse reply.");
780 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
781 log_error("Failed to parse reply.");
786 dbus_message_iter_recurse(&sub2, &sub3);
787 dbus_message_iter_next(&sub);
789 if (!nulstr_contains(dependencies, prop))
792 if (dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_ARRAY) {
793 if (dbus_message_iter_get_element_type(&sub3) == DBUS_TYPE_STRING) {
794 DBusMessageIter sub4;
795 dbus_message_iter_recurse(&sub3, &sub4);
797 while (dbus_message_iter_get_arg_type(&sub4) != DBUS_TYPE_INVALID) {
800 assert(dbus_message_iter_get_arg_type(&sub4) == DBUS_TYPE_STRING);
801 dbus_message_iter_get_basic(&sub4, &s);
803 r = strv_extend(&ret, s);
809 dbus_message_iter_next(&sub4);
822 static int list_dependencies_compare(const void *_a, const void *_b) {
823 const char **a = (const char**) _a, **b = (const char**) _b;
824 if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET)
826 if (unit_name_to_type(*a) != UNIT_TARGET && unit_name_to_type(*b) == UNIT_TARGET)
828 return strcasecmp(*a, *b);
831 static int list_dependencies_one(DBusConnection *bus, const char *name, int level, char **units, unsigned int branches) {
837 u = strv_append(units, name);
841 r = list_dependencies_get_dependencies(bus, name, &deps);
845 qsort(deps, strv_length(deps), sizeof (char*), list_dependencies_compare);
847 STRV_FOREACH(c, deps) {
848 if (strv_contains(u, *c)) {
849 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
855 r = list_dependencies_print(*c, level, branches, c[1] == NULL);
859 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
860 r = list_dependencies_one(bus, *c, level + 1, u, (branches << 1) | (c[1] == NULL ? 0 : 1));
873 static int list_dependencies(DBusConnection *bus, char **args) {
874 _cleanup_free_ char *unit = NULL;
880 unit = unit_name_mangle(args[1]);
885 u = SPECIAL_DEFAULT_TARGET;
887 pager_open_if_enabled();
891 return list_dependencies_one(bus, u, 0, NULL, 0);
894 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
896 static const char * const colors[] = {
897 "Requires", "[color=\"black\"]",
898 "RequiresOverridable", "[color=\"black\"]",
899 "Requisite", "[color=\"darkblue\"]",
900 "RequisiteOverridable", "[color=\"darkblue\"]",
901 "Wants", "[color=\"grey66\"]",
902 "Conflicts", "[color=\"red\"]",
903 "ConflictedBy", "[color=\"red\"]",
904 "After", "[color=\"green\"]"
907 const char *c = NULL;
914 for (i = 0; i < ELEMENTSOF(colors); i += 2)
915 if (streq(colors[i], prop)) {
923 if (arg_dot != DOT_ALL)
924 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
927 switch (dbus_message_iter_get_arg_type(iter)) {
929 case DBUS_TYPE_ARRAY:
931 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
934 dbus_message_iter_recurse(iter, &sub);
936 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
939 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
940 dbus_message_iter_get_basic(&sub, &s);
941 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
943 dbus_message_iter_next(&sub);
953 static int dot_one(DBusConnection *bus, const struct unit_info *u) {
954 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
955 const char *interface = "org.freedesktop.systemd1.Unit";
957 DBusMessageIter iter, sub, sub2, sub3;
962 r = bus_method_call_with_reply(
964 "org.freedesktop.systemd1",
966 "org.freedesktop.DBus.Properties",
970 DBUS_TYPE_STRING, &interface,
975 if (!dbus_message_iter_init(reply, &iter) ||
976 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
977 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
978 log_error("Failed to parse reply.");
982 dbus_message_iter_recurse(&iter, &sub);
984 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
987 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
988 dbus_message_iter_recurse(&sub, &sub2);
990 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0 ||
991 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
992 log_error("Failed to parse reply.");
996 dbus_message_iter_recurse(&sub2, &sub3);
997 r = dot_one_property(u->id, prop, &sub3);
1001 dbus_message_iter_next(&sub);
1007 static int dot(DBusConnection *bus, char **args) {
1008 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1009 DBusMessageIter iter, sub;
1012 r = bus_method_call_with_reply(
1014 "org.freedesktop.systemd1",
1015 "/org/freedesktop/systemd1",
1016 "org.freedesktop.systemd1.Manager",
1024 if (!dbus_message_iter_init(reply, &iter) ||
1025 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1026 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1027 log_error("Failed to parse reply.");
1031 printf("digraph systemd {\n");
1033 dbus_message_iter_recurse(&iter, &sub);
1034 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1037 r = bus_parse_unit_info(&sub, &u);
1041 r = dot_one(bus, &u);
1045 /* printf("\t\"%s\";\n", u.id); */
1046 dbus_message_iter_next(&sub);
1051 log_info(" Color legend: black = Requires\n"
1052 " dark blue = Requisite\n"
1053 " dark grey = Wants\n"
1054 " red = Conflicts\n"
1055 " green = After\n");
1058 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
1059 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
1064 static int list_jobs(DBusConnection *bus, char **args) {
1065 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1066 DBusMessageIter iter, sub, sub2;
1070 pager_open_if_enabled();
1072 r = bus_method_call_with_reply(
1074 "org.freedesktop.systemd1",
1075 "/org/freedesktop/systemd1",
1076 "org.freedesktop.systemd1.Manager",
1084 if (!dbus_message_iter_init(reply, &iter) ||
1085 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1086 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1087 log_error("Failed to parse reply.");
1091 dbus_message_iter_recurse(&iter, &sub);
1094 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
1096 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1097 const char *name, *type, *state, *job_path, *unit_path;
1101 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1102 log_error("Failed to parse reply.");
1106 dbus_message_iter_recurse(&sub, &sub2);
1108 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1109 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1110 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1111 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1112 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1113 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1114 log_error("Failed to parse reply.");
1118 e = arg_full ? NULL : ellipsize(name, 25, 33);
1119 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1124 dbus_message_iter_next(&sub);
1128 printf("\n%u jobs listed.\n", k);
1133 static int load_unit(DBusConnection *bus, char **args) {
1138 STRV_FOREACH(name, args+1) {
1139 _cleanup_free_ char *n = NULL;
1142 n = unit_name_mangle(*name);
1146 r = bus_method_call_with_reply(
1148 "org.freedesktop.systemd1",
1149 "/org/freedesktop/systemd1",
1150 "org.freedesktop.systemd1.Manager",
1154 DBUS_TYPE_STRING, &n,
1163 static int cancel_job(DBusConnection *bus, char **args) {
1168 if (strv_length(args) <= 1)
1169 return daemon_reload(bus, args);
1171 STRV_FOREACH(name, args+1) {
1175 r = safe_atou32(*name, &id);
1177 log_error("Failed to parse job id: %s", strerror(-r));
1181 r = bus_method_call_with_reply(
1183 "org.freedesktop.systemd1",
1184 "/org/freedesktop/systemd1",
1185 "org.freedesktop.systemd1.Manager",
1189 DBUS_TYPE_UINT32, &id,
1198 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1199 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1200 dbus_bool_t b = FALSE;
1201 DBusMessageIter iter, sub;
1203 *interface = "org.freedesktop.systemd1.Unit",
1204 *property = "NeedDaemonReload",
1206 _cleanup_free_ char *n = NULL;
1209 /* We ignore all errors here, since this is used to show a warning only */
1211 n = unit_name_mangle(unit);
1215 r = bus_method_call_with_reply (
1217 "org.freedesktop.systemd1",
1218 "/org/freedesktop/systemd1",
1219 "org.freedesktop.systemd1.Manager",
1223 DBUS_TYPE_STRING, &n,
1228 if (!dbus_message_get_args(reply, NULL,
1229 DBUS_TYPE_OBJECT_PATH, &path,
1233 dbus_message_unref(reply);
1236 r = bus_method_call_with_reply(
1238 "org.freedesktop.systemd1",
1240 "org.freedesktop.DBus.Properties",
1244 DBUS_TYPE_STRING, &interface,
1245 DBUS_TYPE_STRING, &property,
1250 if (!dbus_message_iter_init(reply, &iter) ||
1251 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1254 dbus_message_iter_recurse(&iter, &sub);
1255 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1258 dbus_message_iter_get_basic(&sub, &b);
1262 typedef struct WaitData {
1269 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1277 dbus_error_init(&error);
1279 log_debug("Got D-Bus request: %s.%s() on %s",
1280 dbus_message_get_interface(message),
1281 dbus_message_get_member(message),
1282 dbus_message_get_path(message));
1284 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1285 log_error("Warning! D-Bus connection terminated.");
1286 dbus_connection_close(connection);
1288 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1290 const char *path, *result, *unit;
1292 if (dbus_message_get_args(message, &error,
1293 DBUS_TYPE_UINT32, &id,
1294 DBUS_TYPE_OBJECT_PATH, &path,
1295 DBUS_TYPE_STRING, &unit,
1296 DBUS_TYPE_STRING, &result,
1297 DBUS_TYPE_INVALID)) {
1299 free(set_remove(d->set, (char*) path));
1301 if (!isempty(result))
1302 d->result = strdup(result);
1305 d->name = strdup(unit);
1310 dbus_error_free(&error);
1311 if (dbus_message_get_args(message, &error,
1312 DBUS_TYPE_UINT32, &id,
1313 DBUS_TYPE_OBJECT_PATH, &path,
1314 DBUS_TYPE_STRING, &result,
1315 DBUS_TYPE_INVALID)) {
1316 /* Compatibility with older systemd versions <
1317 * 183 during upgrades. This should be dropped
1319 free(set_remove(d->set, (char*) path));
1322 d->result = strdup(result);
1328 log_error("Failed to parse message: %s", bus_error_message(&error));
1332 dbus_error_free(&error);
1333 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1336 static int enable_wait_for_jobs(DBusConnection *bus) {
1344 dbus_error_init(&error);
1345 dbus_bus_add_match(bus,
1347 "sender='org.freedesktop.systemd1',"
1348 "interface='org.freedesktop.systemd1.Manager',"
1349 "member='JobRemoved',"
1350 "path='/org/freedesktop/systemd1'",
1353 if (dbus_error_is_set(&error)) {
1354 log_error("Failed to add match: %s", bus_error_message(&error));
1355 dbus_error_free(&error);
1359 /* This is slightly dirty, since we don't undo the match registrations. */
1363 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1373 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1376 while (!set_isempty(s)) {
1378 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1379 log_error("Disconnected from bus.");
1380 return -ECONNREFUSED;
1387 if (streq(d.result, "timeout"))
1388 log_error("Job for %s timed out.", strna(d.name));
1389 else if (streq(d.result, "canceled"))
1390 log_error("Job for %s canceled.", strna(d.name));
1391 else if (streq(d.result, "dependency"))
1392 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1393 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1394 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1397 if (streq_ptr(d.result, "timeout"))
1399 else if (streq_ptr(d.result, "canceled"))
1401 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1412 dbus_connection_remove_filter(bus, wait_filter, &d);
1416 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1417 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1418 _cleanup_free_ char *n = NULL;
1419 DBusMessageIter iter, sub;
1421 *interface = "org.freedesktop.systemd1.Unit",
1422 *property = "ActiveState";
1423 const char *state, *path;
1429 dbus_error_init(&error);
1431 n = unit_name_mangle(name);
1435 r = bus_method_call_with_reply (
1437 "org.freedesktop.systemd1",
1438 "/org/freedesktop/systemd1",
1439 "org.freedesktop.systemd1.Manager",
1443 DBUS_TYPE_STRING, &n,
1446 dbus_error_free(&error);
1453 if (!dbus_message_get_args(reply, NULL,
1454 DBUS_TYPE_OBJECT_PATH, &path,
1455 DBUS_TYPE_INVALID)) {
1456 log_error("Failed to parse reply.");
1460 dbus_message_unref(reply);
1463 r = bus_method_call_with_reply(
1465 "org.freedesktop.systemd1",
1467 "org.freedesktop.DBus.Properties",
1471 DBUS_TYPE_STRING, &interface,
1472 DBUS_TYPE_STRING, &property,
1480 if (!dbus_message_iter_init(reply, &iter) ||
1481 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1482 log_error("Failed to parse reply.");
1486 dbus_message_iter_recurse(&iter, &sub);
1488 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1489 log_error("Failed to parse reply.");
1493 dbus_message_iter_get_basic(&sub, &state);
1498 return strv_find(check_states, state) ? 1 : 0;
1501 static void check_triggering_units(
1502 DBusConnection *bus,
1503 const char *unit_name) {
1505 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1506 DBusMessageIter iter, sub;
1507 const char *interface = "org.freedesktop.systemd1.Unit",
1508 *triggered_by_property = "TriggeredBy";
1509 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1510 bool print_warning_label = true;
1513 n = unit_name_mangle(unit_name);
1519 unit_path = unit_dbus_path_from_name(n);
1525 r = bus_method_call_with_reply(
1527 "org.freedesktop.systemd1",
1529 "org.freedesktop.DBus.Properties",
1533 DBUS_TYPE_STRING, &interface,
1534 DBUS_TYPE_STRING, &triggered_by_property,
1539 if (!dbus_message_iter_init(reply, &iter) ||
1540 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1541 log_error("Failed to parse reply.");
1545 dbus_message_iter_recurse(&iter, &sub);
1546 dbus_message_iter_recurse(&sub, &iter);
1549 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1550 const char * const check_states[] = {
1555 const char *service_trigger;
1557 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1558 log_error("Failed to parse reply.");
1562 dbus_message_iter_get_basic(&sub, &service_trigger);
1564 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1568 if (print_warning_label) {
1569 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1570 print_warning_label = false;
1573 log_warning(" %s", service_trigger);
1576 dbus_message_iter_next(&sub);
1580 static int start_unit_one(
1581 DBusConnection *bus,
1588 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1589 _cleanup_free_ char *n;
1598 n = unit_name_mangle(name);
1602 r = bus_method_call_with_reply(
1604 "org.freedesktop.systemd1",
1605 "/org/freedesktop/systemd1",
1606 "org.freedesktop.systemd1.Manager",
1610 DBUS_TYPE_STRING, &n,
1611 DBUS_TYPE_STRING, &mode,
1614 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1615 /* There's always a fallback possible for
1616 * legacy actions. */
1619 log_error("Failed to issue method call: %s", bus_error_message(error));
1624 if (!dbus_message_get_args(reply, error,
1625 DBUS_TYPE_OBJECT_PATH, &path,
1626 DBUS_TYPE_INVALID)) {
1627 log_error("Failed to parse reply: %s", bus_error_message(error));
1631 if (need_daemon_reload(bus, n))
1632 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1633 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1645 log_error("Failed to add path to set.");
1653 static enum action verb_to_action(const char *verb) {
1654 if (streq(verb, "halt"))
1656 else if (streq(verb, "poweroff"))
1657 return ACTION_POWEROFF;
1658 else if (streq(verb, "reboot"))
1659 return ACTION_REBOOT;
1660 else if (streq(verb, "kexec"))
1661 return ACTION_KEXEC;
1662 else if (streq(verb, "rescue"))
1663 return ACTION_RESCUE;
1664 else if (streq(verb, "emergency"))
1665 return ACTION_EMERGENCY;
1666 else if (streq(verb, "default"))
1667 return ACTION_DEFAULT;
1668 else if (streq(verb, "exit"))
1670 else if (streq(verb, "suspend"))
1671 return ACTION_SUSPEND;
1672 else if (streq(verb, "hibernate"))
1673 return ACTION_HIBERNATE;
1674 else if (streq(verb, "hybrid-sleep"))
1675 return ACTION_HYBRID_SLEEP;
1677 return ACTION_INVALID;
1680 static int start_unit(DBusConnection *bus, char **args) {
1682 static const char * const table[_ACTION_MAX] = {
1683 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1684 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1685 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1686 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1687 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1688 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1689 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1690 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1691 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1692 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1693 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1694 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1695 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1696 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
1697 [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
1701 const char *method, *mode, *one_name;
1706 dbus_error_init(&error);
1710 ask_password_agent_open_if_enabled();
1712 if (arg_action == ACTION_SYSTEMCTL) {
1714 streq(args[0], "stop") ||
1715 streq(args[0], "condstop") ? "StopUnit" :
1716 streq(args[0], "reload") ? "ReloadUnit" :
1717 streq(args[0], "restart") ? "RestartUnit" :
1719 streq(args[0], "try-restart") ||
1720 streq(args[0], "condrestart") ? "TryRestartUnit" :
1722 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1724 streq(args[0], "reload-or-try-restart") ||
1725 streq(args[0], "condreload") ||
1727 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1731 (streq(args[0], "isolate") ||
1732 streq(args[0], "rescue") ||
1733 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1735 one_name = table[verb_to_action(args[0])];
1738 assert(arg_action < ELEMENTSOF(table));
1739 assert(table[arg_action]);
1741 method = "StartUnit";
1743 mode = (arg_action == ACTION_EMERGENCY ||
1744 arg_action == ACTION_RESCUE ||
1745 arg_action == ACTION_RUNLEVEL2 ||
1746 arg_action == ACTION_RUNLEVEL3 ||
1747 arg_action == ACTION_RUNLEVEL4 ||
1748 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1750 one_name = table[arg_action];
1753 if (!arg_no_block) {
1754 ret = enable_wait_for_jobs(bus);
1756 log_error("Could not watch jobs: %s", strerror(-ret));
1760 s = set_new(string_hash_func, string_compare_func);
1768 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1770 ret = translate_bus_error_to_exit_status(ret, &error);
1772 STRV_FOREACH(name, args+1) {
1773 r = start_unit_one(bus, method, *name, mode, &error, s);
1775 ret = translate_bus_error_to_exit_status(r, &error);
1776 dbus_error_free(&error);
1781 if (!arg_no_block) {
1782 r = wait_for_jobs(bus, s);
1788 /* When stopping units, warn if they can still be triggered by
1789 * another active unit (socket, path, timer) */
1790 if (!arg_quiet && streq(method, "StopUnit")) {
1792 check_triggering_units(bus, one_name);
1794 STRV_FOREACH(name, args+1)
1795 check_triggering_units(bus, *name);
1801 dbus_error_free(&error);
1806 /* Ask systemd-logind, which might grant access to unprivileged users
1807 * through PolicyKit */
1808 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1811 dbus_bool_t interactive = true;
1816 polkit_agent_open_if_enabled();
1824 case ACTION_POWEROFF:
1825 method = "PowerOff";
1828 case ACTION_SUSPEND:
1832 case ACTION_HIBERNATE:
1833 method = "Hibernate";
1836 case ACTION_HYBRID_SLEEP:
1837 method = "HybridSleep";
1844 return bus_method_call_with_reply(
1846 "org.freedesktop.login1",
1847 "/org/freedesktop/login1",
1848 "org.freedesktop.login1.Manager",
1852 DBUS_TYPE_BOOLEAN, &interactive,
1859 static int check_inhibitors(DBusConnection *bus, enum action a) {
1861 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1862 DBusMessageIter iter, sub, sub2;
1865 _cleanup_strv_free_ char **sessions = NULL;
1871 if (arg_ignore_inhibitors || arg_force > 0)
1883 r = bus_method_call_with_reply(
1885 "org.freedesktop.login1",
1886 "/org/freedesktop/login1",
1887 "org.freedesktop.login1.Manager",
1893 /* If logind is not around, then there are no inhibitors... */
1896 if (!dbus_message_iter_init(reply, &iter) ||
1897 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1898 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1899 log_error("Failed to parse reply.");
1903 dbus_message_iter_recurse(&iter, &sub);
1904 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1905 const char *what, *who, *why, *mode;
1907 _cleanup_strv_free_ char **sv = NULL;
1908 _cleanup_free_ char *comm = NULL, *user = NULL;
1910 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1911 log_error("Failed to parse reply.");
1915 dbus_message_iter_recurse(&sub, &sub2);
1917 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
1918 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
1919 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
1920 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
1921 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
1922 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
1923 log_error("Failed to parse reply.");
1927 if (!streq(mode, "block"))
1930 sv = strv_split(what, ":");
1934 if (!strv_contains(sv,
1936 a == ACTION_POWEROFF ||
1937 a == ACTION_REBOOT ||
1938 a == ACTION_KEXEC ? "shutdown" : "sleep"))
1941 get_process_comm(pid, &comm);
1942 user = uid_to_name(uid);
1943 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", user %s), reason is \"%s\".",
1944 who, (unsigned long) pid, strna(comm), strna(user), why);
1948 dbus_message_iter_next(&sub);
1951 dbus_message_iter_recurse(&iter, &sub);
1953 /* Check for current sessions */
1954 sd_get_sessions(&sessions);
1955 STRV_FOREACH(s, sessions) {
1957 _cleanup_free_ char *type = NULL, *tty = NULL, *seat = NULL, *user = NULL, *service = NULL, *class = NULL;
1959 if (sd_session_get_uid(*s, &uid) < 0 || uid == getuid())
1962 if (sd_session_get_class(*s, &class) < 0 || !streq(class, "user"))
1965 if (sd_session_get_type(*s, &type) < 0 || (!streq(type, "x11") && !streq(type, "tty")))
1968 sd_session_get_tty(*s, &tty);
1969 sd_session_get_seat(*s, &seat);
1970 sd_session_get_service(*s, &service);
1971 user = uid_to_name(uid);
1973 log_warning("User %s is logged in on %s.", strna(user), isempty(tty) ? (isempty(seat) ? strna(service) : seat) : tty);
1980 log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
1981 a == ACTION_HALT ? "halt" :
1982 a == ACTION_POWEROFF ? "poweroff" :
1983 a == ACTION_REBOOT ? "reboot" :
1984 a == ACTION_KEXEC ? "kexec" :
1985 a == ACTION_SUSPEND ? "suspend" :
1986 a == ACTION_HIBERNATE ? "hibernate" : "hybrid-sleep");
1994 static int start_special(DBusConnection *bus, char **args) {
2000 a = verb_to_action(args[0]);
2002 r = check_inhibitors(bus, a);
2006 if (arg_force >= 2 && geteuid() != 0) {
2007 log_error("Must be root.");
2011 if (arg_force >= 2 &&
2012 (a == ACTION_HALT ||
2013 a == ACTION_POWEROFF ||
2014 a == ACTION_REBOOT))
2017 if (arg_force >= 1 &&
2018 (a == ACTION_HALT ||
2019 a == ACTION_POWEROFF ||
2020 a == ACTION_REBOOT ||
2021 a == ACTION_KEXEC ||
2023 return daemon_reload(bus, args);
2025 /* first try logind, to allow authentication with polkit */
2026 if (geteuid() != 0 &&
2027 (a == ACTION_POWEROFF ||
2028 a == ACTION_REBOOT ||
2029 a == ACTION_SUSPEND ||
2030 a == ACTION_HIBERNATE ||
2031 a == ACTION_HYBRID_SLEEP)) {
2032 r = reboot_with_logind(bus, a);
2037 r = start_unit(bus, args);
2044 static int check_unit_active(DBusConnection *bus, char **args) {
2045 const char * const check_states[] = {
2052 int r = 3; /* According to LSB: "program is not running" */
2057 STRV_FOREACH(name, args+1) {
2060 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2070 static int check_unit_failed(DBusConnection *bus, char **args) {
2071 const char * const check_states[] = {
2082 STRV_FOREACH(name, args+1) {
2085 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
2095 static int kill_unit(DBusConnection *bus, char **args) {
2103 arg_kill_who = "all";
2105 STRV_FOREACH(name, args+1) {
2106 _cleanup_free_ char *n = NULL;
2108 n = unit_name_mangle(*name);
2112 r = bus_method_call_with_reply(
2114 "org.freedesktop.systemd1",
2115 "/org/freedesktop/systemd1",
2116 "org.freedesktop.systemd1.Manager",
2120 DBUS_TYPE_STRING, &n,
2121 DBUS_TYPE_STRING, &arg_kill_who,
2122 DBUS_TYPE_INT32, &arg_signal,
2130 static int set_cgroup(DBusConnection *bus, char **args) {
2131 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2134 DBusMessageIter iter;
2136 _cleanup_free_ char *n = NULL;
2137 const char *runtime;
2142 dbus_error_init(&error);
2145 streq(args[0], "set-cgroup") ? "SetUnitControlGroups" :
2146 streq(args[0], "unset-group") ? "UnsetUnitControlGroups"
2147 : "UnsetUnitControlGroupAttributes";
2149 n = unit_name_mangle(args[1]);
2153 m = dbus_message_new_method_call(
2154 "org.freedesktop.systemd1",
2155 "/org/freedesktop/systemd1",
2156 "org.freedesktop.systemd1.Manager",
2161 dbus_message_iter_init_append(m, &iter);
2162 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
2165 r = bus_append_strv_iter(&iter, args + 2);
2169 runtime = arg_runtime ? "runtime" : "persistent";
2170 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2173 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2175 log_error("Failed to issue method call: %s", bus_error_message(&error));
2176 dbus_error_free(&error);
2183 static int set_cgroup_attr(DBusConnection *bus, char **args) {
2184 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2186 DBusMessageIter iter, sub, sub2;
2188 _cleanup_free_ char *n = NULL;
2189 const char *runtime;
2194 dbus_error_init(&error);
2196 if (strv_length(args) % 2 != 0) {
2197 log_error("Expecting an uneven number of arguments!");
2201 n = unit_name_mangle(args[1]);
2205 m = dbus_message_new_method_call(
2206 "org.freedesktop.systemd1",
2207 "/org/freedesktop/systemd1",
2208 "org.freedesktop.systemd1.Manager",
2209 "SetUnitControlGroupAttributes");
2213 dbus_message_iter_init_append(m, &iter);
2214 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
2215 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub))
2218 STRV_FOREACH_PAIR(x, y, args + 2) {
2219 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
2220 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, x) ||
2221 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, y) ||
2222 !dbus_message_iter_close_container(&sub, &sub2))
2226 runtime = arg_runtime ? "runtime" : "persistent";
2227 if (!dbus_message_iter_close_container(&iter, &sub) ||
2228 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
2231 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2233 log_error("Failed to issue method call: %s", bus_error_message(&error));
2234 dbus_error_free(&error);
2241 static int get_cgroup_attr(DBusConnection *bus, char **args) {
2242 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
2244 DBusMessageIter iter;
2246 _cleanup_free_ char *n = NULL;
2247 _cleanup_strv_free_ char **list = NULL;
2253 dbus_error_init(&error);
2255 n = unit_name_mangle(args[1]);
2259 m = dbus_message_new_method_call(
2260 "org.freedesktop.systemd1",
2261 "/org/freedesktop/systemd1",
2262 "org.freedesktop.systemd1.Manager",
2263 "GetUnitControlGroupAttributes");
2267 dbus_message_iter_init_append(m, &iter);
2268 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
2271 r = bus_append_strv_iter(&iter, args + 2);
2275 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
2277 log_error("Failed to issue method call: %s", bus_error_message(&error));
2278 dbus_error_free(&error);
2282 dbus_message_iter_init(reply, &iter);
2283 r = bus_parse_strv_iter(&iter, &list);
2285 log_error("Failed to parse value list.");
2289 STRV_FOREACH(a, list) {
2290 if (endswith(*a, "\n"))
2299 typedef struct ExecStatusInfo {
2307 usec_t start_timestamp;
2308 usec_t exit_timestamp;
2313 LIST_FIELDS(struct ExecStatusInfo, exec);
2316 static void exec_status_info_free(ExecStatusInfo *i) {
2325 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2326 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2327 DBusMessageIter sub2, sub3;
2331 int32_t code, status;
2337 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2340 dbus_message_iter_recurse(sub, &sub2);
2342 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2345 i->path = strdup(path);
2349 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2350 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2354 dbus_message_iter_recurse(&sub2, &sub3);
2355 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2356 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2357 dbus_message_iter_next(&sub3);
2361 i->argv = new0(char*, n+1);
2366 dbus_message_iter_recurse(&sub2, &sub3);
2367 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2370 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2371 dbus_message_iter_get_basic(&sub3, &s);
2372 dbus_message_iter_next(&sub3);
2374 i->argv[n] = strdup(s);
2381 if (!dbus_message_iter_next(&sub2) ||
2382 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2383 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2384 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2385 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2386 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2387 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2388 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2389 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2393 i->start_timestamp = (usec_t) start_timestamp;
2394 i->exit_timestamp = (usec_t) exit_timestamp;
2395 i->pid = (pid_t) pid;
2402 typedef struct UnitStatusInfo {
2404 const char *load_state;
2405 const char *active_state;
2406 const char *sub_state;
2407 const char *unit_file_state;
2409 const char *description;
2410 const char *following;
2412 char **documentation;
2414 const char *fragment_path;
2415 const char *source_path;
2416 const char *default_control_group;
2418 const char *load_error;
2421 usec_t inactive_exit_timestamp;
2422 usec_t inactive_exit_timestamp_monotonic;
2423 usec_t active_enter_timestamp;
2424 usec_t active_exit_timestamp;
2425 usec_t inactive_enter_timestamp;
2427 bool need_daemon_reload;
2432 const char *status_text;
2435 usec_t start_timestamp;
2436 usec_t exit_timestamp;
2438 int exit_code, exit_status;
2440 usec_t condition_timestamp;
2441 bool condition_result;
2444 unsigned n_accepted;
2445 unsigned n_connections;
2449 const char *sysfs_path;
2451 /* Mount, Automount */
2457 LIST_HEAD(ExecStatusInfo, exec);
2460 static void print_status_info(UnitStatusInfo *i) {
2462 const char *on, *off, *ss;
2464 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2465 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2468 arg_all * OUTPUT_SHOW_ALL |
2469 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2470 on_tty() * OUTPUT_COLOR |
2471 !arg_quiet * OUTPUT_WARN_CUTOFF |
2472 arg_full * OUTPUT_FULL_WIDTH;
2476 /* This shows pretty information about a unit. See
2477 * print_property() for a low-level property printer */
2479 printf("%s", strna(i->id));
2481 if (i->description && !streq_ptr(i->id, i->description))
2482 printf(" - %s", i->description);
2487 printf("\t Follow: unit currently follows state of %s\n", i->following);
2489 if (streq_ptr(i->load_state, "error")) {
2490 on = ansi_highlight_red(true);
2491 off = ansi_highlight_red(false);
2495 path = i->source_path ? i->source_path : i->fragment_path;
2498 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2499 else if (path && i->unit_file_state)
2500 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2502 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2504 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2506 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2508 if (streq_ptr(i->active_state, "failed")) {
2509 on = ansi_highlight_red(true);
2510 off = ansi_highlight_red(false);
2511 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2512 on = ansi_highlight_green(true);
2513 off = ansi_highlight_green(false);
2518 printf("\t Active: %s%s (%s)%s",
2520 strna(i->active_state),
2524 printf("\t Active: %s%s%s",
2526 strna(i->active_state),
2529 if (!isempty(i->result) && !streq(i->result, "success"))
2530 printf(" (Result: %s)", i->result);
2532 timestamp = (streq_ptr(i->active_state, "active") ||
2533 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2534 (streq_ptr(i->active_state, "inactive") ||
2535 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2536 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2537 i->active_exit_timestamp;
2539 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2540 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2543 printf(" since %s; %s\n", s2, s1);
2545 printf(" since %s\n", s2);
2549 if (!i->condition_result && i->condition_timestamp > 0) {
2550 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2551 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2554 printf("\t start condition failed at %s; %s\n", s2, s1);
2556 printf("\t start condition failed at %s\n", s2);
2560 printf("\t Device: %s\n", i->sysfs_path);
2562 printf("\t Where: %s\n", i->where);
2564 printf("\t What: %s\n", i->what);
2566 if (!strv_isempty(i->documentation)) {
2570 STRV_FOREACH(t, i->documentation) {
2572 printf("\t Docs: %s\n", *t);
2575 printf("\t %s\n", *t);
2580 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2582 LIST_FOREACH(exec, p, i->exec) {
2583 _cleanup_free_ char *t = NULL;
2586 /* Only show exited processes here */
2590 t = strv_join(p->argv, " ");
2591 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2593 good = is_clean_exit_lsb(p->code, p->status, NULL);
2595 on = ansi_highlight_red(true);
2596 off = ansi_highlight_red(false);
2600 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2602 if (p->code == CLD_EXITED) {
2605 printf("status=%i", p->status);
2607 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2612 printf("signal=%s", signal_to_string(p->status));
2614 printf(")%s\n", off);
2616 if (i->main_pid == p->pid &&
2617 i->start_timestamp == p->start_timestamp &&
2618 i->exit_timestamp == p->start_timestamp)
2619 /* Let's not show this twice */
2622 if (p->pid == i->control_pid)
2626 if (i->main_pid > 0 || i->control_pid > 0) {
2629 if (i->main_pid > 0) {
2630 printf("Main PID: %u", (unsigned) i->main_pid);
2633 _cleanup_free_ char *t = NULL;
2634 get_process_comm(i->main_pid, &t);
2637 } else if (i->exit_code > 0) {
2638 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2640 if (i->exit_code == CLD_EXITED) {
2643 printf("status=%i", i->exit_status);
2645 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2650 printf("signal=%s", signal_to_string(i->exit_status));
2655 if (i->main_pid > 0 && i->control_pid > 0)
2658 if (i->control_pid > 0) {
2659 _cleanup_free_ char *t = NULL;
2661 printf(" Control: %u", (unsigned) i->control_pid);
2663 get_process_comm(i->control_pid, &t);
2672 printf("\t Status: \"%s\"\n", i->status_text);
2674 if (i->default_control_group &&
2675 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2678 printf("\t CGroup: %s\n", i->default_control_group);
2680 if (arg_transport != TRANSPORT_SSH) {
2690 if (i->main_pid > 0)
2691 extra[k++] = i->main_pid;
2693 if (i->control_pid > 0)
2694 extra[k++] = i->control_pid;
2696 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, extra, k, flags);
2700 if (i->id && arg_transport != TRANSPORT_SSH) {
2702 if(arg_scope == UNIT_FILE_SYSTEM)
2703 show_journal_by_unit(stdout,
2707 i->inactive_exit_timestamp_monotonic,
2711 show_journal_by_user_unit(stdout,
2715 i->inactive_exit_timestamp_monotonic,
2721 if (i->need_daemon_reload)
2722 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2723 ansi_highlight_red(true),
2724 ansi_highlight_red(false),
2725 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2728 static void show_unit_help(UnitStatusInfo *i) {
2733 if (!i->documentation) {
2734 log_info("Documentation for %s not known.", i->id);
2738 STRV_FOREACH(p, i->documentation) {
2740 if (startswith(*p, "man:")) {
2743 char *page = NULL, *section = NULL;
2744 const char *args[4] = { "man", NULL, NULL, NULL };
2749 if ((*p)[k-1] == ')')
2750 e = strrchr(*p, '(');
2753 page = strndup((*p) + 4, e - *p - 4);
2759 section = strndup(e + 1, *p + k - e - 2);
2773 log_error("Failed to fork: %m");
2781 execvp(args[0], (char**) args);
2782 log_error("Failed to execute man: %m");
2783 _exit(EXIT_FAILURE);
2789 wait_for_terminate(pid, NULL);
2791 log_info("Can't show: %s", *p);
2795 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2801 switch (dbus_message_iter_get_arg_type(iter)) {
2803 case DBUS_TYPE_STRING: {
2806 dbus_message_iter_get_basic(iter, &s);
2809 if (streq(name, "Id"))
2811 else if (streq(name, "LoadState"))
2813 else if (streq(name, "ActiveState"))
2814 i->active_state = s;
2815 else if (streq(name, "SubState"))
2817 else if (streq(name, "Description"))
2819 else if (streq(name, "FragmentPath"))
2820 i->fragment_path = s;
2821 else if (streq(name, "SourcePath"))
2823 else if (streq(name, "DefaultControlGroup"))
2824 i->default_control_group = s;
2825 else if (streq(name, "StatusText"))
2827 else if (streq(name, "SysFSPath"))
2829 else if (streq(name, "Where"))
2831 else if (streq(name, "What"))
2833 else if (streq(name, "Following"))
2835 else if (streq(name, "UnitFileState"))
2836 i->unit_file_state = s;
2837 else if (streq(name, "Result"))
2844 case DBUS_TYPE_BOOLEAN: {
2847 dbus_message_iter_get_basic(iter, &b);
2849 if (streq(name, "Accept"))
2851 else if (streq(name, "NeedDaemonReload"))
2852 i->need_daemon_reload = b;
2853 else if (streq(name, "ConditionResult"))
2854 i->condition_result = b;
2859 case DBUS_TYPE_UINT32: {
2862 dbus_message_iter_get_basic(iter, &u);
2864 if (streq(name, "MainPID")) {
2866 i->main_pid = (pid_t) u;
2869 } else if (streq(name, "ControlPID"))
2870 i->control_pid = (pid_t) u;
2871 else if (streq(name, "ExecMainPID")) {
2873 i->main_pid = (pid_t) u;
2874 } else if (streq(name, "NAccepted"))
2876 else if (streq(name, "NConnections"))
2877 i->n_connections = u;
2882 case DBUS_TYPE_INT32: {
2885 dbus_message_iter_get_basic(iter, &j);
2887 if (streq(name, "ExecMainCode"))
2888 i->exit_code = (int) j;
2889 else if (streq(name, "ExecMainStatus"))
2890 i->exit_status = (int) j;
2895 case DBUS_TYPE_UINT64: {
2898 dbus_message_iter_get_basic(iter, &u);
2900 if (streq(name, "ExecMainStartTimestamp"))
2901 i->start_timestamp = (usec_t) u;
2902 else if (streq(name, "ExecMainExitTimestamp"))
2903 i->exit_timestamp = (usec_t) u;
2904 else if (streq(name, "ActiveEnterTimestamp"))
2905 i->active_enter_timestamp = (usec_t) u;
2906 else if (streq(name, "InactiveEnterTimestamp"))
2907 i->inactive_enter_timestamp = (usec_t) u;
2908 else if (streq(name, "InactiveExitTimestamp"))
2909 i->inactive_exit_timestamp = (usec_t) u;
2910 else if (streq(name, "InactiveExitTimestampMonotonic"))
2911 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2912 else if (streq(name, "ActiveExitTimestamp"))
2913 i->active_exit_timestamp = (usec_t) u;
2914 else if (streq(name, "ConditionTimestamp"))
2915 i->condition_timestamp = (usec_t) u;
2920 case DBUS_TYPE_ARRAY: {
2922 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2923 startswith(name, "Exec")) {
2924 DBusMessageIter sub;
2926 dbus_message_iter_recurse(iter, &sub);
2927 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2928 ExecStatusInfo *info;
2931 if (!(info = new0(ExecStatusInfo, 1)))
2934 if (!(info->name = strdup(name))) {
2939 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2944 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2946 dbus_message_iter_next(&sub);
2948 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2949 streq(name, "Documentation")) {
2951 DBusMessageIter sub;
2953 dbus_message_iter_recurse(iter, &sub);
2954 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2958 dbus_message_iter_get_basic(&sub, &s);
2960 l = strv_append(i->documentation, s);
2964 strv_free(i->documentation);
2965 i->documentation = l;
2967 dbus_message_iter_next(&sub);
2974 case DBUS_TYPE_STRUCT: {
2976 if (streq(name, "LoadError")) {
2977 DBusMessageIter sub;
2978 const char *n, *message;
2981 dbus_message_iter_recurse(iter, &sub);
2983 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2987 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2991 if (!isempty(message))
2992 i->load_error = message;
3002 static int print_property(const char *name, DBusMessageIter *iter) {
3006 /* This is a low-level property printer, see
3007 * print_status_info() for the nicer output */
3009 if (arg_property && !strv_find(arg_property, name))
3012 switch (dbus_message_iter_get_arg_type(iter)) {
3014 case DBUS_TYPE_STRUCT: {
3015 DBusMessageIter sub;
3016 dbus_message_iter_recurse(iter, &sub);
3018 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
3021 dbus_message_iter_get_basic(&sub, &u);
3024 printf("%s=%u\n", name, (unsigned) u);
3026 printf("%s=\n", name);
3029 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
3032 dbus_message_iter_get_basic(&sub, &s);
3034 if (arg_all || s[0])
3035 printf("%s=%s\n", name, s);
3038 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
3039 const char *a = NULL, *b = NULL;
3041 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
3042 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
3044 if (arg_all || !isempty(a) || !isempty(b))
3045 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
3053 case DBUS_TYPE_ARRAY:
3055 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
3056 DBusMessageIter sub, sub2;
3058 dbus_message_iter_recurse(iter, &sub);
3059 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3063 dbus_message_iter_recurse(&sub, &sub2);
3065 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
3066 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
3067 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
3069 dbus_message_iter_next(&sub);
3074 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
3075 DBusMessageIter sub, sub2;
3077 dbus_message_iter_recurse(iter, &sub);
3078 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3079 const char *type, *path;
3081 dbus_message_iter_recurse(&sub, &sub2);
3083 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
3084 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
3085 printf("%s=%s\n", type, path);
3087 dbus_message_iter_next(&sub);
3092 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
3093 DBusMessageIter sub, sub2;
3095 dbus_message_iter_recurse(iter, &sub);
3096 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3098 uint64_t value, next_elapse;
3100 dbus_message_iter_recurse(&sub, &sub2);
3102 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
3103 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
3104 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
3105 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
3107 printf("%s={ value=%s ; next_elapse=%s }\n",
3109 format_timespan(timespan1, sizeof(timespan1), value),
3110 format_timespan(timespan2, sizeof(timespan2), next_elapse));
3113 dbus_message_iter_next(&sub);
3118 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
3119 DBusMessageIter sub, sub2;
3121 dbus_message_iter_recurse(iter, &sub);
3122 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3123 const char *controller, *attr, *value;
3125 dbus_message_iter_recurse(&sub, &sub2);
3127 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
3128 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
3129 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
3131 printf("ControlGroupAttributes={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
3137 dbus_message_iter_next(&sub);
3142 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
3143 DBusMessageIter sub;
3145 dbus_message_iter_recurse(iter, &sub);
3146 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
3147 ExecStatusInfo info;
3150 if (exec_status_info_deserialize(&sub, &info) >= 0) {
3151 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
3154 t = strv_join(info.argv, " ");
3156 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
3160 yes_no(info.ignore),
3161 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
3162 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
3163 (unsigned) info. pid,
3164 sigchld_code_to_string(info.code),
3166 info.code == CLD_EXITED ? "" : "/",
3167 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
3173 strv_free(info.argv);
3175 dbus_message_iter_next(&sub);
3184 if (generic_print_property(name, iter, arg_all) > 0)
3188 printf("%s=[unprintable]\n", name);
3193 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
3194 _cleanup_free_ DBusMessage *reply = NULL;
3195 const char *interface = "";
3197 DBusMessageIter iter, sub, sub2, sub3;
3198 UnitStatusInfo info;
3206 r = bus_method_call_with_reply(
3208 "org.freedesktop.systemd1",
3210 "org.freedesktop.DBus.Properties",
3214 DBUS_TYPE_STRING, &interface,
3219 if (!dbus_message_iter_init(reply, &iter) ||
3220 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3221 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
3222 log_error("Failed to parse reply.");
3226 dbus_message_iter_recurse(&iter, &sub);
3233 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3236 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_DICT_ENTRY);
3237 dbus_message_iter_recurse(&sub, &sub2);
3239 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
3240 dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
3241 log_error("Failed to parse reply.");
3245 dbus_message_iter_recurse(&sub2, &sub3);
3247 if (show_properties)
3248 r = print_property(name, &sub3);
3250 r = status_property(name, &sub3, &info);
3252 log_error("Failed to parse reply.");
3256 dbus_message_iter_next(&sub);
3261 if (!show_properties) {
3262 if (streq(verb, "help"))
3263 show_unit_help(&info);
3265 print_status_info(&info);
3268 strv_free(info.documentation);
3270 if (!streq_ptr(info.active_state, "active") &&
3271 !streq_ptr(info.active_state, "reloading") &&
3272 streq(verb, "status"))
3273 /* According to LSB: "program not running" */
3276 while ((p = info.exec)) {
3277 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3278 exec_status_info_free(p);
3284 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3285 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3286 const char *path = NULL;
3290 dbus_error_init(&error);
3292 r = bus_method_call_with_reply(
3294 "org.freedesktop.systemd1",
3295 "/org/freedesktop/systemd1",
3296 "org.freedesktop.systemd1.Manager",
3300 DBUS_TYPE_UINT32, &pid,
3305 if (!dbus_message_get_args(reply, &error,
3306 DBUS_TYPE_OBJECT_PATH, &path,
3307 DBUS_TYPE_INVALID)) {
3308 log_error("Failed to parse reply: %s", bus_error_message(&error));
3313 r = show_one(verb, bus, path, false, new_line);
3316 dbus_error_free(&error);
3321 static int show(DBusConnection *bus, char **args) {
3323 bool show_properties, new_line = false;
3329 show_properties = streq(args[0], "show");
3331 if (show_properties)
3332 pager_open_if_enabled();
3334 /* If no argument is specified inspect the manager itself */
3336 if (show_properties && strv_length(args) <= 1)
3337 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3339 STRV_FOREACH(name, args+1) {
3342 if (safe_atou32(*name, &id) < 0) {
3343 _cleanup_free_ char *p = NULL, *n = NULL;
3344 /* Interpret as unit name */
3346 n = unit_name_mangle(*name);
3350 p = unit_dbus_path_from_name(n);
3354 r = show_one(args[0], bus, p, show_properties, &new_line);
3358 } else if (show_properties) {
3359 _cleanup_free_ char *p = NULL;
3361 /* Interpret as job id */
3362 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3365 r = show_one(args[0], bus, p, show_properties, &new_line);
3370 /* Interpret as PID */
3371 r = show_one_by_pid(args[0], bus, id, &new_line);
3380 static int dump(DBusConnection *bus, char **args) {
3381 _cleanup_free_ DBusMessage *reply = NULL;
3386 dbus_error_init(&error);
3388 pager_open_if_enabled();
3390 r = bus_method_call_with_reply(
3392 "org.freedesktop.systemd1",
3393 "/org/freedesktop/systemd1",
3394 "org.freedesktop.systemd1.Manager",
3402 if (!dbus_message_get_args(reply, &error,
3403 DBUS_TYPE_STRING, &text,
3404 DBUS_TYPE_INVALID)) {
3405 log_error("Failed to parse reply: %s", bus_error_message(&error));
3406 dbus_error_free(&error);
3410 fputs(text, stdout);
3414 static int snapshot(DBusConnection *bus, char **args) {
3415 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3418 dbus_bool_t cleanup = FALSE;
3419 DBusMessageIter iter, sub;
3422 *interface = "org.freedesktop.systemd1.Unit",
3424 _cleanup_free_ char *n = NULL;
3426 dbus_error_init(&error);
3428 if (strv_length(args) > 1)
3429 n = snapshot_name_mangle(args[1]);
3435 r = bus_method_call_with_reply (
3437 "org.freedesktop.systemd1",
3438 "/org/freedesktop/systemd1",
3439 "org.freedesktop.systemd1.Manager",
3443 DBUS_TYPE_STRING, &n,
3444 DBUS_TYPE_BOOLEAN, &cleanup,
3449 if (!dbus_message_get_args(reply, &error,
3450 DBUS_TYPE_OBJECT_PATH, &path,
3451 DBUS_TYPE_INVALID)) {
3452 log_error("Failed to parse reply: %s", bus_error_message(&error));
3453 dbus_error_free(&error);
3457 dbus_message_unref(reply);
3460 r = bus_method_call_with_reply (
3462 "org.freedesktop.systemd1",
3464 "org.freedesktop.DBus.Properties",
3468 DBUS_TYPE_STRING, &interface,
3469 DBUS_TYPE_STRING, &property,
3474 if (!dbus_message_iter_init(reply, &iter) ||
3475 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3476 log_error("Failed to parse reply.");
3480 dbus_message_iter_recurse(&iter, &sub);
3482 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3483 log_error("Failed to parse reply.");
3487 dbus_message_iter_get_basic(&sub, &id);
3495 static int delete_snapshot(DBusConnection *bus, char **args) {
3500 STRV_FOREACH(name, args+1) {
3501 _cleanup_free_ char *n = NULL;
3504 n = snapshot_name_mangle(*name);
3508 r = bus_method_call_with_reply(
3510 "org.freedesktop.systemd1",
3511 "/org/freedesktop/systemd1",
3512 "org.freedesktop.systemd1.Manager",
3516 DBUS_TYPE_STRING, &n,
3525 static int daemon_reload(DBusConnection *bus, char **args) {
3530 if (arg_action == ACTION_RELOAD)
3532 else if (arg_action == ACTION_REEXEC)
3533 method = "Reexecute";
3535 assert(arg_action == ACTION_SYSTEMCTL);
3538 streq(args[0], "clear-jobs") ||
3539 streq(args[0], "cancel") ? "ClearJobs" :
3540 streq(args[0], "daemon-reexec") ? "Reexecute" :
3541 streq(args[0], "reset-failed") ? "ResetFailed" :
3542 streq(args[0], "halt") ? "Halt" :
3543 streq(args[0], "poweroff") ? "PowerOff" :
3544 streq(args[0], "reboot") ? "Reboot" :
3545 streq(args[0], "kexec") ? "KExec" :
3546 streq(args[0], "exit") ? "Exit" :
3547 /* "daemon-reload" */ "Reload";
3550 r = bus_method_call_with_reply(
3552 "org.freedesktop.systemd1",
3553 "/org/freedesktop/systemd1",
3554 "org.freedesktop.systemd1.Manager",
3560 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3561 /* There's always a fallback possible for
3562 * legacy actions. */
3564 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3565 /* On reexecution, we expect a disconnect, not
3569 log_error("Failed to issue method call: %s", bus_error_message(&error));
3571 dbus_error_free(&error);
3575 static int reset_failed(DBusConnection *bus, char **args) {
3579 if (strv_length(args) <= 1)
3580 return daemon_reload(bus, args);
3582 STRV_FOREACH(name, args+1) {
3583 _cleanup_free_ char *n;
3585 n = unit_name_mangle(*name);
3589 r = bus_method_call_with_reply(
3591 "org.freedesktop.systemd1",
3592 "/org/freedesktop/systemd1",
3593 "org.freedesktop.systemd1.Manager",
3597 DBUS_TYPE_STRING, &n,
3606 static int show_enviroment(DBusConnection *bus, char **args) {
3607 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3608 DBusMessageIter iter, sub, sub2;
3611 *interface = "org.freedesktop.systemd1.Manager",
3612 *property = "Environment";
3614 pager_open_if_enabled();
3616 r = bus_method_call_with_reply(
3618 "org.freedesktop.systemd1",
3619 "/org/freedesktop/systemd1",
3620 "org.freedesktop.DBus.Properties",
3624 DBUS_TYPE_STRING, &interface,
3625 DBUS_TYPE_STRING, &property,
3630 if (!dbus_message_iter_init(reply, &iter) ||
3631 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3632 log_error("Failed to parse reply.");
3636 dbus_message_iter_recurse(&iter, &sub);
3638 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3639 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3640 log_error("Failed to parse reply.");
3644 dbus_message_iter_recurse(&sub, &sub2);
3646 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3649 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3650 log_error("Failed to parse reply.");
3654 dbus_message_iter_get_basic(&sub2, &text);
3657 dbus_message_iter_next(&sub2);
3663 static int switch_root(DBusConnection *bus, char **args) {
3666 _cleanup_free_ char *init = NULL;
3668 l = strv_length(args);
3669 if (l < 2 || l > 3) {
3670 log_error("Wrong number of arguments.");
3677 init = strdup(args[2]);
3679 parse_env_file("/proc/cmdline", WHITESPACE,
3689 log_debug("switching root - root: %s; init: %s", root, init);
3691 return bus_method_call_with_reply(
3693 "org.freedesktop.systemd1",
3694 "/org/freedesktop/systemd1",
3695 "org.freedesktop.systemd1.Manager",
3699 DBUS_TYPE_STRING, &root,
3700 DBUS_TYPE_STRING, &init,
3704 static int set_environment(DBusConnection *bus, char **args) {
3705 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3708 DBusMessageIter iter;
3714 dbus_error_init(&error);
3716 method = streq(args[0], "set-environment")
3718 : "UnsetEnvironment";
3720 m = dbus_message_new_method_call(
3721 "org.freedesktop.systemd1",
3722 "/org/freedesktop/systemd1",
3723 "org.freedesktop.systemd1.Manager",
3728 dbus_message_iter_init_append(m, &iter);
3730 r = bus_append_strv_iter(&iter, args + 1);
3734 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3736 log_error("Failed to issue method call: %s", bus_error_message(&error));
3737 dbus_error_free(&error);
3744 static int enable_sysv_units(char **args) {
3747 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3748 const char *verb = args[0];
3749 unsigned f = 1, t = 1;
3752 if (arg_scope != UNIT_FILE_SYSTEM)
3755 if (!streq(verb, "enable") &&
3756 !streq(verb, "disable") &&
3757 !streq(verb, "is-enabled"))
3760 /* Processes all SysV units, and reshuffles the array so that
3761 * afterwards only the native units remain */
3764 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3769 for (f = 1; args[f]; f++) {
3772 bool found_native = false, found_sysv;
3774 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3775 char **k, *l, *q = NULL;
3782 if (!endswith(name, ".service"))
3785 if (path_is_absolute(name))
3788 STRV_FOREACH(k, paths.unit_path) {
3791 if (!isempty(arg_root))
3792 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3794 asprintf(&p, "%s/%s", *k, name);
3801 found_native = access(p, F_OK) >= 0;
3812 if (!isempty(arg_root))
3813 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3815 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3821 p[strlen(p) - sizeof(".service") + 1] = 0;
3822 found_sysv = access(p, F_OK) >= 0;
3829 /* Mark this entry, so that we don't try enabling it as native unit */
3830 args[f] = (char*) "";
3832 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3834 if (!isempty(arg_root))
3835 argv[c++] = q = strappend("--root=", arg_root);
3837 argv[c++] = path_get_file_name(p);
3839 streq(verb, "enable") ? "on" :
3840 streq(verb, "disable") ? "off" : "--level=5";
3843 l = strv_join((char**)argv, " ");
3851 log_info("Executing %s", l);
3856 log_error("Failed to fork: %m");
3861 } else if (pid == 0) {
3864 execv(argv[0], (char**) argv);
3865 _exit(EXIT_FAILURE);
3871 j = wait_for_terminate(pid, &status);
3873 log_error("Failed to wait for child: %s", strerror(-r));
3878 if (status.si_code == CLD_EXITED) {
3879 if (streq(verb, "is-enabled")) {
3880 if (status.si_status == 0) {
3889 } else if (status.si_status != 0) {
3900 lookup_paths_free(&paths);
3902 /* Drop all SysV units */
3903 for (f = 1, t = 1; args[f]; f++) {
3905 if (isempty(args[f]))
3908 args[t++] = args[f];
3917 static int mangle_names(char **original_names, char ***mangled_names) {
3918 char **i, **l, **name;
3920 l = new(char*, strv_length(original_names) + 1);
3925 STRV_FOREACH(name, original_names) {
3927 /* When enabling units qualified path names are OK,
3928 * too, hence allow them explicitly. */
3933 *i = unit_name_mangle(*name);
3949 static int enable_unit(DBusConnection *bus, char **args) {
3950 const char *verb = args[0];
3951 UnitFileChange *changes = NULL;
3952 unsigned n_changes = 0, i;
3953 int carries_install_info = -1;
3954 DBusMessage *m = NULL, *reply = NULL;
3957 char **mangled_names = NULL;
3959 r = enable_sysv_units(args);
3966 dbus_error_init(&error);
3968 if (!bus || avoid_bus()) {
3969 if (streq(verb, "enable")) {
3970 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3971 carries_install_info = r;
3972 } else if (streq(verb, "disable"))
3973 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3974 else if (streq(verb, "reenable")) {
3975 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3976 carries_install_info = r;
3977 } else if (streq(verb, "link"))
3978 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3979 else if (streq(verb, "preset")) {
3980 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3981 carries_install_info = r;
3982 } else if (streq(verb, "mask"))
3983 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3984 else if (streq(verb, "unmask"))
3985 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3987 assert_not_reached("Unknown verb");
3990 log_error("Operation failed: %s", strerror(-r));
3995 for (i = 0; i < n_changes; i++) {
3996 if (changes[i].type == UNIT_FILE_SYMLINK)
3997 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3999 log_info("rm '%s'", changes[i].path);
4006 bool send_force = true, expect_carries_install_info = false;
4008 DBusMessageIter iter, sub, sub2;
4010 if (streq(verb, "enable")) {
4011 method = "EnableUnitFiles";
4012 expect_carries_install_info = true;
4013 } else if (streq(verb, "disable")) {
4014 method = "DisableUnitFiles";
4016 } else if (streq(verb, "reenable")) {
4017 method = "ReenableUnitFiles";
4018 expect_carries_install_info = true;
4019 } else if (streq(verb, "link"))
4020 method = "LinkUnitFiles";
4021 else if (streq(verb, "preset")) {
4022 method = "PresetUnitFiles";
4023 expect_carries_install_info = true;
4024 } else if (streq(verb, "mask"))
4025 method = "MaskUnitFiles";
4026 else if (streq(verb, "unmask")) {
4027 method = "UnmaskUnitFiles";
4030 assert_not_reached("Unknown verb");
4032 m = dbus_message_new_method_call(
4033 "org.freedesktop.systemd1",
4034 "/org/freedesktop/systemd1",
4035 "org.freedesktop.systemd1.Manager",
4042 dbus_message_iter_init_append(m, &iter);
4044 r = mangle_names(args+1, &mangled_names);
4048 r = bus_append_strv_iter(&iter, mangled_names);
4050 log_error("Failed to append unit files.");
4055 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
4056 log_error("Failed to append runtime boolean.");
4064 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
4065 log_error("Failed to append force boolean.");
4071 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
4073 log_error("Failed to issue method call: %s", bus_error_message(&error));
4078 if (!dbus_message_iter_init(reply, &iter)) {
4079 log_error("Failed to initialize iterator.");
4083 if (expect_carries_install_info) {
4084 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
4086 log_error("Failed to parse reply.");
4090 carries_install_info = b;
4093 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
4094 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
4095 log_error("Failed to parse reply.");
4100 dbus_message_iter_recurse(&iter, &sub);
4101 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
4102 const char *type, *path, *source;
4104 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
4105 log_error("Failed to parse reply.");
4110 dbus_message_iter_recurse(&sub, &sub2);
4112 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
4113 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
4114 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
4115 log_error("Failed to parse reply.");
4121 if (streq(type, "symlink"))
4122 log_info("ln -s '%s' '%s'", source, path);
4124 log_info("rm '%s'", path);
4127 dbus_message_iter_next(&sub);
4130 /* Try to reload if enabeld */
4132 r = daemon_reload(bus, args);
4135 if (carries_install_info == 0)
4137 "The unit files have no [Install] section. They are not meant to be enabled\n"
4138 "using systemctl.\n"
4139 "Possible reasons for having this kind of units are:\n"
4140 "1) A unit may be statically enabled by being symlinked from another unit's\n"
4141 " .wants/ or .requires/ directory.\n"
4142 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
4143 " a requirement dependency on it.\n"
4144 "3) A unit may be started when needed via activation (socket, path, timer,\n"
4145 " D-Bus, udev, scripted systemctl call, ...).\n");
4149 dbus_message_unref(m);
4152 dbus_message_unref(reply);
4154 unit_file_changes_free(changes, n_changes);
4156 dbus_error_free(&error);
4158 strv_free(mangled_names);
4163 static int unit_is_enabled(DBusConnection *bus, char **args) {
4166 DBusMessage *reply = NULL;
4170 dbus_error_init(&error);
4172 r = enable_sysv_units(args);
4178 if (!bus || avoid_bus()) {
4180 STRV_FOREACH(name, args+1) {
4181 UnitFileState state;
4183 state = unit_file_get_state(arg_scope, arg_root, *name);
4189 if (state == UNIT_FILE_ENABLED ||
4190 state == UNIT_FILE_ENABLED_RUNTIME ||
4191 state == UNIT_FILE_STATIC)
4195 puts(unit_file_state_to_string(state));
4199 STRV_FOREACH(name, args+1) {
4202 r = bus_method_call_with_reply (
4204 "org.freedesktop.systemd1",
4205 "/org/freedesktop/systemd1",
4206 "org.freedesktop.systemd1.Manager",
4210 DBUS_TYPE_STRING, name,
4215 if (!dbus_message_get_args(reply, &error,
4216 DBUS_TYPE_STRING, &s,
4217 DBUS_TYPE_INVALID)) {
4218 log_error("Failed to parse reply: %s", bus_error_message(&error));
4223 dbus_message_unref(reply);
4226 if (streq(s, "enabled") ||
4227 streq(s, "enabled-runtime") ||
4236 r = enabled ? 0 : 1;
4240 dbus_message_unref(reply);
4242 dbus_error_free(&error);
4246 static int systemctl_help(void) {
4248 pager_open_if_enabled();
4250 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4251 "Query or send control commands to the systemd manager.\n\n"
4252 " -h --help Show this help\n"
4253 " --version Show package version\n"
4254 " -t --type=TYPE List only units of a particular type\n"
4255 " -p --property=NAME Show only properties by this name\n"
4256 " -a --all Show all units/properties, including dead/empty ones\n"
4257 " --failed Show only failed units\n"
4258 " --full Don't ellipsize unit names on output\n"
4259 " --fail When queueing a new job, fail if conflicting jobs are\n"
4261 " --ignore-dependencies\n"
4262 " When queueing a new job, ignore all its dependencies\n"
4263 " -i --ignore-inhibitors\n"
4264 " When shutting down or sleeping, ignore inhibitors\n"
4265 " --kill-who=WHO Who to send signal to\n"
4266 " -s --signal=SIGNAL Which signal to send\n"
4267 " -H --host=[USER@]HOST\n"
4268 " Show information for remote host\n"
4269 " -P --privileged Acquire privileges before execution\n"
4270 " -q --quiet Suppress output\n"
4271 " --no-block Do not wait until operation finished\n"
4272 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4273 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4275 " --no-legend Do not print a legend (column headers and hints)\n"
4276 " --no-pager Do not pipe output into a pager\n"
4277 " --no-ask-password\n"
4278 " Do not ask for system passwords\n"
4279 " --order When generating graph for dot, show only order\n"
4280 " --require When generating graph for dot, show only requirement\n"
4281 " --system Connect to system manager\n"
4282 " --user Connect to user service manager\n"
4283 " --global Enable/disable unit files globally\n"
4284 " -f --force When enabling unit files, override existing symlinks\n"
4285 " When shutting down, execute action immediately\n"
4286 " --root=PATH Enable unit files in the specified root directory\n"
4287 " --runtime Enable unit files only temporarily until next reboot\n"
4288 " -n --lines=INTEGER Journal entries to show\n"
4289 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4290 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4292 " list-units List loaded units\n"
4293 " start [NAME...] Start (activate) one or more units\n"
4294 " stop [NAME...] Stop (deactivate) one or more units\n"
4295 " reload [NAME...] Reload one or more units\n"
4296 " restart [NAME...] Start or restart one or more units\n"
4297 " try-restart [NAME...] Restart one or more units if active\n"
4298 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4299 " otherwise start or restart\n"
4300 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4301 " otherwise restart if active\n"
4302 " isolate [NAME] Start one unit and stop all others\n"
4303 " kill [NAME...] Send signal to processes of a unit\n"
4304 " is-active [NAME...] Check whether units are active\n"
4305 " is-failed [NAME...] Check whether units are failed\n"
4306 " status [NAME...|PID...] Show runtime status of one or more units\n"
4307 " show [NAME...|JOB...] Show properties of one or more\n"
4308 " units/jobs or the manager\n"
4309 " help [NAME...|PID...] Show manual for one or more units\n"
4310 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4312 " get-cgroup-attr [NAME] [ATTR] ...\n"
4313 " Get control group attrubute\n"
4314 " set-cgroup-attr [NAME] [ATTR] [VALUE] ...\n"
4315 " Set control group attribute\n"
4316 " unset-cgroup-attr [NAME] [ATTR...]\n"
4317 " Unset control group attribute\n"
4318 " set-cgroup [NAME] [CGROUP...] Add unit to a control group\n"
4319 " unset-cgroup [NAME] [CGROUP...] Remove unit from a control group\n"
4320 " load [NAME...] Load one or more units\n"
4321 " list-dependencies [NAME] Recursively show units which are required\n"
4322 " or wanted by this unit\n\n"
4323 "Unit File Commands:\n"
4324 " list-unit-files List installed unit files\n"
4325 " enable [NAME...] Enable one or more unit files\n"
4326 " disable [NAME...] Disable one or more unit files\n"
4327 " reenable [NAME...] Reenable one or more unit files\n"
4328 " preset [NAME...] Enable/disable one or more unit files\n"
4329 " based on preset configuration\n"
4330 " mask [NAME...] Mask one or more units\n"
4331 " unmask [NAME...] Unmask one or more units\n"
4332 " link [PATH...] Link one or more units files into\n"
4333 " the search path\n"
4334 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4336 " list-jobs List jobs\n"
4337 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4338 "Status Commands:\n"
4339 " dump Dump server status\n"
4340 " dot Dump dependency graph for dot(1)\n\n"
4341 "Snapshot Commands:\n"
4342 " snapshot [NAME] Create a snapshot\n"
4343 " delete [NAME...] Remove one or more snapshots\n\n"
4344 "Environment Commands:\n"
4345 " show-environment Dump environment\n"
4346 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4347 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4348 "Manager Lifecycle Commands:\n"
4349 " daemon-reload Reload systemd manager configuration\n"
4350 " daemon-reexec Reexecute systemd manager\n\n"
4351 "System Commands:\n"
4352 " default Enter system default mode\n"
4353 " rescue Enter system rescue mode\n"
4354 " emergency Enter system emergency mode\n"
4355 " halt Shut down and halt the system\n"
4356 " poweroff Shut down and power-off the system\n"
4357 " reboot Shut down and reboot the system\n"
4358 " kexec Shut down and reboot the system with kexec\n"
4359 " exit Request user instance exit\n"
4360 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4361 " suspend Suspend the system\n"
4362 " hibernate Hibernate the system\n"
4363 " hybrid-sleep Hibernate and suspend the system\n",
4364 program_invocation_short_name);
4369 static int halt_help(void) {
4371 printf("%s [OPTIONS...]\n\n"
4372 "%s the system.\n\n"
4373 " --help Show this help\n"
4374 " --halt Halt the machine\n"
4375 " -p --poweroff Switch off the machine\n"
4376 " --reboot Reboot the machine\n"
4377 " -f --force Force immediate halt/power-off/reboot\n"
4378 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4379 " -d --no-wtmp Don't write wtmp record\n"
4380 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4381 program_invocation_short_name,
4382 arg_action == ACTION_REBOOT ? "Reboot" :
4383 arg_action == ACTION_POWEROFF ? "Power off" :
4389 static int shutdown_help(void) {
4391 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4392 "Shut down the system.\n\n"
4393 " --help Show this help\n"
4394 " -H --halt Halt the machine\n"
4395 " -P --poweroff Power-off the machine\n"
4396 " -r --reboot Reboot the machine\n"
4397 " -h Equivalent to --poweroff, overridden by --halt\n"
4398 " -k Don't halt/power-off/reboot, just send warnings\n"
4399 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4400 " -c Cancel a pending shutdown\n",
4401 program_invocation_short_name);
4406 static int telinit_help(void) {
4408 printf("%s [OPTIONS...] {COMMAND}\n\n"
4409 "Send control commands to the init daemon.\n\n"
4410 " --help Show this help\n"
4411 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4413 " 0 Power-off the machine\n"
4414 " 6 Reboot the machine\n"
4415 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4416 " 1, s, S Enter rescue mode\n"
4417 " q, Q Reload init daemon configuration\n"
4418 " u, U Reexecute init daemon\n",
4419 program_invocation_short_name);
4424 static int runlevel_help(void) {
4426 printf("%s [OPTIONS...]\n\n"
4427 "Prints the previous and current runlevel of the init system.\n\n"
4428 " --help Show this help\n",
4429 program_invocation_short_name);
4434 static int help_types(void) {
4437 puts("Available unit types:");
4438 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4439 if (unit_type_table[i])
4440 puts(unit_type_table[i]);
4442 puts("\nAvailable unit load states: ");
4443 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4444 if (unit_type_table[i])
4445 puts(unit_load_state_table[i]);
4450 static int systemctl_parse_argv(int argc, char *argv[]) {
4454 ARG_IGNORE_DEPENDENCIES,
4469 ARG_NO_ASK_PASSWORD,
4475 static const struct option options[] = {
4476 { "help", no_argument, NULL, 'h' },
4477 { "version", no_argument, NULL, ARG_VERSION },
4478 { "type", required_argument, NULL, 't' },
4479 { "property", required_argument, NULL, 'p' },
4480 { "all", no_argument, NULL, 'a' },
4481 { "failed", no_argument, NULL, ARG_FAILED },
4482 { "full", no_argument, NULL, ARG_FULL },
4483 { "fail", no_argument, NULL, ARG_FAIL },
4484 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4485 { "ignore-inhibitors", no_argument, NULL, 'i' },
4486 { "user", no_argument, NULL, ARG_USER },
4487 { "system", no_argument, NULL, ARG_SYSTEM },
4488 { "global", no_argument, NULL, ARG_GLOBAL },
4489 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4490 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4491 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4492 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4493 { "quiet", no_argument, NULL, 'q' },
4494 { "order", no_argument, NULL, ARG_ORDER },
4495 { "require", no_argument, NULL, ARG_REQUIRE },
4496 { "root", required_argument, NULL, ARG_ROOT },
4497 { "force", no_argument, NULL, ARG_FORCE },
4498 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4499 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4500 { "signal", required_argument, NULL, 's' },
4501 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4502 { "host", required_argument, NULL, 'H' },
4503 { "privileged",no_argument, NULL, 'P' },
4504 { "runtime", no_argument, NULL, ARG_RUNTIME },
4505 { "lines", required_argument, NULL, 'n' },
4506 { "output", required_argument, NULL, 'o' },
4507 { NULL, 0, NULL, 0 }
4515 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4524 puts(PACKAGE_STRING);
4525 puts(SYSTEMD_FEATURES);
4529 if (streq(optarg, "help")) {
4534 if (unit_type_from_string(optarg) >= 0) {
4538 if (unit_load_state_from_string(optarg) >= 0) {
4539 arg_load_state = optarg;
4542 log_error("Unkown unit type or load state '%s'.",
4544 log_info("Use -t help to see a list of allowed values.");
4549 if (!(l = strv_append(arg_property, optarg)))
4552 strv_free(arg_property);
4555 /* If the user asked for a particular
4556 * property, show it to him, even if it is
4567 arg_job_mode = "fail";
4570 case ARG_IGNORE_DEPENDENCIES:
4571 arg_job_mode = "ignore-dependencies";
4575 arg_scope = UNIT_FILE_USER;
4579 arg_scope = UNIT_FILE_SYSTEM;
4583 arg_scope = UNIT_FILE_GLOBAL;
4587 arg_no_block = true;
4591 arg_no_legend = true;
4595 arg_no_pager = true;
4603 arg_dot = DOT_ORDER;
4607 arg_dot = DOT_REQUIRE;
4635 arg_no_reload = true;
4639 arg_kill_who = optarg;
4643 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4644 log_error("Failed to parse signal string %s.", optarg);
4649 case ARG_NO_ASK_PASSWORD:
4650 arg_ask_password = false;
4654 arg_transport = TRANSPORT_POLKIT;
4658 arg_transport = TRANSPORT_SSH;
4667 if (safe_atou(optarg, &arg_lines) < 0) {
4668 log_error("Failed to parse lines '%s'", optarg);
4674 arg_output = output_mode_from_string(optarg);
4675 if (arg_output < 0) {
4676 log_error("Unknown output '%s'.", optarg);
4682 arg_ignore_inhibitors = true;
4689 log_error("Unknown option code '%c'.", c);
4694 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4695 log_error("Cannot access user instance remotely.");
4702 static int halt_parse_argv(int argc, char *argv[]) {
4711 static const struct option options[] = {
4712 { "help", no_argument, NULL, ARG_HELP },
4713 { "halt", no_argument, NULL, ARG_HALT },
4714 { "poweroff", no_argument, NULL, 'p' },
4715 { "reboot", no_argument, NULL, ARG_REBOOT },
4716 { "force", no_argument, NULL, 'f' },
4717 { "wtmp-only", no_argument, NULL, 'w' },
4718 { "no-wtmp", no_argument, NULL, 'd' },
4719 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4720 { NULL, 0, NULL, 0 }
4728 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4729 if (runlevel == '0' || runlevel == '6')
4732 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4740 arg_action = ACTION_HALT;
4744 if (arg_action != ACTION_REBOOT)
4745 arg_action = ACTION_POWEROFF;
4749 arg_action = ACTION_REBOOT;
4771 /* Compatibility nops */
4778 log_error("Unknown option code '%c'.", c);
4783 if (optind < argc) {
4784 log_error("Too many arguments.");
4791 static int parse_time_spec(const char *t, usec_t *_u) {
4795 if (streq(t, "now"))
4797 else if (!strchr(t, ':')) {
4800 if (safe_atou64(t, &u) < 0)
4803 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4812 hour = strtol(t, &e, 10);
4813 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4816 minute = strtol(e+1, &e, 10);
4817 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4820 n = now(CLOCK_REALTIME);
4821 s = (time_t) (n / USEC_PER_SEC);
4824 assert_se(localtime_r(&s, &tm));
4826 tm.tm_hour = (int) hour;
4827 tm.tm_min = (int) minute;
4830 assert_se(s = mktime(&tm));
4832 *_u = (usec_t) s * USEC_PER_SEC;
4835 *_u += USEC_PER_DAY;
4841 static int shutdown_parse_argv(int argc, char *argv[]) {
4848 static const struct option options[] = {
4849 { "help", no_argument, NULL, ARG_HELP },
4850 { "halt", no_argument, NULL, 'H' },
4851 { "poweroff", no_argument, NULL, 'P' },
4852 { "reboot", no_argument, NULL, 'r' },
4853 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4854 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4855 { NULL, 0, NULL, 0 }
4863 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4871 arg_action = ACTION_HALT;
4875 arg_action = ACTION_POWEROFF;
4880 arg_action = ACTION_KEXEC;
4882 arg_action = ACTION_REBOOT;
4886 arg_action = ACTION_KEXEC;
4890 if (arg_action != ACTION_HALT)
4891 arg_action = ACTION_POWEROFF;
4904 /* Compatibility nops */
4908 arg_action = ACTION_CANCEL_SHUTDOWN;
4915 log_error("Unknown option code '%c'.", c);
4920 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4921 r = parse_time_spec(argv[optind], &arg_when);
4923 log_error("Failed to parse time specification: %s", argv[optind]);
4927 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4929 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4930 /* No time argument for shutdown cancel */
4931 arg_wall = argv + optind;
4932 else if (argc > optind + 1)
4933 /* We skip the time argument */
4934 arg_wall = argv + optind + 1;
4941 static int telinit_parse_argv(int argc, char *argv[]) {
4948 static const struct option options[] = {
4949 { "help", no_argument, NULL, ARG_HELP },
4950 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4951 { NULL, 0, NULL, 0 }
4954 static const struct {
4958 { '0', ACTION_POWEROFF },
4959 { '6', ACTION_REBOOT },
4960 { '1', ACTION_RESCUE },
4961 { '2', ACTION_RUNLEVEL2 },
4962 { '3', ACTION_RUNLEVEL3 },
4963 { '4', ACTION_RUNLEVEL4 },
4964 { '5', ACTION_RUNLEVEL5 },
4965 { 's', ACTION_RESCUE },
4966 { 'S', ACTION_RESCUE },
4967 { 'q', ACTION_RELOAD },
4968 { 'Q', ACTION_RELOAD },
4969 { 'u', ACTION_REEXEC },
4970 { 'U', ACTION_REEXEC }
4979 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4994 log_error("Unknown option code '%c'.", c);
4999 if (optind >= argc) {
5004 if (optind + 1 < argc) {
5005 log_error("Too many arguments.");
5009 if (strlen(argv[optind]) != 1) {
5010 log_error("Expected single character argument.");
5014 for (i = 0; i < ELEMENTSOF(table); i++)
5015 if (table[i].from == argv[optind][0])
5018 if (i >= ELEMENTSOF(table)) {
5019 log_error("Unknown command '%s'.", argv[optind]);
5023 arg_action = table[i].to;
5030 static int runlevel_parse_argv(int argc, char *argv[]) {
5036 static const struct option options[] = {
5037 { "help", no_argument, NULL, ARG_HELP },
5038 { NULL, 0, NULL, 0 }
5046 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
5057 log_error("Unknown option code '%c'.", c);
5062 if (optind < argc) {
5063 log_error("Too many arguments.");
5070 static int parse_argv(int argc, char *argv[]) {
5074 if (program_invocation_short_name) {
5076 if (strstr(program_invocation_short_name, "halt")) {
5077 arg_action = ACTION_HALT;
5078 return halt_parse_argv(argc, argv);
5079 } else if (strstr(program_invocation_short_name, "poweroff")) {
5080 arg_action = ACTION_POWEROFF;
5081 return halt_parse_argv(argc, argv);
5082 } else if (strstr(program_invocation_short_name, "reboot")) {
5084 arg_action = ACTION_KEXEC;
5086 arg_action = ACTION_REBOOT;
5087 return halt_parse_argv(argc, argv);
5088 } else if (strstr(program_invocation_short_name, "shutdown")) {
5089 arg_action = ACTION_POWEROFF;
5090 return shutdown_parse_argv(argc, argv);
5091 } else if (strstr(program_invocation_short_name, "init")) {
5093 if (sd_booted() > 0) {
5094 arg_action = ACTION_INVALID;
5095 return telinit_parse_argv(argc, argv);
5097 /* Hmm, so some other init system is
5098 * running, we need to forward this
5099 * request to it. For now we simply
5100 * guess that it is Upstart. */
5102 execv("/lib/upstart/telinit", argv);
5104 log_error("Couldn't find an alternative telinit implementation to spawn.");
5108 } else if (strstr(program_invocation_short_name, "runlevel")) {
5109 arg_action = ACTION_RUNLEVEL;
5110 return runlevel_parse_argv(argc, argv);
5114 arg_action = ACTION_SYSTEMCTL;
5115 return systemctl_parse_argv(argc, argv);
5118 static int action_to_runlevel(void) {
5120 static const char table[_ACTION_MAX] = {
5121 [ACTION_HALT] = '0',
5122 [ACTION_POWEROFF] = '0',
5123 [ACTION_REBOOT] = '6',
5124 [ACTION_RUNLEVEL2] = '2',
5125 [ACTION_RUNLEVEL3] = '3',
5126 [ACTION_RUNLEVEL4] = '4',
5127 [ACTION_RUNLEVEL5] = '5',
5128 [ACTION_RESCUE] = '1'
5131 assert(arg_action < _ACTION_MAX);
5133 return table[arg_action];
5136 static int talk_upstart(void) {
5137 DBusMessage *m = NULL, *reply = NULL;
5139 int previous, rl, r;
5141 env1_buf[] = "RUNLEVEL=X",
5142 env2_buf[] = "PREVLEVEL=X";
5143 char *env1 = env1_buf, *env2 = env2_buf;
5144 const char *emit = "runlevel";
5145 dbus_bool_t b_false = FALSE;
5146 DBusMessageIter iter, sub;
5147 DBusConnection *bus;
5149 dbus_error_init(&error);
5151 if (!(rl = action_to_runlevel()))
5154 if (utmp_get_runlevel(&previous, NULL) < 0)
5157 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
5158 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
5163 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
5168 if ((r = bus_check_peercred(bus)) < 0) {
5169 log_error("Failed to verify owner of bus.");
5173 if (!(m = dbus_message_new_method_call(
5174 "com.ubuntu.Upstart",
5175 "/com/ubuntu/Upstart",
5176 "com.ubuntu.Upstart0_6",
5179 log_error("Could not allocate message.");
5184 dbus_message_iter_init_append(m, &iter);
5186 env1_buf[sizeof(env1_buf)-2] = rl;
5187 env2_buf[sizeof(env2_buf)-2] = previous;
5189 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
5190 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
5191 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
5192 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
5193 !dbus_message_iter_close_container(&iter, &sub) ||
5194 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
5195 log_error("Could not append arguments to message.");
5200 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
5202 if (bus_error_is_no_service(&error)) {
5207 log_error("Failed to issue method call: %s", bus_error_message(&error));
5216 dbus_message_unref(m);
5219 dbus_message_unref(reply);
5222 dbus_connection_flush(bus);
5223 dbus_connection_close(bus);
5224 dbus_connection_unref(bus);
5227 dbus_error_free(&error);
5232 static int talk_initctl(void) {
5233 struct init_request request;
5237 if (!(rl = action_to_runlevel()))
5241 request.magic = INIT_MAGIC;
5242 request.sleeptime = 0;
5243 request.cmd = INIT_CMD_RUNLVL;
5244 request.runlevel = rl;
5246 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5248 if (errno == ENOENT)
5251 log_error("Failed to open "INIT_FIFO": %m");
5256 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5257 close_nointr_nofail(fd);
5260 log_error("Failed to write to "INIT_FIFO": %m");
5261 return errno ? -errno : -EIO;
5267 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5269 static const struct {
5277 int (* const dispatch)(DBusConnection *bus, char **args);
5279 { "list-units", LESS, 1, list_units },
5280 { "list-unit-files", EQUAL, 1, list_unit_files },
5281 { "list-jobs", EQUAL, 1, list_jobs },
5282 { "clear-jobs", EQUAL, 1, daemon_reload },
5283 { "load", MORE, 2, load_unit },
5284 { "cancel", MORE, 2, cancel_job },
5285 { "start", MORE, 2, start_unit },
5286 { "stop", MORE, 2, start_unit },
5287 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5288 { "reload", MORE, 2, start_unit },
5289 { "restart", MORE, 2, start_unit },
5290 { "try-restart", MORE, 2, start_unit },
5291 { "reload-or-restart", MORE, 2, start_unit },
5292 { "reload-or-try-restart", MORE, 2, start_unit },
5293 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5294 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5295 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5296 { "isolate", EQUAL, 2, start_unit },
5297 { "set-cgroup", MORE, 2, set_cgroup },
5298 { "unset-cgroup", MORE, 2, set_cgroup },
5299 { "get-cgroup-attr", MORE, 2, get_cgroup_attr },
5300 { "set-cgroup-attr", MORE, 2, set_cgroup_attr },
5301 { "unset-cgroup-attr", MORE, 2, set_cgroup },
5302 { "kill", MORE, 2, kill_unit },
5303 { "is-active", MORE, 2, check_unit_active },
5304 { "check", MORE, 2, check_unit_active },
5305 { "is-failed", MORE, 2, check_unit_failed },
5306 { "show", MORE, 1, show },
5307 { "status", MORE, 2, show },
5308 { "help", MORE, 2, show },
5309 { "dump", EQUAL, 1, dump },
5310 { "dot", EQUAL, 1, dot },
5311 { "snapshot", LESS, 2, snapshot },
5312 { "delete", MORE, 2, delete_snapshot },
5313 { "daemon-reload", EQUAL, 1, daemon_reload },
5314 { "daemon-reexec", EQUAL, 1, daemon_reload },
5315 { "show-environment", EQUAL, 1, show_enviroment },
5316 { "set-environment", MORE, 2, set_environment },
5317 { "unset-environment", MORE, 2, set_environment },
5318 { "halt", EQUAL, 1, start_special },
5319 { "poweroff", EQUAL, 1, start_special },
5320 { "reboot", EQUAL, 1, start_special },
5321 { "kexec", EQUAL, 1, start_special },
5322 { "suspend", EQUAL, 1, start_special },
5323 { "hibernate", EQUAL, 1, start_special },
5324 { "hybrid-sleep", EQUAL, 1, start_special },
5325 { "default", EQUAL, 1, start_special },
5326 { "rescue", EQUAL, 1, start_special },
5327 { "emergency", EQUAL, 1, start_special },
5328 { "exit", EQUAL, 1, start_special },
5329 { "reset-failed", MORE, 1, reset_failed },
5330 { "enable", MORE, 2, enable_unit },
5331 { "disable", MORE, 2, enable_unit },
5332 { "is-enabled", MORE, 2, unit_is_enabled },
5333 { "reenable", MORE, 2, enable_unit },
5334 { "preset", MORE, 2, enable_unit },
5335 { "mask", MORE, 2, enable_unit },
5336 { "unmask", MORE, 2, enable_unit },
5337 { "link", MORE, 2, enable_unit },
5338 { "switch-root", MORE, 2, switch_root },
5339 { "list-dependencies", LESS, 2, list_dependencies },
5349 left = argc - optind;
5352 /* Special rule: no arguments means "list-units" */
5355 if (streq(argv[optind], "help") && !argv[optind+1]) {
5356 log_error("This command expects one or more "
5357 "unit names. Did you mean --help?");
5361 for (i = 0; i < ELEMENTSOF(verbs); i++)
5362 if (streq(argv[optind], verbs[i].verb))
5365 if (i >= ELEMENTSOF(verbs)) {
5366 log_error("Unknown operation '%s'.", argv[optind]);
5371 switch (verbs[i].argc_cmp) {
5374 if (left != verbs[i].argc) {
5375 log_error("Invalid number of arguments.");
5382 if (left < verbs[i].argc) {
5383 log_error("Too few arguments.");
5390 if (left > verbs[i].argc) {
5391 log_error("Too many arguments.");
5398 assert_not_reached("Unknown comparison operator.");
5401 /* Require a bus connection for all operations but
5403 if (!streq(verbs[i].verb, "enable") &&
5404 !streq(verbs[i].verb, "disable") &&
5405 !streq(verbs[i].verb, "is-enabled") &&
5406 !streq(verbs[i].verb, "list-unit-files") &&
5407 !streq(verbs[i].verb, "reenable") &&
5408 !streq(verbs[i].verb, "preset") &&
5409 !streq(verbs[i].verb, "mask") &&
5410 !streq(verbs[i].verb, "unmask") &&
5411 !streq(verbs[i].verb, "link")) {
5413 if (running_in_chroot() > 0) {
5414 log_info("Running in chroot, ignoring request.");
5418 if (((!streq(verbs[i].verb, "reboot") &&
5419 !streq(verbs[i].verb, "halt") &&
5420 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5421 log_error("Failed to get D-Bus connection: %s",
5422 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5428 if (!bus && !avoid_bus()) {
5429 log_error("Failed to get D-Bus connection: %s",
5430 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5435 return verbs[i].dispatch(bus, argv + optind);
5438 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5440 struct msghdr msghdr;
5441 struct iovec iovec[2];
5442 union sockaddr_union sockaddr;
5443 struct sd_shutdown_command c;
5445 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5452 c.dry_run = dry_run;
5456 sockaddr.sa.sa_family = AF_UNIX;
5457 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5460 msghdr.msg_name = &sockaddr;
5461 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5464 iovec[0].iov_base = (char*) &c;
5465 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5467 if (isempty(message))
5468 msghdr.msg_iovlen = 1;
5470 iovec[1].iov_base = (char*) message;
5471 iovec[1].iov_len = strlen(message);
5472 msghdr.msg_iovlen = 2;
5474 msghdr.msg_iov = iovec;
5476 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5477 close_nointr_nofail(fd);
5481 close_nointr_nofail(fd);
5485 static int reload_with_fallback(DBusConnection *bus) {
5488 /* First, try systemd via D-Bus. */
5489 if (daemon_reload(bus, NULL) >= 0)
5493 /* Nothing else worked, so let's try signals */
5494 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5496 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5497 log_error("kill() failed: %m");
5504 static int start_with_fallback(DBusConnection *bus) {
5507 /* First, try systemd via D-Bus. */
5508 if (start_unit(bus, NULL) >= 0)
5512 /* Hmm, talking to systemd via D-Bus didn't work. Then
5513 * let's try to talk to Upstart via D-Bus. */
5514 if (talk_upstart() > 0)
5517 /* Nothing else worked, so let's try
5519 if (talk_initctl() > 0)
5522 log_error("Failed to talk to init daemon.");
5526 warn_wall(arg_action);
5530 static _noreturn_ void halt_now(enum action a) {
5532 /* Make sure C-A-D is handled by the kernel from this
5534 reboot(RB_ENABLE_CAD);
5539 log_info("Halting.");
5540 reboot(RB_HALT_SYSTEM);
5543 case ACTION_POWEROFF:
5544 log_info("Powering off.");
5545 reboot(RB_POWER_OFF);
5549 log_info("Rebooting.");
5550 reboot(RB_AUTOBOOT);
5554 assert_not_reached("Unknown halt action.");
5557 assert_not_reached("Uh? This shouldn't happen.");
5560 static int halt_main(DBusConnection *bus) {
5563 r = check_inhibitors(bus, arg_action);
5567 if (geteuid() != 0) {
5568 /* Try logind if we are a normal user and no special
5569 * mode applies. Maybe PolicyKit allows us to shutdown
5572 if (arg_when <= 0 &&
5575 (arg_action == ACTION_POWEROFF ||
5576 arg_action == ACTION_REBOOT)) {
5577 r = reboot_with_logind(bus, arg_action);
5582 log_error("Must be root.");
5589 m = strv_join(arg_wall, " ");
5590 r = send_shutdownd(arg_when,
5591 arg_action == ACTION_HALT ? 'H' :
5592 arg_action == ACTION_POWEROFF ? 'P' :
5593 arg_action == ACTION_KEXEC ? 'K' :
5601 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5603 char date[FORMAT_TIMESTAMP_MAX];
5605 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5606 format_timestamp(date, sizeof(date), arg_when));
5611 if (!arg_dry && !arg_force)
5612 return start_with_fallback(bus);
5615 if (sd_booted() > 0)
5616 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5618 r = utmp_put_shutdown();
5620 log_warning("Failed to write utmp record: %s", strerror(-r));
5627 halt_now(arg_action);
5628 /* We should never reach this. */
5632 static int runlevel_main(void) {
5633 int r, runlevel, previous;
5635 r = utmp_get_runlevel(&runlevel, &previous);
5642 previous <= 0 ? 'N' : previous,
5643 runlevel <= 0 ? 'N' : runlevel);
5648 int main(int argc, char*argv[]) {
5649 int r, retval = EXIT_FAILURE;
5650 DBusConnection *bus = NULL;
5653 dbus_error_init(&error);
5655 setlocale(LC_ALL, "");
5656 log_parse_environment();
5659 r = parse_argv(argc, argv);
5663 retval = EXIT_SUCCESS;
5667 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5668 * let's shortcut this */
5669 if (arg_action == ACTION_RUNLEVEL) {
5670 r = runlevel_main();
5671 retval = r < 0 ? EXIT_FAILURE : r;
5675 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5676 log_info("Running in chroot, ignoring request.");
5682 if (arg_transport == TRANSPORT_NORMAL)
5683 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5684 else if (arg_transport == TRANSPORT_POLKIT) {
5685 bus_connect_system_polkit(&bus, &error);
5686 private_bus = false;
5687 } else if (arg_transport == TRANSPORT_SSH) {
5688 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5689 private_bus = false;
5691 assert_not_reached("Uh, invalid transport...");
5694 switch (arg_action) {
5696 case ACTION_SYSTEMCTL:
5697 r = systemctl_main(bus, argc, argv, &error);
5701 case ACTION_POWEROFF:
5707 case ACTION_RUNLEVEL2:
5708 case ACTION_RUNLEVEL3:
5709 case ACTION_RUNLEVEL4:
5710 case ACTION_RUNLEVEL5:
5712 case ACTION_EMERGENCY:
5713 case ACTION_DEFAULT:
5714 r = start_with_fallback(bus);
5719 r = reload_with_fallback(bus);
5722 case ACTION_CANCEL_SHUTDOWN: {
5726 m = strv_join(arg_wall, " ");
5728 retval = EXIT_FAILURE;
5732 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5734 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5739 case ACTION_INVALID:
5740 case ACTION_RUNLEVEL:
5742 assert_not_reached("Unknown action");
5745 retval = r < 0 ? EXIT_FAILURE : r;
5749 dbus_connection_flush(bus);
5750 dbus_connection_close(bus);
5751 dbus_connection_unref(bus);
5754 dbus_error_free(&error);
5758 strv_free(arg_property);
5761 ask_password_agent_close();
5762 polkit_agent_close();