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;
1329 if (streq(d.result, "timeout"))
1330 log_error("Job for %s timed out.", strna(d.name));
1331 else if (streq(d.result, "canceled"))
1332 log_error("Job for %s canceled.", strna(d.name));
1333 else if (streq(d.result, "dependency"))
1334 log_error("A dependency job for %s failed. See 'journalctl' for details.", strna(d.name));
1335 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1336 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl' for details.", strna(d.name), strna(d.name));
1339 if (streq_ptr(d.result, "timeout"))
1341 else if (streq_ptr(d.result, "canceled"))
1343 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1354 dbus_connection_remove_filter(bus, wait_filter, &d);
1358 static int check_one_unit(DBusConnection *bus, char *name, bool quiet) {
1359 DBusMessage *reply = NULL;
1360 DBusMessageIter iter, sub;
1362 *interface = "org.freedesktop.systemd1.Unit",
1363 *property = "ActiveState";
1364 const char *path = NULL;
1371 n = unit_name_mangle(name);
1372 r = bus_method_call_with_reply (
1374 "org.freedesktop.systemd1",
1375 "/org/freedesktop/systemd1",
1376 "org.freedesktop.systemd1.Manager",
1380 DBUS_TYPE_STRING, n ? &n : &name,
1384 if ((r != -ENOMEM) && (!quiet))
1389 if (!dbus_message_get_args(reply, NULL,
1390 DBUS_TYPE_OBJECT_PATH, &path,
1391 DBUS_TYPE_INVALID)) {
1392 log_error("Failed to parse reply.");
1397 dbus_message_unref(reply);
1398 r = bus_method_call_with_reply (
1400 "org.freedesktop.systemd1",
1402 "org.freedesktop.DBus.Properties",
1406 DBUS_TYPE_STRING, &interface,
1407 DBUS_TYPE_STRING, &property,
1412 if (!dbus_message_iter_init(reply, &iter) ||
1413 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1414 log_error("Failed to parse reply.");
1419 dbus_message_iter_recurse(&iter, &sub);
1421 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1422 log_error("Failed to parse reply.");
1427 dbus_message_iter_get_basic(&sub, &state);
1432 if (streq(state, "active") || streq(state, "reloading"))
1435 r = 3; /* According to LSB: "program is not running" */
1439 dbus_message_unref(reply);
1444 static void check_triggering_units(
1445 DBusConnection *bus,
1446 const char *unit_name) {
1448 DBusMessage _cleanup_dbus_msg_unref_ *reply = NULL;
1449 DBusMessageIter iter, sub;
1450 char *service_trigger = NULL;
1451 const char *interface = "org.freedesktop.systemd1.Unit",
1452 *triggered_by_property = "TriggeredBy";
1454 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1455 bool print_warning_label = true;
1458 n = unit_name_mangle(unit_name);
1464 unit_path = unit_dbus_path_from_name(n);
1470 r = bus_method_call_with_reply (
1472 "org.freedesktop.systemd1",
1474 "org.freedesktop.DBus.Properties",
1478 DBUS_TYPE_STRING, &interface,
1479 DBUS_TYPE_STRING, &triggered_by_property,
1484 if (!dbus_message_iter_init(reply, &iter) ||
1485 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1486 log_error("Failed to parse reply.");
1490 dbus_message_iter_recurse(&iter, &sub);
1491 dbus_message_iter_recurse(&sub, &iter);
1494 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1496 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1497 log_error("Failed to parse reply.");
1501 dbus_message_iter_get_basic(&sub, &service_trigger);
1503 r = check_one_unit(bus, service_trigger, true);
1507 if (print_warning_label) {
1508 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1509 print_warning_label = false;
1511 log_warning(" %s", service_trigger);
1514 dbus_message_iter_next(&sub);
1518 static int start_unit_one(
1519 DBusConnection *bus,
1526 DBusMessage _cleanup_dbus_msg_unref_ *reply = NULL;
1529 _cleanup_free_ char *n, *p = NULL;
1536 n = unit_name_mangle(name);
1540 r = bus_method_call_with_reply(
1542 "org.freedesktop.systemd1",
1543 "/org/freedesktop/systemd1",
1544 "org.freedesktop.systemd1.Manager",
1548 DBUS_TYPE_STRING, &n,
1549 DBUS_TYPE_STRING, &mode,
1552 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1553 /* There's always a fallback possible for
1554 * legacy actions. */
1557 log_error("Failed to issue method call: %s", bus_error_message(error));
1562 if (!dbus_message_get_args(reply, error,
1563 DBUS_TYPE_OBJECT_PATH, &path,
1564 DBUS_TYPE_INVALID)) {
1565 log_error("Failed to parse reply: %s", bus_error_message(error));
1569 if (need_daemon_reload(bus, n))
1570 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1571 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1580 log_error("Failed to add path to set.");
1587 /* When stopping a unit warn if it can still be triggered by
1588 * another active unit (socket, path, timer) */
1589 if (!arg_quiet && streq(method, "StopUnit"))
1590 check_triggering_units(bus, name);
1595 static enum action verb_to_action(const char *verb) {
1596 if (streq(verb, "halt"))
1598 else if (streq(verb, "poweroff"))
1599 return ACTION_POWEROFF;
1600 else if (streq(verb, "reboot"))
1601 return ACTION_REBOOT;
1602 else if (streq(verb, "kexec"))
1603 return ACTION_KEXEC;
1604 else if (streq(verb, "rescue"))
1605 return ACTION_RESCUE;
1606 else if (streq(verb, "emergency"))
1607 return ACTION_EMERGENCY;
1608 else if (streq(verb, "default"))
1609 return ACTION_DEFAULT;
1610 else if (streq(verb, "exit"))
1612 else if (streq(verb, "suspend"))
1613 return ACTION_SUSPEND;
1614 else if (streq(verb, "hibernate"))
1615 return ACTION_HIBERNATE;
1617 return ACTION_INVALID;
1620 static int start_unit(DBusConnection *bus, char **args) {
1622 static const char * const table[_ACTION_MAX] = {
1623 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1624 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1625 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1626 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1627 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1628 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1629 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1630 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1631 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1632 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1633 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1634 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1635 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1636 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET
1640 const char *method, *mode, *one_name;
1645 dbus_error_init(&error);
1649 ask_password_agent_open_if_enabled();
1651 if (arg_action == ACTION_SYSTEMCTL) {
1653 streq(args[0], "stop") ||
1654 streq(args[0], "condstop") ? "StopUnit" :
1655 streq(args[0], "reload") ? "ReloadUnit" :
1656 streq(args[0], "restart") ? "RestartUnit" :
1658 streq(args[0], "try-restart") ||
1659 streq(args[0], "condrestart") ? "TryRestartUnit" :
1661 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1663 streq(args[0], "reload-or-try-restart") ||
1664 streq(args[0], "condreload") ||
1666 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1670 (streq(args[0], "isolate") ||
1671 streq(args[0], "rescue") ||
1672 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1674 one_name = table[verb_to_action(args[0])];
1677 assert(arg_action < ELEMENTSOF(table));
1678 assert(table[arg_action]);
1680 method = "StartUnit";
1682 mode = (arg_action == ACTION_EMERGENCY ||
1683 arg_action == ACTION_RESCUE ||
1684 arg_action == ACTION_RUNLEVEL2 ||
1685 arg_action == ACTION_RUNLEVEL3 ||
1686 arg_action == ACTION_RUNLEVEL4 ||
1687 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1689 one_name = table[arg_action];
1692 if (!arg_no_block) {
1693 ret = enable_wait_for_jobs(bus);
1695 log_error("Could not watch jobs: %s", strerror(-ret));
1699 s = set_new(string_hash_func, string_compare_func);
1707 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1709 ret = translate_bus_error_to_exit_status(ret, &error);
1711 STRV_FOREACH(name, args+1) {
1712 r = start_unit_one(bus, method, *name, mode, &error, s);
1714 ret = translate_bus_error_to_exit_status(r, &error);
1715 dbus_error_free(&error);
1720 if (!arg_no_block) {
1721 r = wait_for_jobs(bus, s);
1730 dbus_error_free(&error);
1735 /* Ask systemd-logind, which might grant access to unprivileged users
1736 * through PolicyKit */
1737 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1740 dbus_bool_t interactive = true;
1742 polkit_agent_open_if_enabled();
1750 case ACTION_POWEROFF:
1751 method = "PowerOff";
1754 case ACTION_SUSPEND:
1758 case ACTION_HIBERNATE:
1759 method = "Hibernate";
1766 return bus_method_call_with_reply (
1768 "org.freedesktop.login1",
1769 "/org/freedesktop/login1",
1770 "org.freedesktop.login1.Manager",
1774 DBUS_TYPE_BOOLEAN, &interactive,
1781 static int start_special(DBusConnection *bus, char **args) {
1787 a = verb_to_action(args[0]);
1789 if (arg_force >= 2 && geteuid() != 0) {
1790 log_error("Must be root.");
1794 if (arg_force >= 2 &&
1795 (a == ACTION_HALT ||
1796 a == ACTION_POWEROFF ||
1797 a == ACTION_REBOOT))
1800 if (arg_force >= 1 &&
1801 (a == ACTION_HALT ||
1802 a == ACTION_POWEROFF ||
1803 a == ACTION_REBOOT ||
1804 a == ACTION_KEXEC ||
1806 return daemon_reload(bus, args);
1808 /* first try logind, to allow authentication with polkit */
1809 if (geteuid() != 0 &&
1810 (a == ACTION_POWEROFF ||
1811 a == ACTION_REBOOT ||
1812 a == ACTION_SUSPEND ||
1813 a == ACTION_HIBERNATE)) {
1814 r = reboot_with_logind(bus, a);
1819 r = start_unit(bus, args);
1826 static int check_unit(DBusConnection *bus, char **args) {
1828 int r = 3; /* According to LSB: "program is not running" */
1833 STRV_FOREACH(name, args+1) {
1834 int state = check_one_unit(bus, *name, arg_quiet);
1844 static int kill_unit(DBusConnection *bus, char **args) {
1851 arg_kill_who = "all";
1853 STRV_FOREACH(name, args+1) {
1854 n = unit_name_mangle(*name);
1855 r = bus_method_call_with_reply (
1857 "org.freedesktop.systemd1",
1858 "/org/freedesktop/systemd1",
1859 "org.freedesktop.systemd1.Manager",
1863 DBUS_TYPE_STRING, n ? &n : name,
1864 DBUS_TYPE_STRING, &arg_kill_who,
1865 DBUS_TYPE_INT32, &arg_signal,
1874 typedef struct ExecStatusInfo {
1882 usec_t start_timestamp;
1883 usec_t exit_timestamp;
1888 LIST_FIELDS(struct ExecStatusInfo, exec);
1891 static void exec_status_info_free(ExecStatusInfo *i) {
1900 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
1901 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
1902 DBusMessageIter sub2, sub3;
1906 int32_t code, status;
1912 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
1915 dbus_message_iter_recurse(sub, &sub2);
1917 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
1920 if (!(i->path = strdup(path)))
1923 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
1924 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
1928 dbus_message_iter_recurse(&sub2, &sub3);
1929 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1930 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1931 dbus_message_iter_next(&sub3);
1936 if (!(i->argv = new0(char*, n+1)))
1940 dbus_message_iter_recurse(&sub2, &sub3);
1941 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1944 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1945 dbus_message_iter_get_basic(&sub3, &s);
1946 dbus_message_iter_next(&sub3);
1948 if (!(i->argv[n++] = strdup(s)))
1952 if (!dbus_message_iter_next(&sub2) ||
1953 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
1954 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
1955 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
1956 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
1957 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
1958 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
1959 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
1960 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
1964 i->start_timestamp = (usec_t) start_timestamp;
1965 i->exit_timestamp = (usec_t) exit_timestamp;
1966 i->pid = (pid_t) pid;
1973 typedef struct UnitStatusInfo {
1975 const char *load_state;
1976 const char *active_state;
1977 const char *sub_state;
1978 const char *unit_file_state;
1980 const char *description;
1981 const char *following;
1983 char **documentation;
1985 const char *fragment_path;
1986 const char *source_path;
1987 const char *default_control_group;
1989 const char *load_error;
1992 usec_t inactive_exit_timestamp;
1993 usec_t inactive_exit_timestamp_monotonic;
1994 usec_t active_enter_timestamp;
1995 usec_t active_exit_timestamp;
1996 usec_t inactive_enter_timestamp;
1998 bool need_daemon_reload;
2003 const char *status_text;
2006 usec_t start_timestamp;
2007 usec_t exit_timestamp;
2009 int exit_code, exit_status;
2011 usec_t condition_timestamp;
2012 bool condition_result;
2015 unsigned n_accepted;
2016 unsigned n_connections;
2020 const char *sysfs_path;
2022 /* Mount, Automount */
2028 LIST_HEAD(ExecStatusInfo, exec);
2031 static void print_status_info(UnitStatusInfo *i) {
2033 const char *on, *off, *ss;
2035 char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
2036 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2041 /* This shows pretty information about a unit. See
2042 * print_property() for a low-level property printer */
2044 printf("%s", strna(i->id));
2046 if (i->description && !streq_ptr(i->id, i->description))
2047 printf(" - %s", i->description);
2052 printf("\t Follow: unit currently follows state of %s\n", i->following);
2054 if (streq_ptr(i->load_state, "error")) {
2055 on = ansi_highlight_red(true);
2056 off = ansi_highlight_red(false);
2060 path = i->source_path ? i->source_path : i->fragment_path;
2063 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2064 else if (path && i->unit_file_state)
2065 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2067 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2069 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2071 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2073 if (streq_ptr(i->active_state, "failed")) {
2074 on = ansi_highlight_red(true);
2075 off = ansi_highlight_red(false);
2076 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2077 on = ansi_highlight_green(true);
2078 off = ansi_highlight_green(false);
2083 printf("\t Active: %s%s (%s)%s",
2085 strna(i->active_state),
2089 printf("\t Active: %s%s%s",
2091 strna(i->active_state),
2094 if (!isempty(i->result) && !streq(i->result, "success"))
2095 printf(" (Result: %s)", i->result);
2097 timestamp = (streq_ptr(i->active_state, "active") ||
2098 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2099 (streq_ptr(i->active_state, "inactive") ||
2100 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2101 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2102 i->active_exit_timestamp;
2104 s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
2105 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2108 printf(" since %s; %s\n", s2, s1);
2110 printf(" since %s\n", s2);
2114 if (!i->condition_result && i->condition_timestamp > 0) {
2115 s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
2116 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2119 printf("\t start condition failed at %s; %s\n", s2, s1);
2121 printf("\t start condition failed at %s\n", s2);
2125 printf("\t Device: %s\n", i->sysfs_path);
2127 printf("\t Where: %s\n", i->where);
2129 printf("\t What: %s\n", i->what);
2131 if (!strv_isempty(i->documentation)) {
2135 STRV_FOREACH(t, i->documentation) {
2137 printf("\t Docs: %s\n", *t);
2140 printf("\t %s\n", *t);
2145 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2147 LIST_FOREACH(exec, p, i->exec) {
2151 /* Only show exited processes here */
2155 t = strv_join(p->argv, " ");
2156 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2159 good = is_clean_exit_lsb(p->code, p->status, NULL);
2161 on = ansi_highlight_red(true);
2162 off = ansi_highlight_red(false);
2166 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2168 if (p->code == CLD_EXITED) {
2171 printf("status=%i", p->status);
2173 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2178 printf("signal=%s", signal_to_string(p->status));
2180 printf(")%s\n", off);
2182 if (i->main_pid == p->pid &&
2183 i->start_timestamp == p->start_timestamp &&
2184 i->exit_timestamp == p->start_timestamp)
2185 /* Let's not show this twice */
2188 if (p->pid == i->control_pid)
2192 if (i->main_pid > 0 || i->control_pid > 0) {
2195 if (i->main_pid > 0) {
2196 printf("Main PID: %u", (unsigned) i->main_pid);
2200 get_process_comm(i->main_pid, &t);
2205 } else if (i->exit_code > 0) {
2206 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2208 if (i->exit_code == CLD_EXITED) {
2211 printf("status=%i", i->exit_status);
2213 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2218 printf("signal=%s", signal_to_string(i->exit_status));
2223 if (i->main_pid > 0 && i->control_pid > 0)
2226 if (i->control_pid > 0) {
2229 printf(" Control: %u", (unsigned) i->control_pid);
2231 get_process_comm(i->control_pid, &t);
2242 printf("\t Status: \"%s\"\n", i->status_text);
2244 if (i->default_control_group) {
2247 printf("\t CGroup: %s\n", i->default_control_group);
2249 if (arg_transport != TRANSPORT_SSH) {
2259 if (i->main_pid > 0)
2260 extra[k++] = i->main_pid;
2262 if (i->control_pid > 0)
2263 extra[k++] = i->control_pid;
2265 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2269 if (i->id && arg_transport != TRANSPORT_SSH) {
2271 arg_all * OUTPUT_SHOW_ALL |
2272 arg_follow * OUTPUT_FOLLOW |
2273 !arg_quiet * OUTPUT_WARN_CUTOFF |
2274 on_tty() * OUTPUT_COLOR;
2277 show_journal_by_unit(i->id, arg_output, 0,
2278 i->inactive_exit_timestamp_monotonic,
2282 if (i->need_daemon_reload)
2283 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2284 ansi_highlight_red(true),
2285 ansi_highlight_red(false),
2286 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2289 static void show_unit_help(UnitStatusInfo *i) {
2294 if (!i->documentation) {
2295 log_info("Documentation for %s not known.", i->id);
2299 STRV_FOREACH(p, i->documentation) {
2301 if (startswith(*p, "man:")) {
2304 char *page = NULL, *section = NULL;
2305 const char *args[4] = { "man", NULL, NULL, NULL };
2310 if ((*p)[k-1] == ')')
2311 e = strrchr(*p, '(');
2314 page = strndup((*p) + 4, e - *p - 4);
2320 section = strndup(e + 1, *p + k - e - 2);
2334 log_error("Failed to fork: %m");
2342 execvp(args[0], (char**) args);
2343 log_error("Failed to execute man: %m");
2344 _exit(EXIT_FAILURE);
2350 wait_for_terminate(pid, NULL);
2352 log_info("Can't show: %s", *p);
2356 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2362 switch (dbus_message_iter_get_arg_type(iter)) {
2364 case DBUS_TYPE_STRING: {
2367 dbus_message_iter_get_basic(iter, &s);
2370 if (streq(name, "Id"))
2372 else if (streq(name, "LoadState"))
2374 else if (streq(name, "ActiveState"))
2375 i->active_state = s;
2376 else if (streq(name, "SubState"))
2378 else if (streq(name, "Description"))
2380 else if (streq(name, "FragmentPath"))
2381 i->fragment_path = s;
2382 else if (streq(name, "SourcePath"))
2384 else if (streq(name, "DefaultControlGroup"))
2385 i->default_control_group = s;
2386 else if (streq(name, "StatusText"))
2388 else if (streq(name, "SysFSPath"))
2390 else if (streq(name, "Where"))
2392 else if (streq(name, "What"))
2394 else if (streq(name, "Following"))
2396 else if (streq(name, "UnitFileState"))
2397 i->unit_file_state = s;
2398 else if (streq(name, "Result"))
2405 case DBUS_TYPE_BOOLEAN: {
2408 dbus_message_iter_get_basic(iter, &b);
2410 if (streq(name, "Accept"))
2412 else if (streq(name, "NeedDaemonReload"))
2413 i->need_daemon_reload = b;
2414 else if (streq(name, "ConditionResult"))
2415 i->condition_result = b;
2420 case DBUS_TYPE_UINT32: {
2423 dbus_message_iter_get_basic(iter, &u);
2425 if (streq(name, "MainPID")) {
2427 i->main_pid = (pid_t) u;
2430 } else if (streq(name, "ControlPID"))
2431 i->control_pid = (pid_t) u;
2432 else if (streq(name, "ExecMainPID")) {
2434 i->main_pid = (pid_t) u;
2435 } else if (streq(name, "NAccepted"))
2437 else if (streq(name, "NConnections"))
2438 i->n_connections = u;
2443 case DBUS_TYPE_INT32: {
2446 dbus_message_iter_get_basic(iter, &j);
2448 if (streq(name, "ExecMainCode"))
2449 i->exit_code = (int) j;
2450 else if (streq(name, "ExecMainStatus"))
2451 i->exit_status = (int) j;
2456 case DBUS_TYPE_UINT64: {
2459 dbus_message_iter_get_basic(iter, &u);
2461 if (streq(name, "ExecMainStartTimestamp"))
2462 i->start_timestamp = (usec_t) u;
2463 else if (streq(name, "ExecMainExitTimestamp"))
2464 i->exit_timestamp = (usec_t) u;
2465 else if (streq(name, "ActiveEnterTimestamp"))
2466 i->active_enter_timestamp = (usec_t) u;
2467 else if (streq(name, "InactiveEnterTimestamp"))
2468 i->inactive_enter_timestamp = (usec_t) u;
2469 else if (streq(name, "InactiveExitTimestamp"))
2470 i->inactive_exit_timestamp = (usec_t) u;
2471 else if (streq(name, "InactiveExitTimestampMonotonic"))
2472 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2473 else if (streq(name, "ActiveExitTimestamp"))
2474 i->active_exit_timestamp = (usec_t) u;
2475 else if (streq(name, "ConditionTimestamp"))
2476 i->condition_timestamp = (usec_t) u;
2481 case DBUS_TYPE_ARRAY: {
2483 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2484 startswith(name, "Exec")) {
2485 DBusMessageIter sub;
2487 dbus_message_iter_recurse(iter, &sub);
2488 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2489 ExecStatusInfo *info;
2492 if (!(info = new0(ExecStatusInfo, 1)))
2495 if (!(info->name = strdup(name))) {
2500 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2505 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2507 dbus_message_iter_next(&sub);
2509 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2510 streq(name, "Documentation")) {
2512 DBusMessageIter sub;
2514 dbus_message_iter_recurse(iter, &sub);
2515 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2519 dbus_message_iter_get_basic(&sub, &s);
2521 l = strv_append(i->documentation, s);
2525 strv_free(i->documentation);
2526 i->documentation = l;
2528 dbus_message_iter_next(&sub);
2535 case DBUS_TYPE_STRUCT: {
2537 if (streq(name, "LoadError")) {
2538 DBusMessageIter sub;
2539 const char *n, *message;
2542 dbus_message_iter_recurse(iter, &sub);
2544 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2548 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2552 if (!isempty(message))
2553 i->load_error = message;
2563 static int print_property(const char *name, DBusMessageIter *iter) {
2567 /* This is a low-level property printer, see
2568 * print_status_info() for the nicer output */
2570 if (arg_property && !strv_find(arg_property, name))
2573 switch (dbus_message_iter_get_arg_type(iter)) {
2575 case DBUS_TYPE_STRUCT: {
2576 DBusMessageIter sub;
2577 dbus_message_iter_recurse(iter, &sub);
2579 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2582 dbus_message_iter_get_basic(&sub, &u);
2585 printf("%s=%u\n", name, (unsigned) u);
2587 printf("%s=\n", name);
2590 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2593 dbus_message_iter_get_basic(&sub, &s);
2595 if (arg_all || s[0])
2596 printf("%s=%s\n", name, s);
2599 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2600 const char *a = NULL, *b = NULL;
2602 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2603 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2605 if (arg_all || !isempty(a) || !isempty(b))
2606 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2614 case DBUS_TYPE_ARRAY:
2616 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2617 DBusMessageIter sub, sub2;
2619 dbus_message_iter_recurse(iter, &sub);
2620 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2624 dbus_message_iter_recurse(&sub, &sub2);
2626 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2627 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2628 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2630 dbus_message_iter_next(&sub);
2635 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2636 DBusMessageIter sub, sub2;
2638 dbus_message_iter_recurse(iter, &sub);
2639 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2640 const char *type, *path;
2642 dbus_message_iter_recurse(&sub, &sub2);
2644 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2645 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2646 printf("%s=%s\n", type, path);
2648 dbus_message_iter_next(&sub);
2653 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2654 DBusMessageIter sub, sub2;
2656 dbus_message_iter_recurse(iter, &sub);
2657 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2659 uint64_t value, next_elapse;
2661 dbus_message_iter_recurse(&sub, &sub2);
2663 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2664 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2665 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2666 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2668 printf("%s={ value=%s ; next_elapse=%s }\n",
2670 format_timespan(timespan1, sizeof(timespan1), value),
2671 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2674 dbus_message_iter_next(&sub);
2679 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2680 DBusMessageIter sub, sub2;
2682 dbus_message_iter_recurse(iter, &sub);
2683 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2684 const char *controller, *attr, *value;
2686 dbus_message_iter_recurse(&sub, &sub2);
2688 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2689 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2690 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2692 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2698 dbus_message_iter_next(&sub);
2703 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2704 DBusMessageIter sub;
2706 dbus_message_iter_recurse(iter, &sub);
2707 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2708 ExecStatusInfo info;
2711 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2712 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2715 t = strv_join(info.argv, " ");
2717 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2721 yes_no(info.ignore),
2722 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2723 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2724 (unsigned) info. pid,
2725 sigchld_code_to_string(info.code),
2727 info.code == CLD_EXITED ? "" : "/",
2728 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2734 strv_free(info.argv);
2736 dbus_message_iter_next(&sub);
2745 if (generic_print_property(name, iter, arg_all) > 0)
2749 printf("%s=[unprintable]\n", name);
2754 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2755 DBusMessage *reply = NULL;
2756 const char *interface = "";
2758 DBusMessageIter iter, sub, sub2, sub3;
2759 UnitStatusInfo info;
2767 r = bus_method_call_with_reply (
2769 "org.freedesktop.systemd1",
2771 "org.freedesktop.DBus.Properties",
2775 DBUS_TYPE_STRING, &interface,
2780 if (!dbus_message_iter_init(reply, &iter) ||
2781 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2782 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2783 log_error("Failed to parse reply.");
2788 dbus_message_iter_recurse(&iter, &sub);
2795 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2798 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2799 log_error("Failed to parse reply.");
2804 dbus_message_iter_recurse(&sub, &sub2);
2806 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2807 log_error("Failed to parse reply.");
2812 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2813 log_error("Failed to parse reply.");
2818 dbus_message_iter_recurse(&sub2, &sub3);
2820 if (show_properties)
2821 r = print_property(name, &sub3);
2823 r = status_property(name, &sub3, &info);
2826 log_error("Failed to parse reply.");
2831 dbus_message_iter_next(&sub);
2836 if (!show_properties) {
2837 if (streq(verb, "help"))
2838 show_unit_help(&info);
2840 print_status_info(&info);
2843 strv_free(info.documentation);
2845 if (!streq_ptr(info.active_state, "active") &&
2846 !streq_ptr(info.active_state, "reloading") &&
2847 streq(verb, "status"))
2848 /* According to LSB: "program not running" */
2851 while ((p = info.exec)) {
2852 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2853 exec_status_info_free(p);
2858 dbus_message_unref(reply);
2863 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
2864 DBusMessage *reply = NULL;
2865 const char *path = NULL;
2869 dbus_error_init(&error);
2871 r = bus_method_call_with_reply (
2873 "org.freedesktop.systemd1",
2874 "/org/freedesktop/systemd1",
2875 "org.freedesktop.systemd1.Manager",
2879 DBUS_TYPE_UINT32, &pid,
2884 if (!dbus_message_get_args(reply, &error,
2885 DBUS_TYPE_OBJECT_PATH, &path,
2886 DBUS_TYPE_INVALID)) {
2887 log_error("Failed to parse reply: %s", bus_error_message(&error));
2892 r = show_one(verb, bus, path, false, new_line);
2896 dbus_message_unref(reply);
2898 dbus_error_free(&error);
2903 static int show(DBusConnection *bus, char **args) {
2905 bool show_properties, new_line = false;
2911 show_properties = streq(args[0], "show");
2913 if (show_properties)
2914 pager_open_if_enabled();
2916 if (show_properties && strv_length(args) <= 1) {
2917 /* If not argument is specified inspect the manager
2920 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2923 STRV_FOREACH(name, args+1) {
2926 if (safe_atou32(*name, &id) < 0) {
2928 /* Interpret as unit name */
2930 n = unit_name_mangle(*name);
2931 p = unit_dbus_path_from_name(n ? n : *name);
2936 r = show_one(args[0], bus, p, show_properties, &new_line);
2942 } else if (show_properties) {
2944 /* Interpret as job id */
2947 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
2950 r = show_one(args[0], bus, p, show_properties, &new_line);
2958 /* Interpret as PID */
2960 r = show_one_by_pid(args[0], bus, id, &new_line);
2969 static int dump(DBusConnection *bus, char **args) {
2970 DBusMessage *reply = NULL;
2975 dbus_error_init(&error);
2977 pager_open_if_enabled();
2979 r = bus_method_call_with_reply (
2981 "org.freedesktop.systemd1",
2982 "/org/freedesktop/systemd1",
2983 "org.freedesktop.systemd1.Manager",
2991 if (!dbus_message_get_args(reply, &error,
2992 DBUS_TYPE_STRING, &text,
2993 DBUS_TYPE_INVALID)) {
2994 log_error("Failed to parse reply: %s", bus_error_message(&error));
2999 fputs(text, stdout);
3003 dbus_message_unref(reply);
3005 dbus_error_free(&error);
3010 static int snapshot(DBusConnection *bus, char **args) {
3011 DBusMessage *reply = NULL;
3014 dbus_bool_t cleanup = FALSE;
3015 DBusMessageIter iter, sub;
3017 *name = "", *path, *id,
3018 *interface = "org.freedesktop.systemd1.Unit",
3022 dbus_error_init(&error);
3024 if (strv_length(args) > 1)
3027 n = unit_name_mangle(name);
3028 r = bus_method_call_with_reply (
3030 "org.freedesktop.systemd1",
3031 "/org/freedesktop/systemd1",
3032 "org.freedesktop.systemd1.Manager",
3036 DBUS_TYPE_STRING, n ? (const char**) &n : &name,
3037 DBUS_TYPE_BOOLEAN, &cleanup,
3043 if (!dbus_message_get_args(reply, &error,
3044 DBUS_TYPE_OBJECT_PATH, &path,
3045 DBUS_TYPE_INVALID)) {
3046 log_error("Failed to parse reply: %s", bus_error_message(&error));
3051 dbus_message_unref(reply);
3052 r = bus_method_call_with_reply (
3054 "org.freedesktop.systemd1",
3056 "org.freedesktop.DBus.Properties",
3060 DBUS_TYPE_STRING, &interface,
3061 DBUS_TYPE_STRING, &property,
3066 if (!dbus_message_iter_init(reply, &iter) ||
3067 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3068 log_error("Failed to parse reply.");
3073 dbus_message_iter_recurse(&iter, &sub);
3075 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3076 log_error("Failed to parse reply.");
3081 dbus_message_iter_get_basic(&sub, &id);
3088 dbus_message_unref(reply);
3090 dbus_error_free(&error);
3095 static int delete_snapshot(DBusConnection *bus, char **args) {
3096 DBusMessage *reply = NULL;
3103 dbus_error_init(&error);
3105 STRV_FOREACH(name, args+1) {
3106 const char *path = NULL;
3109 n = unit_name_mangle(*name);
3110 r = bus_method_call_with_reply (
3112 "org.freedesktop.systemd1",
3113 "/org/freedesktop/systemd1",
3114 "org.freedesktop.systemd1.Manager",
3118 DBUS_TYPE_STRING, n ? &n : name,
3124 if (!dbus_message_get_args(reply, &error,
3125 DBUS_TYPE_OBJECT_PATH, &path,
3126 DBUS_TYPE_INVALID)) {
3127 log_error("Failed to parse reply: %s", bus_error_message(&error));
3129 dbus_message_unref(reply);
3130 dbus_error_free(&error);
3133 dbus_message_unref(reply);
3135 r = bus_method_call_with_reply (
3137 "org.freedesktop.systemd1",
3139 "org.freedesktop.systemd1.Snapshot",
3152 static int daemon_reload(DBusConnection *bus, char **args) {
3157 if (arg_action == ACTION_RELOAD)
3159 else if (arg_action == ACTION_REEXEC)
3160 method = "Reexecute";
3162 assert(arg_action == ACTION_SYSTEMCTL);
3165 streq(args[0], "clear-jobs") ||
3166 streq(args[0], "cancel") ? "ClearJobs" :
3167 streq(args[0], "daemon-reexec") ? "Reexecute" :
3168 streq(args[0], "reset-failed") ? "ResetFailed" :
3169 streq(args[0], "halt") ? "Halt" :
3170 streq(args[0], "poweroff") ? "PowerOff" :
3171 streq(args[0], "reboot") ? "Reboot" :
3172 streq(args[0], "kexec") ? "KExec" :
3173 streq(args[0], "exit") ? "Exit" :
3174 /* "daemon-reload" */ "Reload";
3177 r = bus_method_call_with_reply (
3179 "org.freedesktop.systemd1",
3180 "/org/freedesktop/systemd1",
3181 "org.freedesktop.systemd1.Manager",
3187 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3188 /* There's always a fallback possible for
3189 * legacy actions. */
3191 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3192 /* On reexecution, we expect a disconnect, not
3196 log_error("Failed to issue method call: %s", bus_error_message(&error));
3197 dbus_error_free(&error);
3202 static int reset_failed(DBusConnection *bus, char **args) {
3206 if (strv_length(args) <= 1)
3207 return daemon_reload(bus, args);
3209 STRV_FOREACH(name, args+1) {
3210 n = unit_name_mangle(*name);
3211 r = bus_method_call_with_reply (
3213 "org.freedesktop.systemd1",
3214 "/org/freedesktop/systemd1",
3215 "org.freedesktop.systemd1.Manager",
3219 DBUS_TYPE_STRING, n ? &n : name,
3230 static int show_enviroment(DBusConnection *bus, char **args) {
3231 DBusMessage *reply = NULL;
3232 DBusMessageIter iter, sub, sub2;
3235 *interface = "org.freedesktop.systemd1.Manager",
3236 *property = "Environment";
3238 pager_open_if_enabled();
3240 r = bus_method_call_with_reply (
3242 "org.freedesktop.systemd1",
3243 "/org/freedesktop/systemd1",
3244 "org.freedesktop.DBus.Properties",
3248 DBUS_TYPE_STRING, &interface,
3249 DBUS_TYPE_STRING, &property,
3254 if (!dbus_message_iter_init(reply, &iter) ||
3255 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3256 log_error("Failed to parse reply.");
3261 dbus_message_iter_recurse(&iter, &sub);
3263 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3264 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3265 log_error("Failed to parse reply.");
3270 dbus_message_iter_recurse(&sub, &sub2);
3272 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3275 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3276 log_error("Failed to parse reply.");
3281 dbus_message_iter_get_basic(&sub2, &text);
3282 printf("%s\n", text);
3284 dbus_message_iter_next(&sub2);
3291 dbus_message_unref(reply);
3296 static int switch_root(DBusConnection *bus, char **args) {
3298 const char *root, *init;
3300 l = strv_length(args);
3301 if (l < 2 || l > 3) {
3302 log_error("Wrong number of arguments.");
3307 init = l >= 3 ? args[2] : "";
3309 return bus_method_call_with_reply (
3311 "org.freedesktop.systemd1",
3312 "/org/freedesktop/systemd1",
3313 "org.freedesktop.systemd1.Manager",
3317 DBUS_TYPE_STRING, &root,
3318 DBUS_TYPE_STRING, &init,
3322 static int set_environment(DBusConnection *bus, char **args) {
3323 DBusMessage *m = NULL, *reply = NULL;
3327 DBusMessageIter iter, sub;
3330 dbus_error_init(&error);
3332 method = streq(args[0], "set-environment")
3334 : "UnsetEnvironment";
3336 if (!(m = dbus_message_new_method_call(
3337 "org.freedesktop.systemd1",
3338 "/org/freedesktop/systemd1",
3339 "org.freedesktop.systemd1.Manager",
3342 log_error("Could not allocate message.");
3346 dbus_message_iter_init_append(m, &iter);
3348 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
3349 log_error("Could not append arguments to message.");
3354 STRV_FOREACH(name, args+1)
3355 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, name)) {
3356 log_error("Could not append arguments to message.");
3361 if (!dbus_message_iter_close_container(&iter, &sub)) {
3362 log_error("Could not append arguments to message.");
3367 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3368 log_error("Failed to issue method call: %s", bus_error_message(&error));
3377 dbus_message_unref(m);
3380 dbus_message_unref(reply);
3382 dbus_error_free(&error);
3387 static int enable_sysv_units(char **args) {
3390 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3391 const char *verb = args[0];
3392 unsigned f = 1, t = 1;
3395 if (arg_scope != UNIT_FILE_SYSTEM)
3398 if (!streq(verb, "enable") &&
3399 !streq(verb, "disable") &&
3400 !streq(verb, "is-enabled"))
3403 /* Processes all SysV units, and reshuffles the array so that
3404 * afterwards only the native units remain */
3407 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3412 for (f = 1; args[f]; f++) {
3415 bool found_native = false, found_sysv;
3417 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3418 char **k, *l, *q = NULL;
3425 if (!endswith(name, ".service"))
3428 if (path_is_absolute(name))
3431 STRV_FOREACH(k, paths.unit_path) {
3434 if (!isempty(arg_root))
3435 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3437 asprintf(&p, "%s/%s", *k, name);
3444 found_native = access(p, F_OK) >= 0;
3455 if (!isempty(arg_root))
3456 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3458 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3464 p[strlen(p) - sizeof(".service") + 1] = 0;
3465 found_sysv = access(p, F_OK) >= 0;
3472 /* Mark this entry, so that we don't try enabling it as native unit */
3473 args[f] = (char*) "";
3475 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3477 if (!isempty(arg_root))
3478 argv[c++] = q = strappend("--root=", arg_root);
3480 argv[c++] = path_get_file_name(p);
3482 streq(verb, "enable") ? "on" :
3483 streq(verb, "disable") ? "off" : "--level=5";
3486 l = strv_join((char**)argv, " ");
3494 log_info("Executing %s", l);
3499 log_error("Failed to fork: %m");
3504 } else if (pid == 0) {
3507 execv(argv[0], (char**) argv);
3508 _exit(EXIT_FAILURE);
3514 j = wait_for_terminate(pid, &status);
3516 log_error("Failed to wait for child: %s", strerror(-r));
3521 if (status.si_code == CLD_EXITED) {
3522 if (streq(verb, "is-enabled")) {
3523 if (status.si_status == 0) {
3532 } else if (status.si_status != 0) {
3543 lookup_paths_free(&paths);
3545 /* Drop all SysV units */
3546 for (f = 1, t = 1; args[f]; f++) {
3548 if (isempty(args[f]))
3551 args[t++] = args[f];
3560 static int mangle_names(char **original_names, char ***mangled_names) {
3561 char **i, **l, **name;
3563 l = new(char*, strv_length(original_names) + 1);
3568 STRV_FOREACH(name, original_names) {
3569 *i = unit_name_mangle(*name);
3584 static int enable_unit(DBusConnection *bus, char **args) {
3585 const char *verb = args[0];
3586 UnitFileChange *changes = NULL;
3587 unsigned n_changes = 0, i;
3588 int carries_install_info = -1;
3589 DBusMessage *m = NULL, *reply = NULL;
3592 char **mangled_names = NULL;
3594 r = enable_sysv_units(args);
3601 dbus_error_init(&error);
3603 if (!bus || avoid_bus()) {
3604 if (streq(verb, "enable")) {
3605 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3606 carries_install_info = r;
3607 } else if (streq(verb, "disable"))
3608 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3609 else if (streq(verb, "reenable")) {
3610 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3611 carries_install_info = r;
3612 } else if (streq(verb, "link"))
3613 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3614 else if (streq(verb, "preset")) {
3615 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3616 carries_install_info = r;
3617 } else if (streq(verb, "mask"))
3618 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3619 else if (streq(verb, "unmask"))
3620 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3622 assert_not_reached("Unknown verb");
3625 log_error("Operation failed: %s", strerror(-r));
3630 for (i = 0; i < n_changes; i++) {
3631 if (changes[i].type == UNIT_FILE_SYMLINK)
3632 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3634 log_info("rm '%s'", changes[i].path);
3640 bool send_force = true, expect_carries_install_info = false;
3642 DBusMessageIter iter, sub, sub2;
3644 if (streq(verb, "enable")) {
3645 method = "EnableUnitFiles";
3646 expect_carries_install_info = true;
3647 } else if (streq(verb, "disable")) {
3648 method = "DisableUnitFiles";
3650 } else if (streq(verb, "reenable")) {
3651 method = "ReenableUnitFiles";
3652 expect_carries_install_info = true;
3653 } else if (streq(verb, "link"))
3654 method = "LinkUnitFiles";
3655 else if (streq(verb, "preset")) {
3656 method = "PresetUnitFiles";
3657 expect_carries_install_info = true;
3658 } else if (streq(verb, "mask"))
3659 method = "MaskUnitFiles";
3660 else if (streq(verb, "unmask")) {
3661 method = "UnmaskUnitFiles";
3664 assert_not_reached("Unknown verb");
3666 m = dbus_message_new_method_call(
3667 "org.freedesktop.systemd1",
3668 "/org/freedesktop/systemd1",
3669 "org.freedesktop.systemd1.Manager",
3676 dbus_message_iter_init_append(m, &iter);
3678 r = mangle_names(args+1, &mangled_names);
3682 r = bus_append_strv_iter(&iter, mangled_names);
3684 log_error("Failed to append unit files.");
3689 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3690 log_error("Failed to append runtime boolean.");
3698 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3699 log_error("Failed to append force boolean.");
3705 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3707 log_error("Failed to issue method call: %s", bus_error_message(&error));
3712 if (!dbus_message_iter_init(reply, &iter)) {
3713 log_error("Failed to initialize iterator.");
3717 if (expect_carries_install_info) {
3718 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3720 log_error("Failed to parse reply.");
3724 carries_install_info = b;
3727 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3728 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3729 log_error("Failed to parse reply.");
3734 dbus_message_iter_recurse(&iter, &sub);
3735 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3736 const char *type, *path, *source;
3738 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3739 log_error("Failed to parse reply.");
3744 dbus_message_iter_recurse(&sub, &sub2);
3746 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3747 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3748 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3749 log_error("Failed to parse reply.");
3755 if (streq(type, "symlink"))
3756 log_info("ln -s '%s' '%s'", source, path);
3758 log_info("rm '%s'", path);
3761 dbus_message_iter_next(&sub);
3764 /* Try to reload if enabeld */
3766 r = daemon_reload(bus, args);
3769 if (carries_install_info == 0)
3770 log_warning("The unit files have no [Install] section. They are not meant to be enabled using systemctl.");
3774 dbus_message_unref(m);
3777 dbus_message_unref(reply);
3779 unit_file_changes_free(changes, n_changes);
3781 dbus_error_free(&error);
3783 strv_free(mangled_names);
3788 static int unit_is_enabled(DBusConnection *bus, char **args) {
3791 DBusMessage *reply = NULL;
3795 dbus_error_init(&error);
3797 r = enable_sysv_units(args);
3803 if (!bus || avoid_bus()) {
3805 STRV_FOREACH(name, args+1) {
3806 UnitFileState state;
3808 state = unit_file_get_state(arg_scope, arg_root, *name);
3814 if (state == UNIT_FILE_ENABLED ||
3815 state == UNIT_FILE_ENABLED_RUNTIME ||
3816 state == UNIT_FILE_STATIC)
3820 puts(unit_file_state_to_string(state));
3824 STRV_FOREACH(name, args+1) {
3827 r = bus_method_call_with_reply (
3829 "org.freedesktop.systemd1",
3830 "/org/freedesktop/systemd1",
3831 "org.freedesktop.systemd1.Manager",
3835 DBUS_TYPE_STRING, name,
3840 if (!dbus_message_get_args(reply, &error,
3841 DBUS_TYPE_STRING, &s,
3842 DBUS_TYPE_INVALID)) {
3843 log_error("Failed to parse reply: %s", bus_error_message(&error));
3848 dbus_message_unref(reply);
3851 if (streq(s, "enabled") ||
3852 streq(s, "enabled-runtime") ||
3861 r = enabled ? 0 : 1;
3865 dbus_message_unref(reply);
3867 dbus_error_free(&error);
3871 static int systemctl_help(void) {
3873 pager_open_if_enabled();
3875 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
3876 "Query or send control commands to the systemd manager.\n\n"
3877 " -h --help Show this help\n"
3878 " --version Show package version\n"
3879 " -t --type=TYPE List only units of a particular type\n"
3880 " -p --property=NAME Show only properties by this name\n"
3881 " -a --all Show all units/properties, including dead/empty ones\n"
3882 " --failed Show only failed units\n"
3883 " --full Don't ellipsize unit names on output\n"
3884 " --fail When queueing a new job, fail if conflicting jobs are\n"
3886 " --ignore-dependencies\n"
3887 " When queueing a new job, ignore all its dependencies\n"
3888 " --kill-who=WHO Who to send signal to\n"
3889 " -s --signal=SIGNAL Which signal to send\n"
3890 " -H --host=[USER@]HOST\n"
3891 " Show information for remote host\n"
3892 " -P --privileged Acquire privileges before execution\n"
3893 " -q --quiet Suppress output\n"
3894 " --no-block Do not wait until operation finished\n"
3895 " --no-wall Don't send wall message before halt/power-off/reboot\n"
3896 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
3898 " --no-legend Do not print a legend (column headers and hints)\n"
3899 " --no-pager Do not pipe output into a pager\n"
3900 " --no-ask-password\n"
3901 " Do not ask for system passwords\n"
3902 " --order When generating graph for dot, show only order\n"
3903 " --require When generating graph for dot, show only requirement\n"
3904 " --system Connect to system manager\n"
3905 " --user Connect to user service manager\n"
3906 " --global Enable/disable unit files globally\n"
3907 " -f --force When enabling unit files, override existing symlinks\n"
3908 " When shutting down, execute action immediately\n"
3909 " --root=PATH Enable unit files in the specified root directory\n"
3910 " --runtime Enable unit files only temporarily until next reboot\n"
3911 " -n --lines=INTEGER Journal entries to show\n"
3912 " --follow Follow journal\n"
3913 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
3914 " verbose, export, json, json-pretty, cat)\n\n"
3916 " list-units List loaded units\n"
3917 " start [NAME...] Start (activate) one or more units\n"
3918 " stop [NAME...] Stop (deactivate) one or more units\n"
3919 " reload [NAME...] Reload one or more units\n"
3920 " restart [NAME...] Start or restart one or more units\n"
3921 " try-restart [NAME...] Restart one or more units if active\n"
3922 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
3923 " otherwise start or restart\n"
3924 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
3925 " otherwise restart if active\n"
3926 " isolate [NAME] Start one unit and stop all others\n"
3927 " kill [NAME...] Send signal to processes of a unit\n"
3928 " is-active [NAME...] Check whether units are active\n"
3929 " status [NAME...|PID...] Show runtime status of one or more units\n"
3930 " show [NAME...|JOB...] Show properties of one or more\n"
3931 " units/jobs or the manager\n"
3932 " help [NAME...|PID...] Show manual for one or more units\n"
3933 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
3935 " load [NAME...] Load one or more units\n\n"
3936 "Unit File Commands:\n"
3937 " list-unit-files List installed unit files\n"
3938 " enable [NAME...] Enable one or more unit files\n"
3939 " disable [NAME...] Disable one or more unit files\n"
3940 " reenable [NAME...] Reenable one or more unit files\n"
3941 " preset [NAME...] Enable/disable one or more unit files\n"
3942 " based on preset configuration\n"
3943 " mask [NAME...] Mask one or more units\n"
3944 " unmask [NAME...] Unmask one or more units\n"
3945 " link [PATH...] Link one or more units files into\n"
3946 " the search path\n"
3947 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
3949 " list-jobs List jobs\n"
3950 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
3951 "Status Commands:\n"
3952 " dump Dump server status\n"
3953 " dot Dump dependency graph for dot(1)\n\n"
3954 "Snapshot Commands:\n"
3955 " snapshot [NAME] Create a snapshot\n"
3956 " delete [NAME...] Remove one or more snapshots\n\n"
3957 "Environment Commands:\n"
3958 " show-environment Dump environment\n"
3959 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
3960 " unset-environment [NAME...] Unset one or more environment variables\n\n"
3961 "Manager Lifecycle Commands:\n"
3962 " daemon-reload Reload systemd manager configuration\n"
3963 " daemon-reexec Reexecute systemd manager\n\n"
3964 "System Commands:\n"
3965 " default Enter system default mode\n"
3966 " rescue Enter system rescue mode\n"
3967 " emergency Enter system emergency mode\n"
3968 " halt Shut down and halt the system\n"
3969 " poweroff Shut down and power-off the system\n"
3970 " reboot Shut down and reboot the system\n"
3971 " kexec Shut down and reboot the system with kexec\n"
3972 " exit Request user instance exit\n"
3973 " switch-root [ROOT] [INIT] Change to a different root file system\n"
3974 " suspend Suspend the system\n"
3975 " hibernate Hibernate the system\n",
3976 program_invocation_short_name);
3981 static int halt_help(void) {
3983 printf("%s [OPTIONS...]\n\n"
3984 "%s the system.\n\n"
3985 " --help Show this help\n"
3986 " --halt Halt the machine\n"
3987 " -p --poweroff Switch off the machine\n"
3988 " --reboot Reboot the machine\n"
3989 " -f --force Force immediate halt/power-off/reboot\n"
3990 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
3991 " -d --no-wtmp Don't write wtmp record\n"
3992 " --no-wall Don't send wall message before halt/power-off/reboot\n",
3993 program_invocation_short_name,
3994 arg_action == ACTION_REBOOT ? "Reboot" :
3995 arg_action == ACTION_POWEROFF ? "Power off" :
4001 static int shutdown_help(void) {
4003 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4004 "Shut down the system.\n\n"
4005 " --help Show this help\n"
4006 " -H --halt Halt the machine\n"
4007 " -P --poweroff Power-off the machine\n"
4008 " -r --reboot Reboot the machine\n"
4009 " -h Equivalent to --poweroff, overridden by --halt\n"
4010 " -k Don't halt/power-off/reboot, just send warnings\n"
4011 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4012 " -c Cancel a pending shutdown\n",
4013 program_invocation_short_name);
4018 static int telinit_help(void) {
4020 printf("%s [OPTIONS...] {COMMAND}\n\n"
4021 "Send control commands to the init daemon.\n\n"
4022 " --help Show this help\n"
4023 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4025 " 0 Power-off the machine\n"
4026 " 6 Reboot the machine\n"
4027 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4028 " 1, s, S Enter rescue mode\n"
4029 " q, Q Reload init daemon configuration\n"
4030 " u, U Reexecute init daemon\n",
4031 program_invocation_short_name);
4036 static int runlevel_help(void) {
4038 printf("%s [OPTIONS...]\n\n"
4039 "Prints the previous and current runlevel of the init system.\n\n"
4040 " --help Show this help\n",
4041 program_invocation_short_name);
4046 static int systemctl_parse_argv(int argc, char *argv[]) {
4050 ARG_IGNORE_DEPENDENCIES,
4065 ARG_NO_ASK_PASSWORD,
4072 static const struct option options[] = {
4073 { "help", no_argument, NULL, 'h' },
4074 { "version", no_argument, NULL, ARG_VERSION },
4075 { "type", required_argument, NULL, 't' },
4076 { "property", required_argument, NULL, 'p' },
4077 { "all", no_argument, NULL, 'a' },
4078 { "failed", no_argument, NULL, ARG_FAILED },
4079 { "full", no_argument, NULL, ARG_FULL },
4080 { "fail", no_argument, NULL, ARG_FAIL },
4081 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4082 { "user", no_argument, NULL, ARG_USER },
4083 { "system", no_argument, NULL, ARG_SYSTEM },
4084 { "global", no_argument, NULL, ARG_GLOBAL },
4085 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4086 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4087 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4088 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4089 { "quiet", no_argument, NULL, 'q' },
4090 { "order", no_argument, NULL, ARG_ORDER },
4091 { "require", no_argument, NULL, ARG_REQUIRE },
4092 { "root", required_argument, NULL, ARG_ROOT },
4093 { "force", no_argument, NULL, ARG_FORCE },
4094 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4095 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4096 { "signal", required_argument, NULL, 's' },
4097 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4098 { "host", required_argument, NULL, 'H' },
4099 { "privileged",no_argument, NULL, 'P' },
4100 { "runtime", no_argument, NULL, ARG_RUNTIME },
4101 { "lines", required_argument, NULL, 'n' },
4102 { "follow", no_argument, NULL, ARG_FOLLOW },
4103 { "output", required_argument, NULL, 'o' },
4104 { NULL, 0, NULL, 0 }
4112 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4121 puts(PACKAGE_STRING);
4123 puts(SYSTEMD_FEATURES);
4127 if (unit_type_from_string(optarg) >= 0) {
4131 if (unit_load_state_from_string(optarg) >= 0) {
4132 arg_load_state = optarg;
4135 log_error("Unkown unit type or load state '%s'.",
4141 if (!(l = strv_append(arg_property, optarg)))
4144 strv_free(arg_property);
4147 /* If the user asked for a particular
4148 * property, show it to him, even if it is
4159 arg_job_mode = "fail";
4162 case ARG_IGNORE_DEPENDENCIES:
4163 arg_job_mode = "ignore-dependencies";
4167 arg_scope = UNIT_FILE_USER;
4171 arg_scope = UNIT_FILE_SYSTEM;
4175 arg_scope = UNIT_FILE_GLOBAL;
4179 arg_no_block = true;
4183 arg_no_legend = true;
4187 arg_no_pager = true;
4195 arg_dot = DOT_ORDER;
4199 arg_dot = DOT_REQUIRE;
4227 /* -f is short for both --follow and --force! */
4233 arg_no_reload = true;
4237 arg_kill_who = optarg;
4241 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4242 log_error("Failed to parse signal string %s.", optarg);
4247 case ARG_NO_ASK_PASSWORD:
4248 arg_ask_password = false;
4252 arg_transport = TRANSPORT_POLKIT;
4256 arg_transport = TRANSPORT_SSH;
4265 if (safe_atou(optarg, &arg_lines) < 0) {
4266 log_error("Failed to parse lines '%s'", optarg);
4272 arg_output = output_mode_from_string(optarg);
4273 if (arg_output < 0) {
4274 log_error("Unknown output '%s'.", optarg);
4283 log_error("Unknown option code '%c'.", c);
4288 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4289 log_error("Cannot access user instance remotely.");
4296 static int halt_parse_argv(int argc, char *argv[]) {
4305 static const struct option options[] = {
4306 { "help", no_argument, NULL, ARG_HELP },
4307 { "halt", no_argument, NULL, ARG_HALT },
4308 { "poweroff", no_argument, NULL, 'p' },
4309 { "reboot", no_argument, NULL, ARG_REBOOT },
4310 { "force", no_argument, NULL, 'f' },
4311 { "wtmp-only", no_argument, NULL, 'w' },
4312 { "no-wtmp", no_argument, NULL, 'd' },
4313 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4314 { NULL, 0, NULL, 0 }
4322 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4323 if (runlevel == '0' || runlevel == '6')
4326 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4334 arg_action = ACTION_HALT;
4338 if (arg_action != ACTION_REBOOT)
4339 arg_action = ACTION_POWEROFF;
4343 arg_action = ACTION_REBOOT;
4365 /* Compatibility nops */
4372 log_error("Unknown option code '%c'.", c);
4377 if (optind < argc) {
4378 log_error("Too many arguments.");
4385 static int parse_time_spec(const char *t, usec_t *_u) {
4389 if (streq(t, "now"))
4391 else if (!strchr(t, ':')) {
4394 if (safe_atou64(t, &u) < 0)
4397 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4406 hour = strtol(t, &e, 10);
4407 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4410 minute = strtol(e+1, &e, 10);
4411 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4414 n = now(CLOCK_REALTIME);
4415 s = (time_t) (n / USEC_PER_SEC);
4418 assert_se(localtime_r(&s, &tm));
4420 tm.tm_hour = (int) hour;
4421 tm.tm_min = (int) minute;
4424 assert_se(s = mktime(&tm));
4426 *_u = (usec_t) s * USEC_PER_SEC;
4429 *_u += USEC_PER_DAY;
4435 static int shutdown_parse_argv(int argc, char *argv[]) {
4442 static const struct option options[] = {
4443 { "help", no_argument, NULL, ARG_HELP },
4444 { "halt", no_argument, NULL, 'H' },
4445 { "poweroff", no_argument, NULL, 'P' },
4446 { "reboot", no_argument, NULL, 'r' },
4447 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4448 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4449 { NULL, 0, NULL, 0 }
4457 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4465 arg_action = ACTION_HALT;
4469 arg_action = ACTION_POWEROFF;
4474 arg_action = ACTION_KEXEC;
4476 arg_action = ACTION_REBOOT;
4480 arg_action = ACTION_KEXEC;
4484 if (arg_action != ACTION_HALT)
4485 arg_action = ACTION_POWEROFF;
4498 /* Compatibility nops */
4502 arg_action = ACTION_CANCEL_SHUTDOWN;
4509 log_error("Unknown option code '%c'.", c);
4514 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4515 r = parse_time_spec(argv[optind], &arg_when);
4517 log_error("Failed to parse time specification: %s", argv[optind]);
4521 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4523 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4524 /* No time argument for shutdown cancel */
4525 arg_wall = argv + optind;
4526 else if (argc > optind + 1)
4527 /* We skip the time argument */
4528 arg_wall = argv + optind + 1;
4535 static int telinit_parse_argv(int argc, char *argv[]) {
4542 static const struct option options[] = {
4543 { "help", no_argument, NULL, ARG_HELP },
4544 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4545 { NULL, 0, NULL, 0 }
4548 static const struct {
4552 { '0', ACTION_POWEROFF },
4553 { '6', ACTION_REBOOT },
4554 { '1', ACTION_RESCUE },
4555 { '2', ACTION_RUNLEVEL2 },
4556 { '3', ACTION_RUNLEVEL3 },
4557 { '4', ACTION_RUNLEVEL4 },
4558 { '5', ACTION_RUNLEVEL5 },
4559 { 's', ACTION_RESCUE },
4560 { 'S', ACTION_RESCUE },
4561 { 'q', ACTION_RELOAD },
4562 { 'Q', ACTION_RELOAD },
4563 { 'u', ACTION_REEXEC },
4564 { 'U', ACTION_REEXEC }
4573 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4588 log_error("Unknown option code '%c'.", c);
4593 if (optind >= argc) {
4598 if (optind + 1 < argc) {
4599 log_error("Too many arguments.");
4603 if (strlen(argv[optind]) != 1) {
4604 log_error("Expected single character argument.");
4608 for (i = 0; i < ELEMENTSOF(table); i++)
4609 if (table[i].from == argv[optind][0])
4612 if (i >= ELEMENTSOF(table)) {
4613 log_error("Unknown command '%s'.", argv[optind]);
4617 arg_action = table[i].to;
4624 static int runlevel_parse_argv(int argc, char *argv[]) {
4630 static const struct option options[] = {
4631 { "help", no_argument, NULL, ARG_HELP },
4632 { NULL, 0, NULL, 0 }
4640 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4651 log_error("Unknown option code '%c'.", c);
4656 if (optind < argc) {
4657 log_error("Too many arguments.");
4664 static int parse_argv(int argc, char *argv[]) {
4668 if (program_invocation_short_name) {
4670 if (strstr(program_invocation_short_name, "halt")) {
4671 arg_action = ACTION_HALT;
4672 return halt_parse_argv(argc, argv);
4673 } else if (strstr(program_invocation_short_name, "poweroff")) {
4674 arg_action = ACTION_POWEROFF;
4675 return halt_parse_argv(argc, argv);
4676 } else if (strstr(program_invocation_short_name, "reboot")) {
4678 arg_action = ACTION_KEXEC;
4680 arg_action = ACTION_REBOOT;
4681 return halt_parse_argv(argc, argv);
4682 } else if (strstr(program_invocation_short_name, "shutdown")) {
4683 arg_action = ACTION_POWEROFF;
4684 return shutdown_parse_argv(argc, argv);
4685 } else if (strstr(program_invocation_short_name, "init")) {
4687 if (sd_booted() > 0) {
4688 arg_action = ACTION_INVALID;
4689 return telinit_parse_argv(argc, argv);
4691 /* Hmm, so some other init system is
4692 * running, we need to forward this
4693 * request to it. For now we simply
4694 * guess that it is Upstart. */
4696 execv("/lib/upstart/telinit", argv);
4698 log_error("Couldn't find an alternative telinit implementation to spawn.");
4702 } else if (strstr(program_invocation_short_name, "runlevel")) {
4703 arg_action = ACTION_RUNLEVEL;
4704 return runlevel_parse_argv(argc, argv);
4708 arg_action = ACTION_SYSTEMCTL;
4709 return systemctl_parse_argv(argc, argv);
4712 static int action_to_runlevel(void) {
4714 static const char table[_ACTION_MAX] = {
4715 [ACTION_HALT] = '0',
4716 [ACTION_POWEROFF] = '0',
4717 [ACTION_REBOOT] = '6',
4718 [ACTION_RUNLEVEL2] = '2',
4719 [ACTION_RUNLEVEL3] = '3',
4720 [ACTION_RUNLEVEL4] = '4',
4721 [ACTION_RUNLEVEL5] = '5',
4722 [ACTION_RESCUE] = '1'
4725 assert(arg_action < _ACTION_MAX);
4727 return table[arg_action];
4730 static int talk_upstart(void) {
4731 DBusMessage *m = NULL, *reply = NULL;
4733 int previous, rl, r;
4735 env1_buf[] = "RUNLEVEL=X",
4736 env2_buf[] = "PREVLEVEL=X";
4737 char *env1 = env1_buf, *env2 = env2_buf;
4738 const char *emit = "runlevel";
4739 dbus_bool_t b_false = FALSE;
4740 DBusMessageIter iter, sub;
4741 DBusConnection *bus;
4743 dbus_error_init(&error);
4745 if (!(rl = action_to_runlevel()))
4748 if (utmp_get_runlevel(&previous, NULL) < 0)
4751 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4752 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4757 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4762 if ((r = bus_check_peercred(bus)) < 0) {
4763 log_error("Failed to verify owner of bus.");
4767 if (!(m = dbus_message_new_method_call(
4768 "com.ubuntu.Upstart",
4769 "/com/ubuntu/Upstart",
4770 "com.ubuntu.Upstart0_6",
4773 log_error("Could not allocate message.");
4778 dbus_message_iter_init_append(m, &iter);
4780 env1_buf[sizeof(env1_buf)-2] = rl;
4781 env2_buf[sizeof(env2_buf)-2] = previous;
4783 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4784 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4785 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4786 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4787 !dbus_message_iter_close_container(&iter, &sub) ||
4788 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4789 log_error("Could not append arguments to message.");
4794 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4796 if (bus_error_is_no_service(&error)) {
4801 log_error("Failed to issue method call: %s", bus_error_message(&error));
4810 dbus_message_unref(m);
4813 dbus_message_unref(reply);
4816 dbus_connection_flush(bus);
4817 dbus_connection_close(bus);
4818 dbus_connection_unref(bus);
4821 dbus_error_free(&error);
4826 static int talk_initctl(void) {
4827 struct init_request request;
4831 if (!(rl = action_to_runlevel()))
4835 request.magic = INIT_MAGIC;
4836 request.sleeptime = 0;
4837 request.cmd = INIT_CMD_RUNLVL;
4838 request.runlevel = rl;
4840 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4842 if (errno == ENOENT)
4845 log_error("Failed to open "INIT_FIFO": %m");
4850 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
4851 close_nointr_nofail(fd);
4854 log_error("Failed to write to "INIT_FIFO": %m");
4855 return errno ? -errno : -EIO;
4861 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
4863 static const struct {
4871 int (* const dispatch)(DBusConnection *bus, char **args);
4873 { "list-units", LESS, 1, list_units },
4874 { "list-unit-files", EQUAL, 1, list_unit_files },
4875 { "list-jobs", EQUAL, 1, list_jobs },
4876 { "clear-jobs", EQUAL, 1, daemon_reload },
4877 { "load", MORE, 2, load_unit },
4878 { "cancel", MORE, 2, cancel_job },
4879 { "start", MORE, 2, start_unit },
4880 { "stop", MORE, 2, start_unit },
4881 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4882 { "reload", MORE, 2, start_unit },
4883 { "restart", MORE, 2, start_unit },
4884 { "try-restart", MORE, 2, start_unit },
4885 { "reload-or-restart", MORE, 2, start_unit },
4886 { "reload-or-try-restart", MORE, 2, start_unit },
4887 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
4888 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4889 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
4890 { "isolate", EQUAL, 2, start_unit },
4891 { "kill", MORE, 2, kill_unit },
4892 { "is-active", MORE, 2, check_unit },
4893 { "check", MORE, 2, check_unit },
4894 { "show", MORE, 1, show },
4895 { "status", MORE, 2, show },
4896 { "help", MORE, 2, show },
4897 { "dump", EQUAL, 1, dump },
4898 { "dot", EQUAL, 1, dot },
4899 { "snapshot", LESS, 2, snapshot },
4900 { "delete", MORE, 2, delete_snapshot },
4901 { "daemon-reload", EQUAL, 1, daemon_reload },
4902 { "daemon-reexec", EQUAL, 1, daemon_reload },
4903 { "show-environment", EQUAL, 1, show_enviroment },
4904 { "set-environment", MORE, 2, set_environment },
4905 { "unset-environment", MORE, 2, set_environment },
4906 { "halt", EQUAL, 1, start_special },
4907 { "poweroff", EQUAL, 1, start_special },
4908 { "reboot", EQUAL, 1, start_special },
4909 { "kexec", EQUAL, 1, start_special },
4910 { "suspend", EQUAL, 1, start_special },
4911 { "hibernate", EQUAL, 1, start_special },
4912 { "default", EQUAL, 1, start_special },
4913 { "rescue", EQUAL, 1, start_special },
4914 { "emergency", EQUAL, 1, start_special },
4915 { "exit", EQUAL, 1, start_special },
4916 { "reset-failed", MORE, 1, reset_failed },
4917 { "enable", MORE, 2, enable_unit },
4918 { "disable", MORE, 2, enable_unit },
4919 { "is-enabled", MORE, 2, unit_is_enabled },
4920 { "reenable", MORE, 2, enable_unit },
4921 { "preset", MORE, 2, enable_unit },
4922 { "mask", MORE, 2, enable_unit },
4923 { "unmask", MORE, 2, enable_unit },
4924 { "link", MORE, 2, enable_unit },
4925 { "switch-root", MORE, 2, switch_root },
4935 left = argc - optind;
4938 /* Special rule: no arguments means "list-units" */
4941 if (streq(argv[optind], "help") && !argv[optind+1]) {
4942 log_error("This command expects one or more "
4943 "unit names. Did you mean --help?");
4947 for (i = 0; i < ELEMENTSOF(verbs); i++)
4948 if (streq(argv[optind], verbs[i].verb))
4951 if (i >= ELEMENTSOF(verbs)) {
4952 log_error("Unknown operation '%s'.", argv[optind]);
4957 switch (verbs[i].argc_cmp) {
4960 if (left != verbs[i].argc) {
4961 log_error("Invalid number of arguments.");
4968 if (left < verbs[i].argc) {
4969 log_error("Too few arguments.");
4976 if (left > verbs[i].argc) {
4977 log_error("Too many arguments.");
4984 assert_not_reached("Unknown comparison operator.");
4987 /* Require a bus connection for all operations but
4989 if (!streq(verbs[i].verb, "enable") &&
4990 !streq(verbs[i].verb, "disable") &&
4991 !streq(verbs[i].verb, "is-enabled") &&
4992 !streq(verbs[i].verb, "list-unit-files") &&
4993 !streq(verbs[i].verb, "reenable") &&
4994 !streq(verbs[i].verb, "preset") &&
4995 !streq(verbs[i].verb, "mask") &&
4996 !streq(verbs[i].verb, "unmask") &&
4997 !streq(verbs[i].verb, "link")) {
4999 if (running_in_chroot() > 0) {
5000 log_info("Running in chroot, ignoring request.");
5004 if (((!streq(verbs[i].verb, "reboot") &&
5005 !streq(verbs[i].verb, "halt") &&
5006 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5007 log_error("Failed to get D-Bus connection: %s",
5008 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5014 if (!bus && !avoid_bus()) {
5015 log_error("Failed to get D-Bus connection: %s",
5016 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5021 return verbs[i].dispatch(bus, argv + optind);
5024 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5026 struct msghdr msghdr;
5027 struct iovec iovec[2];
5028 union sockaddr_union sockaddr;
5029 struct sd_shutdown_command c;
5031 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5038 c.dry_run = dry_run;
5042 sockaddr.sa.sa_family = AF_UNIX;
5043 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5046 msghdr.msg_name = &sockaddr;
5047 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5050 iovec[0].iov_base = (char*) &c;
5051 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5053 if (isempty(message))
5054 msghdr.msg_iovlen = 1;
5056 iovec[1].iov_base = (char*) message;
5057 iovec[1].iov_len = strlen(message);
5058 msghdr.msg_iovlen = 2;
5060 msghdr.msg_iov = iovec;
5062 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5063 close_nointr_nofail(fd);
5067 close_nointr_nofail(fd);
5071 static int reload_with_fallback(DBusConnection *bus) {
5074 /* First, try systemd via D-Bus. */
5075 if (daemon_reload(bus, NULL) >= 0)
5079 /* Nothing else worked, so let's try signals */
5080 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5082 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5083 log_error("kill() failed: %m");
5090 static int start_with_fallback(DBusConnection *bus) {
5093 /* First, try systemd via D-Bus. */
5094 if (start_unit(bus, NULL) >= 0)
5098 /* Hmm, talking to systemd via D-Bus didn't work. Then
5099 * let's try to talk to Upstart via D-Bus. */
5100 if (talk_upstart() > 0)
5103 /* Nothing else worked, so let's try
5105 if (talk_initctl() > 0)
5108 log_error("Failed to talk to init daemon.");
5112 warn_wall(arg_action);
5116 static _noreturn_ void halt_now(enum action a) {
5118 /* Make sure C-A-D is handled by the kernel from this
5120 reboot(RB_ENABLE_CAD);
5125 log_info("Halting.");
5126 reboot(RB_HALT_SYSTEM);
5129 case ACTION_POWEROFF:
5130 log_info("Powering off.");
5131 reboot(RB_POWER_OFF);
5135 log_info("Rebooting.");
5136 reboot(RB_AUTOBOOT);
5140 assert_not_reached("Unknown halt action.");
5143 assert_not_reached("Uh? This shouldn't happen.");
5146 static int halt_main(DBusConnection *bus) {
5149 if (geteuid() != 0) {
5150 /* Try logind if we are a normal user and no special
5151 * mode applies. Maybe PolicyKit allows us to shutdown
5154 if (arg_when <= 0 &&
5157 (arg_action == ACTION_POWEROFF ||
5158 arg_action == ACTION_REBOOT)) {
5159 r = reboot_with_logind(bus, arg_action);
5164 log_error("Must be root.");
5171 m = strv_join(arg_wall, " ");
5172 r = send_shutdownd(arg_when,
5173 arg_action == ACTION_HALT ? 'H' :
5174 arg_action == ACTION_POWEROFF ? 'P' :
5175 arg_action == ACTION_KEXEC ? 'K' :
5183 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5185 char date[FORMAT_TIMESTAMP_MAX];
5187 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5188 format_timestamp(date, sizeof(date), arg_when));
5193 if (!arg_dry && !arg_force)
5194 return start_with_fallback(bus);
5197 if (sd_booted() > 0)
5198 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5200 r = utmp_put_shutdown();
5202 log_warning("Failed to write utmp record: %s", strerror(-r));
5209 halt_now(arg_action);
5210 /* We should never reach this. */
5214 static int runlevel_main(void) {
5215 int r, runlevel, previous;
5217 r = utmp_get_runlevel(&runlevel, &previous);
5224 previous <= 0 ? 'N' : previous,
5225 runlevel <= 0 ? 'N' : runlevel);
5230 int main(int argc, char*argv[]) {
5231 int r, retval = EXIT_FAILURE;
5232 DBusConnection *bus = NULL;
5235 dbus_error_init(&error);
5237 log_parse_environment();
5240 r = parse_argv(argc, argv);
5244 retval = EXIT_SUCCESS;
5248 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5249 * let's shortcut this */
5250 if (arg_action == ACTION_RUNLEVEL) {
5251 r = runlevel_main();
5252 retval = r < 0 ? EXIT_FAILURE : r;
5256 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5257 log_info("Running in chroot, ignoring request.");
5263 if (arg_transport == TRANSPORT_NORMAL)
5264 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5265 else if (arg_transport == TRANSPORT_POLKIT) {
5266 bus_connect_system_polkit(&bus, &error);
5267 private_bus = false;
5268 } else if (arg_transport == TRANSPORT_SSH) {
5269 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5270 private_bus = false;
5272 assert_not_reached("Uh, invalid transport...");
5275 switch (arg_action) {
5277 case ACTION_SYSTEMCTL:
5278 r = systemctl_main(bus, argc, argv, &error);
5282 case ACTION_POWEROFF:
5288 case ACTION_RUNLEVEL2:
5289 case ACTION_RUNLEVEL3:
5290 case ACTION_RUNLEVEL4:
5291 case ACTION_RUNLEVEL5:
5293 case ACTION_EMERGENCY:
5294 case ACTION_DEFAULT:
5295 r = start_with_fallback(bus);
5300 r = reload_with_fallback(bus);
5303 case ACTION_CANCEL_SHUTDOWN: {
5307 m = strv_join(arg_wall, " ");
5309 retval = EXIT_FAILURE;
5313 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5315 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5320 case ACTION_INVALID:
5321 case ACTION_RUNLEVEL:
5323 assert_not_reached("Unknown action");
5326 retval = r < 0 ? EXIT_FAILURE : r;
5330 dbus_connection_flush(bus);
5331 dbus_connection_close(bus);
5332 dbus_connection_unref(bus);
5335 dbus_error_free(&error);
5339 strv_free(arg_property);
5342 ask_password_agent_close();
5343 polkit_agent_close();