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>
28 #include <sys/ioctl.h>
32 #include <sys/socket.h>
35 #include <sys/prctl.h>
36 #include <dbus/dbus.h>
38 #include <systemd/sd-daemon.h>
39 #include <systemd/sd-shutdown.h>
45 #include "utmp-wtmp.h"
48 #include "path-util.h"
50 #include "dbus-common.h"
51 #include "cgroup-show.h"
52 #include "cgroup-util.h"
54 #include "path-lookup.h"
55 #include "conf-parser.h"
56 #include "exit-status.h"
57 #include "bus-errors.h"
59 #include "unit-name.h"
61 #include "spawn-ask-password-agent.h"
62 #include "spawn-polkit-agent.h"
64 #include "logs-show.h"
65 #include "path-util.h"
66 #include "socket-util.h"
68 static const char *arg_type = NULL;
69 static const char *arg_load_state = NULL;
70 static char **arg_property = NULL;
71 static bool arg_all = false;
72 static const char *arg_job_mode = "replace";
73 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
74 static bool arg_no_block = false;
75 static bool arg_no_legend = false;
76 static bool arg_no_pager = false;
77 static bool arg_no_wtmp = false;
78 static bool arg_no_wall = false;
79 static bool arg_no_reload = false;
80 static bool arg_dry = false;
81 static bool arg_quiet = false;
82 static bool arg_full = false;
83 static int arg_force = 0;
84 static bool arg_ask_password = true;
85 static bool arg_failed = false;
86 static bool arg_runtime = false;
87 static char **arg_wall = NULL;
88 static const char *arg_kill_who = NULL;
89 static int arg_signal = SIGTERM;
90 static const char *arg_root = NULL;
91 static usec_t arg_when = 0;
112 ACTION_CANCEL_SHUTDOWN,
114 } arg_action = ACTION_SYSTEMCTL;
120 static enum transport {
124 } arg_transport = TRANSPORT_NORMAL;
125 static const char *arg_host = NULL;
126 static bool arg_follow = false;
127 static unsigned arg_lines = 10;
128 static OutputMode arg_output = OUTPUT_SHORT;
130 static bool private_bus = false;
132 static int daemon_reload(DBusConnection *bus, char **args);
133 static void halt_now(enum action a);
135 static bool on_tty(void) {
138 /* Note that this is invoked relatively early, before we start
139 * the pager. That means the value we return reflects whether
140 * we originally were started on a tty, not if we currently
141 * are. But this is intended, since we want colour and so on
142 * when run in our own pager. */
144 if (_unlikely_(t < 0))
145 t = isatty(STDOUT_FILENO) > 0;
150 static void pager_open_if_enabled(void) {
152 /* Cache result before we open the pager */
161 static void ask_password_agent_open_if_enabled(void) {
163 /* Open the password agent as a child process if necessary */
165 if (!arg_ask_password)
168 if (arg_scope != UNIT_FILE_SYSTEM)
171 ask_password_agent_open();
175 static void polkit_agent_open_if_enabled(void) {
177 /* Open the polkit agent as a child process if necessary */
179 if (!arg_ask_password)
182 if (arg_scope != UNIT_FILE_SYSTEM)
189 static const char *ansi_highlight_red(bool b) {
194 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
197 static const char *ansi_highlight_green(bool b) {
202 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
205 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
208 if (!dbus_error_is_set(error))
211 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
212 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
213 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
214 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
215 return EXIT_NOPERMISSION;
217 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
218 return EXIT_NOTINSTALLED;
220 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
221 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
222 return EXIT_NOTIMPLEMENTED;
224 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
225 return EXIT_NOTCONFIGURED;
233 static void warn_wall(enum action a) {
234 static const char *table[_ACTION_MAX] = {
235 [ACTION_HALT] = "The system is going down for system halt NOW!",
236 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
237 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
238 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
239 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
240 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
241 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
250 p = strv_join(arg_wall, " ");
252 log_error("Failed to join strings.");
268 utmp_wall(table[a], NULL);
271 static bool avoid_bus(void) {
273 if (running_in_chroot() > 0)
276 if (sd_booted() <= 0)
279 if (!isempty(arg_root))
282 if (arg_scope == UNIT_FILE_GLOBAL)
290 const char *description;
291 const char *load_state;
292 const char *active_state;
293 const char *sub_state;
294 const char *following;
295 const char *unit_path;
297 const char *job_type;
298 const char *job_path;
301 static int compare_unit_info(const void *a, const void *b) {
303 const struct unit_info *u = a, *v = b;
305 d1 = strrchr(u->id, '.');
306 d2 = strrchr(v->id, '.');
311 if ((r = strcasecmp(d1, d2)) != 0)
315 return strcasecmp(u->id, v->id);
318 static bool output_show_unit(const struct unit_info *u) {
322 return streq(u->active_state, "failed");
324 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
325 streq(dot+1, arg_type))) &&
326 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
327 (arg_all || !(streq(u->active_state, "inactive")
328 || u->following[0]) || u->job_id > 0);
331 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
332 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
333 const struct unit_info *u;
335 max_id_len = sizeof("UNIT")-1;
336 active_len = sizeof("ACTIVE")-1;
337 sub_len = sizeof("SUB")-1;
338 job_len = sizeof("JOB")-1;
341 for (u = unit_infos; u < unit_infos + c; u++) {
342 if (!output_show_unit(u))
345 max_id_len = MAX(max_id_len, strlen(u->id));
346 active_len = MAX(active_len, strlen(u->active_state));
347 sub_len = MAX(sub_len, strlen(u->sub_state));
349 job_len = MAX(job_len, strlen(u->job_type));
354 id_len = MIN(max_id_len, 25);
355 basic_len = 5 + id_len + 6 + active_len + sub_len + job_len;
356 if (basic_len < (unsigned) columns()) {
357 unsigned extra_len, incr;
358 extra_len = columns() - basic_len;
359 /* Either UNIT already got 25, or is fully satisfied.
360 * Grant up to 25 to DESC now. */
361 incr = MIN(extra_len, 25);
364 /* split the remaining space between UNIT and DESC,
365 * but do not give UNIT more than it needs. */
367 incr = MIN(extra_len / 2, max_id_len - id_len);
369 desc_len += extra_len - incr;
375 if (!arg_no_legend) {
376 printf("%-*s %-6s %-*s %-*s %-*s ", id_len, "UNIT", "LOAD",
377 active_len, "ACTIVE", sub_len, "SUB", job_len, "JOB");
378 if (!arg_full && arg_no_pager)
379 printf("%.*s\n", desc_len, "DESCRIPTION");
381 printf("%s\n", "DESCRIPTION");
384 for (u = unit_infos; u < unit_infos + c; u++) {
386 const char *on_loaded, *off_loaded;
387 const char *on_active, *off_active;
389 if (!output_show_unit(u))
394 if (streq(u->load_state, "error")) {
395 on_loaded = ansi_highlight_red(true);
396 off_loaded = ansi_highlight_red(false);
398 on_loaded = off_loaded = "";
400 if (streq(u->active_state, "failed")) {
401 on_active = ansi_highlight_red(true);
402 off_active = ansi_highlight_red(false);
404 on_active = off_active = "";
406 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
408 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s ",
409 id_len, e ? e : u->id,
410 on_loaded, u->load_state, off_loaded,
411 on_active, active_len, u->active_state,
412 sub_len, u->sub_state, off_active,
413 job_len, u->job_id ? u->job_type : "");
414 if (!arg_full && arg_no_pager)
415 printf("%.*s\n", desc_len, u->description);
417 printf("%s\n", u->description);
422 if (!arg_no_legend) {
423 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
424 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
425 "SUB = The low-level unit activation state, values depend on unit type.\n"
426 "JOB = Pending job for the unit.\n");
429 printf("\n%u loaded units listed.\n"
430 "To show all installed unit files use 'systemctl list-unit-files'.\n", n_shown);
432 printf("\n%u loaded units listed. Pass --all to see loaded but inactive units, too.\n"
433 "To show all installed unit files use 'systemctl list-unit-files'.\n", n_shown);
437 static int list_units(DBusConnection *bus, char **args) {
438 DBusMessage *reply = NULL;
440 DBusMessageIter iter, sub, sub2;
441 unsigned c = 0, n_units = 0;
442 struct unit_info *unit_infos = NULL;
444 pager_open_if_enabled();
446 r = bus_method_call_with_reply (
448 "org.freedesktop.systemd1",
449 "/org/freedesktop/systemd1",
450 "org.freedesktop.systemd1.Manager",
458 if (!dbus_message_iter_init(reply, &iter) ||
459 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
460 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
461 log_error("Failed to parse reply.");
466 dbus_message_iter_recurse(&iter, &sub);
468 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
471 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
472 log_error("Failed to parse reply.");
480 n_units = MAX(2*c, 16);
481 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
484 log_error("Failed to allocate unit array.");
494 dbus_message_iter_recurse(&sub, &sub2);
496 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
497 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
498 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
499 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
500 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
501 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
502 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
503 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
504 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
505 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
506 log_error("Failed to parse reply.");
511 dbus_message_iter_next(&sub);
516 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
517 output_units_list(unit_infos, c);
522 dbus_message_unref(reply);
529 static int compare_unit_file_list(const void *a, const void *b) {
531 const UnitFileList *u = a, *v = b;
533 d1 = strrchr(u->path, '.');
534 d2 = strrchr(v->path, '.');
539 r = strcasecmp(d1, d2);
544 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
547 static bool output_show_unit_file(const UnitFileList *u) {
550 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
553 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
554 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
555 const UnitFileList *u;
557 max_id_len = sizeof("UNIT FILE")-1;
558 state_cols = sizeof("STATE")-1;
559 for (u = units; u < units + c; u++) {
560 if (!output_show_unit_file(u))
563 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
564 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
569 id_cols = MIN(max_id_len, 25);
570 basic_cols = 1 + id_cols + state_cols;
571 if (basic_cols < (unsigned) columns())
572 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
574 id_cols = max_id_len;
577 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
579 for (u = units; u < units + c; u++) {
581 const char *on, *off;
584 if (!output_show_unit_file(u))
589 if (u->state == UNIT_FILE_MASKED ||
590 u->state == UNIT_FILE_MASKED_RUNTIME ||
591 u->state == UNIT_FILE_DISABLED ||
592 u->state == UNIT_FILE_INVALID) {
593 on = ansi_highlight_red(true);
594 off = ansi_highlight_red(false);
595 } else if (u->state == UNIT_FILE_ENABLED) {
596 on = ansi_highlight_green(true);
597 off = ansi_highlight_green(false);
601 id = path_get_file_name(u->path);
603 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
605 printf("%-*s %s%-*s%s\n",
607 on, state_cols, unit_file_state_to_string(u->state), off);
613 printf("\n%u unit files listed.\n", n_shown);
616 static int list_unit_files(DBusConnection *bus, char **args) {
617 DBusMessage *reply = NULL;
619 DBusMessageIter iter, sub, sub2;
620 unsigned c = 0, n_units = 0;
621 UnitFileList *units = NULL;
623 pager_open_if_enabled();
630 h = hashmap_new(string_hash_func, string_compare_func);
634 r = unit_file_get_list(arg_scope, arg_root, h);
636 unit_file_list_free(h);
637 log_error("Failed to get unit file list: %s", strerror(-r));
641 n_units = hashmap_size(h);
642 units = new(UnitFileList, n_units);
644 unit_file_list_free(h);
648 HASHMAP_FOREACH(u, h, i) {
649 memcpy(units + c++, u, sizeof(UnitFileList));
655 r = bus_method_call_with_reply (
657 "org.freedesktop.systemd1",
658 "/org/freedesktop/systemd1",
659 "org.freedesktop.systemd1.Manager",
667 if (!dbus_message_iter_init(reply, &iter) ||
668 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
669 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
670 log_error("Failed to parse reply.");
675 dbus_message_iter_recurse(&iter, &sub);
677 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
681 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
682 log_error("Failed to parse reply.");
690 n_units = MAX(2*c, 16);
691 w = realloc(units, sizeof(struct UnitFileList) * n_units);
694 log_error("Failed to allocate unit array.");
704 dbus_message_iter_recurse(&sub, &sub2);
706 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
707 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
708 log_error("Failed to parse reply.");
713 u->state = unit_file_state_from_string(state);
715 dbus_message_iter_next(&sub);
721 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
722 output_unit_file_list(units, c);
729 dbus_message_unref(reply);
736 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
737 static const char * const colors[] = {
738 "Requires", "[color=\"black\"]",
739 "RequiresOverridable", "[color=\"black\"]",
740 "Requisite", "[color=\"darkblue\"]",
741 "RequisiteOverridable", "[color=\"darkblue\"]",
742 "Wants", "[color=\"grey66\"]",
743 "Conflicts", "[color=\"red\"]",
744 "ConflictedBy", "[color=\"red\"]",
745 "After", "[color=\"green\"]"
748 const char *c = NULL;
755 for (i = 0; i < ELEMENTSOF(colors); i += 2)
756 if (streq(colors[i], prop)) {
764 if (arg_dot != DOT_ALL)
765 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
768 switch (dbus_message_iter_get_arg_type(iter)) {
770 case DBUS_TYPE_ARRAY:
772 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
775 dbus_message_iter_recurse(iter, &sub);
777 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
780 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
781 dbus_message_iter_get_basic(&sub, &s);
782 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
784 dbus_message_iter_next(&sub);
794 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
795 DBusMessage *reply = NULL;
796 const char *interface = "org.freedesktop.systemd1.Unit";
798 DBusMessageIter iter, sub, sub2, sub3;
802 r = bus_method_call_with_reply (
804 "org.freedesktop.systemd1",
806 "org.freedesktop.DBus.Properties",
810 DBUS_TYPE_STRING, &interface,
815 if (!dbus_message_iter_init(reply, &iter) ||
816 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
817 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
818 log_error("Failed to parse reply.");
823 dbus_message_iter_recurse(&iter, &sub);
825 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
828 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
829 log_error("Failed to parse reply.");
834 dbus_message_iter_recurse(&sub, &sub2);
836 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
837 log_error("Failed to parse reply.");
842 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
843 log_error("Failed to parse reply.");
848 dbus_message_iter_recurse(&sub2, &sub3);
850 if (dot_one_property(name, prop, &sub3)) {
851 log_error("Failed to parse reply.");
856 dbus_message_iter_next(&sub);
861 dbus_message_unref(reply);
866 static int dot(DBusConnection *bus, char **args) {
867 DBusMessage *reply = NULL;
869 DBusMessageIter iter, sub, sub2;
871 r = bus_method_call_with_reply (
873 "org.freedesktop.systemd1",
874 "/org/freedesktop/systemd1",
875 "org.freedesktop.systemd1.Manager",
883 if (!dbus_message_iter_init(reply, &iter) ||
884 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
885 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
886 log_error("Failed to parse reply.");
891 printf("digraph systemd {\n");
893 dbus_message_iter_recurse(&iter, &sub);
894 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
895 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
897 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
898 log_error("Failed to parse reply.");
903 dbus_message_iter_recurse(&sub, &sub2);
905 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
906 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
907 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
908 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
909 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
910 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
911 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
912 log_error("Failed to parse reply.");
917 if ((r = dot_one(bus, id, unit_path)) < 0)
920 /* printf("\t\"%s\";\n", id); */
921 dbus_message_iter_next(&sub);
926 log_info(" Color legend: black = Requires\n"
927 " dark blue = Requisite\n"
928 " dark grey = Wants\n"
933 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
934 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
940 dbus_message_unref(reply);
945 static int list_jobs(DBusConnection *bus, char **args) {
946 DBusMessage *reply = NULL;
948 DBusMessageIter iter, sub, sub2;
951 pager_open_if_enabled();
953 r = bus_method_call_with_reply (
955 "org.freedesktop.systemd1",
956 "/org/freedesktop/systemd1",
957 "org.freedesktop.systemd1.Manager",
965 if (!dbus_message_iter_init(reply, &iter) ||
966 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
967 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
968 log_error("Failed to parse reply.");
973 dbus_message_iter_recurse(&iter, &sub);
976 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
978 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
979 const char *name, *type, *state, *job_path, *unit_path;
983 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
984 log_error("Failed to parse reply.");
989 dbus_message_iter_recurse(&sub, &sub2);
991 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
992 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
993 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
994 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
995 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
996 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
997 log_error("Failed to parse reply.");
1002 e = arg_full ? NULL : ellipsize(name, 25, 33);
1003 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1008 dbus_message_iter_next(&sub);
1012 printf("\n%u jobs listed.\n", k);
1018 dbus_message_unref(reply);
1023 static int load_unit(DBusConnection *bus, char **args) {
1029 STRV_FOREACH(name, args+1) {
1030 n = unit_name_mangle(*name);
1031 r = bus_method_call_with_reply (
1033 "org.freedesktop.systemd1",
1034 "/org/freedesktop/systemd1",
1035 "org.freedesktop.systemd1.Manager",
1039 DBUS_TYPE_STRING, n ? &n : name,
1050 static int cancel_job(DBusConnection *bus, char **args) {
1051 DBusMessage *reply = NULL;
1057 if (strv_length(args) <= 1)
1058 return daemon_reload(bus, args);
1060 STRV_FOREACH(name, args+1) {
1064 r = safe_atou(*name, &id);
1066 log_error("Failed to parse job id: %s", strerror(-r));
1069 assert_cc(sizeof(uint32_t) == sizeof(id));
1071 r = bus_method_call_with_reply (
1073 "org.freedesktop.systemd1",
1074 "/org/freedesktop/systemd1",
1075 "org.freedesktop.systemd1.Manager",
1079 DBUS_TYPE_UINT32, &id,
1084 if (!dbus_message_get_args(reply, NULL,
1085 DBUS_TYPE_OBJECT_PATH, &path,
1086 DBUS_TYPE_INVALID)) {
1087 log_error("Failed to parse reply");
1088 dbus_message_unref(reply);
1092 dbus_message_unref(reply);
1094 r = bus_method_call_with_reply (
1096 "org.freedesktop.systemd1",
1098 "org.freedesktop.systemd1.Job",
1111 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1112 DBusMessage *reply = NULL;
1113 dbus_bool_t b = FALSE;
1114 DBusMessageIter iter, sub;
1116 *interface = "org.freedesktop.systemd1.Unit",
1117 *property = "NeedDaemonReload",
1122 /* We ignore all errors here, since this is used to show a warning only */
1124 n = unit_name_mangle(unit);
1125 r = bus_method_call_with_reply (
1127 "org.freedesktop.systemd1",
1128 "/org/freedesktop/systemd1",
1129 "org.freedesktop.systemd1.Manager",
1133 DBUS_TYPE_STRING, n ? (const char**) &n : &unit,
1139 if (!dbus_message_get_args(reply, NULL,
1140 DBUS_TYPE_OBJECT_PATH, &path,
1144 dbus_message_unref(reply);
1145 r = bus_method_call_with_reply (
1147 "org.freedesktop.systemd1",
1149 "org.freedesktop.DBus.Properties",
1153 DBUS_TYPE_STRING, &interface,
1154 DBUS_TYPE_STRING, &property,
1159 if (!dbus_message_iter_init(reply, &iter) ||
1160 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1163 dbus_message_iter_recurse(&iter, &sub);
1165 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1168 dbus_message_iter_get_basic(&sub, &b);
1172 dbus_message_unref(reply);
1177 typedef struct WaitData {
1184 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1192 dbus_error_init(&error);
1194 log_debug("Got D-Bus request: %s.%s() on %s",
1195 dbus_message_get_interface(message),
1196 dbus_message_get_member(message),
1197 dbus_message_get_path(message));
1199 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1200 log_error("Warning! D-Bus connection terminated.");
1201 dbus_connection_close(connection);
1203 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1205 const char *path, *result, *unit;
1206 dbus_bool_t success = true;
1208 if (dbus_message_get_args(message, &error,
1209 DBUS_TYPE_UINT32, &id,
1210 DBUS_TYPE_OBJECT_PATH, &path,
1211 DBUS_TYPE_STRING, &unit,
1212 DBUS_TYPE_STRING, &result,
1213 DBUS_TYPE_INVALID)) {
1216 p = set_remove(d->set, (char*) path);
1219 if (!isempty(result))
1220 d->result = strdup(result);
1223 d->name = strdup(unit);
1228 dbus_error_free(&error);
1229 if (dbus_message_get_args(message, &error,
1230 DBUS_TYPE_UINT32, &id,
1231 DBUS_TYPE_OBJECT_PATH, &path,
1232 DBUS_TYPE_STRING, &result,
1233 DBUS_TYPE_INVALID)) {
1236 /* Compatibility with older systemd versions <
1237 * 183 during upgrades. This should be dropped
1239 p = set_remove(d->set, (char*) path);
1243 d->result = strdup(result);
1248 dbus_error_free(&error);
1249 if (dbus_message_get_args(message, &error,
1250 DBUS_TYPE_UINT32, &id,
1251 DBUS_TYPE_OBJECT_PATH, &path,
1252 DBUS_TYPE_BOOLEAN, &success,
1253 DBUS_TYPE_INVALID)) {
1256 /* Compatibility with older systemd versions <
1257 * 19 during upgrades. This should be dropped
1260 p = set_remove(d->set, (char*) path);
1264 d->result = strdup("failed");
1270 log_error("Failed to parse message: %s", bus_error_message(&error));
1274 dbus_error_free(&error);
1275 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1278 static int enable_wait_for_jobs(DBusConnection *bus) {
1286 dbus_error_init(&error);
1287 dbus_bus_add_match(bus,
1289 "sender='org.freedesktop.systemd1',"
1290 "interface='org.freedesktop.systemd1.Manager',"
1291 "member='JobRemoved',"
1292 "path='/org/freedesktop/systemd1'",
1295 if (dbus_error_is_set(&error)) {
1296 log_error("Failed to add match: %s", bus_error_message(&error));
1297 dbus_error_free(&error);
1301 /* This is slightly dirty, since we don't undo the match registrations. */
1305 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1315 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1318 while (!set_isempty(s)) {
1320 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1321 log_error("Disconnected from bus.");
1322 return -ECONNREFUSED;
1325 if (!arg_quiet && d.result) {
1326 if (streq(d.result, "timeout"))
1327 log_error("Job for %s timed out.", strna(d.name));
1328 else if (streq(d.result, "canceled"))
1329 log_error("Job for %s canceled.", strna(d.name));
1330 else if (streq(d.result, "dependency"))
1331 log_error("A dependency job for %s failed. See 'journalctl' for details.", strna(d.name));
1332 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1333 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl' for details.", strna(d.name), strna(d.name));
1336 if (streq_ptr(d.result, "timeout"))
1338 else if (streq_ptr(d.result, "canceled"))
1340 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1350 /* This is slightly dirty, since we don't undo the filter registration. */
1354 static int check_one_unit(DBusConnection *bus, char *name, bool quiet) {
1355 DBusMessage *reply = NULL;
1356 DBusMessageIter iter, sub;
1358 *interface = "org.freedesktop.systemd1.Unit",
1359 *property = "ActiveState";
1360 const char *path = NULL;
1367 n = unit_name_mangle(name);
1368 r = bus_method_call_with_reply (
1370 "org.freedesktop.systemd1",
1371 "/org/freedesktop/systemd1",
1372 "org.freedesktop.systemd1.Manager",
1376 DBUS_TYPE_STRING, n ? &n : &name,
1380 if ((r != -ENOMEM) && (!quiet))
1385 if (!dbus_message_get_args(reply, NULL,
1386 DBUS_TYPE_OBJECT_PATH, &path,
1387 DBUS_TYPE_INVALID)) {
1388 log_error("Failed to parse reply.");
1393 dbus_message_unref(reply);
1394 r = bus_method_call_with_reply (
1396 "org.freedesktop.systemd1",
1398 "org.freedesktop.DBus.Properties",
1402 DBUS_TYPE_STRING, &interface,
1403 DBUS_TYPE_STRING, &property,
1408 if (!dbus_message_iter_init(reply, &iter) ||
1409 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1410 log_error("Failed to parse reply.");
1415 dbus_message_iter_recurse(&iter, &sub);
1417 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1418 log_error("Failed to parse reply.");
1423 dbus_message_iter_get_basic(&sub, &state);
1428 if (streq(state, "active") || streq(state, "reloading"))
1431 r = 3; /* According to LSB: "program is not running" */
1435 dbus_message_unref(reply);
1440 static void check_triggering_units(
1441 DBusConnection *bus,
1442 const char *unit_name) {
1444 DBusMessage _cleanup_dbus_msg_unref_ *reply = NULL;
1445 DBusMessageIter iter, sub;
1446 char *service_trigger = NULL;
1447 const char *interface = "org.freedesktop.systemd1.Unit",
1448 *triggered_by_property = "TriggeredBy";
1450 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1451 bool print_warning_label = true;
1454 n = unit_name_mangle(unit_name);
1460 unit_path = unit_dbus_path_from_name(n);
1466 r = bus_method_call_with_reply (
1468 "org.freedesktop.systemd1",
1470 "org.freedesktop.DBus.Properties",
1474 DBUS_TYPE_STRING, &interface,
1475 DBUS_TYPE_STRING, &triggered_by_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);
1487 dbus_message_iter_recurse(&sub, &iter);
1490 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1492 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1493 log_error("Failed to parse reply.");
1497 dbus_message_iter_get_basic(&sub, &service_trigger);
1499 r = check_one_unit(bus, service_trigger, true);
1503 if (print_warning_label) {
1504 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1505 print_warning_label = false;
1507 log_warning(" %s", service_trigger);
1510 dbus_message_iter_next(&sub);
1514 static int start_unit_one(
1515 DBusConnection *bus,
1522 DBusMessage _cleanup_dbus_msg_unref_ *reply = NULL;
1525 _cleanup_free_ char *n, *p = NULL;
1532 n = unit_name_mangle(name);
1536 r = bus_method_call_with_reply(
1538 "org.freedesktop.systemd1",
1539 "/org/freedesktop/systemd1",
1540 "org.freedesktop.systemd1.Manager",
1544 DBUS_TYPE_STRING, &n,
1545 DBUS_TYPE_STRING, &mode,
1548 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1549 /* There's always a fallback possible for
1550 * legacy actions. */
1553 log_error("Failed to issue method call: %s", bus_error_message(error));
1558 if (!dbus_message_get_args(reply, error,
1559 DBUS_TYPE_OBJECT_PATH, &path,
1560 DBUS_TYPE_INVALID)) {
1561 log_error("Failed to parse reply: %s", bus_error_message(error));
1565 if (need_daemon_reload(bus, n))
1566 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1567 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1576 log_error("Failed to add path to set.");
1583 /* When stopping a unit warn if it can still be triggered by
1584 * another active unit (socket, path, timer) */
1585 if (!arg_quiet && streq(method, "StopUnit"))
1586 check_triggering_units(bus, name);
1591 static enum action verb_to_action(const char *verb) {
1592 if (streq(verb, "halt"))
1594 else if (streq(verb, "poweroff"))
1595 return ACTION_POWEROFF;
1596 else if (streq(verb, "reboot"))
1597 return ACTION_REBOOT;
1598 else if (streq(verb, "kexec"))
1599 return ACTION_KEXEC;
1600 else if (streq(verb, "rescue"))
1601 return ACTION_RESCUE;
1602 else if (streq(verb, "emergency"))
1603 return ACTION_EMERGENCY;
1604 else if (streq(verb, "default"))
1605 return ACTION_DEFAULT;
1606 else if (streq(verb, "exit"))
1608 else if (streq(verb, "suspend"))
1609 return ACTION_SUSPEND;
1610 else if (streq(verb, "hibernate"))
1611 return ACTION_HIBERNATE;
1613 return ACTION_INVALID;
1616 static int start_unit(DBusConnection *bus, char **args) {
1618 static const char * const table[_ACTION_MAX] = {
1619 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1620 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1621 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1622 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1623 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1624 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1625 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1626 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1627 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1628 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1629 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1630 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1631 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1632 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET
1636 const char *method, *mode, *one_name;
1641 dbus_error_init(&error);
1645 ask_password_agent_open_if_enabled();
1647 if (arg_action == ACTION_SYSTEMCTL) {
1649 streq(args[0], "stop") ||
1650 streq(args[0], "condstop") ? "StopUnit" :
1651 streq(args[0], "reload") ? "ReloadUnit" :
1652 streq(args[0], "restart") ? "RestartUnit" :
1654 streq(args[0], "try-restart") ||
1655 streq(args[0], "condrestart") ? "TryRestartUnit" :
1657 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1659 streq(args[0], "reload-or-try-restart") ||
1660 streq(args[0], "condreload") ||
1662 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1666 (streq(args[0], "isolate") ||
1667 streq(args[0], "rescue") ||
1668 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1670 one_name = table[verb_to_action(args[0])];
1673 assert(arg_action < ELEMENTSOF(table));
1674 assert(table[arg_action]);
1676 method = "StartUnit";
1678 mode = (arg_action == ACTION_EMERGENCY ||
1679 arg_action == ACTION_RESCUE ||
1680 arg_action == ACTION_RUNLEVEL2 ||
1681 arg_action == ACTION_RUNLEVEL3 ||
1682 arg_action == ACTION_RUNLEVEL4 ||
1683 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1685 one_name = table[arg_action];
1688 if (!arg_no_block) {
1689 ret = enable_wait_for_jobs(bus);
1691 log_error("Could not watch jobs: %s", strerror(-ret));
1695 s = set_new(string_hash_func, string_compare_func);
1703 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1705 ret = translate_bus_error_to_exit_status(ret, &error);
1707 STRV_FOREACH(name, args+1) {
1708 r = start_unit_one(bus, method, *name, mode, &error, s);
1710 ret = translate_bus_error_to_exit_status(r, &error);
1711 dbus_error_free(&error);
1716 if (!arg_no_block) {
1717 r = wait_for_jobs(bus, s);
1726 dbus_error_free(&error);
1731 /* Ask systemd-logind, which might grant access to unprivileged users
1732 * through PolicyKit */
1733 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1736 dbus_bool_t interactive = true;
1738 polkit_agent_open_if_enabled();
1746 case ACTION_POWEROFF:
1747 method = "PowerOff";
1750 case ACTION_SUSPEND:
1754 case ACTION_HIBERNATE:
1755 method = "Hibernate";
1762 return bus_method_call_with_reply (
1764 "org.freedesktop.login1",
1765 "/org/freedesktop/login1",
1766 "org.freedesktop.login1.Manager",
1770 DBUS_TYPE_BOOLEAN, &interactive,
1777 static int start_special(DBusConnection *bus, char **args) {
1783 a = verb_to_action(args[0]);
1785 if (arg_force >= 2 && geteuid() != 0) {
1786 log_error("Must be root.");
1790 if (arg_force >= 2 &&
1791 (a == ACTION_HALT ||
1792 a == ACTION_POWEROFF ||
1793 a == ACTION_REBOOT))
1796 if (arg_force >= 1 &&
1797 (a == ACTION_HALT ||
1798 a == ACTION_POWEROFF ||
1799 a == ACTION_REBOOT ||
1800 a == ACTION_KEXEC ||
1802 return daemon_reload(bus, args);
1804 /* first try logind, to allow authentication with polkit */
1805 if (geteuid() != 0 &&
1806 (a == ACTION_POWEROFF ||
1807 a == ACTION_REBOOT ||
1808 a == ACTION_SUSPEND ||
1809 a == ACTION_HIBERNATE)) {
1810 r = reboot_with_logind(bus, a);
1815 r = start_unit(bus, args);
1822 static int check_unit(DBusConnection *bus, char **args) {
1824 int r = 3; /* According to LSB: "program is not running" */
1829 STRV_FOREACH(name, args+1) {
1830 int state = check_one_unit(bus, *name, arg_quiet);
1840 static int kill_unit(DBusConnection *bus, char **args) {
1847 arg_kill_who = "all";
1849 STRV_FOREACH(name, args+1) {
1850 n = unit_name_mangle(*name);
1851 r = bus_method_call_with_reply (
1853 "org.freedesktop.systemd1",
1854 "/org/freedesktop/systemd1",
1855 "org.freedesktop.systemd1.Manager",
1859 DBUS_TYPE_STRING, n ? &n : name,
1860 DBUS_TYPE_STRING, &arg_kill_who,
1861 DBUS_TYPE_INT32, &arg_signal,
1870 typedef struct ExecStatusInfo {
1878 usec_t start_timestamp;
1879 usec_t exit_timestamp;
1884 LIST_FIELDS(struct ExecStatusInfo, exec);
1887 static void exec_status_info_free(ExecStatusInfo *i) {
1896 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
1897 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
1898 DBusMessageIter sub2, sub3;
1902 int32_t code, status;
1908 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
1911 dbus_message_iter_recurse(sub, &sub2);
1913 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
1916 if (!(i->path = strdup(path)))
1919 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
1920 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
1924 dbus_message_iter_recurse(&sub2, &sub3);
1925 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1926 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1927 dbus_message_iter_next(&sub3);
1932 if (!(i->argv = new0(char*, n+1)))
1936 dbus_message_iter_recurse(&sub2, &sub3);
1937 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1940 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1941 dbus_message_iter_get_basic(&sub3, &s);
1942 dbus_message_iter_next(&sub3);
1944 if (!(i->argv[n++] = strdup(s)))
1948 if (!dbus_message_iter_next(&sub2) ||
1949 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
1950 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
1951 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
1952 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
1953 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
1954 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
1955 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
1956 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
1960 i->start_timestamp = (usec_t) start_timestamp;
1961 i->exit_timestamp = (usec_t) exit_timestamp;
1962 i->pid = (pid_t) pid;
1969 typedef struct UnitStatusInfo {
1971 const char *load_state;
1972 const char *active_state;
1973 const char *sub_state;
1974 const char *unit_file_state;
1976 const char *description;
1977 const char *following;
1979 char **documentation;
1981 const char *fragment_path;
1982 const char *source_path;
1983 const char *default_control_group;
1985 const char *load_error;
1988 usec_t inactive_exit_timestamp;
1989 usec_t inactive_exit_timestamp_monotonic;
1990 usec_t active_enter_timestamp;
1991 usec_t active_exit_timestamp;
1992 usec_t inactive_enter_timestamp;
1994 bool need_daemon_reload;
1999 const char *status_text;
2002 usec_t start_timestamp;
2003 usec_t exit_timestamp;
2005 int exit_code, exit_status;
2007 usec_t condition_timestamp;
2008 bool condition_result;
2011 unsigned n_accepted;
2012 unsigned n_connections;
2016 const char *sysfs_path;
2018 /* Mount, Automount */
2024 LIST_HEAD(ExecStatusInfo, exec);
2027 static void print_status_info(UnitStatusInfo *i) {
2029 const char *on, *off, *ss;
2031 char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
2032 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2037 /* This shows pretty information about a unit. See
2038 * print_property() for a low-level property printer */
2040 printf("%s", strna(i->id));
2042 if (i->description && !streq_ptr(i->id, i->description))
2043 printf(" - %s", i->description);
2048 printf("\t Follow: unit currently follows state of %s\n", i->following);
2050 if (streq_ptr(i->load_state, "error")) {
2051 on = ansi_highlight_red(true);
2052 off = ansi_highlight_red(false);
2056 path = i->source_path ? i->source_path : i->fragment_path;
2059 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2060 else if (path && i->unit_file_state)
2061 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2063 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2065 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2067 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2069 if (streq_ptr(i->active_state, "failed")) {
2070 on = ansi_highlight_red(true);
2071 off = ansi_highlight_red(false);
2072 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2073 on = ansi_highlight_green(true);
2074 off = ansi_highlight_green(false);
2079 printf("\t Active: %s%s (%s)%s",
2081 strna(i->active_state),
2085 printf("\t Active: %s%s%s",
2087 strna(i->active_state),
2090 if (!isempty(i->result) && !streq(i->result, "success"))
2091 printf(" (Result: %s)", i->result);
2093 timestamp = (streq_ptr(i->active_state, "active") ||
2094 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2095 (streq_ptr(i->active_state, "inactive") ||
2096 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2097 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2098 i->active_exit_timestamp;
2100 s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
2101 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2104 printf(" since %s; %s\n", s2, s1);
2106 printf(" since %s\n", s2);
2110 if (!i->condition_result && i->condition_timestamp > 0) {
2111 s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
2112 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2115 printf("\t start condition failed at %s; %s\n", s2, s1);
2117 printf("\t start condition failed at %s\n", s2);
2121 printf("\t Device: %s\n", i->sysfs_path);
2123 printf("\t Where: %s\n", i->where);
2125 printf("\t What: %s\n", i->what);
2127 if (!strv_isempty(i->documentation)) {
2131 STRV_FOREACH(t, i->documentation) {
2133 printf("\t Docs: %s\n", *t);
2136 printf("\t %s\n", *t);
2141 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2143 LIST_FOREACH(exec, p, i->exec) {
2147 /* Only show exited processes here */
2151 t = strv_join(p->argv, " ");
2152 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2155 good = is_clean_exit_lsb(p->code, p->status, NULL);
2157 on = ansi_highlight_red(true);
2158 off = ansi_highlight_red(false);
2162 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2164 if (p->code == CLD_EXITED) {
2167 printf("status=%i", p->status);
2169 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2174 printf("signal=%s", signal_to_string(p->status));
2176 printf(")%s\n", off);
2178 if (i->main_pid == p->pid &&
2179 i->start_timestamp == p->start_timestamp &&
2180 i->exit_timestamp == p->start_timestamp)
2181 /* Let's not show this twice */
2184 if (p->pid == i->control_pid)
2188 if (i->main_pid > 0 || i->control_pid > 0) {
2191 if (i->main_pid > 0) {
2192 printf("Main PID: %u", (unsigned) i->main_pid);
2196 get_process_comm(i->main_pid, &t);
2201 } else if (i->exit_code > 0) {
2202 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2204 if (i->exit_code == CLD_EXITED) {
2207 printf("status=%i", i->exit_status);
2209 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2214 printf("signal=%s", signal_to_string(i->exit_status));
2219 if (i->main_pid > 0 && i->control_pid > 0)
2222 if (i->control_pid > 0) {
2225 printf(" Control: %u", (unsigned) i->control_pid);
2227 get_process_comm(i->control_pid, &t);
2238 printf("\t Status: \"%s\"\n", i->status_text);
2240 if (i->default_control_group) {
2243 printf("\t CGroup: %s\n", i->default_control_group);
2245 if (arg_transport != TRANSPORT_SSH) {
2255 if (i->main_pid > 0)
2256 extra[k++] = i->main_pid;
2258 if (i->control_pid > 0)
2259 extra[k++] = i->control_pid;
2261 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2265 if (i->id && arg_transport != TRANSPORT_SSH) {
2267 arg_all * OUTPUT_SHOW_ALL |
2268 arg_follow * OUTPUT_FOLLOW |
2269 !arg_quiet * OUTPUT_WARN_CUTOFF |
2270 on_tty() * OUTPUT_COLOR;
2273 show_journal_by_unit(i->id, arg_output, 0,
2274 i->inactive_exit_timestamp_monotonic,
2278 if (i->need_daemon_reload)
2279 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2280 ansi_highlight_red(true),
2281 ansi_highlight_red(false),
2282 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2285 static void show_unit_help(UnitStatusInfo *i) {
2290 if (!i->documentation) {
2291 log_info("Documentation for %s not known.", i->id);
2295 STRV_FOREACH(p, i->documentation) {
2297 if (startswith(*p, "man:")) {
2300 char *page = NULL, *section = NULL;
2301 const char *args[4] = { "man", NULL, NULL, NULL };
2306 if ((*p)[k-1] == ')')
2307 e = strrchr(*p, '(');
2310 page = strndup((*p) + 4, e - *p - 4);
2316 section = strndup(e + 1, *p + k - e - 2);
2330 log_error("Failed to fork: %m");
2338 execvp(args[0], (char**) args);
2339 log_error("Failed to execute man: %m");
2340 _exit(EXIT_FAILURE);
2346 wait_for_terminate(pid, NULL);
2348 log_info("Can't show: %s", *p);
2352 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2358 switch (dbus_message_iter_get_arg_type(iter)) {
2360 case DBUS_TYPE_STRING: {
2363 dbus_message_iter_get_basic(iter, &s);
2366 if (streq(name, "Id"))
2368 else if (streq(name, "LoadState"))
2370 else if (streq(name, "ActiveState"))
2371 i->active_state = s;
2372 else if (streq(name, "SubState"))
2374 else if (streq(name, "Description"))
2376 else if (streq(name, "FragmentPath"))
2377 i->fragment_path = s;
2378 else if (streq(name, "SourcePath"))
2380 else if (streq(name, "DefaultControlGroup"))
2381 i->default_control_group = s;
2382 else if (streq(name, "StatusText"))
2384 else if (streq(name, "SysFSPath"))
2386 else if (streq(name, "Where"))
2388 else if (streq(name, "What"))
2390 else if (streq(name, "Following"))
2392 else if (streq(name, "UnitFileState"))
2393 i->unit_file_state = s;
2394 else if (streq(name, "Result"))
2401 case DBUS_TYPE_BOOLEAN: {
2404 dbus_message_iter_get_basic(iter, &b);
2406 if (streq(name, "Accept"))
2408 else if (streq(name, "NeedDaemonReload"))
2409 i->need_daemon_reload = b;
2410 else if (streq(name, "ConditionResult"))
2411 i->condition_result = b;
2416 case DBUS_TYPE_UINT32: {
2419 dbus_message_iter_get_basic(iter, &u);
2421 if (streq(name, "MainPID")) {
2423 i->main_pid = (pid_t) u;
2426 } else if (streq(name, "ControlPID"))
2427 i->control_pid = (pid_t) u;
2428 else if (streq(name, "ExecMainPID")) {
2430 i->main_pid = (pid_t) u;
2431 } else if (streq(name, "NAccepted"))
2433 else if (streq(name, "NConnections"))
2434 i->n_connections = u;
2439 case DBUS_TYPE_INT32: {
2442 dbus_message_iter_get_basic(iter, &j);
2444 if (streq(name, "ExecMainCode"))
2445 i->exit_code = (int) j;
2446 else if (streq(name, "ExecMainStatus"))
2447 i->exit_status = (int) j;
2452 case DBUS_TYPE_UINT64: {
2455 dbus_message_iter_get_basic(iter, &u);
2457 if (streq(name, "ExecMainStartTimestamp"))
2458 i->start_timestamp = (usec_t) u;
2459 else if (streq(name, "ExecMainExitTimestamp"))
2460 i->exit_timestamp = (usec_t) u;
2461 else if (streq(name, "ActiveEnterTimestamp"))
2462 i->active_enter_timestamp = (usec_t) u;
2463 else if (streq(name, "InactiveEnterTimestamp"))
2464 i->inactive_enter_timestamp = (usec_t) u;
2465 else if (streq(name, "InactiveExitTimestamp"))
2466 i->inactive_exit_timestamp = (usec_t) u;
2467 else if (streq(name, "InactiveExitTimestampMonotonic"))
2468 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2469 else if (streq(name, "ActiveExitTimestamp"))
2470 i->active_exit_timestamp = (usec_t) u;
2471 else if (streq(name, "ConditionTimestamp"))
2472 i->condition_timestamp = (usec_t) u;
2477 case DBUS_TYPE_ARRAY: {
2479 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2480 startswith(name, "Exec")) {
2481 DBusMessageIter sub;
2483 dbus_message_iter_recurse(iter, &sub);
2484 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2485 ExecStatusInfo *info;
2488 if (!(info = new0(ExecStatusInfo, 1)))
2491 if (!(info->name = strdup(name))) {
2496 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2501 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2503 dbus_message_iter_next(&sub);
2505 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2506 streq(name, "Documentation")) {
2508 DBusMessageIter sub;
2510 dbus_message_iter_recurse(iter, &sub);
2511 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2515 dbus_message_iter_get_basic(&sub, &s);
2517 l = strv_append(i->documentation, s);
2521 strv_free(i->documentation);
2522 i->documentation = l;
2524 dbus_message_iter_next(&sub);
2531 case DBUS_TYPE_STRUCT: {
2533 if (streq(name, "LoadError")) {
2534 DBusMessageIter sub;
2535 const char *n, *message;
2538 dbus_message_iter_recurse(iter, &sub);
2540 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2544 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2548 if (!isempty(message))
2549 i->load_error = message;
2559 static int print_property(const char *name, DBusMessageIter *iter) {
2563 /* This is a low-level property printer, see
2564 * print_status_info() for the nicer output */
2566 if (arg_property && !strv_find(arg_property, name))
2569 switch (dbus_message_iter_get_arg_type(iter)) {
2571 case DBUS_TYPE_STRUCT: {
2572 DBusMessageIter sub;
2573 dbus_message_iter_recurse(iter, &sub);
2575 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2578 dbus_message_iter_get_basic(&sub, &u);
2581 printf("%s=%u\n", name, (unsigned) u);
2583 printf("%s=\n", name);
2586 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2589 dbus_message_iter_get_basic(&sub, &s);
2591 if (arg_all || s[0])
2592 printf("%s=%s\n", name, s);
2595 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2596 const char *a = NULL, *b = NULL;
2598 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2599 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2601 if (arg_all || !isempty(a) || !isempty(b))
2602 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2610 case DBUS_TYPE_ARRAY:
2612 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2613 DBusMessageIter sub, sub2;
2615 dbus_message_iter_recurse(iter, &sub);
2616 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2620 dbus_message_iter_recurse(&sub, &sub2);
2622 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2623 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2624 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2626 dbus_message_iter_next(&sub);
2631 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2632 DBusMessageIter sub, sub2;
2634 dbus_message_iter_recurse(iter, &sub);
2635 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2636 const char *type, *path;
2638 dbus_message_iter_recurse(&sub, &sub2);
2640 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2641 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2642 printf("%s=%s\n", type, path);
2644 dbus_message_iter_next(&sub);
2649 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2650 DBusMessageIter sub, sub2;
2652 dbus_message_iter_recurse(iter, &sub);
2653 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2655 uint64_t value, next_elapse;
2657 dbus_message_iter_recurse(&sub, &sub2);
2659 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2660 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2661 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2662 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2664 printf("%s={ value=%s ; next_elapse=%s }\n",
2666 format_timespan(timespan1, sizeof(timespan1), value),
2667 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2670 dbus_message_iter_next(&sub);
2675 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2676 DBusMessageIter sub, sub2;
2678 dbus_message_iter_recurse(iter, &sub);
2679 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2680 const char *controller, *attr, *value;
2682 dbus_message_iter_recurse(&sub, &sub2);
2684 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2685 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2686 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2688 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2694 dbus_message_iter_next(&sub);
2699 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2700 DBusMessageIter sub;
2702 dbus_message_iter_recurse(iter, &sub);
2703 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2704 ExecStatusInfo info;
2707 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2708 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2711 t = strv_join(info.argv, " ");
2713 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2717 yes_no(info.ignore),
2718 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2719 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2720 (unsigned) info. pid,
2721 sigchld_code_to_string(info.code),
2723 info.code == CLD_EXITED ? "" : "/",
2724 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2730 strv_free(info.argv);
2732 dbus_message_iter_next(&sub);
2741 if (generic_print_property(name, iter, arg_all) > 0)
2745 printf("%s=[unprintable]\n", name);
2750 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2751 DBusMessage *reply = NULL;
2752 const char *interface = "";
2754 DBusMessageIter iter, sub, sub2, sub3;
2755 UnitStatusInfo info;
2763 r = bus_method_call_with_reply (
2765 "org.freedesktop.systemd1",
2767 "org.freedesktop.DBus.Properties",
2771 DBUS_TYPE_STRING, &interface,
2776 if (!dbus_message_iter_init(reply, &iter) ||
2777 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2778 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2779 log_error("Failed to parse reply.");
2784 dbus_message_iter_recurse(&iter, &sub);
2791 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2794 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2795 log_error("Failed to parse reply.");
2800 dbus_message_iter_recurse(&sub, &sub2);
2802 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2803 log_error("Failed to parse reply.");
2808 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2809 log_error("Failed to parse reply.");
2814 dbus_message_iter_recurse(&sub2, &sub3);
2816 if (show_properties)
2817 r = print_property(name, &sub3);
2819 r = status_property(name, &sub3, &info);
2822 log_error("Failed to parse reply.");
2827 dbus_message_iter_next(&sub);
2832 if (!show_properties) {
2833 if (streq(verb, "help"))
2834 show_unit_help(&info);
2836 print_status_info(&info);
2839 strv_free(info.documentation);
2841 if (!streq_ptr(info.active_state, "active") &&
2842 !streq_ptr(info.active_state, "reloading") &&
2843 streq(verb, "status"))
2844 /* According to LSB: "program not running" */
2847 while ((p = info.exec)) {
2848 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2849 exec_status_info_free(p);
2854 dbus_message_unref(reply);
2859 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
2860 DBusMessage *reply = NULL;
2861 const char *path = NULL;
2865 dbus_error_init(&error);
2867 r = bus_method_call_with_reply (
2869 "org.freedesktop.systemd1",
2870 "/org/freedesktop/systemd1",
2871 "org.freedesktop.systemd1.Manager",
2875 DBUS_TYPE_UINT32, &pid,
2880 if (!dbus_message_get_args(reply, &error,
2881 DBUS_TYPE_OBJECT_PATH, &path,
2882 DBUS_TYPE_INVALID)) {
2883 log_error("Failed to parse reply: %s", bus_error_message(&error));
2888 r = show_one(verb, bus, path, false, new_line);
2892 dbus_message_unref(reply);
2894 dbus_error_free(&error);
2899 static int show(DBusConnection *bus, char **args) {
2901 bool show_properties, new_line = false;
2907 show_properties = streq(args[0], "show");
2909 if (show_properties)
2910 pager_open_if_enabled();
2912 if (show_properties && strv_length(args) <= 1) {
2913 /* If not argument is specified inspect the manager
2916 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2919 STRV_FOREACH(name, args+1) {
2922 if (safe_atou32(*name, &id) < 0) {
2924 /* Interpret as unit name */
2926 n = unit_name_mangle(*name);
2927 p = unit_dbus_path_from_name(n ? n : *name);
2932 r = show_one(args[0], bus, p, show_properties, &new_line);
2938 } else if (show_properties) {
2940 /* Interpret as job id */
2943 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
2946 r = show_one(args[0], bus, p, show_properties, &new_line);
2954 /* Interpret as PID */
2956 r = show_one_by_pid(args[0], bus, id, &new_line);
2965 static int dump(DBusConnection *bus, char **args) {
2966 DBusMessage *reply = NULL;
2971 dbus_error_init(&error);
2973 pager_open_if_enabled();
2975 r = bus_method_call_with_reply (
2977 "org.freedesktop.systemd1",
2978 "/org/freedesktop/systemd1",
2979 "org.freedesktop.systemd1.Manager",
2987 if (!dbus_message_get_args(reply, &error,
2988 DBUS_TYPE_STRING, &text,
2989 DBUS_TYPE_INVALID)) {
2990 log_error("Failed to parse reply: %s", bus_error_message(&error));
2995 fputs(text, stdout);
2999 dbus_message_unref(reply);
3001 dbus_error_free(&error);
3006 static int snapshot(DBusConnection *bus, char **args) {
3007 DBusMessage *reply = NULL;
3010 dbus_bool_t cleanup = FALSE;
3011 DBusMessageIter iter, sub;
3013 *name = "", *path, *id,
3014 *interface = "org.freedesktop.systemd1.Unit",
3018 dbus_error_init(&error);
3020 if (strv_length(args) > 1)
3023 n = unit_name_mangle(name);
3024 r = bus_method_call_with_reply (
3026 "org.freedesktop.systemd1",
3027 "/org/freedesktop/systemd1",
3028 "org.freedesktop.systemd1.Manager",
3032 DBUS_TYPE_STRING, n ? (const char**) &n : &name,
3033 DBUS_TYPE_BOOLEAN, &cleanup,
3039 if (!dbus_message_get_args(reply, &error,
3040 DBUS_TYPE_OBJECT_PATH, &path,
3041 DBUS_TYPE_INVALID)) {
3042 log_error("Failed to parse reply: %s", bus_error_message(&error));
3047 dbus_message_unref(reply);
3048 r = bus_method_call_with_reply (
3050 "org.freedesktop.systemd1",
3052 "org.freedesktop.DBus.Properties",
3056 DBUS_TYPE_STRING, &interface,
3057 DBUS_TYPE_STRING, &property,
3062 if (!dbus_message_iter_init(reply, &iter) ||
3063 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3064 log_error("Failed to parse reply.");
3069 dbus_message_iter_recurse(&iter, &sub);
3071 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3072 log_error("Failed to parse reply.");
3077 dbus_message_iter_get_basic(&sub, &id);
3084 dbus_message_unref(reply);
3086 dbus_error_free(&error);
3091 static int delete_snapshot(DBusConnection *bus, char **args) {
3092 DBusMessage *reply = NULL;
3099 dbus_error_init(&error);
3101 STRV_FOREACH(name, args+1) {
3102 const char *path = NULL;
3105 n = unit_name_mangle(*name);
3106 r = bus_method_call_with_reply (
3108 "org.freedesktop.systemd1",
3109 "/org/freedesktop/systemd1",
3110 "org.freedesktop.systemd1.Manager",
3114 DBUS_TYPE_STRING, n ? &n : name,
3120 if (!dbus_message_get_args(reply, &error,
3121 DBUS_TYPE_OBJECT_PATH, &path,
3122 DBUS_TYPE_INVALID)) {
3123 log_error("Failed to parse reply: %s", bus_error_message(&error));
3125 dbus_message_unref(reply);
3126 dbus_error_free(&error);
3129 dbus_message_unref(reply);
3131 r = bus_method_call_with_reply (
3133 "org.freedesktop.systemd1",
3135 "org.freedesktop.systemd1.Snapshot",
3148 static int daemon_reload(DBusConnection *bus, char **args) {
3153 if (arg_action == ACTION_RELOAD)
3155 else if (arg_action == ACTION_REEXEC)
3156 method = "Reexecute";
3158 assert(arg_action == ACTION_SYSTEMCTL);
3161 streq(args[0], "clear-jobs") ||
3162 streq(args[0], "cancel") ? "ClearJobs" :
3163 streq(args[0], "daemon-reexec") ? "Reexecute" :
3164 streq(args[0], "reset-failed") ? "ResetFailed" :
3165 streq(args[0], "halt") ? "Halt" :
3166 streq(args[0], "poweroff") ? "PowerOff" :
3167 streq(args[0], "reboot") ? "Reboot" :
3168 streq(args[0], "kexec") ? "KExec" :
3169 streq(args[0], "exit") ? "Exit" :
3170 /* "daemon-reload" */ "Reload";
3173 r = bus_method_call_with_reply (
3175 "org.freedesktop.systemd1",
3176 "/org/freedesktop/systemd1",
3177 "org.freedesktop.systemd1.Manager",
3183 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3184 /* There's always a fallback possible for
3185 * legacy actions. */
3187 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3188 /* On reexecution, we expect a disconnect, not
3192 log_error("Failed to issue method call: %s", bus_error_message(&error));
3193 dbus_error_free(&error);
3198 static int reset_failed(DBusConnection *bus, char **args) {
3202 if (strv_length(args) <= 1)
3203 return daemon_reload(bus, args);
3205 STRV_FOREACH(name, args+1) {
3206 n = unit_name_mangle(*name);
3207 r = bus_method_call_with_reply (
3209 "org.freedesktop.systemd1",
3210 "/org/freedesktop/systemd1",
3211 "org.freedesktop.systemd1.Manager",
3215 DBUS_TYPE_STRING, n ? &n : name,
3226 static int show_enviroment(DBusConnection *bus, char **args) {
3227 DBusMessage *reply = NULL;
3228 DBusMessageIter iter, sub, sub2;
3231 *interface = "org.freedesktop.systemd1.Manager",
3232 *property = "Environment";
3234 pager_open_if_enabled();
3236 r = bus_method_call_with_reply (
3238 "org.freedesktop.systemd1",
3239 "/org/freedesktop/systemd1",
3240 "org.freedesktop.DBus.Properties",
3244 DBUS_TYPE_STRING, &interface,
3245 DBUS_TYPE_STRING, &property,
3250 if (!dbus_message_iter_init(reply, &iter) ||
3251 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3252 log_error("Failed to parse reply.");
3257 dbus_message_iter_recurse(&iter, &sub);
3259 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3260 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3261 log_error("Failed to parse reply.");
3266 dbus_message_iter_recurse(&sub, &sub2);
3268 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3271 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3272 log_error("Failed to parse reply.");
3277 dbus_message_iter_get_basic(&sub2, &text);
3278 printf("%s\n", text);
3280 dbus_message_iter_next(&sub2);
3287 dbus_message_unref(reply);
3292 static int switch_root(DBusConnection *bus, char **args) {
3294 const char *root, *init;
3296 l = strv_length(args);
3297 if (l < 2 || l > 3) {
3298 log_error("Wrong number of arguments.");
3303 init = l >= 3 ? args[2] : "";
3305 return bus_method_call_with_reply (
3307 "org.freedesktop.systemd1",
3308 "/org/freedesktop/systemd1",
3309 "org.freedesktop.systemd1.Manager",
3313 DBUS_TYPE_STRING, &root,
3314 DBUS_TYPE_STRING, &init,
3318 static int set_environment(DBusConnection *bus, char **args) {
3319 DBusMessage *m = NULL, *reply = NULL;
3323 DBusMessageIter iter, sub;
3326 dbus_error_init(&error);
3328 method = streq(args[0], "set-environment")
3330 : "UnsetEnvironment";
3332 if (!(m = dbus_message_new_method_call(
3333 "org.freedesktop.systemd1",
3334 "/org/freedesktop/systemd1",
3335 "org.freedesktop.systemd1.Manager",
3338 log_error("Could not allocate message.");
3342 dbus_message_iter_init_append(m, &iter);
3344 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
3345 log_error("Could not append arguments to message.");
3350 STRV_FOREACH(name, args+1)
3351 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, name)) {
3352 log_error("Could not append arguments to message.");
3357 if (!dbus_message_iter_close_container(&iter, &sub)) {
3358 log_error("Could not append arguments to message.");
3363 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3364 log_error("Failed to issue method call: %s", bus_error_message(&error));
3373 dbus_message_unref(m);
3376 dbus_message_unref(reply);
3378 dbus_error_free(&error);
3383 static int enable_sysv_units(char **args) {
3386 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3387 const char *verb = args[0];
3388 unsigned f = 1, t = 1;
3391 if (arg_scope != UNIT_FILE_SYSTEM)
3394 if (!streq(verb, "enable") &&
3395 !streq(verb, "disable") &&
3396 !streq(verb, "is-enabled"))
3399 /* Processes all SysV units, and reshuffles the array so that
3400 * afterwards only the native units remain */
3403 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3408 for (f = 1; args[f]; f++) {
3411 bool found_native = false, found_sysv;
3413 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3414 char **k, *l, *q = NULL;
3421 if (!endswith(name, ".service"))
3424 if (path_is_absolute(name))
3427 STRV_FOREACH(k, paths.unit_path) {
3430 if (!isempty(arg_root))
3431 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3433 asprintf(&p, "%s/%s", *k, name);
3440 found_native = access(p, F_OK) >= 0;
3451 if (!isempty(arg_root))
3452 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3454 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3460 p[strlen(p) - sizeof(".service") + 1] = 0;
3461 found_sysv = access(p, F_OK) >= 0;
3468 /* Mark this entry, so that we don't try enabling it as native unit */
3469 args[f] = (char*) "";
3471 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3473 if (!isempty(arg_root))
3474 argv[c++] = q = strappend("--root=", arg_root);
3476 argv[c++] = path_get_file_name(p);
3478 streq(verb, "enable") ? "on" :
3479 streq(verb, "disable") ? "off" : "--level=5";
3482 l = strv_join((char**)argv, " ");
3490 log_info("Executing %s", l);
3495 log_error("Failed to fork: %m");
3500 } else if (pid == 0) {
3503 execv(argv[0], (char**) argv);
3504 _exit(EXIT_FAILURE);
3510 j = wait_for_terminate(pid, &status);
3512 log_error("Failed to wait for child: %s", strerror(-r));
3517 if (status.si_code == CLD_EXITED) {
3518 if (streq(verb, "is-enabled")) {
3519 if (status.si_status == 0) {
3528 } else if (status.si_status != 0) {
3539 lookup_paths_free(&paths);
3541 /* Drop all SysV units */
3542 for (f = 1, t = 1; args[f]; f++) {
3544 if (isempty(args[f]))
3547 args[t++] = args[f];
3556 static int mangle_names(char **original_names, char ***mangled_names) {
3557 char **i, **l, **name;
3559 l = new(char*, strv_length(original_names) + 1);
3564 STRV_FOREACH(name, original_names) {
3565 *i = unit_name_mangle(*name);
3580 static int enable_unit(DBusConnection *bus, char **args) {
3581 const char *verb = args[0];
3582 UnitFileChange *changes = NULL;
3583 unsigned n_changes = 0, i;
3584 int carries_install_info = -1;
3585 DBusMessage *m = NULL, *reply = NULL;
3588 char **mangled_names = NULL;
3590 r = enable_sysv_units(args);
3597 dbus_error_init(&error);
3599 if (!bus || avoid_bus()) {
3600 if (streq(verb, "enable")) {
3601 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3602 carries_install_info = r;
3603 } else if (streq(verb, "disable"))
3604 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3605 else if (streq(verb, "reenable")) {
3606 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3607 carries_install_info = r;
3608 } else if (streq(verb, "link"))
3609 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3610 else if (streq(verb, "preset")) {
3611 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3612 carries_install_info = r;
3613 } else if (streq(verb, "mask"))
3614 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3615 else if (streq(verb, "unmask"))
3616 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3618 assert_not_reached("Unknown verb");
3621 log_error("Operation failed: %s", strerror(-r));
3626 for (i = 0; i < n_changes; i++) {
3627 if (changes[i].type == UNIT_FILE_SYMLINK)
3628 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3630 log_info("rm '%s'", changes[i].path);
3636 bool send_force = true, expect_carries_install_info = false;
3638 DBusMessageIter iter, sub, sub2;
3640 if (streq(verb, "enable")) {
3641 method = "EnableUnitFiles";
3642 expect_carries_install_info = true;
3643 } else if (streq(verb, "disable")) {
3644 method = "DisableUnitFiles";
3646 } else if (streq(verb, "reenable")) {
3647 method = "ReenableUnitFiles";
3648 expect_carries_install_info = true;
3649 } else if (streq(verb, "link"))
3650 method = "LinkUnitFiles";
3651 else if (streq(verb, "preset")) {
3652 method = "PresetUnitFiles";
3653 expect_carries_install_info = true;
3654 } else if (streq(verb, "mask"))
3655 method = "MaskUnitFiles";
3656 else if (streq(verb, "unmask")) {
3657 method = "UnmaskUnitFiles";
3660 assert_not_reached("Unknown verb");
3662 m = dbus_message_new_method_call(
3663 "org.freedesktop.systemd1",
3664 "/org/freedesktop/systemd1",
3665 "org.freedesktop.systemd1.Manager",
3672 dbus_message_iter_init_append(m, &iter);
3674 r = mangle_names(args+1, &mangled_names);
3678 r = bus_append_strv_iter(&iter, mangled_names);
3680 log_error("Failed to append unit files.");
3685 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3686 log_error("Failed to append runtime boolean.");
3694 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3695 log_error("Failed to append force boolean.");
3701 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3703 log_error("Failed to issue method call: %s", bus_error_message(&error));
3708 if (!dbus_message_iter_init(reply, &iter)) {
3709 log_error("Failed to initialize iterator.");
3713 if (expect_carries_install_info) {
3714 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3716 log_error("Failed to parse reply.");
3720 carries_install_info = b;
3723 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3724 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3725 log_error("Failed to parse reply.");
3730 dbus_message_iter_recurse(&iter, &sub);
3731 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3732 const char *type, *path, *source;
3734 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3735 log_error("Failed to parse reply.");
3740 dbus_message_iter_recurse(&sub, &sub2);
3742 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3743 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3744 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3745 log_error("Failed to parse reply.");
3751 if (streq(type, "symlink"))
3752 log_info("ln -s '%s' '%s'", source, path);
3754 log_info("rm '%s'", path);
3757 dbus_message_iter_next(&sub);
3760 /* Try to reload if enabeld */
3762 r = daemon_reload(bus, args);
3765 if (carries_install_info == 0)
3766 log_warning("The unit files have no [Install] section. They are not meant to be enabled using systemctl.");
3770 dbus_message_unref(m);
3773 dbus_message_unref(reply);
3775 unit_file_changes_free(changes, n_changes);
3777 dbus_error_free(&error);
3779 strv_free(mangled_names);
3784 static int unit_is_enabled(DBusConnection *bus, char **args) {
3787 DBusMessage *reply = NULL;
3791 dbus_error_init(&error);
3793 r = enable_sysv_units(args);
3799 if (!bus || avoid_bus()) {
3801 STRV_FOREACH(name, args+1) {
3802 UnitFileState state;
3804 state = unit_file_get_state(arg_scope, arg_root, *name);
3810 if (state == UNIT_FILE_ENABLED ||
3811 state == UNIT_FILE_ENABLED_RUNTIME ||
3812 state == UNIT_FILE_STATIC)
3816 puts(unit_file_state_to_string(state));
3820 STRV_FOREACH(name, args+1) {
3823 r = bus_method_call_with_reply (
3825 "org.freedesktop.systemd1",
3826 "/org/freedesktop/systemd1",
3827 "org.freedesktop.systemd1.Manager",
3831 DBUS_TYPE_STRING, name,
3836 if (!dbus_message_get_args(reply, &error,
3837 DBUS_TYPE_STRING, &s,
3838 DBUS_TYPE_INVALID)) {
3839 log_error("Failed to parse reply: %s", bus_error_message(&error));
3844 dbus_message_unref(reply);
3847 if (streq(s, "enabled") ||
3848 streq(s, "enabled-runtime") ||
3857 r = enabled ? 0 : 1;
3861 dbus_message_unref(reply);
3863 dbus_error_free(&error);
3867 static int systemctl_help(void) {
3869 pager_open_if_enabled();
3871 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
3872 "Query or send control commands to the systemd manager.\n\n"
3873 " -h --help Show this help\n"
3874 " --version Show package version\n"
3875 " -t --type=TYPE List only units of a particular type\n"
3876 " -p --property=NAME Show only properties by this name\n"
3877 " -a --all Show all units/properties, including dead/empty ones\n"
3878 " --failed Show only failed units\n"
3879 " --full Don't ellipsize unit names on output\n"
3880 " --fail When queueing a new job, fail if conflicting jobs are\n"
3882 " --ignore-dependencies\n"
3883 " When queueing a new job, ignore all its dependencies\n"
3884 " --kill-who=WHO Who to send signal to\n"
3885 " -s --signal=SIGNAL Which signal to send\n"
3886 " -H --host=[USER@]HOST\n"
3887 " Show information for remote host\n"
3888 " -P --privileged Acquire privileges before execution\n"
3889 " -q --quiet Suppress output\n"
3890 " --no-block Do not wait until operation finished\n"
3891 " --no-wall Don't send wall message before halt/power-off/reboot\n"
3892 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
3894 " --no-legend Do not print a legend (column headers and hints)\n"
3895 " --no-pager Do not pipe output into a pager\n"
3896 " --no-ask-password\n"
3897 " Do not ask for system passwords\n"
3898 " --order When generating graph for dot, show only order\n"
3899 " --require When generating graph for dot, show only requirement\n"
3900 " --system Connect to system manager\n"
3901 " --user Connect to user service manager\n"
3902 " --global Enable/disable unit files globally\n"
3903 " -f --force When enabling unit files, override existing symlinks\n"
3904 " When shutting down, execute action immediately\n"
3905 " --root=PATH Enable unit files in the specified root directory\n"
3906 " --runtime Enable unit files only temporarily until next reboot\n"
3907 " -n --lines=INTEGER Journal entries to show\n"
3908 " --follow Follow journal\n"
3909 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
3910 " verbose, export, json, json-pretty, cat)\n\n"
3912 " list-units List loaded units\n"
3913 " start [NAME...] Start (activate) one or more units\n"
3914 " stop [NAME...] Stop (deactivate) one or more units\n"
3915 " reload [NAME...] Reload one or more units\n"
3916 " restart [NAME...] Start or restart one or more units\n"
3917 " try-restart [NAME...] Restart one or more units if active\n"
3918 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
3919 " otherwise start or restart\n"
3920 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
3921 " otherwise restart if active\n"
3922 " isolate [NAME] Start one unit and stop all others\n"
3923 " kill [NAME...] Send signal to processes of a unit\n"
3924 " is-active [NAME...] Check whether units are active\n"
3925 " status [NAME...|PID...] Show runtime status of one or more units\n"
3926 " show [NAME...|JOB...] Show properties of one or more\n"
3927 " units/jobs or the manager\n"
3928 " help [NAME...|PID...] Show manual for one or more units\n"
3929 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
3931 " load [NAME...] Load one or more units\n\n"
3932 "Unit File Commands:\n"
3933 " list-unit-files List installed unit files\n"
3934 " enable [NAME...] Enable one or more unit files\n"
3935 " disable [NAME...] Disable one or more unit files\n"
3936 " reenable [NAME...] Reenable one or more unit files\n"
3937 " preset [NAME...] Enable/disable one or more unit files\n"
3938 " based on preset configuration\n"
3939 " mask [NAME...] Mask one or more units\n"
3940 " unmask [NAME...] Unmask one or more units\n"
3941 " link [PATH...] Link one or more units files into\n"
3942 " the search path\n"
3943 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
3945 " list-jobs List jobs\n"
3946 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
3947 "Status Commands:\n"
3948 " dump Dump server status\n"
3949 " dot Dump dependency graph for dot(1)\n\n"
3950 "Snapshot Commands:\n"
3951 " snapshot [NAME] Create a snapshot\n"
3952 " delete [NAME...] Remove one or more snapshots\n\n"
3953 "Environment Commands:\n"
3954 " show-environment Dump environment\n"
3955 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
3956 " unset-environment [NAME...] Unset one or more environment variables\n\n"
3957 "Manager Lifecycle Commands:\n"
3958 " daemon-reload Reload systemd manager configuration\n"
3959 " daemon-reexec Reexecute systemd manager\n\n"
3960 "System Commands:\n"
3961 " default Enter system default mode\n"
3962 " rescue Enter system rescue mode\n"
3963 " emergency Enter system emergency mode\n"
3964 " halt Shut down and halt the system\n"
3965 " poweroff Shut down and power-off the system\n"
3966 " reboot Shut down and reboot the system\n"
3967 " kexec Shut down and reboot the system with kexec\n"
3968 " exit Request user instance exit\n"
3969 " switch-root [ROOT] [INIT] Change to a different root file system\n"
3970 " suspend Suspend the system\n"
3971 " hibernate Hibernate the system\n",
3972 program_invocation_short_name);
3977 static int halt_help(void) {
3979 printf("%s [OPTIONS...]\n\n"
3980 "%s the system.\n\n"
3981 " --help Show this help\n"
3982 " --halt Halt the machine\n"
3983 " -p --poweroff Switch off the machine\n"
3984 " --reboot Reboot the machine\n"
3985 " -f --force Force immediate halt/power-off/reboot\n"
3986 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
3987 " -d --no-wtmp Don't write wtmp record\n"
3988 " --no-wall Don't send wall message before halt/power-off/reboot\n",
3989 program_invocation_short_name,
3990 arg_action == ACTION_REBOOT ? "Reboot" :
3991 arg_action == ACTION_POWEROFF ? "Power off" :
3997 static int shutdown_help(void) {
3999 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4000 "Shut down the system.\n\n"
4001 " --help Show this help\n"
4002 " -H --halt Halt the machine\n"
4003 " -P --poweroff Power-off the machine\n"
4004 " -r --reboot Reboot the machine\n"
4005 " -h Equivalent to --poweroff, overridden by --halt\n"
4006 " -k Don't halt/power-off/reboot, just send warnings\n"
4007 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4008 " -c Cancel a pending shutdown\n",
4009 program_invocation_short_name);
4014 static int telinit_help(void) {
4016 printf("%s [OPTIONS...] {COMMAND}\n\n"
4017 "Send control commands to the init daemon.\n\n"
4018 " --help Show this help\n"
4019 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4021 " 0 Power-off the machine\n"
4022 " 6 Reboot the machine\n"
4023 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4024 " 1, s, S Enter rescue mode\n"
4025 " q, Q Reload init daemon configuration\n"
4026 " u, U Reexecute init daemon\n",
4027 program_invocation_short_name);
4032 static int runlevel_help(void) {
4034 printf("%s [OPTIONS...]\n\n"
4035 "Prints the previous and current runlevel of the init system.\n\n"
4036 " --help Show this help\n",
4037 program_invocation_short_name);
4042 static int systemctl_parse_argv(int argc, char *argv[]) {
4046 ARG_IGNORE_DEPENDENCIES,
4061 ARG_NO_ASK_PASSWORD,
4068 static const struct option options[] = {
4069 { "help", no_argument, NULL, 'h' },
4070 { "version", no_argument, NULL, ARG_VERSION },
4071 { "type", required_argument, NULL, 't' },
4072 { "property", required_argument, NULL, 'p' },
4073 { "all", no_argument, NULL, 'a' },
4074 { "failed", no_argument, NULL, ARG_FAILED },
4075 { "full", no_argument, NULL, ARG_FULL },
4076 { "fail", no_argument, NULL, ARG_FAIL },
4077 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4078 { "user", no_argument, NULL, ARG_USER },
4079 { "system", no_argument, NULL, ARG_SYSTEM },
4080 { "global", no_argument, NULL, ARG_GLOBAL },
4081 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4082 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4083 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4084 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4085 { "quiet", no_argument, NULL, 'q' },
4086 { "order", no_argument, NULL, ARG_ORDER },
4087 { "require", no_argument, NULL, ARG_REQUIRE },
4088 { "root", required_argument, NULL, ARG_ROOT },
4089 { "force", no_argument, NULL, ARG_FORCE },
4090 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4091 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4092 { "signal", required_argument, NULL, 's' },
4093 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4094 { "host", required_argument, NULL, 'H' },
4095 { "privileged",no_argument, NULL, 'P' },
4096 { "runtime", no_argument, NULL, ARG_RUNTIME },
4097 { "lines", required_argument, NULL, 'n' },
4098 { "follow", no_argument, NULL, ARG_FOLLOW },
4099 { "output", required_argument, NULL, 'o' },
4100 { NULL, 0, NULL, 0 }
4108 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4117 puts(PACKAGE_STRING);
4119 puts(SYSTEMD_FEATURES);
4123 if (unit_type_from_string(optarg) >= 0) {
4127 if (unit_load_state_from_string(optarg) >= 0) {
4128 arg_load_state = optarg;
4131 log_error("Unkown unit type or load state '%s'.",
4137 if (!(l = strv_append(arg_property, optarg)))
4140 strv_free(arg_property);
4143 /* If the user asked for a particular
4144 * property, show it to him, even if it is
4155 arg_job_mode = "fail";
4158 case ARG_IGNORE_DEPENDENCIES:
4159 arg_job_mode = "ignore-dependencies";
4163 arg_scope = UNIT_FILE_USER;
4167 arg_scope = UNIT_FILE_SYSTEM;
4171 arg_scope = UNIT_FILE_GLOBAL;
4175 arg_no_block = true;
4179 arg_no_legend = true;
4183 arg_no_pager = true;
4191 arg_dot = DOT_ORDER;
4195 arg_dot = DOT_REQUIRE;
4223 /* -f is short for both --follow and --force! */
4229 arg_no_reload = true;
4233 arg_kill_who = optarg;
4237 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4238 log_error("Failed to parse signal string %s.", optarg);
4243 case ARG_NO_ASK_PASSWORD:
4244 arg_ask_password = false;
4248 arg_transport = TRANSPORT_POLKIT;
4252 arg_transport = TRANSPORT_SSH;
4261 if (safe_atou(optarg, &arg_lines) < 0) {
4262 log_error("Failed to parse lines '%s'", optarg);
4268 arg_output = output_mode_from_string(optarg);
4269 if (arg_output < 0) {
4270 log_error("Unknown output '%s'.", optarg);
4279 log_error("Unknown option code '%c'.", c);
4284 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4285 log_error("Cannot access user instance remotely.");
4292 static int halt_parse_argv(int argc, char *argv[]) {
4301 static const struct option options[] = {
4302 { "help", no_argument, NULL, ARG_HELP },
4303 { "halt", no_argument, NULL, ARG_HALT },
4304 { "poweroff", no_argument, NULL, 'p' },
4305 { "reboot", no_argument, NULL, ARG_REBOOT },
4306 { "force", no_argument, NULL, 'f' },
4307 { "wtmp-only", no_argument, NULL, 'w' },
4308 { "no-wtmp", no_argument, NULL, 'd' },
4309 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4310 { NULL, 0, NULL, 0 }
4318 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4319 if (runlevel == '0' || runlevel == '6')
4322 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4330 arg_action = ACTION_HALT;
4334 if (arg_action != ACTION_REBOOT)
4335 arg_action = ACTION_POWEROFF;
4339 arg_action = ACTION_REBOOT;
4361 /* Compatibility nops */
4368 log_error("Unknown option code '%c'.", c);
4373 if (optind < argc) {
4374 log_error("Too many arguments.");
4381 static int parse_time_spec(const char *t, usec_t *_u) {
4385 if (streq(t, "now"))
4387 else if (!strchr(t, ':')) {
4390 if (safe_atou64(t, &u) < 0)
4393 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4402 hour = strtol(t, &e, 10);
4403 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4406 minute = strtol(e+1, &e, 10);
4407 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4410 n = now(CLOCK_REALTIME);
4411 s = (time_t) (n / USEC_PER_SEC);
4414 assert_se(localtime_r(&s, &tm));
4416 tm.tm_hour = (int) hour;
4417 tm.tm_min = (int) minute;
4420 assert_se(s = mktime(&tm));
4422 *_u = (usec_t) s * USEC_PER_SEC;
4425 *_u += USEC_PER_DAY;
4431 static int shutdown_parse_argv(int argc, char *argv[]) {
4438 static const struct option options[] = {
4439 { "help", no_argument, NULL, ARG_HELP },
4440 { "halt", no_argument, NULL, 'H' },
4441 { "poweroff", no_argument, NULL, 'P' },
4442 { "reboot", no_argument, NULL, 'r' },
4443 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4444 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4445 { NULL, 0, NULL, 0 }
4453 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4461 arg_action = ACTION_HALT;
4465 arg_action = ACTION_POWEROFF;
4470 arg_action = ACTION_KEXEC;
4472 arg_action = ACTION_REBOOT;
4476 arg_action = ACTION_KEXEC;
4480 if (arg_action != ACTION_HALT)
4481 arg_action = ACTION_POWEROFF;
4494 /* Compatibility nops */
4498 arg_action = ACTION_CANCEL_SHUTDOWN;
4505 log_error("Unknown option code '%c'.", c);
4510 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4511 r = parse_time_spec(argv[optind], &arg_when);
4513 log_error("Failed to parse time specification: %s", argv[optind]);
4517 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4519 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4520 /* No time argument for shutdown cancel */
4521 arg_wall = argv + optind;
4522 else if (argc > optind + 1)
4523 /* We skip the time argument */
4524 arg_wall = argv + optind + 1;
4531 static int telinit_parse_argv(int argc, char *argv[]) {
4538 static const struct option options[] = {
4539 { "help", no_argument, NULL, ARG_HELP },
4540 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4541 { NULL, 0, NULL, 0 }
4544 static const struct {
4548 { '0', ACTION_POWEROFF },
4549 { '6', ACTION_REBOOT },
4550 { '1', ACTION_RESCUE },
4551 { '2', ACTION_RUNLEVEL2 },
4552 { '3', ACTION_RUNLEVEL3 },
4553 { '4', ACTION_RUNLEVEL4 },
4554 { '5', ACTION_RUNLEVEL5 },
4555 { 's', ACTION_RESCUE },
4556 { 'S', ACTION_RESCUE },
4557 { 'q', ACTION_RELOAD },
4558 { 'Q', ACTION_RELOAD },
4559 { 'u', ACTION_REEXEC },
4560 { 'U', ACTION_REEXEC }
4569 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4584 log_error("Unknown option code '%c'.", c);
4589 if (optind >= argc) {
4594 if (optind + 1 < argc) {
4595 log_error("Too many arguments.");
4599 if (strlen(argv[optind]) != 1) {
4600 log_error("Expected single character argument.");
4604 for (i = 0; i < ELEMENTSOF(table); i++)
4605 if (table[i].from == argv[optind][0])
4608 if (i >= ELEMENTSOF(table)) {
4609 log_error("Unknown command '%s'.", argv[optind]);
4613 arg_action = table[i].to;
4620 static int runlevel_parse_argv(int argc, char *argv[]) {
4626 static const struct option options[] = {
4627 { "help", no_argument, NULL, ARG_HELP },
4628 { NULL, 0, NULL, 0 }
4636 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4647 log_error("Unknown option code '%c'.", c);
4652 if (optind < argc) {
4653 log_error("Too many arguments.");
4660 static int parse_argv(int argc, char *argv[]) {
4664 if (program_invocation_short_name) {
4666 if (strstr(program_invocation_short_name, "halt")) {
4667 arg_action = ACTION_HALT;
4668 return halt_parse_argv(argc, argv);
4669 } else if (strstr(program_invocation_short_name, "poweroff")) {
4670 arg_action = ACTION_POWEROFF;
4671 return halt_parse_argv(argc, argv);
4672 } else if (strstr(program_invocation_short_name, "reboot")) {
4674 arg_action = ACTION_KEXEC;
4676 arg_action = ACTION_REBOOT;
4677 return halt_parse_argv(argc, argv);
4678 } else if (strstr(program_invocation_short_name, "shutdown")) {
4679 arg_action = ACTION_POWEROFF;
4680 return shutdown_parse_argv(argc, argv);
4681 } else if (strstr(program_invocation_short_name, "init")) {
4683 if (sd_booted() > 0) {
4684 arg_action = ACTION_INVALID;
4685 return telinit_parse_argv(argc, argv);
4687 /* Hmm, so some other init system is
4688 * running, we need to forward this
4689 * request to it. For now we simply
4690 * guess that it is Upstart. */
4692 execv("/lib/upstart/telinit", argv);
4694 log_error("Couldn't find an alternative telinit implementation to spawn.");
4698 } else if (strstr(program_invocation_short_name, "runlevel")) {
4699 arg_action = ACTION_RUNLEVEL;
4700 return runlevel_parse_argv(argc, argv);
4704 arg_action = ACTION_SYSTEMCTL;
4705 return systemctl_parse_argv(argc, argv);
4708 static int action_to_runlevel(void) {
4710 static const char table[_ACTION_MAX] = {
4711 [ACTION_HALT] = '0',
4712 [ACTION_POWEROFF] = '0',
4713 [ACTION_REBOOT] = '6',
4714 [ACTION_RUNLEVEL2] = '2',
4715 [ACTION_RUNLEVEL3] = '3',
4716 [ACTION_RUNLEVEL4] = '4',
4717 [ACTION_RUNLEVEL5] = '5',
4718 [ACTION_RESCUE] = '1'
4721 assert(arg_action < _ACTION_MAX);
4723 return table[arg_action];
4726 static int talk_upstart(void) {
4727 DBusMessage *m = NULL, *reply = NULL;
4729 int previous, rl, r;
4731 env1_buf[] = "RUNLEVEL=X",
4732 env2_buf[] = "PREVLEVEL=X";
4733 char *env1 = env1_buf, *env2 = env2_buf;
4734 const char *emit = "runlevel";
4735 dbus_bool_t b_false = FALSE;
4736 DBusMessageIter iter, sub;
4737 DBusConnection *bus;
4739 dbus_error_init(&error);
4741 if (!(rl = action_to_runlevel()))
4744 if (utmp_get_runlevel(&previous, NULL) < 0)
4747 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4748 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4753 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4758 if ((r = bus_check_peercred(bus)) < 0) {
4759 log_error("Failed to verify owner of bus.");
4763 if (!(m = dbus_message_new_method_call(
4764 "com.ubuntu.Upstart",
4765 "/com/ubuntu/Upstart",
4766 "com.ubuntu.Upstart0_6",
4769 log_error("Could not allocate message.");
4774 dbus_message_iter_init_append(m, &iter);
4776 env1_buf[sizeof(env1_buf)-2] = rl;
4777 env2_buf[sizeof(env2_buf)-2] = previous;
4779 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4780 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4781 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4782 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4783 !dbus_message_iter_close_container(&iter, &sub) ||
4784 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4785 log_error("Could not append arguments to message.");
4790 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4792 if (bus_error_is_no_service(&error)) {
4797 log_error("Failed to issue method call: %s", bus_error_message(&error));
4806 dbus_message_unref(m);
4809 dbus_message_unref(reply);
4812 dbus_connection_flush(bus);
4813 dbus_connection_close(bus);
4814 dbus_connection_unref(bus);
4817 dbus_error_free(&error);
4822 static int talk_initctl(void) {
4823 struct init_request request;
4827 if (!(rl = action_to_runlevel()))
4831 request.magic = INIT_MAGIC;
4832 request.sleeptime = 0;
4833 request.cmd = INIT_CMD_RUNLVL;
4834 request.runlevel = rl;
4836 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4838 if (errno == ENOENT)
4841 log_error("Failed to open "INIT_FIFO": %m");
4846 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
4847 close_nointr_nofail(fd);
4850 log_error("Failed to write to "INIT_FIFO": %m");
4851 return errno ? -errno : -EIO;
4857 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
4859 static const struct {
4867 int (* const dispatch)(DBusConnection *bus, char **args);
4869 { "list-units", LESS, 1, list_units },
4870 { "list-unit-files", EQUAL, 1, list_unit_files },
4871 { "list-jobs", EQUAL, 1, list_jobs },
4872 { "clear-jobs", EQUAL, 1, daemon_reload },
4873 { "load", MORE, 2, load_unit },
4874 { "cancel", MORE, 2, cancel_job },
4875 { "start", MORE, 2, start_unit },
4876 { "stop", MORE, 2, start_unit },
4877 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4878 { "reload", MORE, 2, start_unit },
4879 { "restart", MORE, 2, start_unit },
4880 { "try-restart", MORE, 2, start_unit },
4881 { "reload-or-restart", MORE, 2, start_unit },
4882 { "reload-or-try-restart", MORE, 2, start_unit },
4883 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
4884 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4885 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
4886 { "isolate", EQUAL, 2, start_unit },
4887 { "kill", MORE, 2, kill_unit },
4888 { "is-active", MORE, 2, check_unit },
4889 { "check", MORE, 2, check_unit },
4890 { "show", MORE, 1, show },
4891 { "status", MORE, 2, show },
4892 { "help", MORE, 2, show },
4893 { "dump", EQUAL, 1, dump },
4894 { "dot", EQUAL, 1, dot },
4895 { "snapshot", LESS, 2, snapshot },
4896 { "delete", MORE, 2, delete_snapshot },
4897 { "daemon-reload", EQUAL, 1, daemon_reload },
4898 { "daemon-reexec", EQUAL, 1, daemon_reload },
4899 { "show-environment", EQUAL, 1, show_enviroment },
4900 { "set-environment", MORE, 2, set_environment },
4901 { "unset-environment", MORE, 2, set_environment },
4902 { "halt", EQUAL, 1, start_special },
4903 { "poweroff", EQUAL, 1, start_special },
4904 { "reboot", EQUAL, 1, start_special },
4905 { "kexec", EQUAL, 1, start_special },
4906 { "suspend", EQUAL, 1, start_special },
4907 { "hibernate", EQUAL, 1, start_special },
4908 { "default", EQUAL, 1, start_special },
4909 { "rescue", EQUAL, 1, start_special },
4910 { "emergency", EQUAL, 1, start_special },
4911 { "exit", EQUAL, 1, start_special },
4912 { "reset-failed", MORE, 1, reset_failed },
4913 { "enable", MORE, 2, enable_unit },
4914 { "disable", MORE, 2, enable_unit },
4915 { "is-enabled", MORE, 2, unit_is_enabled },
4916 { "reenable", MORE, 2, enable_unit },
4917 { "preset", MORE, 2, enable_unit },
4918 { "mask", MORE, 2, enable_unit },
4919 { "unmask", MORE, 2, enable_unit },
4920 { "link", MORE, 2, enable_unit },
4921 { "switch-root", MORE, 2, switch_root },
4931 left = argc - optind;
4934 /* Special rule: no arguments means "list-units" */
4937 if (streq(argv[optind], "help") && !argv[optind+1]) {
4938 log_error("This command expects one or more "
4939 "unit names. Did you mean --help?");
4943 for (i = 0; i < ELEMENTSOF(verbs); i++)
4944 if (streq(argv[optind], verbs[i].verb))
4947 if (i >= ELEMENTSOF(verbs)) {
4948 log_error("Unknown operation '%s'.", argv[optind]);
4953 switch (verbs[i].argc_cmp) {
4956 if (left != verbs[i].argc) {
4957 log_error("Invalid number of arguments.");
4964 if (left < verbs[i].argc) {
4965 log_error("Too few arguments.");
4972 if (left > verbs[i].argc) {
4973 log_error("Too many arguments.");
4980 assert_not_reached("Unknown comparison operator.");
4983 /* Require a bus connection for all operations but
4985 if (!streq(verbs[i].verb, "enable") &&
4986 !streq(verbs[i].verb, "disable") &&
4987 !streq(verbs[i].verb, "is-enabled") &&
4988 !streq(verbs[i].verb, "list-unit-files") &&
4989 !streq(verbs[i].verb, "reenable") &&
4990 !streq(verbs[i].verb, "preset") &&
4991 !streq(verbs[i].verb, "mask") &&
4992 !streq(verbs[i].verb, "unmask") &&
4993 !streq(verbs[i].verb, "link")) {
4995 if (running_in_chroot() > 0) {
4996 log_info("Running in chroot, ignoring request.");
5000 if (((!streq(verbs[i].verb, "reboot") &&
5001 !streq(verbs[i].verb, "halt") &&
5002 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5003 log_error("Failed to get D-Bus connection: %s",
5004 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5010 if (!bus && !avoid_bus()) {
5011 log_error("Failed to get D-Bus connection: %s",
5012 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5017 return verbs[i].dispatch(bus, argv + optind);
5020 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5022 struct msghdr msghdr;
5023 struct iovec iovec[2];
5024 union sockaddr_union sockaddr;
5025 struct sd_shutdown_command c;
5027 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5034 c.dry_run = dry_run;
5038 sockaddr.sa.sa_family = AF_UNIX;
5039 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5042 msghdr.msg_name = &sockaddr;
5043 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5046 iovec[0].iov_base = (char*) &c;
5047 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5049 if (isempty(message))
5050 msghdr.msg_iovlen = 1;
5052 iovec[1].iov_base = (char*) message;
5053 iovec[1].iov_len = strlen(message);
5054 msghdr.msg_iovlen = 2;
5056 msghdr.msg_iov = iovec;
5058 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5059 close_nointr_nofail(fd);
5063 close_nointr_nofail(fd);
5067 static int reload_with_fallback(DBusConnection *bus) {
5070 /* First, try systemd via D-Bus. */
5071 if (daemon_reload(bus, NULL) >= 0)
5075 /* Nothing else worked, so let's try signals */
5076 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5078 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5079 log_error("kill() failed: %m");
5086 static int start_with_fallback(DBusConnection *bus) {
5089 /* First, try systemd via D-Bus. */
5090 if (start_unit(bus, NULL) >= 0)
5094 /* Hmm, talking to systemd via D-Bus didn't work. Then
5095 * let's try to talk to Upstart via D-Bus. */
5096 if (talk_upstart() > 0)
5099 /* Nothing else worked, so let's try
5101 if (talk_initctl() > 0)
5104 log_error("Failed to talk to init daemon.");
5108 warn_wall(arg_action);
5112 static _noreturn_ void halt_now(enum action a) {
5114 /* Make sure C-A-D is handled by the kernel from this
5116 reboot(RB_ENABLE_CAD);
5121 log_info("Halting.");
5122 reboot(RB_HALT_SYSTEM);
5125 case ACTION_POWEROFF:
5126 log_info("Powering off.");
5127 reboot(RB_POWER_OFF);
5131 log_info("Rebooting.");
5132 reboot(RB_AUTOBOOT);
5136 assert_not_reached("Unknown halt action.");
5139 assert_not_reached("Uh? This shouldn't happen.");
5142 static int halt_main(DBusConnection *bus) {
5145 if (geteuid() != 0) {
5146 /* Try logind if we are a normal user and no special
5147 * mode applies. Maybe PolicyKit allows us to shutdown
5150 if (arg_when <= 0 &&
5153 (arg_action == ACTION_POWEROFF ||
5154 arg_action == ACTION_REBOOT)) {
5155 r = reboot_with_logind(bus, arg_action);
5160 log_error("Must be root.");
5167 m = strv_join(arg_wall, " ");
5168 r = send_shutdownd(arg_when,
5169 arg_action == ACTION_HALT ? 'H' :
5170 arg_action == ACTION_POWEROFF ? 'P' :
5171 arg_action == ACTION_KEXEC ? 'K' :
5179 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5181 char date[FORMAT_TIMESTAMP_MAX];
5183 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5184 format_timestamp(date, sizeof(date), arg_when));
5189 if (!arg_dry && !arg_force)
5190 return start_with_fallback(bus);
5193 if (sd_booted() > 0)
5194 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5196 r = utmp_put_shutdown();
5198 log_warning("Failed to write utmp record: %s", strerror(-r));
5205 halt_now(arg_action);
5206 /* We should never reach this. */
5210 static int runlevel_main(void) {
5211 int r, runlevel, previous;
5213 r = utmp_get_runlevel(&runlevel, &previous);
5220 previous <= 0 ? 'N' : previous,
5221 runlevel <= 0 ? 'N' : runlevel);
5226 int main(int argc, char*argv[]) {
5227 int r, retval = EXIT_FAILURE;
5228 DBusConnection *bus = NULL;
5231 dbus_error_init(&error);
5233 log_parse_environment();
5236 r = parse_argv(argc, argv);
5240 retval = EXIT_SUCCESS;
5244 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5245 * let's shortcut this */
5246 if (arg_action == ACTION_RUNLEVEL) {
5247 r = runlevel_main();
5248 retval = r < 0 ? EXIT_FAILURE : r;
5252 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5253 log_info("Running in chroot, ignoring request.");
5259 if (arg_transport == TRANSPORT_NORMAL)
5260 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5261 else if (arg_transport == TRANSPORT_POLKIT) {
5262 bus_connect_system_polkit(&bus, &error);
5263 private_bus = false;
5264 } else if (arg_transport == TRANSPORT_SSH) {
5265 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5266 private_bus = false;
5268 assert_not_reached("Uh, invalid transport...");
5271 switch (arg_action) {
5273 case ACTION_SYSTEMCTL:
5274 r = systemctl_main(bus, argc, argv, &error);
5278 case ACTION_POWEROFF:
5284 case ACTION_RUNLEVEL2:
5285 case ACTION_RUNLEVEL3:
5286 case ACTION_RUNLEVEL4:
5287 case ACTION_RUNLEVEL5:
5289 case ACTION_EMERGENCY:
5290 case ACTION_DEFAULT:
5291 r = start_with_fallback(bus);
5296 r = reload_with_fallback(bus);
5299 case ACTION_CANCEL_SHUTDOWN: {
5303 m = strv_join(arg_wall, " ");
5305 retval = EXIT_FAILURE;
5309 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5311 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5316 case ACTION_INVALID:
5317 case ACTION_RUNLEVEL:
5319 assert_not_reached("Unknown action");
5322 retval = r < 0 ? EXIT_FAILURE : r;
5326 dbus_connection_flush(bus);
5327 dbus_connection_close(bus);
5328 dbus_connection_unref(bus);
5331 dbus_error_free(&error);
5335 strv_free(arg_property);
5338 ask_password_agent_close();
5339 polkit_agent_close();