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.");
1590 static enum action verb_to_action(const char *verb) {
1591 if (streq(verb, "halt"))
1593 else if (streq(verb, "poweroff"))
1594 return ACTION_POWEROFF;
1595 else if (streq(verb, "reboot"))
1596 return ACTION_REBOOT;
1597 else if (streq(verb, "kexec"))
1598 return ACTION_KEXEC;
1599 else if (streq(verb, "rescue"))
1600 return ACTION_RESCUE;
1601 else if (streq(verb, "emergency"))
1602 return ACTION_EMERGENCY;
1603 else if (streq(verb, "default"))
1604 return ACTION_DEFAULT;
1605 else if (streq(verb, "exit"))
1607 else if (streq(verb, "suspend"))
1608 return ACTION_SUSPEND;
1609 else if (streq(verb, "hibernate"))
1610 return ACTION_HIBERNATE;
1612 return ACTION_INVALID;
1615 static int start_unit(DBusConnection *bus, char **args) {
1617 static const char * const table[_ACTION_MAX] = {
1618 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1619 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1620 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1621 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1622 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1623 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1624 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1625 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1626 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1627 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1628 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1629 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1630 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1631 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET
1635 const char *method, *mode, *one_name;
1640 dbus_error_init(&error);
1644 ask_password_agent_open_if_enabled();
1646 if (arg_action == ACTION_SYSTEMCTL) {
1648 streq(args[0], "stop") ||
1649 streq(args[0], "condstop") ? "StopUnit" :
1650 streq(args[0], "reload") ? "ReloadUnit" :
1651 streq(args[0], "restart") ? "RestartUnit" :
1653 streq(args[0], "try-restart") ||
1654 streq(args[0], "condrestart") ? "TryRestartUnit" :
1656 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1658 streq(args[0], "reload-or-try-restart") ||
1659 streq(args[0], "condreload") ||
1661 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1665 (streq(args[0], "isolate") ||
1666 streq(args[0], "rescue") ||
1667 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1669 one_name = table[verb_to_action(args[0])];
1672 assert(arg_action < ELEMENTSOF(table));
1673 assert(table[arg_action]);
1675 method = "StartUnit";
1677 mode = (arg_action == ACTION_EMERGENCY ||
1678 arg_action == ACTION_RESCUE ||
1679 arg_action == ACTION_RUNLEVEL2 ||
1680 arg_action == ACTION_RUNLEVEL3 ||
1681 arg_action == ACTION_RUNLEVEL4 ||
1682 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1684 one_name = table[arg_action];
1687 if (!arg_no_block) {
1688 ret = enable_wait_for_jobs(bus);
1690 log_error("Could not watch jobs: %s", strerror(-ret));
1694 s = set_new(string_hash_func, string_compare_func);
1702 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1704 ret = translate_bus_error_to_exit_status(ret, &error);
1706 STRV_FOREACH(name, args+1) {
1707 r = start_unit_one(bus, method, *name, mode, &error, s);
1709 ret = translate_bus_error_to_exit_status(r, &error);
1710 dbus_error_free(&error);
1715 if (!arg_no_block) {
1716 r = wait_for_jobs(bus, s);
1722 /* When stopping units, warn if they can still be triggered by
1723 * another active unit (socket, path, timer) */
1724 if (!arg_quiet && streq(method, "StopUnit")) {
1726 check_triggering_units(bus, one_name);
1728 STRV_FOREACH(name, args+1)
1729 check_triggering_units(bus, *name);
1735 dbus_error_free(&error);
1740 /* Ask systemd-logind, which might grant access to unprivileged users
1741 * through PolicyKit */
1742 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1745 dbus_bool_t interactive = true;
1747 polkit_agent_open_if_enabled();
1755 case ACTION_POWEROFF:
1756 method = "PowerOff";
1759 case ACTION_SUSPEND:
1763 case ACTION_HIBERNATE:
1764 method = "Hibernate";
1771 return bus_method_call_with_reply (
1773 "org.freedesktop.login1",
1774 "/org/freedesktop/login1",
1775 "org.freedesktop.login1.Manager",
1779 DBUS_TYPE_BOOLEAN, &interactive,
1786 static int start_special(DBusConnection *bus, char **args) {
1792 a = verb_to_action(args[0]);
1794 if (arg_force >= 2 && geteuid() != 0) {
1795 log_error("Must be root.");
1799 if (arg_force >= 2 &&
1800 (a == ACTION_HALT ||
1801 a == ACTION_POWEROFF ||
1802 a == ACTION_REBOOT))
1805 if (arg_force >= 1 &&
1806 (a == ACTION_HALT ||
1807 a == ACTION_POWEROFF ||
1808 a == ACTION_REBOOT ||
1809 a == ACTION_KEXEC ||
1811 return daemon_reload(bus, args);
1813 /* first try logind, to allow authentication with polkit */
1814 if (geteuid() != 0 &&
1815 (a == ACTION_POWEROFF ||
1816 a == ACTION_REBOOT ||
1817 a == ACTION_SUSPEND ||
1818 a == ACTION_HIBERNATE)) {
1819 r = reboot_with_logind(bus, a);
1824 r = start_unit(bus, args);
1831 static int check_unit(DBusConnection *bus, char **args) {
1833 int r = 3; /* According to LSB: "program is not running" */
1838 STRV_FOREACH(name, args+1) {
1839 int state = check_one_unit(bus, *name, arg_quiet);
1849 static int kill_unit(DBusConnection *bus, char **args) {
1856 arg_kill_who = "all";
1858 STRV_FOREACH(name, args+1) {
1859 n = unit_name_mangle(*name);
1860 r = bus_method_call_with_reply (
1862 "org.freedesktop.systemd1",
1863 "/org/freedesktop/systemd1",
1864 "org.freedesktop.systemd1.Manager",
1868 DBUS_TYPE_STRING, n ? &n : name,
1869 DBUS_TYPE_STRING, &arg_kill_who,
1870 DBUS_TYPE_INT32, &arg_signal,
1879 typedef struct ExecStatusInfo {
1887 usec_t start_timestamp;
1888 usec_t exit_timestamp;
1893 LIST_FIELDS(struct ExecStatusInfo, exec);
1896 static void exec_status_info_free(ExecStatusInfo *i) {
1905 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
1906 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
1907 DBusMessageIter sub2, sub3;
1911 int32_t code, status;
1917 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
1920 dbus_message_iter_recurse(sub, &sub2);
1922 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
1925 if (!(i->path = strdup(path)))
1928 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
1929 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
1933 dbus_message_iter_recurse(&sub2, &sub3);
1934 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1935 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1936 dbus_message_iter_next(&sub3);
1941 if (!(i->argv = new0(char*, n+1)))
1945 dbus_message_iter_recurse(&sub2, &sub3);
1946 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1949 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1950 dbus_message_iter_get_basic(&sub3, &s);
1951 dbus_message_iter_next(&sub3);
1953 if (!(i->argv[n++] = strdup(s)))
1957 if (!dbus_message_iter_next(&sub2) ||
1958 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
1959 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
1960 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
1961 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
1962 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
1963 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
1964 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
1965 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
1969 i->start_timestamp = (usec_t) start_timestamp;
1970 i->exit_timestamp = (usec_t) exit_timestamp;
1971 i->pid = (pid_t) pid;
1978 typedef struct UnitStatusInfo {
1980 const char *load_state;
1981 const char *active_state;
1982 const char *sub_state;
1983 const char *unit_file_state;
1985 const char *description;
1986 const char *following;
1988 char **documentation;
1990 const char *fragment_path;
1991 const char *source_path;
1992 const char *default_control_group;
1994 const char *load_error;
1997 usec_t inactive_exit_timestamp;
1998 usec_t inactive_exit_timestamp_monotonic;
1999 usec_t active_enter_timestamp;
2000 usec_t active_exit_timestamp;
2001 usec_t inactive_enter_timestamp;
2003 bool need_daemon_reload;
2008 const char *status_text;
2011 usec_t start_timestamp;
2012 usec_t exit_timestamp;
2014 int exit_code, exit_status;
2016 usec_t condition_timestamp;
2017 bool condition_result;
2020 unsigned n_accepted;
2021 unsigned n_connections;
2025 const char *sysfs_path;
2027 /* Mount, Automount */
2033 LIST_HEAD(ExecStatusInfo, exec);
2036 static void print_status_info(UnitStatusInfo *i) {
2038 const char *on, *off, *ss;
2040 char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
2041 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2046 /* This shows pretty information about a unit. See
2047 * print_property() for a low-level property printer */
2049 printf("%s", strna(i->id));
2051 if (i->description && !streq_ptr(i->id, i->description))
2052 printf(" - %s", i->description);
2057 printf("\t Follow: unit currently follows state of %s\n", i->following);
2059 if (streq_ptr(i->load_state, "error")) {
2060 on = ansi_highlight_red(true);
2061 off = ansi_highlight_red(false);
2065 path = i->source_path ? i->source_path : i->fragment_path;
2068 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2069 else if (path && i->unit_file_state)
2070 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2072 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2074 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2076 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2078 if (streq_ptr(i->active_state, "failed")) {
2079 on = ansi_highlight_red(true);
2080 off = ansi_highlight_red(false);
2081 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2082 on = ansi_highlight_green(true);
2083 off = ansi_highlight_green(false);
2088 printf("\t Active: %s%s (%s)%s",
2090 strna(i->active_state),
2094 printf("\t Active: %s%s%s",
2096 strna(i->active_state),
2099 if (!isempty(i->result) && !streq(i->result, "success"))
2100 printf(" (Result: %s)", i->result);
2102 timestamp = (streq_ptr(i->active_state, "active") ||
2103 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2104 (streq_ptr(i->active_state, "inactive") ||
2105 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2106 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2107 i->active_exit_timestamp;
2109 s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
2110 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2113 printf(" since %s; %s\n", s2, s1);
2115 printf(" since %s\n", s2);
2119 if (!i->condition_result && i->condition_timestamp > 0) {
2120 s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
2121 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2124 printf("\t start condition failed at %s; %s\n", s2, s1);
2126 printf("\t start condition failed at %s\n", s2);
2130 printf("\t Device: %s\n", i->sysfs_path);
2132 printf("\t Where: %s\n", i->where);
2134 printf("\t What: %s\n", i->what);
2136 if (!strv_isempty(i->documentation)) {
2140 STRV_FOREACH(t, i->documentation) {
2142 printf("\t Docs: %s\n", *t);
2145 printf("\t %s\n", *t);
2150 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2152 LIST_FOREACH(exec, p, i->exec) {
2156 /* Only show exited processes here */
2160 t = strv_join(p->argv, " ");
2161 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2164 good = is_clean_exit_lsb(p->code, p->status, NULL);
2166 on = ansi_highlight_red(true);
2167 off = ansi_highlight_red(false);
2171 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2173 if (p->code == CLD_EXITED) {
2176 printf("status=%i", p->status);
2178 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2183 printf("signal=%s", signal_to_string(p->status));
2185 printf(")%s\n", off);
2187 if (i->main_pid == p->pid &&
2188 i->start_timestamp == p->start_timestamp &&
2189 i->exit_timestamp == p->start_timestamp)
2190 /* Let's not show this twice */
2193 if (p->pid == i->control_pid)
2197 if (i->main_pid > 0 || i->control_pid > 0) {
2200 if (i->main_pid > 0) {
2201 printf("Main PID: %u", (unsigned) i->main_pid);
2205 get_process_comm(i->main_pid, &t);
2210 } else if (i->exit_code > 0) {
2211 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2213 if (i->exit_code == CLD_EXITED) {
2216 printf("status=%i", i->exit_status);
2218 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2223 printf("signal=%s", signal_to_string(i->exit_status));
2228 if (i->main_pid > 0 && i->control_pid > 0)
2231 if (i->control_pid > 0) {
2234 printf(" Control: %u", (unsigned) i->control_pid);
2236 get_process_comm(i->control_pid, &t);
2247 printf("\t Status: \"%s\"\n", i->status_text);
2249 if (i->default_control_group) {
2252 printf("\t CGroup: %s\n", i->default_control_group);
2254 if (arg_transport != TRANSPORT_SSH) {
2264 if (i->main_pid > 0)
2265 extra[k++] = i->main_pid;
2267 if (i->control_pid > 0)
2268 extra[k++] = i->control_pid;
2270 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2274 if (i->id && arg_transport != TRANSPORT_SSH) {
2276 arg_all * OUTPUT_SHOW_ALL |
2277 arg_follow * OUTPUT_FOLLOW |
2278 !arg_quiet * OUTPUT_WARN_CUTOFF |
2279 on_tty() * OUTPUT_COLOR;
2282 show_journal_by_unit(i->id, arg_output, 0,
2283 i->inactive_exit_timestamp_monotonic,
2287 if (i->need_daemon_reload)
2288 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2289 ansi_highlight_red(true),
2290 ansi_highlight_red(false),
2291 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2294 static void show_unit_help(UnitStatusInfo *i) {
2299 if (!i->documentation) {
2300 log_info("Documentation for %s not known.", i->id);
2304 STRV_FOREACH(p, i->documentation) {
2306 if (startswith(*p, "man:")) {
2309 char *page = NULL, *section = NULL;
2310 const char *args[4] = { "man", NULL, NULL, NULL };
2315 if ((*p)[k-1] == ')')
2316 e = strrchr(*p, '(');
2319 page = strndup((*p) + 4, e - *p - 4);
2325 section = strndup(e + 1, *p + k - e - 2);
2339 log_error("Failed to fork: %m");
2347 execvp(args[0], (char**) args);
2348 log_error("Failed to execute man: %m");
2349 _exit(EXIT_FAILURE);
2355 wait_for_terminate(pid, NULL);
2357 log_info("Can't show: %s", *p);
2361 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2367 switch (dbus_message_iter_get_arg_type(iter)) {
2369 case DBUS_TYPE_STRING: {
2372 dbus_message_iter_get_basic(iter, &s);
2375 if (streq(name, "Id"))
2377 else if (streq(name, "LoadState"))
2379 else if (streq(name, "ActiveState"))
2380 i->active_state = s;
2381 else if (streq(name, "SubState"))
2383 else if (streq(name, "Description"))
2385 else if (streq(name, "FragmentPath"))
2386 i->fragment_path = s;
2387 else if (streq(name, "SourcePath"))
2389 else if (streq(name, "DefaultControlGroup"))
2390 i->default_control_group = s;
2391 else if (streq(name, "StatusText"))
2393 else if (streq(name, "SysFSPath"))
2395 else if (streq(name, "Where"))
2397 else if (streq(name, "What"))
2399 else if (streq(name, "Following"))
2401 else if (streq(name, "UnitFileState"))
2402 i->unit_file_state = s;
2403 else if (streq(name, "Result"))
2410 case DBUS_TYPE_BOOLEAN: {
2413 dbus_message_iter_get_basic(iter, &b);
2415 if (streq(name, "Accept"))
2417 else if (streq(name, "NeedDaemonReload"))
2418 i->need_daemon_reload = b;
2419 else if (streq(name, "ConditionResult"))
2420 i->condition_result = b;
2425 case DBUS_TYPE_UINT32: {
2428 dbus_message_iter_get_basic(iter, &u);
2430 if (streq(name, "MainPID")) {
2432 i->main_pid = (pid_t) u;
2435 } else if (streq(name, "ControlPID"))
2436 i->control_pid = (pid_t) u;
2437 else if (streq(name, "ExecMainPID")) {
2439 i->main_pid = (pid_t) u;
2440 } else if (streq(name, "NAccepted"))
2442 else if (streq(name, "NConnections"))
2443 i->n_connections = u;
2448 case DBUS_TYPE_INT32: {
2451 dbus_message_iter_get_basic(iter, &j);
2453 if (streq(name, "ExecMainCode"))
2454 i->exit_code = (int) j;
2455 else if (streq(name, "ExecMainStatus"))
2456 i->exit_status = (int) j;
2461 case DBUS_TYPE_UINT64: {
2464 dbus_message_iter_get_basic(iter, &u);
2466 if (streq(name, "ExecMainStartTimestamp"))
2467 i->start_timestamp = (usec_t) u;
2468 else if (streq(name, "ExecMainExitTimestamp"))
2469 i->exit_timestamp = (usec_t) u;
2470 else if (streq(name, "ActiveEnterTimestamp"))
2471 i->active_enter_timestamp = (usec_t) u;
2472 else if (streq(name, "InactiveEnterTimestamp"))
2473 i->inactive_enter_timestamp = (usec_t) u;
2474 else if (streq(name, "InactiveExitTimestamp"))
2475 i->inactive_exit_timestamp = (usec_t) u;
2476 else if (streq(name, "InactiveExitTimestampMonotonic"))
2477 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2478 else if (streq(name, "ActiveExitTimestamp"))
2479 i->active_exit_timestamp = (usec_t) u;
2480 else if (streq(name, "ConditionTimestamp"))
2481 i->condition_timestamp = (usec_t) u;
2486 case DBUS_TYPE_ARRAY: {
2488 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2489 startswith(name, "Exec")) {
2490 DBusMessageIter sub;
2492 dbus_message_iter_recurse(iter, &sub);
2493 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2494 ExecStatusInfo *info;
2497 if (!(info = new0(ExecStatusInfo, 1)))
2500 if (!(info->name = strdup(name))) {
2505 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2510 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2512 dbus_message_iter_next(&sub);
2514 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2515 streq(name, "Documentation")) {
2517 DBusMessageIter sub;
2519 dbus_message_iter_recurse(iter, &sub);
2520 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2524 dbus_message_iter_get_basic(&sub, &s);
2526 l = strv_append(i->documentation, s);
2530 strv_free(i->documentation);
2531 i->documentation = l;
2533 dbus_message_iter_next(&sub);
2540 case DBUS_TYPE_STRUCT: {
2542 if (streq(name, "LoadError")) {
2543 DBusMessageIter sub;
2544 const char *n, *message;
2547 dbus_message_iter_recurse(iter, &sub);
2549 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2553 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2557 if (!isempty(message))
2558 i->load_error = message;
2568 static int print_property(const char *name, DBusMessageIter *iter) {
2572 /* This is a low-level property printer, see
2573 * print_status_info() for the nicer output */
2575 if (arg_property && !strv_find(arg_property, name))
2578 switch (dbus_message_iter_get_arg_type(iter)) {
2580 case DBUS_TYPE_STRUCT: {
2581 DBusMessageIter sub;
2582 dbus_message_iter_recurse(iter, &sub);
2584 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2587 dbus_message_iter_get_basic(&sub, &u);
2590 printf("%s=%u\n", name, (unsigned) u);
2592 printf("%s=\n", name);
2595 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2598 dbus_message_iter_get_basic(&sub, &s);
2600 if (arg_all || s[0])
2601 printf("%s=%s\n", name, s);
2604 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2605 const char *a = NULL, *b = NULL;
2607 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2608 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2610 if (arg_all || !isempty(a) || !isempty(b))
2611 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2619 case DBUS_TYPE_ARRAY:
2621 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2622 DBusMessageIter sub, sub2;
2624 dbus_message_iter_recurse(iter, &sub);
2625 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2629 dbus_message_iter_recurse(&sub, &sub2);
2631 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2632 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2633 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2635 dbus_message_iter_next(&sub);
2640 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2641 DBusMessageIter sub, sub2;
2643 dbus_message_iter_recurse(iter, &sub);
2644 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2645 const char *type, *path;
2647 dbus_message_iter_recurse(&sub, &sub2);
2649 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2650 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2651 printf("%s=%s\n", type, path);
2653 dbus_message_iter_next(&sub);
2658 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2659 DBusMessageIter sub, sub2;
2661 dbus_message_iter_recurse(iter, &sub);
2662 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2664 uint64_t value, next_elapse;
2666 dbus_message_iter_recurse(&sub, &sub2);
2668 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2669 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2670 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2671 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2673 printf("%s={ value=%s ; next_elapse=%s }\n",
2675 format_timespan(timespan1, sizeof(timespan1), value),
2676 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2679 dbus_message_iter_next(&sub);
2684 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2685 DBusMessageIter sub, sub2;
2687 dbus_message_iter_recurse(iter, &sub);
2688 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2689 const char *controller, *attr, *value;
2691 dbus_message_iter_recurse(&sub, &sub2);
2693 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2694 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2695 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2697 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2703 dbus_message_iter_next(&sub);
2708 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2709 DBusMessageIter sub;
2711 dbus_message_iter_recurse(iter, &sub);
2712 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2713 ExecStatusInfo info;
2716 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2717 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2720 t = strv_join(info.argv, " ");
2722 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2726 yes_no(info.ignore),
2727 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2728 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2729 (unsigned) info. pid,
2730 sigchld_code_to_string(info.code),
2732 info.code == CLD_EXITED ? "" : "/",
2733 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2739 strv_free(info.argv);
2741 dbus_message_iter_next(&sub);
2750 if (generic_print_property(name, iter, arg_all) > 0)
2754 printf("%s=[unprintable]\n", name);
2759 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2760 DBusMessage *reply = NULL;
2761 const char *interface = "";
2763 DBusMessageIter iter, sub, sub2, sub3;
2764 UnitStatusInfo info;
2772 r = bus_method_call_with_reply (
2774 "org.freedesktop.systemd1",
2776 "org.freedesktop.DBus.Properties",
2780 DBUS_TYPE_STRING, &interface,
2785 if (!dbus_message_iter_init(reply, &iter) ||
2786 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2787 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2788 log_error("Failed to parse reply.");
2793 dbus_message_iter_recurse(&iter, &sub);
2800 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2803 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2804 log_error("Failed to parse reply.");
2809 dbus_message_iter_recurse(&sub, &sub2);
2811 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2812 log_error("Failed to parse reply.");
2817 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2818 log_error("Failed to parse reply.");
2823 dbus_message_iter_recurse(&sub2, &sub3);
2825 if (show_properties)
2826 r = print_property(name, &sub3);
2828 r = status_property(name, &sub3, &info);
2831 log_error("Failed to parse reply.");
2836 dbus_message_iter_next(&sub);
2841 if (!show_properties) {
2842 if (streq(verb, "help"))
2843 show_unit_help(&info);
2845 print_status_info(&info);
2848 strv_free(info.documentation);
2850 if (!streq_ptr(info.active_state, "active") &&
2851 !streq_ptr(info.active_state, "reloading") &&
2852 streq(verb, "status"))
2853 /* According to LSB: "program not running" */
2856 while ((p = info.exec)) {
2857 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2858 exec_status_info_free(p);
2863 dbus_message_unref(reply);
2868 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
2869 DBusMessage *reply = NULL;
2870 const char *path = NULL;
2874 dbus_error_init(&error);
2876 r = bus_method_call_with_reply (
2878 "org.freedesktop.systemd1",
2879 "/org/freedesktop/systemd1",
2880 "org.freedesktop.systemd1.Manager",
2884 DBUS_TYPE_UINT32, &pid,
2889 if (!dbus_message_get_args(reply, &error,
2890 DBUS_TYPE_OBJECT_PATH, &path,
2891 DBUS_TYPE_INVALID)) {
2892 log_error("Failed to parse reply: %s", bus_error_message(&error));
2897 r = show_one(verb, bus, path, false, new_line);
2901 dbus_message_unref(reply);
2903 dbus_error_free(&error);
2908 static int show(DBusConnection *bus, char **args) {
2910 bool show_properties, new_line = false;
2916 show_properties = streq(args[0], "show");
2918 if (show_properties)
2919 pager_open_if_enabled();
2921 if (show_properties && strv_length(args) <= 1) {
2922 /* If not argument is specified inspect the manager
2925 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2928 STRV_FOREACH(name, args+1) {
2931 if (safe_atou32(*name, &id) < 0) {
2933 /* Interpret as unit name */
2935 n = unit_name_mangle(*name);
2936 p = unit_dbus_path_from_name(n ? n : *name);
2941 r = show_one(args[0], bus, p, show_properties, &new_line);
2947 } else if (show_properties) {
2949 /* Interpret as job id */
2952 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
2955 r = show_one(args[0], bus, p, show_properties, &new_line);
2963 /* Interpret as PID */
2965 r = show_one_by_pid(args[0], bus, id, &new_line);
2974 static int dump(DBusConnection *bus, char **args) {
2975 DBusMessage *reply = NULL;
2980 dbus_error_init(&error);
2982 pager_open_if_enabled();
2984 r = bus_method_call_with_reply (
2986 "org.freedesktop.systemd1",
2987 "/org/freedesktop/systemd1",
2988 "org.freedesktop.systemd1.Manager",
2996 if (!dbus_message_get_args(reply, &error,
2997 DBUS_TYPE_STRING, &text,
2998 DBUS_TYPE_INVALID)) {
2999 log_error("Failed to parse reply: %s", bus_error_message(&error));
3004 fputs(text, stdout);
3008 dbus_message_unref(reply);
3010 dbus_error_free(&error);
3015 static int snapshot(DBusConnection *bus, char **args) {
3016 DBusMessage *reply = NULL;
3019 dbus_bool_t cleanup = FALSE;
3020 DBusMessageIter iter, sub;
3022 *name = "", *path, *id,
3023 *interface = "org.freedesktop.systemd1.Unit",
3027 dbus_error_init(&error);
3029 if (strv_length(args) > 1)
3032 n = unit_name_mangle(name);
3033 r = bus_method_call_with_reply (
3035 "org.freedesktop.systemd1",
3036 "/org/freedesktop/systemd1",
3037 "org.freedesktop.systemd1.Manager",
3041 DBUS_TYPE_STRING, n ? (const char**) &n : &name,
3042 DBUS_TYPE_BOOLEAN, &cleanup,
3048 if (!dbus_message_get_args(reply, &error,
3049 DBUS_TYPE_OBJECT_PATH, &path,
3050 DBUS_TYPE_INVALID)) {
3051 log_error("Failed to parse reply: %s", bus_error_message(&error));
3056 dbus_message_unref(reply);
3057 r = bus_method_call_with_reply (
3059 "org.freedesktop.systemd1",
3061 "org.freedesktop.DBus.Properties",
3065 DBUS_TYPE_STRING, &interface,
3066 DBUS_TYPE_STRING, &property,
3071 if (!dbus_message_iter_init(reply, &iter) ||
3072 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3073 log_error("Failed to parse reply.");
3078 dbus_message_iter_recurse(&iter, &sub);
3080 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3081 log_error("Failed to parse reply.");
3086 dbus_message_iter_get_basic(&sub, &id);
3093 dbus_message_unref(reply);
3095 dbus_error_free(&error);
3100 static int delete_snapshot(DBusConnection *bus, char **args) {
3101 DBusMessage *reply = NULL;
3108 dbus_error_init(&error);
3110 STRV_FOREACH(name, args+1) {
3111 const char *path = NULL;
3114 n = unit_name_mangle(*name);
3115 r = bus_method_call_with_reply (
3117 "org.freedesktop.systemd1",
3118 "/org/freedesktop/systemd1",
3119 "org.freedesktop.systemd1.Manager",
3123 DBUS_TYPE_STRING, n ? &n : name,
3129 if (!dbus_message_get_args(reply, &error,
3130 DBUS_TYPE_OBJECT_PATH, &path,
3131 DBUS_TYPE_INVALID)) {
3132 log_error("Failed to parse reply: %s", bus_error_message(&error));
3134 dbus_message_unref(reply);
3135 dbus_error_free(&error);
3138 dbus_message_unref(reply);
3140 r = bus_method_call_with_reply (
3142 "org.freedesktop.systemd1",
3144 "org.freedesktop.systemd1.Snapshot",
3157 static int daemon_reload(DBusConnection *bus, char **args) {
3162 if (arg_action == ACTION_RELOAD)
3164 else if (arg_action == ACTION_REEXEC)
3165 method = "Reexecute";
3167 assert(arg_action == ACTION_SYSTEMCTL);
3170 streq(args[0], "clear-jobs") ||
3171 streq(args[0], "cancel") ? "ClearJobs" :
3172 streq(args[0], "daemon-reexec") ? "Reexecute" :
3173 streq(args[0], "reset-failed") ? "ResetFailed" :
3174 streq(args[0], "halt") ? "Halt" :
3175 streq(args[0], "poweroff") ? "PowerOff" :
3176 streq(args[0], "reboot") ? "Reboot" :
3177 streq(args[0], "kexec") ? "KExec" :
3178 streq(args[0], "exit") ? "Exit" :
3179 /* "daemon-reload" */ "Reload";
3182 r = bus_method_call_with_reply (
3184 "org.freedesktop.systemd1",
3185 "/org/freedesktop/systemd1",
3186 "org.freedesktop.systemd1.Manager",
3192 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3193 /* There's always a fallback possible for
3194 * legacy actions. */
3196 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3197 /* On reexecution, we expect a disconnect, not
3201 log_error("Failed to issue method call: %s", bus_error_message(&error));
3202 dbus_error_free(&error);
3207 static int reset_failed(DBusConnection *bus, char **args) {
3211 if (strv_length(args) <= 1)
3212 return daemon_reload(bus, args);
3214 STRV_FOREACH(name, args+1) {
3215 n = unit_name_mangle(*name);
3216 r = bus_method_call_with_reply (
3218 "org.freedesktop.systemd1",
3219 "/org/freedesktop/systemd1",
3220 "org.freedesktop.systemd1.Manager",
3224 DBUS_TYPE_STRING, n ? &n : name,
3235 static int show_enviroment(DBusConnection *bus, char **args) {
3236 DBusMessage *reply = NULL;
3237 DBusMessageIter iter, sub, sub2;
3240 *interface = "org.freedesktop.systemd1.Manager",
3241 *property = "Environment";
3243 pager_open_if_enabled();
3245 r = bus_method_call_with_reply (
3247 "org.freedesktop.systemd1",
3248 "/org/freedesktop/systemd1",
3249 "org.freedesktop.DBus.Properties",
3253 DBUS_TYPE_STRING, &interface,
3254 DBUS_TYPE_STRING, &property,
3259 if (!dbus_message_iter_init(reply, &iter) ||
3260 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3261 log_error("Failed to parse reply.");
3266 dbus_message_iter_recurse(&iter, &sub);
3268 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3269 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3270 log_error("Failed to parse reply.");
3275 dbus_message_iter_recurse(&sub, &sub2);
3277 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3280 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3281 log_error("Failed to parse reply.");
3286 dbus_message_iter_get_basic(&sub2, &text);
3287 printf("%s\n", text);
3289 dbus_message_iter_next(&sub2);
3296 dbus_message_unref(reply);
3301 static int switch_root(DBusConnection *bus, char **args) {
3303 const char *root, *init;
3305 l = strv_length(args);
3306 if (l < 2 || l > 3) {
3307 log_error("Wrong number of arguments.");
3312 init = l >= 3 ? args[2] : "";
3314 return bus_method_call_with_reply (
3316 "org.freedesktop.systemd1",
3317 "/org/freedesktop/systemd1",
3318 "org.freedesktop.systemd1.Manager",
3322 DBUS_TYPE_STRING, &root,
3323 DBUS_TYPE_STRING, &init,
3327 static int set_environment(DBusConnection *bus, char **args) {
3328 DBusMessage *m = NULL, *reply = NULL;
3332 DBusMessageIter iter, sub;
3335 dbus_error_init(&error);
3337 method = streq(args[0], "set-environment")
3339 : "UnsetEnvironment";
3341 if (!(m = dbus_message_new_method_call(
3342 "org.freedesktop.systemd1",
3343 "/org/freedesktop/systemd1",
3344 "org.freedesktop.systemd1.Manager",
3347 log_error("Could not allocate message.");
3351 dbus_message_iter_init_append(m, &iter);
3353 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
3354 log_error("Could not append arguments to message.");
3359 STRV_FOREACH(name, args+1)
3360 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, name)) {
3361 log_error("Could not append arguments to message.");
3366 if (!dbus_message_iter_close_container(&iter, &sub)) {
3367 log_error("Could not append arguments to message.");
3372 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3373 log_error("Failed to issue method call: %s", bus_error_message(&error));
3382 dbus_message_unref(m);
3385 dbus_message_unref(reply);
3387 dbus_error_free(&error);
3392 static int enable_sysv_units(char **args) {
3395 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3396 const char *verb = args[0];
3397 unsigned f = 1, t = 1;
3400 if (arg_scope != UNIT_FILE_SYSTEM)
3403 if (!streq(verb, "enable") &&
3404 !streq(verb, "disable") &&
3405 !streq(verb, "is-enabled"))
3408 /* Processes all SysV units, and reshuffles the array so that
3409 * afterwards only the native units remain */
3412 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3417 for (f = 1; args[f]; f++) {
3420 bool found_native = false, found_sysv;
3422 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3423 char **k, *l, *q = NULL;
3430 if (!endswith(name, ".service"))
3433 if (path_is_absolute(name))
3436 STRV_FOREACH(k, paths.unit_path) {
3439 if (!isempty(arg_root))
3440 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3442 asprintf(&p, "%s/%s", *k, name);
3449 found_native = access(p, F_OK) >= 0;
3460 if (!isempty(arg_root))
3461 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3463 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3469 p[strlen(p) - sizeof(".service") + 1] = 0;
3470 found_sysv = access(p, F_OK) >= 0;
3477 /* Mark this entry, so that we don't try enabling it as native unit */
3478 args[f] = (char*) "";
3480 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3482 if (!isempty(arg_root))
3483 argv[c++] = q = strappend("--root=", arg_root);
3485 argv[c++] = path_get_file_name(p);
3487 streq(verb, "enable") ? "on" :
3488 streq(verb, "disable") ? "off" : "--level=5";
3491 l = strv_join((char**)argv, " ");
3499 log_info("Executing %s", l);
3504 log_error("Failed to fork: %m");
3509 } else if (pid == 0) {
3512 execv(argv[0], (char**) argv);
3513 _exit(EXIT_FAILURE);
3519 j = wait_for_terminate(pid, &status);
3521 log_error("Failed to wait for child: %s", strerror(-r));
3526 if (status.si_code == CLD_EXITED) {
3527 if (streq(verb, "is-enabled")) {
3528 if (status.si_status == 0) {
3537 } else if (status.si_status != 0) {
3548 lookup_paths_free(&paths);
3550 /* Drop all SysV units */
3551 for (f = 1, t = 1; args[f]; f++) {
3553 if (isempty(args[f]))
3556 args[t++] = args[f];
3565 static int mangle_names(char **original_names, char ***mangled_names) {
3566 char **i, **l, **name;
3568 l = new(char*, strv_length(original_names) + 1);
3573 STRV_FOREACH(name, original_names) {
3574 *i = unit_name_mangle(*name);
3589 static int enable_unit(DBusConnection *bus, char **args) {
3590 const char *verb = args[0];
3591 UnitFileChange *changes = NULL;
3592 unsigned n_changes = 0, i;
3593 int carries_install_info = -1;
3594 DBusMessage *m = NULL, *reply = NULL;
3597 char **mangled_names = NULL;
3599 r = enable_sysv_units(args);
3606 dbus_error_init(&error);
3608 if (!bus || avoid_bus()) {
3609 if (streq(verb, "enable")) {
3610 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3611 carries_install_info = r;
3612 } else if (streq(verb, "disable"))
3613 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3614 else if (streq(verb, "reenable")) {
3615 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3616 carries_install_info = r;
3617 } else if (streq(verb, "link"))
3618 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3619 else if (streq(verb, "preset")) {
3620 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3621 carries_install_info = r;
3622 } else if (streq(verb, "mask"))
3623 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3624 else if (streq(verb, "unmask"))
3625 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3627 assert_not_reached("Unknown verb");
3630 log_error("Operation failed: %s", strerror(-r));
3635 for (i = 0; i < n_changes; i++) {
3636 if (changes[i].type == UNIT_FILE_SYMLINK)
3637 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3639 log_info("rm '%s'", changes[i].path);
3645 bool send_force = true, expect_carries_install_info = false;
3647 DBusMessageIter iter, sub, sub2;
3649 if (streq(verb, "enable")) {
3650 method = "EnableUnitFiles";
3651 expect_carries_install_info = true;
3652 } else if (streq(verb, "disable")) {
3653 method = "DisableUnitFiles";
3655 } else if (streq(verb, "reenable")) {
3656 method = "ReenableUnitFiles";
3657 expect_carries_install_info = true;
3658 } else if (streq(verb, "link"))
3659 method = "LinkUnitFiles";
3660 else if (streq(verb, "preset")) {
3661 method = "PresetUnitFiles";
3662 expect_carries_install_info = true;
3663 } else if (streq(verb, "mask"))
3664 method = "MaskUnitFiles";
3665 else if (streq(verb, "unmask")) {
3666 method = "UnmaskUnitFiles";
3669 assert_not_reached("Unknown verb");
3671 m = dbus_message_new_method_call(
3672 "org.freedesktop.systemd1",
3673 "/org/freedesktop/systemd1",
3674 "org.freedesktop.systemd1.Manager",
3681 dbus_message_iter_init_append(m, &iter);
3683 r = mangle_names(args+1, &mangled_names);
3687 r = bus_append_strv_iter(&iter, mangled_names);
3689 log_error("Failed to append unit files.");
3694 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3695 log_error("Failed to append runtime boolean.");
3703 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3704 log_error("Failed to append force boolean.");
3710 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3712 log_error("Failed to issue method call: %s", bus_error_message(&error));
3717 if (!dbus_message_iter_init(reply, &iter)) {
3718 log_error("Failed to initialize iterator.");
3722 if (expect_carries_install_info) {
3723 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3725 log_error("Failed to parse reply.");
3729 carries_install_info = b;
3732 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3733 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3734 log_error("Failed to parse reply.");
3739 dbus_message_iter_recurse(&iter, &sub);
3740 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3741 const char *type, *path, *source;
3743 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3744 log_error("Failed to parse reply.");
3749 dbus_message_iter_recurse(&sub, &sub2);
3751 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3752 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3753 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3754 log_error("Failed to parse reply.");
3760 if (streq(type, "symlink"))
3761 log_info("ln -s '%s' '%s'", source, path);
3763 log_info("rm '%s'", path);
3766 dbus_message_iter_next(&sub);
3769 /* Try to reload if enabeld */
3771 r = daemon_reload(bus, args);
3774 if (carries_install_info == 0)
3775 log_warning("The unit files have no [Install] section. They are not meant to be enabled using systemctl.");
3779 dbus_message_unref(m);
3782 dbus_message_unref(reply);
3784 unit_file_changes_free(changes, n_changes);
3786 dbus_error_free(&error);
3788 strv_free(mangled_names);
3793 static int unit_is_enabled(DBusConnection *bus, char **args) {
3796 DBusMessage *reply = NULL;
3800 dbus_error_init(&error);
3802 r = enable_sysv_units(args);
3808 if (!bus || avoid_bus()) {
3810 STRV_FOREACH(name, args+1) {
3811 UnitFileState state;
3813 state = unit_file_get_state(arg_scope, arg_root, *name);
3819 if (state == UNIT_FILE_ENABLED ||
3820 state == UNIT_FILE_ENABLED_RUNTIME ||
3821 state == UNIT_FILE_STATIC)
3825 puts(unit_file_state_to_string(state));
3829 STRV_FOREACH(name, args+1) {
3832 r = bus_method_call_with_reply (
3834 "org.freedesktop.systemd1",
3835 "/org/freedesktop/systemd1",
3836 "org.freedesktop.systemd1.Manager",
3840 DBUS_TYPE_STRING, name,
3845 if (!dbus_message_get_args(reply, &error,
3846 DBUS_TYPE_STRING, &s,
3847 DBUS_TYPE_INVALID)) {
3848 log_error("Failed to parse reply: %s", bus_error_message(&error));
3853 dbus_message_unref(reply);
3856 if (streq(s, "enabled") ||
3857 streq(s, "enabled-runtime") ||
3866 r = enabled ? 0 : 1;
3870 dbus_message_unref(reply);
3872 dbus_error_free(&error);
3876 static int systemctl_help(void) {
3878 pager_open_if_enabled();
3880 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
3881 "Query or send control commands to the systemd manager.\n\n"
3882 " -h --help Show this help\n"
3883 " --version Show package version\n"
3884 " -t --type=TYPE List only units of a particular type\n"
3885 " -p --property=NAME Show only properties by this name\n"
3886 " -a --all Show all units/properties, including dead/empty ones\n"
3887 " --failed Show only failed units\n"
3888 " --full Don't ellipsize unit names on output\n"
3889 " --fail When queueing a new job, fail if conflicting jobs are\n"
3891 " --ignore-dependencies\n"
3892 " When queueing a new job, ignore all its dependencies\n"
3893 " --kill-who=WHO Who to send signal to\n"
3894 " -s --signal=SIGNAL Which signal to send\n"
3895 " -H --host=[USER@]HOST\n"
3896 " Show information for remote host\n"
3897 " -P --privileged Acquire privileges before execution\n"
3898 " -q --quiet Suppress output\n"
3899 " --no-block Do not wait until operation finished\n"
3900 " --no-wall Don't send wall message before halt/power-off/reboot\n"
3901 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
3903 " --no-legend Do not print a legend (column headers and hints)\n"
3904 " --no-pager Do not pipe output into a pager\n"
3905 " --no-ask-password\n"
3906 " Do not ask for system passwords\n"
3907 " --order When generating graph for dot, show only order\n"
3908 " --require When generating graph for dot, show only requirement\n"
3909 " --system Connect to system manager\n"
3910 " --user Connect to user service manager\n"
3911 " --global Enable/disable unit files globally\n"
3912 " -f --force When enabling unit files, override existing symlinks\n"
3913 " When shutting down, execute action immediately\n"
3914 " --root=PATH Enable unit files in the specified root directory\n"
3915 " --runtime Enable unit files only temporarily until next reboot\n"
3916 " -n --lines=INTEGER Journal entries to show\n"
3917 " --follow Follow journal\n"
3918 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
3919 " verbose, export, json, json-pretty, cat)\n\n"
3921 " list-units List loaded units\n"
3922 " start [NAME...] Start (activate) one or more units\n"
3923 " stop [NAME...] Stop (deactivate) one or more units\n"
3924 " reload [NAME...] Reload one or more units\n"
3925 " restart [NAME...] Start or restart one or more units\n"
3926 " try-restart [NAME...] Restart one or more units if active\n"
3927 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
3928 " otherwise start or restart\n"
3929 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
3930 " otherwise restart if active\n"
3931 " isolate [NAME] Start one unit and stop all others\n"
3932 " kill [NAME...] Send signal to processes of a unit\n"
3933 " is-active [NAME...] Check whether units are active\n"
3934 " status [NAME...|PID...] Show runtime status of one or more units\n"
3935 " show [NAME...|JOB...] Show properties of one or more\n"
3936 " units/jobs or the manager\n"
3937 " help [NAME...|PID...] Show manual for one or more units\n"
3938 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
3940 " load [NAME...] Load one or more units\n\n"
3941 "Unit File Commands:\n"
3942 " list-unit-files List installed unit files\n"
3943 " enable [NAME...] Enable one or more unit files\n"
3944 " disable [NAME...] Disable one or more unit files\n"
3945 " reenable [NAME...] Reenable one or more unit files\n"
3946 " preset [NAME...] Enable/disable one or more unit files\n"
3947 " based on preset configuration\n"
3948 " mask [NAME...] Mask one or more units\n"
3949 " unmask [NAME...] Unmask one or more units\n"
3950 " link [PATH...] Link one or more units files into\n"
3951 " the search path\n"
3952 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
3954 " list-jobs List jobs\n"
3955 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
3956 "Status Commands:\n"
3957 " dump Dump server status\n"
3958 " dot Dump dependency graph for dot(1)\n\n"
3959 "Snapshot Commands:\n"
3960 " snapshot [NAME] Create a snapshot\n"
3961 " delete [NAME...] Remove one or more snapshots\n\n"
3962 "Environment Commands:\n"
3963 " show-environment Dump environment\n"
3964 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
3965 " unset-environment [NAME...] Unset one or more environment variables\n\n"
3966 "Manager Lifecycle Commands:\n"
3967 " daemon-reload Reload systemd manager configuration\n"
3968 " daemon-reexec Reexecute systemd manager\n\n"
3969 "System Commands:\n"
3970 " default Enter system default mode\n"
3971 " rescue Enter system rescue mode\n"
3972 " emergency Enter system emergency mode\n"
3973 " halt Shut down and halt the system\n"
3974 " poweroff Shut down and power-off the system\n"
3975 " reboot Shut down and reboot the system\n"
3976 " kexec Shut down and reboot the system with kexec\n"
3977 " exit Request user instance exit\n"
3978 " switch-root [ROOT] [INIT] Change to a different root file system\n"
3979 " suspend Suspend the system\n"
3980 " hibernate Hibernate the system\n",
3981 program_invocation_short_name);
3986 static int halt_help(void) {
3988 printf("%s [OPTIONS...]\n\n"
3989 "%s the system.\n\n"
3990 " --help Show this help\n"
3991 " --halt Halt the machine\n"
3992 " -p --poweroff Switch off the machine\n"
3993 " --reboot Reboot the machine\n"
3994 " -f --force Force immediate halt/power-off/reboot\n"
3995 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
3996 " -d --no-wtmp Don't write wtmp record\n"
3997 " --no-wall Don't send wall message before halt/power-off/reboot\n",
3998 program_invocation_short_name,
3999 arg_action == ACTION_REBOOT ? "Reboot" :
4000 arg_action == ACTION_POWEROFF ? "Power off" :
4006 static int shutdown_help(void) {
4008 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4009 "Shut down the system.\n\n"
4010 " --help Show this help\n"
4011 " -H --halt Halt the machine\n"
4012 " -P --poweroff Power-off the machine\n"
4013 " -r --reboot Reboot the machine\n"
4014 " -h Equivalent to --poweroff, overridden by --halt\n"
4015 " -k Don't halt/power-off/reboot, just send warnings\n"
4016 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4017 " -c Cancel a pending shutdown\n",
4018 program_invocation_short_name);
4023 static int telinit_help(void) {
4025 printf("%s [OPTIONS...] {COMMAND}\n\n"
4026 "Send control commands to the init daemon.\n\n"
4027 " --help Show this help\n"
4028 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4030 " 0 Power-off the machine\n"
4031 " 6 Reboot the machine\n"
4032 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4033 " 1, s, S Enter rescue mode\n"
4034 " q, Q Reload init daemon configuration\n"
4035 " u, U Reexecute init daemon\n",
4036 program_invocation_short_name);
4041 static int runlevel_help(void) {
4043 printf("%s [OPTIONS...]\n\n"
4044 "Prints the previous and current runlevel of the init system.\n\n"
4045 " --help Show this help\n",
4046 program_invocation_short_name);
4051 static int systemctl_parse_argv(int argc, char *argv[]) {
4055 ARG_IGNORE_DEPENDENCIES,
4070 ARG_NO_ASK_PASSWORD,
4077 static const struct option options[] = {
4078 { "help", no_argument, NULL, 'h' },
4079 { "version", no_argument, NULL, ARG_VERSION },
4080 { "type", required_argument, NULL, 't' },
4081 { "property", required_argument, NULL, 'p' },
4082 { "all", no_argument, NULL, 'a' },
4083 { "failed", no_argument, NULL, ARG_FAILED },
4084 { "full", no_argument, NULL, ARG_FULL },
4085 { "fail", no_argument, NULL, ARG_FAIL },
4086 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4087 { "user", no_argument, NULL, ARG_USER },
4088 { "system", no_argument, NULL, ARG_SYSTEM },
4089 { "global", no_argument, NULL, ARG_GLOBAL },
4090 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4091 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4092 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4093 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4094 { "quiet", no_argument, NULL, 'q' },
4095 { "order", no_argument, NULL, ARG_ORDER },
4096 { "require", no_argument, NULL, ARG_REQUIRE },
4097 { "root", required_argument, NULL, ARG_ROOT },
4098 { "force", no_argument, NULL, ARG_FORCE },
4099 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4100 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4101 { "signal", required_argument, NULL, 's' },
4102 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4103 { "host", required_argument, NULL, 'H' },
4104 { "privileged",no_argument, NULL, 'P' },
4105 { "runtime", no_argument, NULL, ARG_RUNTIME },
4106 { "lines", required_argument, NULL, 'n' },
4107 { "follow", no_argument, NULL, ARG_FOLLOW },
4108 { "output", required_argument, NULL, 'o' },
4109 { NULL, 0, NULL, 0 }
4117 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4126 puts(PACKAGE_STRING);
4128 puts(SYSTEMD_FEATURES);
4132 if (unit_type_from_string(optarg) >= 0) {
4136 if (unit_load_state_from_string(optarg) >= 0) {
4137 arg_load_state = optarg;
4140 log_error("Unkown unit type or load state '%s'.",
4146 if (!(l = strv_append(arg_property, optarg)))
4149 strv_free(arg_property);
4152 /* If the user asked for a particular
4153 * property, show it to him, even if it is
4164 arg_job_mode = "fail";
4167 case ARG_IGNORE_DEPENDENCIES:
4168 arg_job_mode = "ignore-dependencies";
4172 arg_scope = UNIT_FILE_USER;
4176 arg_scope = UNIT_FILE_SYSTEM;
4180 arg_scope = UNIT_FILE_GLOBAL;
4184 arg_no_block = true;
4188 arg_no_legend = true;
4192 arg_no_pager = true;
4200 arg_dot = DOT_ORDER;
4204 arg_dot = DOT_REQUIRE;
4232 /* -f is short for both --follow and --force! */
4238 arg_no_reload = true;
4242 arg_kill_who = optarg;
4246 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4247 log_error("Failed to parse signal string %s.", optarg);
4252 case ARG_NO_ASK_PASSWORD:
4253 arg_ask_password = false;
4257 arg_transport = TRANSPORT_POLKIT;
4261 arg_transport = TRANSPORT_SSH;
4270 if (safe_atou(optarg, &arg_lines) < 0) {
4271 log_error("Failed to parse lines '%s'", optarg);
4277 arg_output = output_mode_from_string(optarg);
4278 if (arg_output < 0) {
4279 log_error("Unknown output '%s'.", optarg);
4288 log_error("Unknown option code '%c'.", c);
4293 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4294 log_error("Cannot access user instance remotely.");
4301 static int halt_parse_argv(int argc, char *argv[]) {
4310 static const struct option options[] = {
4311 { "help", no_argument, NULL, ARG_HELP },
4312 { "halt", no_argument, NULL, ARG_HALT },
4313 { "poweroff", no_argument, NULL, 'p' },
4314 { "reboot", no_argument, NULL, ARG_REBOOT },
4315 { "force", no_argument, NULL, 'f' },
4316 { "wtmp-only", no_argument, NULL, 'w' },
4317 { "no-wtmp", no_argument, NULL, 'd' },
4318 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4319 { NULL, 0, NULL, 0 }
4327 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4328 if (runlevel == '0' || runlevel == '6')
4331 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4339 arg_action = ACTION_HALT;
4343 if (arg_action != ACTION_REBOOT)
4344 arg_action = ACTION_POWEROFF;
4348 arg_action = ACTION_REBOOT;
4370 /* Compatibility nops */
4377 log_error("Unknown option code '%c'.", c);
4382 if (optind < argc) {
4383 log_error("Too many arguments.");
4390 static int parse_time_spec(const char *t, usec_t *_u) {
4394 if (streq(t, "now"))
4396 else if (!strchr(t, ':')) {
4399 if (safe_atou64(t, &u) < 0)
4402 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4411 hour = strtol(t, &e, 10);
4412 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4415 minute = strtol(e+1, &e, 10);
4416 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4419 n = now(CLOCK_REALTIME);
4420 s = (time_t) (n / USEC_PER_SEC);
4423 assert_se(localtime_r(&s, &tm));
4425 tm.tm_hour = (int) hour;
4426 tm.tm_min = (int) minute;
4429 assert_se(s = mktime(&tm));
4431 *_u = (usec_t) s * USEC_PER_SEC;
4434 *_u += USEC_PER_DAY;
4440 static int shutdown_parse_argv(int argc, char *argv[]) {
4447 static const struct option options[] = {
4448 { "help", no_argument, NULL, ARG_HELP },
4449 { "halt", no_argument, NULL, 'H' },
4450 { "poweroff", no_argument, NULL, 'P' },
4451 { "reboot", no_argument, NULL, 'r' },
4452 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4453 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4454 { NULL, 0, NULL, 0 }
4462 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4470 arg_action = ACTION_HALT;
4474 arg_action = ACTION_POWEROFF;
4479 arg_action = ACTION_KEXEC;
4481 arg_action = ACTION_REBOOT;
4485 arg_action = ACTION_KEXEC;
4489 if (arg_action != ACTION_HALT)
4490 arg_action = ACTION_POWEROFF;
4503 /* Compatibility nops */
4507 arg_action = ACTION_CANCEL_SHUTDOWN;
4514 log_error("Unknown option code '%c'.", c);
4519 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4520 r = parse_time_spec(argv[optind], &arg_when);
4522 log_error("Failed to parse time specification: %s", argv[optind]);
4526 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4528 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4529 /* No time argument for shutdown cancel */
4530 arg_wall = argv + optind;
4531 else if (argc > optind + 1)
4532 /* We skip the time argument */
4533 arg_wall = argv + optind + 1;
4540 static int telinit_parse_argv(int argc, char *argv[]) {
4547 static const struct option options[] = {
4548 { "help", no_argument, NULL, ARG_HELP },
4549 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4550 { NULL, 0, NULL, 0 }
4553 static const struct {
4557 { '0', ACTION_POWEROFF },
4558 { '6', ACTION_REBOOT },
4559 { '1', ACTION_RESCUE },
4560 { '2', ACTION_RUNLEVEL2 },
4561 { '3', ACTION_RUNLEVEL3 },
4562 { '4', ACTION_RUNLEVEL4 },
4563 { '5', ACTION_RUNLEVEL5 },
4564 { 's', ACTION_RESCUE },
4565 { 'S', ACTION_RESCUE },
4566 { 'q', ACTION_RELOAD },
4567 { 'Q', ACTION_RELOAD },
4568 { 'u', ACTION_REEXEC },
4569 { 'U', ACTION_REEXEC }
4578 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4593 log_error("Unknown option code '%c'.", c);
4598 if (optind >= argc) {
4603 if (optind + 1 < argc) {
4604 log_error("Too many arguments.");
4608 if (strlen(argv[optind]) != 1) {
4609 log_error("Expected single character argument.");
4613 for (i = 0; i < ELEMENTSOF(table); i++)
4614 if (table[i].from == argv[optind][0])
4617 if (i >= ELEMENTSOF(table)) {
4618 log_error("Unknown command '%s'.", argv[optind]);
4622 arg_action = table[i].to;
4629 static int runlevel_parse_argv(int argc, char *argv[]) {
4635 static const struct option options[] = {
4636 { "help", no_argument, NULL, ARG_HELP },
4637 { NULL, 0, NULL, 0 }
4645 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4656 log_error("Unknown option code '%c'.", c);
4661 if (optind < argc) {
4662 log_error("Too many arguments.");
4669 static int parse_argv(int argc, char *argv[]) {
4673 if (program_invocation_short_name) {
4675 if (strstr(program_invocation_short_name, "halt")) {
4676 arg_action = ACTION_HALT;
4677 return halt_parse_argv(argc, argv);
4678 } else if (strstr(program_invocation_short_name, "poweroff")) {
4679 arg_action = ACTION_POWEROFF;
4680 return halt_parse_argv(argc, argv);
4681 } else if (strstr(program_invocation_short_name, "reboot")) {
4683 arg_action = ACTION_KEXEC;
4685 arg_action = ACTION_REBOOT;
4686 return halt_parse_argv(argc, argv);
4687 } else if (strstr(program_invocation_short_name, "shutdown")) {
4688 arg_action = ACTION_POWEROFF;
4689 return shutdown_parse_argv(argc, argv);
4690 } else if (strstr(program_invocation_short_name, "init")) {
4692 if (sd_booted() > 0) {
4693 arg_action = ACTION_INVALID;
4694 return telinit_parse_argv(argc, argv);
4696 /* Hmm, so some other init system is
4697 * running, we need to forward this
4698 * request to it. For now we simply
4699 * guess that it is Upstart. */
4701 execv("/lib/upstart/telinit", argv);
4703 log_error("Couldn't find an alternative telinit implementation to spawn.");
4707 } else if (strstr(program_invocation_short_name, "runlevel")) {
4708 arg_action = ACTION_RUNLEVEL;
4709 return runlevel_parse_argv(argc, argv);
4713 arg_action = ACTION_SYSTEMCTL;
4714 return systemctl_parse_argv(argc, argv);
4717 static int action_to_runlevel(void) {
4719 static const char table[_ACTION_MAX] = {
4720 [ACTION_HALT] = '0',
4721 [ACTION_POWEROFF] = '0',
4722 [ACTION_REBOOT] = '6',
4723 [ACTION_RUNLEVEL2] = '2',
4724 [ACTION_RUNLEVEL3] = '3',
4725 [ACTION_RUNLEVEL4] = '4',
4726 [ACTION_RUNLEVEL5] = '5',
4727 [ACTION_RESCUE] = '1'
4730 assert(arg_action < _ACTION_MAX);
4732 return table[arg_action];
4735 static int talk_upstart(void) {
4736 DBusMessage *m = NULL, *reply = NULL;
4738 int previous, rl, r;
4740 env1_buf[] = "RUNLEVEL=X",
4741 env2_buf[] = "PREVLEVEL=X";
4742 char *env1 = env1_buf, *env2 = env2_buf;
4743 const char *emit = "runlevel";
4744 dbus_bool_t b_false = FALSE;
4745 DBusMessageIter iter, sub;
4746 DBusConnection *bus;
4748 dbus_error_init(&error);
4750 if (!(rl = action_to_runlevel()))
4753 if (utmp_get_runlevel(&previous, NULL) < 0)
4756 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4757 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4762 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4767 if ((r = bus_check_peercred(bus)) < 0) {
4768 log_error("Failed to verify owner of bus.");
4772 if (!(m = dbus_message_new_method_call(
4773 "com.ubuntu.Upstart",
4774 "/com/ubuntu/Upstart",
4775 "com.ubuntu.Upstart0_6",
4778 log_error("Could not allocate message.");
4783 dbus_message_iter_init_append(m, &iter);
4785 env1_buf[sizeof(env1_buf)-2] = rl;
4786 env2_buf[sizeof(env2_buf)-2] = previous;
4788 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4789 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4790 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4791 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4792 !dbus_message_iter_close_container(&iter, &sub) ||
4793 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4794 log_error("Could not append arguments to message.");
4799 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4801 if (bus_error_is_no_service(&error)) {
4806 log_error("Failed to issue method call: %s", bus_error_message(&error));
4815 dbus_message_unref(m);
4818 dbus_message_unref(reply);
4821 dbus_connection_flush(bus);
4822 dbus_connection_close(bus);
4823 dbus_connection_unref(bus);
4826 dbus_error_free(&error);
4831 static int talk_initctl(void) {
4832 struct init_request request;
4836 if (!(rl = action_to_runlevel()))
4840 request.magic = INIT_MAGIC;
4841 request.sleeptime = 0;
4842 request.cmd = INIT_CMD_RUNLVL;
4843 request.runlevel = rl;
4845 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4847 if (errno == ENOENT)
4850 log_error("Failed to open "INIT_FIFO": %m");
4855 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
4856 close_nointr_nofail(fd);
4859 log_error("Failed to write to "INIT_FIFO": %m");
4860 return errno ? -errno : -EIO;
4866 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
4868 static const struct {
4876 int (* const dispatch)(DBusConnection *bus, char **args);
4878 { "list-units", LESS, 1, list_units },
4879 { "list-unit-files", EQUAL, 1, list_unit_files },
4880 { "list-jobs", EQUAL, 1, list_jobs },
4881 { "clear-jobs", EQUAL, 1, daemon_reload },
4882 { "load", MORE, 2, load_unit },
4883 { "cancel", MORE, 2, cancel_job },
4884 { "start", MORE, 2, start_unit },
4885 { "stop", MORE, 2, start_unit },
4886 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4887 { "reload", MORE, 2, start_unit },
4888 { "restart", MORE, 2, start_unit },
4889 { "try-restart", MORE, 2, start_unit },
4890 { "reload-or-restart", MORE, 2, start_unit },
4891 { "reload-or-try-restart", MORE, 2, start_unit },
4892 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
4893 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4894 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
4895 { "isolate", EQUAL, 2, start_unit },
4896 { "kill", MORE, 2, kill_unit },
4897 { "is-active", MORE, 2, check_unit },
4898 { "check", MORE, 2, check_unit },
4899 { "show", MORE, 1, show },
4900 { "status", MORE, 2, show },
4901 { "help", MORE, 2, show },
4902 { "dump", EQUAL, 1, dump },
4903 { "dot", EQUAL, 1, dot },
4904 { "snapshot", LESS, 2, snapshot },
4905 { "delete", MORE, 2, delete_snapshot },
4906 { "daemon-reload", EQUAL, 1, daemon_reload },
4907 { "daemon-reexec", EQUAL, 1, daemon_reload },
4908 { "show-environment", EQUAL, 1, show_enviroment },
4909 { "set-environment", MORE, 2, set_environment },
4910 { "unset-environment", MORE, 2, set_environment },
4911 { "halt", EQUAL, 1, start_special },
4912 { "poweroff", EQUAL, 1, start_special },
4913 { "reboot", EQUAL, 1, start_special },
4914 { "kexec", EQUAL, 1, start_special },
4915 { "suspend", EQUAL, 1, start_special },
4916 { "hibernate", EQUAL, 1, start_special },
4917 { "default", EQUAL, 1, start_special },
4918 { "rescue", EQUAL, 1, start_special },
4919 { "emergency", EQUAL, 1, start_special },
4920 { "exit", EQUAL, 1, start_special },
4921 { "reset-failed", MORE, 1, reset_failed },
4922 { "enable", MORE, 2, enable_unit },
4923 { "disable", MORE, 2, enable_unit },
4924 { "is-enabled", MORE, 2, unit_is_enabled },
4925 { "reenable", MORE, 2, enable_unit },
4926 { "preset", MORE, 2, enable_unit },
4927 { "mask", MORE, 2, enable_unit },
4928 { "unmask", MORE, 2, enable_unit },
4929 { "link", MORE, 2, enable_unit },
4930 { "switch-root", MORE, 2, switch_root },
4940 left = argc - optind;
4943 /* Special rule: no arguments means "list-units" */
4946 if (streq(argv[optind], "help") && !argv[optind+1]) {
4947 log_error("This command expects one or more "
4948 "unit names. Did you mean --help?");
4952 for (i = 0; i < ELEMENTSOF(verbs); i++)
4953 if (streq(argv[optind], verbs[i].verb))
4956 if (i >= ELEMENTSOF(verbs)) {
4957 log_error("Unknown operation '%s'.", argv[optind]);
4962 switch (verbs[i].argc_cmp) {
4965 if (left != verbs[i].argc) {
4966 log_error("Invalid number of arguments.");
4973 if (left < verbs[i].argc) {
4974 log_error("Too few arguments.");
4981 if (left > verbs[i].argc) {
4982 log_error("Too many arguments.");
4989 assert_not_reached("Unknown comparison operator.");
4992 /* Require a bus connection for all operations but
4994 if (!streq(verbs[i].verb, "enable") &&
4995 !streq(verbs[i].verb, "disable") &&
4996 !streq(verbs[i].verb, "is-enabled") &&
4997 !streq(verbs[i].verb, "list-unit-files") &&
4998 !streq(verbs[i].verb, "reenable") &&
4999 !streq(verbs[i].verb, "preset") &&
5000 !streq(verbs[i].verb, "mask") &&
5001 !streq(verbs[i].verb, "unmask") &&
5002 !streq(verbs[i].verb, "link")) {
5004 if (running_in_chroot() > 0) {
5005 log_info("Running in chroot, ignoring request.");
5009 if (((!streq(verbs[i].verb, "reboot") &&
5010 !streq(verbs[i].verb, "halt") &&
5011 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5012 log_error("Failed to get D-Bus connection: %s",
5013 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5019 if (!bus && !avoid_bus()) {
5020 log_error("Failed to get D-Bus connection: %s",
5021 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5026 return verbs[i].dispatch(bus, argv + optind);
5029 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5031 struct msghdr msghdr;
5032 struct iovec iovec[2];
5033 union sockaddr_union sockaddr;
5034 struct sd_shutdown_command c;
5036 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5043 c.dry_run = dry_run;
5047 sockaddr.sa.sa_family = AF_UNIX;
5048 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5051 msghdr.msg_name = &sockaddr;
5052 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5055 iovec[0].iov_base = (char*) &c;
5056 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5058 if (isempty(message))
5059 msghdr.msg_iovlen = 1;
5061 iovec[1].iov_base = (char*) message;
5062 iovec[1].iov_len = strlen(message);
5063 msghdr.msg_iovlen = 2;
5065 msghdr.msg_iov = iovec;
5067 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5068 close_nointr_nofail(fd);
5072 close_nointr_nofail(fd);
5076 static int reload_with_fallback(DBusConnection *bus) {
5079 /* First, try systemd via D-Bus. */
5080 if (daemon_reload(bus, NULL) >= 0)
5084 /* Nothing else worked, so let's try signals */
5085 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5087 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5088 log_error("kill() failed: %m");
5095 static int start_with_fallback(DBusConnection *bus) {
5098 /* First, try systemd via D-Bus. */
5099 if (start_unit(bus, NULL) >= 0)
5103 /* Hmm, talking to systemd via D-Bus didn't work. Then
5104 * let's try to talk to Upstart via D-Bus. */
5105 if (talk_upstart() > 0)
5108 /* Nothing else worked, so let's try
5110 if (talk_initctl() > 0)
5113 log_error("Failed to talk to init daemon.");
5117 warn_wall(arg_action);
5121 static _noreturn_ void halt_now(enum action a) {
5123 /* Make sure C-A-D is handled by the kernel from this
5125 reboot(RB_ENABLE_CAD);
5130 log_info("Halting.");
5131 reboot(RB_HALT_SYSTEM);
5134 case ACTION_POWEROFF:
5135 log_info("Powering off.");
5136 reboot(RB_POWER_OFF);
5140 log_info("Rebooting.");
5141 reboot(RB_AUTOBOOT);
5145 assert_not_reached("Unknown halt action.");
5148 assert_not_reached("Uh? This shouldn't happen.");
5151 static int halt_main(DBusConnection *bus) {
5154 if (geteuid() != 0) {
5155 /* Try logind if we are a normal user and no special
5156 * mode applies. Maybe PolicyKit allows us to shutdown
5159 if (arg_when <= 0 &&
5162 (arg_action == ACTION_POWEROFF ||
5163 arg_action == ACTION_REBOOT)) {
5164 r = reboot_with_logind(bus, arg_action);
5169 log_error("Must be root.");
5176 m = strv_join(arg_wall, " ");
5177 r = send_shutdownd(arg_when,
5178 arg_action == ACTION_HALT ? 'H' :
5179 arg_action == ACTION_POWEROFF ? 'P' :
5180 arg_action == ACTION_KEXEC ? 'K' :
5188 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5190 char date[FORMAT_TIMESTAMP_MAX];
5192 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5193 format_timestamp(date, sizeof(date), arg_when));
5198 if (!arg_dry && !arg_force)
5199 return start_with_fallback(bus);
5202 if (sd_booted() > 0)
5203 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5205 r = utmp_put_shutdown();
5207 log_warning("Failed to write utmp record: %s", strerror(-r));
5214 halt_now(arg_action);
5215 /* We should never reach this. */
5219 static int runlevel_main(void) {
5220 int r, runlevel, previous;
5222 r = utmp_get_runlevel(&runlevel, &previous);
5229 previous <= 0 ? 'N' : previous,
5230 runlevel <= 0 ? 'N' : runlevel);
5235 int main(int argc, char*argv[]) {
5236 int r, retval = EXIT_FAILURE;
5237 DBusConnection *bus = NULL;
5240 dbus_error_init(&error);
5242 log_parse_environment();
5245 r = parse_argv(argc, argv);
5249 retval = EXIT_SUCCESS;
5253 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5254 * let's shortcut this */
5255 if (arg_action == ACTION_RUNLEVEL) {
5256 r = runlevel_main();
5257 retval = r < 0 ? EXIT_FAILURE : r;
5261 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5262 log_info("Running in chroot, ignoring request.");
5268 if (arg_transport == TRANSPORT_NORMAL)
5269 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5270 else if (arg_transport == TRANSPORT_POLKIT) {
5271 bus_connect_system_polkit(&bus, &error);
5272 private_bus = false;
5273 } else if (arg_transport == TRANSPORT_SSH) {
5274 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5275 private_bus = false;
5277 assert_not_reached("Uh, invalid transport...");
5280 switch (arg_action) {
5282 case ACTION_SYSTEMCTL:
5283 r = systemctl_main(bus, argc, argv, &error);
5287 case ACTION_POWEROFF:
5293 case ACTION_RUNLEVEL2:
5294 case ACTION_RUNLEVEL3:
5295 case ACTION_RUNLEVEL4:
5296 case ACTION_RUNLEVEL5:
5298 case ACTION_EMERGENCY:
5299 case ACTION_DEFAULT:
5300 r = start_with_fallback(bus);
5305 r = reload_with_fallback(bus);
5308 case ACTION_CANCEL_SHUTDOWN: {
5312 m = strv_join(arg_wall, " ");
5314 retval = EXIT_FAILURE;
5318 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5320 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5325 case ACTION_INVALID:
5326 case ACTION_RUNLEVEL:
5328 assert_not_reached("Unknown action");
5331 retval = r < 0 ? EXIT_FAILURE : r;
5335 dbus_connection_flush(bus);
5336 dbus_connection_close(bus);
5337 dbus_connection_unref(bus);
5340 dbus_error_free(&error);
5344 strv_free(arg_property);
5347 ask_password_agent_close();
5348 polkit_agent_close();