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;
113 ACTION_CANCEL_SHUTDOWN,
115 } arg_action = ACTION_SYSTEMCTL;
121 static enum transport {
125 } arg_transport = TRANSPORT_NORMAL;
126 static const char *arg_host = NULL;
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 void pager_open_if_enabled(void) {
143 static void ask_password_agent_open_if_enabled(void) {
145 /* Open the password agent as a child process if necessary */
147 if (!arg_ask_password)
150 if (arg_scope != UNIT_FILE_SYSTEM)
153 ask_password_agent_open();
157 static void polkit_agent_open_if_enabled(void) {
159 /* Open the polkit agent as a child process if necessary */
161 if (!arg_ask_password)
164 if (arg_scope != UNIT_FILE_SYSTEM)
171 static const char *ansi_highlight(bool b) {
176 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
179 static const char *ansi_highlight_red(bool b) {
184 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
187 static const char *ansi_highlight_green(bool b) {
192 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
195 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
198 if (!dbus_error_is_set(error))
201 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
202 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
203 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
204 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
205 return EXIT_NOPERMISSION;
207 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
208 return EXIT_NOTINSTALLED;
210 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
211 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
212 return EXIT_NOTIMPLEMENTED;
214 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
215 return EXIT_NOTCONFIGURED;
223 static void warn_wall(enum action a) {
224 static const char *table[_ACTION_MAX] = {
225 [ACTION_HALT] = "The system is going down for system halt NOW!",
226 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
227 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
228 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
229 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
230 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
231 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
240 p = strv_join(arg_wall, " ");
242 log_error("Failed to join strings.");
258 utmp_wall(table[a], NULL);
261 static bool avoid_bus(void) {
263 if (running_in_chroot() > 0)
266 if (sd_booted() <= 0)
269 if (!isempty(arg_root))
272 if (arg_scope == UNIT_FILE_GLOBAL)
280 const char *description;
281 const char *load_state;
282 const char *active_state;
283 const char *sub_state;
284 const char *following;
285 const char *unit_path;
287 const char *job_type;
288 const char *job_path;
291 static int compare_unit_info(const void *a, const void *b) {
293 const struct unit_info *u = a, *v = b;
295 d1 = strrchr(u->id, '.');
296 d2 = strrchr(v->id, '.');
301 if ((r = strcasecmp(d1, d2)) != 0)
305 return strcasecmp(u->id, v->id);
308 static bool output_show_unit(const struct unit_info *u) {
312 return streq(u->active_state, "failed");
314 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
315 streq(dot+1, arg_type))) &&
316 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
317 (arg_all || !(streq(u->active_state, "inactive")
318 || u->following[0]) || u->job_id > 0);
321 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
322 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
323 const struct unit_info *u;
325 max_id_len = sizeof("UNIT")-1;
326 active_len = sizeof("ACTIVE")-1;
327 sub_len = sizeof("SUB")-1;
328 job_len = sizeof("JOB")-1;
331 for (u = unit_infos; u < unit_infos + c; u++) {
332 if (!output_show_unit(u))
335 max_id_len = MAX(max_id_len, strlen(u->id));
336 active_len = MAX(active_len, strlen(u->active_state));
337 sub_len = MAX(sub_len, strlen(u->sub_state));
339 job_len = MAX(job_len, strlen(u->job_type));
344 id_len = MIN(max_id_len, 25);
345 basic_len = 5 + id_len + 6 + active_len + sub_len + job_len;
346 if (basic_len < (unsigned) columns()) {
347 unsigned extra_len, incr;
348 extra_len = columns() - basic_len;
349 /* Either UNIT already got 25, or is fully satisfied.
350 * Grant up to 25 to DESC now. */
351 incr = MIN(extra_len, 25);
354 /* split the remaining space between UNIT and DESC,
355 * but do not give UNIT more than it needs. */
357 incr = MIN(extra_len / 2, max_id_len - id_len);
359 desc_len += extra_len - incr;
365 for (u = unit_infos; u < unit_infos + c; u++) {
367 const char *on_loaded, *off_loaded;
368 const char *on_active, *off_active;
370 if (!output_show_unit(u))
373 if (!n_shown && !arg_no_legend) {
374 printf("%-*s %-6s %-*s %-*s %-*s ", id_len, "UNIT", "LOAD",
375 active_len, "ACTIVE", sub_len, "SUB", job_len, "JOB");
376 if (!arg_full && arg_no_pager)
377 printf("%.*s\n", desc_len, "DESCRIPTION");
379 printf("%s\n", "DESCRIPTION");
384 if (streq(u->load_state, "error")) {
385 on_loaded = ansi_highlight_red(true);
386 off_loaded = ansi_highlight_red(false);
388 on_loaded = off_loaded = "";
390 if (streq(u->active_state, "failed")) {
391 on_active = ansi_highlight_red(true);
392 off_active = ansi_highlight_red(false);
394 on_active = off_active = "";
396 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
398 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s ",
399 id_len, e ? e : u->id,
400 on_loaded, u->load_state, off_loaded,
401 on_active, active_len, u->active_state,
402 sub_len, u->sub_state, off_active,
403 job_len, u->job_id ? u->job_type : "");
404 if (!arg_full && arg_no_pager)
405 printf("%.*s\n", desc_len, u->description);
407 printf("%s\n", u->description);
412 if (!arg_no_legend) {
413 const char *on, *off;
416 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
417 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
418 "SUB = The low-level unit activation state, values depend on unit type.\n"
419 "JOB = Pending job for the unit.\n\n");
420 on = ansi_highlight(true);
421 off = ansi_highlight(false);
423 on = ansi_highlight_red(true);
424 off = ansi_highlight_red(false);
428 printf("%s%u loaded units listed.%s\n"
429 "To show all installed unit files use 'systemctl list-unit-files'.\n",
432 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
433 "To show all installed unit files use 'systemctl list-unit-files'.\n",
438 static int list_units(DBusConnection *bus, char **args) {
439 DBusMessage *reply = NULL;
441 DBusMessageIter iter, sub, sub2;
442 unsigned c = 0, n_units = 0;
443 struct unit_info *unit_infos = NULL;
445 pager_open_if_enabled();
447 r = bus_method_call_with_reply (
449 "org.freedesktop.systemd1",
450 "/org/freedesktop/systemd1",
451 "org.freedesktop.systemd1.Manager",
459 if (!dbus_message_iter_init(reply, &iter) ||
460 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
461 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
462 log_error("Failed to parse reply.");
467 dbus_message_iter_recurse(&iter, &sub);
469 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
472 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
473 log_error("Failed to parse reply.");
481 n_units = MAX(2*c, 16);
482 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
485 log_error("Failed to allocate unit array.");
495 dbus_message_iter_recurse(&sub, &sub2);
497 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
498 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
499 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
500 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
501 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
502 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
503 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
504 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
505 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
506 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
507 log_error("Failed to parse reply.");
512 dbus_message_iter_next(&sub);
517 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
518 output_units_list(unit_infos, c);
523 dbus_message_unref(reply);
530 static int compare_unit_file_list(const void *a, const void *b) {
532 const UnitFileList *u = a, *v = b;
534 d1 = strrchr(u->path, '.');
535 d2 = strrchr(v->path, '.');
540 r = strcasecmp(d1, d2);
545 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
548 static bool output_show_unit_file(const UnitFileList *u) {
551 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
554 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
555 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
556 const UnitFileList *u;
558 max_id_len = sizeof("UNIT FILE")-1;
559 state_cols = sizeof("STATE")-1;
560 for (u = units; u < units + c; u++) {
561 if (!output_show_unit_file(u))
564 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
565 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
570 id_cols = MIN(max_id_len, 25);
571 basic_cols = 1 + id_cols + state_cols;
572 if (basic_cols < (unsigned) columns())
573 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
575 id_cols = max_id_len;
578 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
580 for (u = units; u < units + c; u++) {
582 const char *on, *off;
585 if (!output_show_unit_file(u))
590 if (u->state == UNIT_FILE_MASKED ||
591 u->state == UNIT_FILE_MASKED_RUNTIME ||
592 u->state == UNIT_FILE_DISABLED ||
593 u->state == UNIT_FILE_INVALID) {
594 on = ansi_highlight_red(true);
595 off = ansi_highlight_red(false);
596 } else if (u->state == UNIT_FILE_ENABLED) {
597 on = ansi_highlight_green(true);
598 off = ansi_highlight_green(false);
602 id = path_get_file_name(u->path);
604 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
606 printf("%-*s %s%-*s%s\n",
608 on, state_cols, unit_file_state_to_string(u->state), off);
614 printf("\n%u unit files listed.\n", n_shown);
617 static int list_unit_files(DBusConnection *bus, char **args) {
618 DBusMessage *reply = NULL;
620 DBusMessageIter iter, sub, sub2;
621 unsigned c = 0, n_units = 0;
622 UnitFileList *units = NULL;
624 pager_open_if_enabled();
631 h = hashmap_new(string_hash_func, string_compare_func);
635 r = unit_file_get_list(arg_scope, arg_root, h);
637 unit_file_list_free(h);
638 log_error("Failed to get unit file list: %s", strerror(-r));
642 n_units = hashmap_size(h);
643 units = new(UnitFileList, n_units);
645 unit_file_list_free(h);
649 HASHMAP_FOREACH(u, h, i) {
650 memcpy(units + c++, u, sizeof(UnitFileList));
656 r = bus_method_call_with_reply (
658 "org.freedesktop.systemd1",
659 "/org/freedesktop/systemd1",
660 "org.freedesktop.systemd1.Manager",
668 if (!dbus_message_iter_init(reply, &iter) ||
669 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
670 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
671 log_error("Failed to parse reply.");
676 dbus_message_iter_recurse(&iter, &sub);
678 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
682 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
683 log_error("Failed to parse reply.");
691 n_units = MAX(2*c, 16);
692 w = realloc(units, sizeof(struct UnitFileList) * n_units);
695 log_error("Failed to allocate unit array.");
705 dbus_message_iter_recurse(&sub, &sub2);
707 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
708 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
709 log_error("Failed to parse reply.");
714 u->state = unit_file_state_from_string(state);
716 dbus_message_iter_next(&sub);
722 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
723 output_unit_file_list(units, c);
730 dbus_message_unref(reply);
737 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
738 static const char * const colors[] = {
739 "Requires", "[color=\"black\"]",
740 "RequiresOverridable", "[color=\"black\"]",
741 "Requisite", "[color=\"darkblue\"]",
742 "RequisiteOverridable", "[color=\"darkblue\"]",
743 "Wants", "[color=\"grey66\"]",
744 "Conflicts", "[color=\"red\"]",
745 "ConflictedBy", "[color=\"red\"]",
746 "After", "[color=\"green\"]"
749 const char *c = NULL;
756 for (i = 0; i < ELEMENTSOF(colors); i += 2)
757 if (streq(colors[i], prop)) {
765 if (arg_dot != DOT_ALL)
766 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
769 switch (dbus_message_iter_get_arg_type(iter)) {
771 case DBUS_TYPE_ARRAY:
773 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
776 dbus_message_iter_recurse(iter, &sub);
778 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
781 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
782 dbus_message_iter_get_basic(&sub, &s);
783 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
785 dbus_message_iter_next(&sub);
795 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
796 DBusMessage *reply = NULL;
797 const char *interface = "org.freedesktop.systemd1.Unit";
799 DBusMessageIter iter, sub, sub2, sub3;
803 r = bus_method_call_with_reply (
805 "org.freedesktop.systemd1",
807 "org.freedesktop.DBus.Properties",
811 DBUS_TYPE_STRING, &interface,
816 if (!dbus_message_iter_init(reply, &iter) ||
817 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
818 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
819 log_error("Failed to parse reply.");
824 dbus_message_iter_recurse(&iter, &sub);
826 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
829 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
830 log_error("Failed to parse reply.");
835 dbus_message_iter_recurse(&sub, &sub2);
837 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
838 log_error("Failed to parse reply.");
843 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
844 log_error("Failed to parse reply.");
849 dbus_message_iter_recurse(&sub2, &sub3);
851 if (dot_one_property(name, prop, &sub3)) {
852 log_error("Failed to parse reply.");
857 dbus_message_iter_next(&sub);
862 dbus_message_unref(reply);
867 static int dot(DBusConnection *bus, char **args) {
868 DBusMessage *reply = NULL;
870 DBusMessageIter iter, sub, sub2;
872 r = bus_method_call_with_reply (
874 "org.freedesktop.systemd1",
875 "/org/freedesktop/systemd1",
876 "org.freedesktop.systemd1.Manager",
884 if (!dbus_message_iter_init(reply, &iter) ||
885 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
886 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
887 log_error("Failed to parse reply.");
892 printf("digraph systemd {\n");
894 dbus_message_iter_recurse(&iter, &sub);
895 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
896 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
898 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
899 log_error("Failed to parse reply.");
904 dbus_message_iter_recurse(&sub, &sub2);
906 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
907 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
908 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
909 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
910 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
911 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
912 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
913 log_error("Failed to parse reply.");
918 if ((r = dot_one(bus, id, unit_path)) < 0)
921 /* printf("\t\"%s\";\n", id); */
922 dbus_message_iter_next(&sub);
927 log_info(" Color legend: black = Requires\n"
928 " dark blue = Requisite\n"
929 " dark grey = Wants\n"
934 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
935 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
941 dbus_message_unref(reply);
946 static int list_jobs(DBusConnection *bus, char **args) {
947 DBusMessage *reply = NULL;
949 DBusMessageIter iter, sub, sub2;
952 pager_open_if_enabled();
954 r = bus_method_call_with_reply (
956 "org.freedesktop.systemd1",
957 "/org/freedesktop/systemd1",
958 "org.freedesktop.systemd1.Manager",
966 if (!dbus_message_iter_init(reply, &iter) ||
967 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
968 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
969 log_error("Failed to parse reply.");
974 dbus_message_iter_recurse(&iter, &sub);
977 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
979 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
980 const char *name, *type, *state, *job_path, *unit_path;
984 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
985 log_error("Failed to parse reply.");
990 dbus_message_iter_recurse(&sub, &sub2);
992 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
993 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
994 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
995 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
996 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
997 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
998 log_error("Failed to parse reply.");
1003 e = arg_full ? NULL : ellipsize(name, 25, 33);
1004 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1009 dbus_message_iter_next(&sub);
1013 printf("\n%u jobs listed.\n", k);
1019 dbus_message_unref(reply);
1024 static int load_unit(DBusConnection *bus, char **args) {
1030 STRV_FOREACH(name, args+1) {
1031 n = unit_name_mangle(*name);
1032 r = bus_method_call_with_reply (
1034 "org.freedesktop.systemd1",
1035 "/org/freedesktop/systemd1",
1036 "org.freedesktop.systemd1.Manager",
1040 DBUS_TYPE_STRING, n ? &n : name,
1051 static int cancel_job(DBusConnection *bus, char **args) {
1052 DBusMessage *reply = NULL;
1058 if (strv_length(args) <= 1)
1059 return daemon_reload(bus, args);
1061 STRV_FOREACH(name, args+1) {
1065 r = safe_atou(*name, &id);
1067 log_error("Failed to parse job id: %s", strerror(-r));
1070 assert_cc(sizeof(uint32_t) == sizeof(id));
1072 r = bus_method_call_with_reply (
1074 "org.freedesktop.systemd1",
1075 "/org/freedesktop/systemd1",
1076 "org.freedesktop.systemd1.Manager",
1080 DBUS_TYPE_UINT32, &id,
1085 if (!dbus_message_get_args(reply, NULL,
1086 DBUS_TYPE_OBJECT_PATH, &path,
1087 DBUS_TYPE_INVALID)) {
1088 log_error("Failed to parse reply");
1089 dbus_message_unref(reply);
1093 dbus_message_unref(reply);
1095 r = bus_method_call_with_reply (
1097 "org.freedesktop.systemd1",
1099 "org.freedesktop.systemd1.Job",
1112 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1113 DBusMessage *reply = NULL;
1114 dbus_bool_t b = FALSE;
1115 DBusMessageIter iter, sub;
1117 *interface = "org.freedesktop.systemd1.Unit",
1118 *property = "NeedDaemonReload",
1123 /* We ignore all errors here, since this is used to show a warning only */
1125 n = unit_name_mangle(unit);
1126 r = bus_method_call_with_reply (
1128 "org.freedesktop.systemd1",
1129 "/org/freedesktop/systemd1",
1130 "org.freedesktop.systemd1.Manager",
1134 DBUS_TYPE_STRING, n ? (const char**) &n : &unit,
1140 if (!dbus_message_get_args(reply, NULL,
1141 DBUS_TYPE_OBJECT_PATH, &path,
1145 dbus_message_unref(reply);
1146 r = bus_method_call_with_reply (
1148 "org.freedesktop.systemd1",
1150 "org.freedesktop.DBus.Properties",
1154 DBUS_TYPE_STRING, &interface,
1155 DBUS_TYPE_STRING, &property,
1160 if (!dbus_message_iter_init(reply, &iter) ||
1161 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1164 dbus_message_iter_recurse(&iter, &sub);
1166 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1169 dbus_message_iter_get_basic(&sub, &b);
1173 dbus_message_unref(reply);
1178 typedef struct WaitData {
1185 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1193 dbus_error_init(&error);
1195 log_debug("Got D-Bus request: %s.%s() on %s",
1196 dbus_message_get_interface(message),
1197 dbus_message_get_member(message),
1198 dbus_message_get_path(message));
1200 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1201 log_error("Warning! D-Bus connection terminated.");
1202 dbus_connection_close(connection);
1204 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1206 const char *path, *result, *unit;
1207 dbus_bool_t success = true;
1209 if (dbus_message_get_args(message, &error,
1210 DBUS_TYPE_UINT32, &id,
1211 DBUS_TYPE_OBJECT_PATH, &path,
1212 DBUS_TYPE_STRING, &unit,
1213 DBUS_TYPE_STRING, &result,
1214 DBUS_TYPE_INVALID)) {
1217 p = set_remove(d->set, (char*) path);
1220 if (!isempty(result))
1221 d->result = strdup(result);
1224 d->name = strdup(unit);
1229 dbus_error_free(&error);
1230 if (dbus_message_get_args(message, &error,
1231 DBUS_TYPE_UINT32, &id,
1232 DBUS_TYPE_OBJECT_PATH, &path,
1233 DBUS_TYPE_STRING, &result,
1234 DBUS_TYPE_INVALID)) {
1237 /* Compatibility with older systemd versions <
1238 * 183 during upgrades. This should be dropped
1240 p = set_remove(d->set, (char*) path);
1244 d->result = strdup(result);
1249 dbus_error_free(&error);
1250 if (dbus_message_get_args(message, &error,
1251 DBUS_TYPE_UINT32, &id,
1252 DBUS_TYPE_OBJECT_PATH, &path,
1253 DBUS_TYPE_BOOLEAN, &success,
1254 DBUS_TYPE_INVALID)) {
1257 /* Compatibility with older systemd versions <
1258 * 19 during upgrades. This should be dropped
1261 p = set_remove(d->set, (char*) path);
1265 d->result = strdup("failed");
1271 log_error("Failed to parse message: %s", bus_error_message(&error));
1275 dbus_error_free(&error);
1276 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1279 static int enable_wait_for_jobs(DBusConnection *bus) {
1287 dbus_error_init(&error);
1288 dbus_bus_add_match(bus,
1290 "sender='org.freedesktop.systemd1',"
1291 "interface='org.freedesktop.systemd1.Manager',"
1292 "member='JobRemoved',"
1293 "path='/org/freedesktop/systemd1'",
1296 if (dbus_error_is_set(&error)) {
1297 log_error("Failed to add match: %s", bus_error_message(&error));
1298 dbus_error_free(&error);
1302 /* This is slightly dirty, since we don't undo the match registrations. */
1306 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1316 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1319 while (!set_isempty(s)) {
1321 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1322 log_error("Disconnected from bus.");
1323 return -ECONNREFUSED;
1330 if (streq(d.result, "timeout"))
1331 log_error("Job for %s timed out.", strna(d.name));
1332 else if (streq(d.result, "canceled"))
1333 log_error("Job for %s canceled.", strna(d.name));
1334 else if (streq(d.result, "dependency"))
1335 log_error("A dependency job for %s failed. See 'journalctl -n' for details.", strna(d.name));
1336 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1337 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -n' for details.", strna(d.name), strna(d.name));
1340 if (streq_ptr(d.result, "timeout"))
1342 else if (streq_ptr(d.result, "canceled"))
1344 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1355 dbus_connection_remove_filter(bus, wait_filter, &d);
1359 static int check_one_unit(DBusConnection *bus, char *name, bool quiet) {
1360 DBusMessage *reply = NULL;
1361 DBusMessageIter iter, sub;
1363 *interface = "org.freedesktop.systemd1.Unit",
1364 *property = "ActiveState";
1365 const char *path = NULL;
1372 n = unit_name_mangle(name);
1373 r = bus_method_call_with_reply (
1375 "org.freedesktop.systemd1",
1376 "/org/freedesktop/systemd1",
1377 "org.freedesktop.systemd1.Manager",
1381 DBUS_TYPE_STRING, n ? &n : &name,
1385 if ((r != -ENOMEM) && (!quiet))
1390 if (!dbus_message_get_args(reply, NULL,
1391 DBUS_TYPE_OBJECT_PATH, &path,
1392 DBUS_TYPE_INVALID)) {
1393 log_error("Failed to parse reply.");
1398 dbus_message_unref(reply);
1399 r = bus_method_call_with_reply (
1401 "org.freedesktop.systemd1",
1403 "org.freedesktop.DBus.Properties",
1407 DBUS_TYPE_STRING, &interface,
1408 DBUS_TYPE_STRING, &property,
1413 if (!dbus_message_iter_init(reply, &iter) ||
1414 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1415 log_error("Failed to parse reply.");
1420 dbus_message_iter_recurse(&iter, &sub);
1422 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1423 log_error("Failed to parse reply.");
1428 dbus_message_iter_get_basic(&sub, &state);
1433 if (streq(state, "active") || streq(state, "reloading"))
1436 r = 3; /* According to LSB: "program is not running" */
1440 dbus_message_unref(reply);
1445 static void check_triggering_units(
1446 DBusConnection *bus,
1447 const char *unit_name) {
1449 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1450 DBusMessageIter iter, sub;
1451 char *service_trigger = NULL;
1452 const char *interface = "org.freedesktop.systemd1.Unit",
1453 *triggered_by_property = "TriggeredBy";
1455 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1456 bool print_warning_label = true;
1459 n = unit_name_mangle(unit_name);
1465 unit_path = unit_dbus_path_from_name(n);
1471 r = bus_method_call_with_reply (
1473 "org.freedesktop.systemd1",
1475 "org.freedesktop.DBus.Properties",
1479 DBUS_TYPE_STRING, &interface,
1480 DBUS_TYPE_STRING, &triggered_by_property,
1485 if (!dbus_message_iter_init(reply, &iter) ||
1486 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1487 log_error("Failed to parse reply.");
1491 dbus_message_iter_recurse(&iter, &sub);
1492 dbus_message_iter_recurse(&sub, &iter);
1495 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1497 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1498 log_error("Failed to parse reply.");
1502 dbus_message_iter_get_basic(&sub, &service_trigger);
1504 r = check_one_unit(bus, service_trigger, true);
1508 if (print_warning_label) {
1509 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1510 print_warning_label = false;
1512 log_warning(" %s", service_trigger);
1515 dbus_message_iter_next(&sub);
1519 static int start_unit_one(
1520 DBusConnection *bus,
1527 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1530 _cleanup_free_ char *n, *p = NULL;
1537 n = unit_name_mangle(name);
1541 r = bus_method_call_with_reply(
1543 "org.freedesktop.systemd1",
1544 "/org/freedesktop/systemd1",
1545 "org.freedesktop.systemd1.Manager",
1549 DBUS_TYPE_STRING, &n,
1550 DBUS_TYPE_STRING, &mode,
1553 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1554 /* There's always a fallback possible for
1555 * legacy actions. */
1558 log_error("Failed to issue method call: %s", bus_error_message(error));
1563 if (!dbus_message_get_args(reply, error,
1564 DBUS_TYPE_OBJECT_PATH, &path,
1565 DBUS_TYPE_INVALID)) {
1566 log_error("Failed to parse reply: %s", bus_error_message(error));
1570 if (need_daemon_reload(bus, n))
1571 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1572 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1581 log_error("Failed to add path to set.");
1591 static enum action verb_to_action(const char *verb) {
1592 if (streq(verb, "halt"))
1594 else if (streq(verb, "poweroff"))
1595 return ACTION_POWEROFF;
1596 else if (streq(verb, "reboot"))
1597 return ACTION_REBOOT;
1598 else if (streq(verb, "kexec"))
1599 return ACTION_KEXEC;
1600 else if (streq(verb, "rescue"))
1601 return ACTION_RESCUE;
1602 else if (streq(verb, "emergency"))
1603 return ACTION_EMERGENCY;
1604 else if (streq(verb, "default"))
1605 return ACTION_DEFAULT;
1606 else if (streq(verb, "exit"))
1608 else if (streq(verb, "suspend"))
1609 return ACTION_SUSPEND;
1610 else if (streq(verb, "hibernate"))
1611 return ACTION_HIBERNATE;
1612 else if (streq(verb, "hybrid-sleep"))
1613 return ACTION_HYBRID_SLEEP;
1615 return ACTION_INVALID;
1618 static int start_unit(DBusConnection *bus, char **args) {
1620 static const char * const table[_ACTION_MAX] = {
1621 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1622 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1623 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1624 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1625 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1626 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1627 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1628 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1629 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1630 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1631 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1632 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1633 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1634 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
1635 [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
1639 const char *method, *mode, *one_name;
1644 dbus_error_init(&error);
1648 ask_password_agent_open_if_enabled();
1650 if (arg_action == ACTION_SYSTEMCTL) {
1652 streq(args[0], "stop") ||
1653 streq(args[0], "condstop") ? "StopUnit" :
1654 streq(args[0], "reload") ? "ReloadUnit" :
1655 streq(args[0], "restart") ? "RestartUnit" :
1657 streq(args[0], "try-restart") ||
1658 streq(args[0], "condrestart") ? "TryRestartUnit" :
1660 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1662 streq(args[0], "reload-or-try-restart") ||
1663 streq(args[0], "condreload") ||
1665 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1669 (streq(args[0], "isolate") ||
1670 streq(args[0], "rescue") ||
1671 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1673 one_name = table[verb_to_action(args[0])];
1676 assert(arg_action < ELEMENTSOF(table));
1677 assert(table[arg_action]);
1679 method = "StartUnit";
1681 mode = (arg_action == ACTION_EMERGENCY ||
1682 arg_action == ACTION_RESCUE ||
1683 arg_action == ACTION_RUNLEVEL2 ||
1684 arg_action == ACTION_RUNLEVEL3 ||
1685 arg_action == ACTION_RUNLEVEL4 ||
1686 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1688 one_name = table[arg_action];
1691 if (!arg_no_block) {
1692 ret = enable_wait_for_jobs(bus);
1694 log_error("Could not watch jobs: %s", strerror(-ret));
1698 s = set_new(string_hash_func, string_compare_func);
1706 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1708 ret = translate_bus_error_to_exit_status(ret, &error);
1710 STRV_FOREACH(name, args+1) {
1711 r = start_unit_one(bus, method, *name, mode, &error, s);
1713 ret = translate_bus_error_to_exit_status(r, &error);
1714 dbus_error_free(&error);
1719 if (!arg_no_block) {
1720 r = wait_for_jobs(bus, s);
1726 /* When stopping units, warn if they can still be triggered by
1727 * another active unit (socket, path, timer) */
1728 if (!arg_quiet && streq(method, "StopUnit")) {
1730 check_triggering_units(bus, one_name);
1732 STRV_FOREACH(name, args+1)
1733 check_triggering_units(bus, *name);
1739 dbus_error_free(&error);
1744 /* Ask systemd-logind, which might grant access to unprivileged users
1745 * through PolicyKit */
1746 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1749 dbus_bool_t interactive = true;
1751 polkit_agent_open_if_enabled();
1759 case ACTION_POWEROFF:
1760 method = "PowerOff";
1763 case ACTION_SUSPEND:
1767 case ACTION_HIBERNATE:
1768 method = "Hibernate";
1771 case ACTION_HYBRID_SLEEP:
1772 method = "HybridSleep";
1779 return bus_method_call_with_reply (
1781 "org.freedesktop.login1",
1782 "/org/freedesktop/login1",
1783 "org.freedesktop.login1.Manager",
1787 DBUS_TYPE_BOOLEAN, &interactive,
1794 static int start_special(DBusConnection *bus, char **args) {
1800 a = verb_to_action(args[0]);
1802 if (arg_force >= 2 && geteuid() != 0) {
1803 log_error("Must be root.");
1807 if (arg_force >= 2 &&
1808 (a == ACTION_HALT ||
1809 a == ACTION_POWEROFF ||
1810 a == ACTION_REBOOT))
1813 if (arg_force >= 1 &&
1814 (a == ACTION_HALT ||
1815 a == ACTION_POWEROFF ||
1816 a == ACTION_REBOOT ||
1817 a == ACTION_KEXEC ||
1819 return daemon_reload(bus, args);
1821 /* first try logind, to allow authentication with polkit */
1822 if (geteuid() != 0 &&
1823 (a == ACTION_POWEROFF ||
1824 a == ACTION_REBOOT ||
1825 a == ACTION_SUSPEND ||
1826 a == ACTION_HIBERNATE ||
1827 a == ACTION_HYBRID_SLEEP)) {
1828 r = reboot_with_logind(bus, a);
1833 r = start_unit(bus, args);
1840 static int check_unit(DBusConnection *bus, char **args) {
1842 int r = 3; /* According to LSB: "program is not running" */
1847 STRV_FOREACH(name, args+1) {
1848 int state = check_one_unit(bus, *name, arg_quiet);
1858 static int kill_unit(DBusConnection *bus, char **args) {
1865 arg_kill_who = "all";
1867 STRV_FOREACH(name, args+1) {
1868 n = unit_name_mangle(*name);
1869 r = bus_method_call_with_reply (
1871 "org.freedesktop.systemd1",
1872 "/org/freedesktop/systemd1",
1873 "org.freedesktop.systemd1.Manager",
1877 DBUS_TYPE_STRING, n ? &n : name,
1878 DBUS_TYPE_STRING, &arg_kill_who,
1879 DBUS_TYPE_INT32, &arg_signal,
1888 typedef struct ExecStatusInfo {
1896 usec_t start_timestamp;
1897 usec_t exit_timestamp;
1902 LIST_FIELDS(struct ExecStatusInfo, exec);
1905 static void exec_status_info_free(ExecStatusInfo *i) {
1914 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
1915 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
1916 DBusMessageIter sub2, sub3;
1920 int32_t code, status;
1926 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
1929 dbus_message_iter_recurse(sub, &sub2);
1931 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
1934 if (!(i->path = strdup(path)))
1937 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
1938 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
1942 dbus_message_iter_recurse(&sub2, &sub3);
1943 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1944 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1945 dbus_message_iter_next(&sub3);
1950 if (!(i->argv = new0(char*, n+1)))
1954 dbus_message_iter_recurse(&sub2, &sub3);
1955 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1958 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1959 dbus_message_iter_get_basic(&sub3, &s);
1960 dbus_message_iter_next(&sub3);
1962 if (!(i->argv[n++] = strdup(s)))
1966 if (!dbus_message_iter_next(&sub2) ||
1967 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
1968 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
1969 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
1970 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
1971 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
1972 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
1973 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
1974 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
1978 i->start_timestamp = (usec_t) start_timestamp;
1979 i->exit_timestamp = (usec_t) exit_timestamp;
1980 i->pid = (pid_t) pid;
1987 typedef struct UnitStatusInfo {
1989 const char *load_state;
1990 const char *active_state;
1991 const char *sub_state;
1992 const char *unit_file_state;
1994 const char *description;
1995 const char *following;
1997 char **documentation;
1999 const char *fragment_path;
2000 const char *source_path;
2001 const char *default_control_group;
2003 const char *load_error;
2006 usec_t inactive_exit_timestamp;
2007 usec_t inactive_exit_timestamp_monotonic;
2008 usec_t active_enter_timestamp;
2009 usec_t active_exit_timestamp;
2010 usec_t inactive_enter_timestamp;
2012 bool need_daemon_reload;
2017 const char *status_text;
2020 usec_t start_timestamp;
2021 usec_t exit_timestamp;
2023 int exit_code, exit_status;
2025 usec_t condition_timestamp;
2026 bool condition_result;
2029 unsigned n_accepted;
2030 unsigned n_connections;
2034 const char *sysfs_path;
2036 /* Mount, Automount */
2042 LIST_HEAD(ExecStatusInfo, exec);
2045 static void print_status_info(UnitStatusInfo *i) {
2047 const char *on, *off, *ss;
2049 char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
2050 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2055 /* This shows pretty information about a unit. See
2056 * print_property() for a low-level property printer */
2058 printf("%s", strna(i->id));
2060 if (i->description && !streq_ptr(i->id, i->description))
2061 printf(" - %s", i->description);
2066 printf("\t Follow: unit currently follows state of %s\n", i->following);
2068 if (streq_ptr(i->load_state, "error")) {
2069 on = ansi_highlight_red(true);
2070 off = ansi_highlight_red(false);
2074 path = i->source_path ? i->source_path : i->fragment_path;
2077 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2078 else if (path && i->unit_file_state)
2079 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2081 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2083 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2085 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2087 if (streq_ptr(i->active_state, "failed")) {
2088 on = ansi_highlight_red(true);
2089 off = ansi_highlight_red(false);
2090 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2091 on = ansi_highlight_green(true);
2092 off = ansi_highlight_green(false);
2097 printf("\t Active: %s%s (%s)%s",
2099 strna(i->active_state),
2103 printf("\t Active: %s%s%s",
2105 strna(i->active_state),
2108 if (!isempty(i->result) && !streq(i->result, "success"))
2109 printf(" (Result: %s)", i->result);
2111 timestamp = (streq_ptr(i->active_state, "active") ||
2112 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2113 (streq_ptr(i->active_state, "inactive") ||
2114 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2115 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2116 i->active_exit_timestamp;
2118 s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
2119 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2122 printf(" since %s; %s\n", s2, s1);
2124 printf(" since %s\n", s2);
2128 if (!i->condition_result && i->condition_timestamp > 0) {
2129 s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
2130 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2133 printf("\t start condition failed at %s; %s\n", s2, s1);
2135 printf("\t start condition failed at %s\n", s2);
2139 printf("\t Device: %s\n", i->sysfs_path);
2141 printf("\t Where: %s\n", i->where);
2143 printf("\t What: %s\n", i->what);
2145 if (!strv_isempty(i->documentation)) {
2149 STRV_FOREACH(t, i->documentation) {
2151 printf("\t Docs: %s\n", *t);
2154 printf("\t %s\n", *t);
2159 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2161 LIST_FOREACH(exec, p, i->exec) {
2165 /* Only show exited processes here */
2169 t = strv_join(p->argv, " ");
2170 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2173 good = is_clean_exit_lsb(p->code, p->status, NULL);
2175 on = ansi_highlight_red(true);
2176 off = ansi_highlight_red(false);
2180 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2182 if (p->code == CLD_EXITED) {
2185 printf("status=%i", p->status);
2187 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2192 printf("signal=%s", signal_to_string(p->status));
2194 printf(")%s\n", off);
2196 if (i->main_pid == p->pid &&
2197 i->start_timestamp == p->start_timestamp &&
2198 i->exit_timestamp == p->start_timestamp)
2199 /* Let's not show this twice */
2202 if (p->pid == i->control_pid)
2206 if (i->main_pid > 0 || i->control_pid > 0) {
2209 if (i->main_pid > 0) {
2210 printf("Main PID: %u", (unsigned) i->main_pid);
2214 get_process_comm(i->main_pid, &t);
2219 } else if (i->exit_code > 0) {
2220 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2222 if (i->exit_code == CLD_EXITED) {
2225 printf("status=%i", i->exit_status);
2227 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2232 printf("signal=%s", signal_to_string(i->exit_status));
2237 if (i->main_pid > 0 && i->control_pid > 0)
2240 if (i->control_pid > 0) {
2243 printf(" Control: %u", (unsigned) i->control_pid);
2245 get_process_comm(i->control_pid, &t);
2256 printf("\t Status: \"%s\"\n", i->status_text);
2258 if (i->default_control_group) {
2261 printf("\t CGroup: %s\n", i->default_control_group);
2263 if (arg_transport != TRANSPORT_SSH) {
2273 if (i->main_pid > 0)
2274 extra[k++] = i->main_pid;
2276 if (i->control_pid > 0)
2277 extra[k++] = i->control_pid;
2279 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2283 if (i->id && arg_transport != TRANSPORT_SSH) {
2285 arg_all * OUTPUT_SHOW_ALL |
2286 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2287 on_tty() * OUTPUT_COLOR |
2288 !arg_quiet * OUTPUT_WARN_CUTOFF;
2291 show_journal_by_unit(stdout,
2295 i->inactive_exit_timestamp_monotonic,
2300 if (i->need_daemon_reload)
2301 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2302 ansi_highlight_red(true),
2303 ansi_highlight_red(false),
2304 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2307 static void show_unit_help(UnitStatusInfo *i) {
2312 if (!i->documentation) {
2313 log_info("Documentation for %s not known.", i->id);
2317 STRV_FOREACH(p, i->documentation) {
2319 if (startswith(*p, "man:")) {
2322 char *page = NULL, *section = NULL;
2323 const char *args[4] = { "man", NULL, NULL, NULL };
2328 if ((*p)[k-1] == ')')
2329 e = strrchr(*p, '(');
2332 page = strndup((*p) + 4, e - *p - 4);
2338 section = strndup(e + 1, *p + k - e - 2);
2352 log_error("Failed to fork: %m");
2360 execvp(args[0], (char**) args);
2361 log_error("Failed to execute man: %m");
2362 _exit(EXIT_FAILURE);
2368 wait_for_terminate(pid, NULL);
2370 log_info("Can't show: %s", *p);
2374 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2380 switch (dbus_message_iter_get_arg_type(iter)) {
2382 case DBUS_TYPE_STRING: {
2385 dbus_message_iter_get_basic(iter, &s);
2388 if (streq(name, "Id"))
2390 else if (streq(name, "LoadState"))
2392 else if (streq(name, "ActiveState"))
2393 i->active_state = s;
2394 else if (streq(name, "SubState"))
2396 else if (streq(name, "Description"))
2398 else if (streq(name, "FragmentPath"))
2399 i->fragment_path = s;
2400 else if (streq(name, "SourcePath"))
2402 else if (streq(name, "DefaultControlGroup"))
2403 i->default_control_group = s;
2404 else if (streq(name, "StatusText"))
2406 else if (streq(name, "SysFSPath"))
2408 else if (streq(name, "Where"))
2410 else if (streq(name, "What"))
2412 else if (streq(name, "Following"))
2414 else if (streq(name, "UnitFileState"))
2415 i->unit_file_state = s;
2416 else if (streq(name, "Result"))
2423 case DBUS_TYPE_BOOLEAN: {
2426 dbus_message_iter_get_basic(iter, &b);
2428 if (streq(name, "Accept"))
2430 else if (streq(name, "NeedDaemonReload"))
2431 i->need_daemon_reload = b;
2432 else if (streq(name, "ConditionResult"))
2433 i->condition_result = b;
2438 case DBUS_TYPE_UINT32: {
2441 dbus_message_iter_get_basic(iter, &u);
2443 if (streq(name, "MainPID")) {
2445 i->main_pid = (pid_t) u;
2448 } else if (streq(name, "ControlPID"))
2449 i->control_pid = (pid_t) u;
2450 else if (streq(name, "ExecMainPID")) {
2452 i->main_pid = (pid_t) u;
2453 } else if (streq(name, "NAccepted"))
2455 else if (streq(name, "NConnections"))
2456 i->n_connections = u;
2461 case DBUS_TYPE_INT32: {
2464 dbus_message_iter_get_basic(iter, &j);
2466 if (streq(name, "ExecMainCode"))
2467 i->exit_code = (int) j;
2468 else if (streq(name, "ExecMainStatus"))
2469 i->exit_status = (int) j;
2474 case DBUS_TYPE_UINT64: {
2477 dbus_message_iter_get_basic(iter, &u);
2479 if (streq(name, "ExecMainStartTimestamp"))
2480 i->start_timestamp = (usec_t) u;
2481 else if (streq(name, "ExecMainExitTimestamp"))
2482 i->exit_timestamp = (usec_t) u;
2483 else if (streq(name, "ActiveEnterTimestamp"))
2484 i->active_enter_timestamp = (usec_t) u;
2485 else if (streq(name, "InactiveEnterTimestamp"))
2486 i->inactive_enter_timestamp = (usec_t) u;
2487 else if (streq(name, "InactiveExitTimestamp"))
2488 i->inactive_exit_timestamp = (usec_t) u;
2489 else if (streq(name, "InactiveExitTimestampMonotonic"))
2490 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2491 else if (streq(name, "ActiveExitTimestamp"))
2492 i->active_exit_timestamp = (usec_t) u;
2493 else if (streq(name, "ConditionTimestamp"))
2494 i->condition_timestamp = (usec_t) u;
2499 case DBUS_TYPE_ARRAY: {
2501 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2502 startswith(name, "Exec")) {
2503 DBusMessageIter sub;
2505 dbus_message_iter_recurse(iter, &sub);
2506 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2507 ExecStatusInfo *info;
2510 if (!(info = new0(ExecStatusInfo, 1)))
2513 if (!(info->name = strdup(name))) {
2518 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2523 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2525 dbus_message_iter_next(&sub);
2527 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2528 streq(name, "Documentation")) {
2530 DBusMessageIter sub;
2532 dbus_message_iter_recurse(iter, &sub);
2533 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2537 dbus_message_iter_get_basic(&sub, &s);
2539 l = strv_append(i->documentation, s);
2543 strv_free(i->documentation);
2544 i->documentation = l;
2546 dbus_message_iter_next(&sub);
2553 case DBUS_TYPE_STRUCT: {
2555 if (streq(name, "LoadError")) {
2556 DBusMessageIter sub;
2557 const char *n, *message;
2560 dbus_message_iter_recurse(iter, &sub);
2562 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2566 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2570 if (!isempty(message))
2571 i->load_error = message;
2581 static int print_property(const char *name, DBusMessageIter *iter) {
2585 /* This is a low-level property printer, see
2586 * print_status_info() for the nicer output */
2588 if (arg_property && !strv_find(arg_property, name))
2591 switch (dbus_message_iter_get_arg_type(iter)) {
2593 case DBUS_TYPE_STRUCT: {
2594 DBusMessageIter sub;
2595 dbus_message_iter_recurse(iter, &sub);
2597 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2600 dbus_message_iter_get_basic(&sub, &u);
2603 printf("%s=%u\n", name, (unsigned) u);
2605 printf("%s=\n", name);
2608 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2611 dbus_message_iter_get_basic(&sub, &s);
2613 if (arg_all || s[0])
2614 printf("%s=%s\n", name, s);
2617 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2618 const char *a = NULL, *b = NULL;
2620 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2621 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2623 if (arg_all || !isempty(a) || !isempty(b))
2624 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2632 case DBUS_TYPE_ARRAY:
2634 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2635 DBusMessageIter sub, sub2;
2637 dbus_message_iter_recurse(iter, &sub);
2638 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2642 dbus_message_iter_recurse(&sub, &sub2);
2644 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2645 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2646 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2648 dbus_message_iter_next(&sub);
2653 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2654 DBusMessageIter sub, sub2;
2656 dbus_message_iter_recurse(iter, &sub);
2657 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2658 const char *type, *path;
2660 dbus_message_iter_recurse(&sub, &sub2);
2662 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2663 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2664 printf("%s=%s\n", type, path);
2666 dbus_message_iter_next(&sub);
2671 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2672 DBusMessageIter sub, sub2;
2674 dbus_message_iter_recurse(iter, &sub);
2675 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2677 uint64_t value, next_elapse;
2679 dbus_message_iter_recurse(&sub, &sub2);
2681 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2682 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2683 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2684 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2686 printf("%s={ value=%s ; next_elapse=%s }\n",
2688 format_timespan(timespan1, sizeof(timespan1), value),
2689 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2692 dbus_message_iter_next(&sub);
2697 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2698 DBusMessageIter sub, sub2;
2700 dbus_message_iter_recurse(iter, &sub);
2701 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2702 const char *controller, *attr, *value;
2704 dbus_message_iter_recurse(&sub, &sub2);
2706 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2707 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2708 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2710 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2716 dbus_message_iter_next(&sub);
2721 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2722 DBusMessageIter sub;
2724 dbus_message_iter_recurse(iter, &sub);
2725 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2726 ExecStatusInfo info;
2729 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2730 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2733 t = strv_join(info.argv, " ");
2735 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2739 yes_no(info.ignore),
2740 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2741 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2742 (unsigned) info. pid,
2743 sigchld_code_to_string(info.code),
2745 info.code == CLD_EXITED ? "" : "/",
2746 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2752 strv_free(info.argv);
2754 dbus_message_iter_next(&sub);
2763 if (generic_print_property(name, iter, arg_all) > 0)
2767 printf("%s=[unprintable]\n", name);
2772 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2773 DBusMessage *reply = NULL;
2774 const char *interface = "";
2776 DBusMessageIter iter, sub, sub2, sub3;
2777 UnitStatusInfo info;
2785 r = bus_method_call_with_reply (
2787 "org.freedesktop.systemd1",
2789 "org.freedesktop.DBus.Properties",
2793 DBUS_TYPE_STRING, &interface,
2798 if (!dbus_message_iter_init(reply, &iter) ||
2799 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2800 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2801 log_error("Failed to parse reply.");
2806 dbus_message_iter_recurse(&iter, &sub);
2813 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2816 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2817 log_error("Failed to parse reply.");
2822 dbus_message_iter_recurse(&sub, &sub2);
2824 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2825 log_error("Failed to parse reply.");
2830 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2831 log_error("Failed to parse reply.");
2836 dbus_message_iter_recurse(&sub2, &sub3);
2838 if (show_properties)
2839 r = print_property(name, &sub3);
2841 r = status_property(name, &sub3, &info);
2844 log_error("Failed to parse reply.");
2849 dbus_message_iter_next(&sub);
2854 if (!show_properties) {
2855 if (streq(verb, "help"))
2856 show_unit_help(&info);
2858 print_status_info(&info);
2861 strv_free(info.documentation);
2863 if (!streq_ptr(info.active_state, "active") &&
2864 !streq_ptr(info.active_state, "reloading") &&
2865 streq(verb, "status"))
2866 /* According to LSB: "program not running" */
2869 while ((p = info.exec)) {
2870 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2871 exec_status_info_free(p);
2876 dbus_message_unref(reply);
2881 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
2882 DBusMessage *reply = NULL;
2883 const char *path = NULL;
2887 dbus_error_init(&error);
2889 r = bus_method_call_with_reply (
2891 "org.freedesktop.systemd1",
2892 "/org/freedesktop/systemd1",
2893 "org.freedesktop.systemd1.Manager",
2897 DBUS_TYPE_UINT32, &pid,
2902 if (!dbus_message_get_args(reply, &error,
2903 DBUS_TYPE_OBJECT_PATH, &path,
2904 DBUS_TYPE_INVALID)) {
2905 log_error("Failed to parse reply: %s", bus_error_message(&error));
2910 r = show_one(verb, bus, path, false, new_line);
2914 dbus_message_unref(reply);
2916 dbus_error_free(&error);
2921 static int show(DBusConnection *bus, char **args) {
2923 bool show_properties, new_line = false;
2929 show_properties = streq(args[0], "show");
2931 if (show_properties)
2932 pager_open_if_enabled();
2934 if (show_properties && strv_length(args) <= 1) {
2935 /* If not argument is specified inspect the manager
2938 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2941 STRV_FOREACH(name, args+1) {
2944 if (safe_atou32(*name, &id) < 0) {
2946 /* Interpret as unit name */
2948 n = unit_name_mangle(*name);
2949 p = unit_dbus_path_from_name(n ? n : *name);
2954 r = show_one(args[0], bus, p, show_properties, &new_line);
2960 } else if (show_properties) {
2962 /* Interpret as job id */
2965 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
2968 r = show_one(args[0], bus, p, show_properties, &new_line);
2976 /* Interpret as PID */
2978 r = show_one_by_pid(args[0], bus, id, &new_line);
2987 static int dump(DBusConnection *bus, char **args) {
2988 DBusMessage *reply = NULL;
2993 dbus_error_init(&error);
2995 pager_open_if_enabled();
2997 r = bus_method_call_with_reply (
2999 "org.freedesktop.systemd1",
3000 "/org/freedesktop/systemd1",
3001 "org.freedesktop.systemd1.Manager",
3009 if (!dbus_message_get_args(reply, &error,
3010 DBUS_TYPE_STRING, &text,
3011 DBUS_TYPE_INVALID)) {
3012 log_error("Failed to parse reply: %s", bus_error_message(&error));
3017 fputs(text, stdout);
3021 dbus_message_unref(reply);
3023 dbus_error_free(&error);
3028 static int snapshot(DBusConnection *bus, char **args) {
3029 DBusMessage *reply = NULL;
3032 dbus_bool_t cleanup = FALSE;
3033 DBusMessageIter iter, sub;
3035 *name = "", *path, *id,
3036 *interface = "org.freedesktop.systemd1.Unit",
3040 dbus_error_init(&error);
3042 if (strv_length(args) > 1)
3045 n = unit_name_mangle(name);
3046 r = bus_method_call_with_reply (
3048 "org.freedesktop.systemd1",
3049 "/org/freedesktop/systemd1",
3050 "org.freedesktop.systemd1.Manager",
3054 DBUS_TYPE_STRING, n ? (const char**) &n : &name,
3055 DBUS_TYPE_BOOLEAN, &cleanup,
3061 if (!dbus_message_get_args(reply, &error,
3062 DBUS_TYPE_OBJECT_PATH, &path,
3063 DBUS_TYPE_INVALID)) {
3064 log_error("Failed to parse reply: %s", bus_error_message(&error));
3069 dbus_message_unref(reply);
3070 r = bus_method_call_with_reply (
3072 "org.freedesktop.systemd1",
3074 "org.freedesktop.DBus.Properties",
3078 DBUS_TYPE_STRING, &interface,
3079 DBUS_TYPE_STRING, &property,
3084 if (!dbus_message_iter_init(reply, &iter) ||
3085 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3086 log_error("Failed to parse reply.");
3091 dbus_message_iter_recurse(&iter, &sub);
3093 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3094 log_error("Failed to parse reply.");
3099 dbus_message_iter_get_basic(&sub, &id);
3106 dbus_message_unref(reply);
3108 dbus_error_free(&error);
3113 static int delete_snapshot(DBusConnection *bus, char **args) {
3114 DBusMessage *reply = NULL;
3121 dbus_error_init(&error);
3123 STRV_FOREACH(name, args+1) {
3124 const char *path = NULL;
3127 n = unit_name_mangle(*name);
3128 r = bus_method_call_with_reply (
3130 "org.freedesktop.systemd1",
3131 "/org/freedesktop/systemd1",
3132 "org.freedesktop.systemd1.Manager",
3136 DBUS_TYPE_STRING, n ? &n : name,
3142 if (!dbus_message_get_args(reply, &error,
3143 DBUS_TYPE_OBJECT_PATH, &path,
3144 DBUS_TYPE_INVALID)) {
3145 log_error("Failed to parse reply: %s", bus_error_message(&error));
3147 dbus_message_unref(reply);
3148 dbus_error_free(&error);
3151 dbus_message_unref(reply);
3153 r = bus_method_call_with_reply (
3155 "org.freedesktop.systemd1",
3157 "org.freedesktop.systemd1.Snapshot",
3170 static int daemon_reload(DBusConnection *bus, char **args) {
3175 if (arg_action == ACTION_RELOAD)
3177 else if (arg_action == ACTION_REEXEC)
3178 method = "Reexecute";
3180 assert(arg_action == ACTION_SYSTEMCTL);
3183 streq(args[0], "clear-jobs") ||
3184 streq(args[0], "cancel") ? "ClearJobs" :
3185 streq(args[0], "daemon-reexec") ? "Reexecute" :
3186 streq(args[0], "reset-failed") ? "ResetFailed" :
3187 streq(args[0], "halt") ? "Halt" :
3188 streq(args[0], "poweroff") ? "PowerOff" :
3189 streq(args[0], "reboot") ? "Reboot" :
3190 streq(args[0], "kexec") ? "KExec" :
3191 streq(args[0], "exit") ? "Exit" :
3192 /* "daemon-reload" */ "Reload";
3195 r = bus_method_call_with_reply (
3197 "org.freedesktop.systemd1",
3198 "/org/freedesktop/systemd1",
3199 "org.freedesktop.systemd1.Manager",
3205 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3206 /* There's always a fallback possible for
3207 * legacy actions. */
3209 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3210 /* On reexecution, we expect a disconnect, not
3214 log_error("Failed to issue method call: %s", bus_error_message(&error));
3215 dbus_error_free(&error);
3220 static int reset_failed(DBusConnection *bus, char **args) {
3224 if (strv_length(args) <= 1)
3225 return daemon_reload(bus, args);
3227 STRV_FOREACH(name, args+1) {
3228 n = unit_name_mangle(*name);
3229 r = bus_method_call_with_reply (
3231 "org.freedesktop.systemd1",
3232 "/org/freedesktop/systemd1",
3233 "org.freedesktop.systemd1.Manager",
3237 DBUS_TYPE_STRING, n ? &n : name,
3248 static int show_enviroment(DBusConnection *bus, char **args) {
3249 DBusMessage *reply = NULL;
3250 DBusMessageIter iter, sub, sub2;
3253 *interface = "org.freedesktop.systemd1.Manager",
3254 *property = "Environment";
3256 pager_open_if_enabled();
3258 r = bus_method_call_with_reply (
3260 "org.freedesktop.systemd1",
3261 "/org/freedesktop/systemd1",
3262 "org.freedesktop.DBus.Properties",
3266 DBUS_TYPE_STRING, &interface,
3267 DBUS_TYPE_STRING, &property,
3272 if (!dbus_message_iter_init(reply, &iter) ||
3273 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3274 log_error("Failed to parse reply.");
3279 dbus_message_iter_recurse(&iter, &sub);
3281 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3282 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3283 log_error("Failed to parse reply.");
3288 dbus_message_iter_recurse(&sub, &sub2);
3290 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3293 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3294 log_error("Failed to parse reply.");
3299 dbus_message_iter_get_basic(&sub2, &text);
3300 printf("%s\n", text);
3302 dbus_message_iter_next(&sub2);
3309 dbus_message_unref(reply);
3314 static int switch_root(DBusConnection *bus, char **args) {
3316 const char *root, *init;
3318 l = strv_length(args);
3319 if (l < 2 || l > 3) {
3320 log_error("Wrong number of arguments.");
3325 init = l >= 3 ? args[2] : "";
3327 return bus_method_call_with_reply (
3329 "org.freedesktop.systemd1",
3330 "/org/freedesktop/systemd1",
3331 "org.freedesktop.systemd1.Manager",
3335 DBUS_TYPE_STRING, &root,
3336 DBUS_TYPE_STRING, &init,
3340 static int set_environment(DBusConnection *bus, char **args) {
3341 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3344 DBusMessageIter iter;
3349 dbus_error_init(&error);
3351 method = streq(args[0], "set-environment")
3353 : "UnsetEnvironment";
3355 m = dbus_message_new_method_call(
3356 "org.freedesktop.systemd1",
3357 "/org/freedesktop/systemd1",
3358 "org.freedesktop.systemd1.Manager",
3363 dbus_message_iter_init_append(m, &iter);
3365 r = bus_append_strv_iter(&iter, args + 1);
3369 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3371 log_error("Failed to issue method call: %s", bus_error_message(&error));
3379 dbus_error_free(&error);
3383 static int enable_sysv_units(char **args) {
3386 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3387 const char *verb = args[0];
3388 unsigned f = 1, t = 1;
3391 if (arg_scope != UNIT_FILE_SYSTEM)
3394 if (!streq(verb, "enable") &&
3395 !streq(verb, "disable") &&
3396 !streq(verb, "is-enabled"))
3399 /* Processes all SysV units, and reshuffles the array so that
3400 * afterwards only the native units remain */
3403 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3408 for (f = 1; args[f]; f++) {
3411 bool found_native = false, found_sysv;
3413 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3414 char **k, *l, *q = NULL;
3421 if (!endswith(name, ".service"))
3424 if (path_is_absolute(name))
3427 STRV_FOREACH(k, paths.unit_path) {
3430 if (!isempty(arg_root))
3431 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3433 asprintf(&p, "%s/%s", *k, name);
3440 found_native = access(p, F_OK) >= 0;
3451 if (!isempty(arg_root))
3452 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3454 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3460 p[strlen(p) - sizeof(".service") + 1] = 0;
3461 found_sysv = access(p, F_OK) >= 0;
3468 /* Mark this entry, so that we don't try enabling it as native unit */
3469 args[f] = (char*) "";
3471 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3473 if (!isempty(arg_root))
3474 argv[c++] = q = strappend("--root=", arg_root);
3476 argv[c++] = path_get_file_name(p);
3478 streq(verb, "enable") ? "on" :
3479 streq(verb, "disable") ? "off" : "--level=5";
3482 l = strv_join((char**)argv, " ");
3490 log_info("Executing %s", l);
3495 log_error("Failed to fork: %m");
3500 } else if (pid == 0) {
3503 execv(argv[0], (char**) argv);
3504 _exit(EXIT_FAILURE);
3510 j = wait_for_terminate(pid, &status);
3512 log_error("Failed to wait for child: %s", strerror(-r));
3517 if (status.si_code == CLD_EXITED) {
3518 if (streq(verb, "is-enabled")) {
3519 if (status.si_status == 0) {
3528 } else if (status.si_status != 0) {
3539 lookup_paths_free(&paths);
3541 /* Drop all SysV units */
3542 for (f = 1, t = 1; args[f]; f++) {
3544 if (isempty(args[f]))
3547 args[t++] = args[f];
3556 static int mangle_names(char **original_names, char ***mangled_names) {
3557 char **i, **l, **name;
3559 l = new(char*, strv_length(original_names) + 1);
3564 STRV_FOREACH(name, original_names) {
3566 /* When enabling units qualified path names are OK,
3567 * too, hence allow them explicitly. */
3572 *i = unit_name_mangle(*name);
3588 static int enable_unit(DBusConnection *bus, char **args) {
3589 const char *verb = args[0];
3590 UnitFileChange *changes = NULL;
3591 unsigned n_changes = 0, i;
3592 int carries_install_info = -1;
3593 DBusMessage *m = NULL, *reply = NULL;
3596 char **mangled_names = NULL;
3598 r = enable_sysv_units(args);
3605 dbus_error_init(&error);
3607 if (!bus || avoid_bus()) {
3608 if (streq(verb, "enable")) {
3609 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3610 carries_install_info = r;
3611 } else if (streq(verb, "disable"))
3612 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3613 else if (streq(verb, "reenable")) {
3614 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3615 carries_install_info = r;
3616 } else if (streq(verb, "link"))
3617 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3618 else if (streq(verb, "preset")) {
3619 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3620 carries_install_info = r;
3621 } else if (streq(verb, "mask"))
3622 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3623 else if (streq(verb, "unmask"))
3624 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3626 assert_not_reached("Unknown verb");
3629 log_error("Operation failed: %s", strerror(-r));
3634 for (i = 0; i < n_changes; i++) {
3635 if (changes[i].type == UNIT_FILE_SYMLINK)
3636 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3638 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 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
3918 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
3920 " list-units List loaded units\n"
3921 " start [NAME...] Start (activate) one or more units\n"
3922 " stop [NAME...] Stop (deactivate) one or more units\n"
3923 " reload [NAME...] Reload one or more units\n"
3924 " restart [NAME...] Start or restart one or more units\n"
3925 " try-restart [NAME...] Restart one or more units if active\n"
3926 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
3927 " otherwise start or restart\n"
3928 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
3929 " otherwise restart if active\n"
3930 " isolate [NAME] Start one unit and stop all others\n"
3931 " kill [NAME...] Send signal to processes of a unit\n"
3932 " is-active [NAME...] Check whether units are active\n"
3933 " status [NAME...|PID...] Show runtime status of one or more units\n"
3934 " show [NAME...|JOB...] Show properties of one or more\n"
3935 " units/jobs or the manager\n"
3936 " help [NAME...|PID...] Show manual for one or more units\n"
3937 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
3939 " load [NAME...] Load one or more units\n\n"
3940 "Unit File Commands:\n"
3941 " list-unit-files List installed unit files\n"
3942 " enable [NAME...] Enable one or more unit files\n"
3943 " disable [NAME...] Disable one or more unit files\n"
3944 " reenable [NAME...] Reenable one or more unit files\n"
3945 " preset [NAME...] Enable/disable one or more unit files\n"
3946 " based on preset configuration\n"
3947 " mask [NAME...] Mask one or more units\n"
3948 " unmask [NAME...] Unmask one or more units\n"
3949 " link [PATH...] Link one or more units files into\n"
3950 " the search path\n"
3951 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
3953 " list-jobs List jobs\n"
3954 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
3955 "Status Commands:\n"
3956 " dump Dump server status\n"
3957 " dot Dump dependency graph for dot(1)\n\n"
3958 "Snapshot Commands:\n"
3959 " snapshot [NAME] Create a snapshot\n"
3960 " delete [NAME...] Remove one or more snapshots\n\n"
3961 "Environment Commands:\n"
3962 " show-environment Dump environment\n"
3963 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
3964 " unset-environment [NAME...] Unset one or more environment variables\n\n"
3965 "Manager Lifecycle Commands:\n"
3966 " daemon-reload Reload systemd manager configuration\n"
3967 " daemon-reexec Reexecute systemd manager\n\n"
3968 "System Commands:\n"
3969 " default Enter system default mode\n"
3970 " rescue Enter system rescue mode\n"
3971 " emergency Enter system emergency mode\n"
3972 " halt Shut down and halt the system\n"
3973 " poweroff Shut down and power-off the system\n"
3974 " reboot Shut down and reboot the system\n"
3975 " kexec Shut down and reboot the system with kexec\n"
3976 " exit Request user instance exit\n"
3977 " switch-root [ROOT] [INIT] Change to a different root file system\n"
3978 " suspend Suspend the system\n"
3979 " hibernate Hibernate the system\n"
3980 " hybrid-sleep Hibernate and suspend 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,
4076 static const struct option options[] = {
4077 { "help", no_argument, NULL, 'h' },
4078 { "version", no_argument, NULL, ARG_VERSION },
4079 { "type", required_argument, NULL, 't' },
4080 { "property", required_argument, NULL, 'p' },
4081 { "all", no_argument, NULL, 'a' },
4082 { "failed", no_argument, NULL, ARG_FAILED },
4083 { "full", no_argument, NULL, ARG_FULL },
4084 { "fail", no_argument, NULL, ARG_FAIL },
4085 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4086 { "user", no_argument, NULL, ARG_USER },
4087 { "system", no_argument, NULL, ARG_SYSTEM },
4088 { "global", no_argument, NULL, ARG_GLOBAL },
4089 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4090 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4091 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4092 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4093 { "quiet", no_argument, NULL, 'q' },
4094 { "order", no_argument, NULL, ARG_ORDER },
4095 { "require", no_argument, NULL, ARG_REQUIRE },
4096 { "root", required_argument, NULL, ARG_ROOT },
4097 { "force", no_argument, NULL, ARG_FORCE },
4098 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4099 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4100 { "signal", required_argument, NULL, 's' },
4101 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4102 { "host", required_argument, NULL, 'H' },
4103 { "privileged",no_argument, NULL, 'P' },
4104 { "runtime", no_argument, NULL, ARG_RUNTIME },
4105 { "lines", required_argument, NULL, 'n' },
4106 { "output", required_argument, NULL, 'o' },
4107 { NULL, 0, NULL, 0 }
4115 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4124 puts(PACKAGE_STRING);
4126 puts(SYSTEMD_FEATURES);
4130 if (unit_type_from_string(optarg) >= 0) {
4134 if (unit_load_state_from_string(optarg) >= 0) {
4135 arg_load_state = optarg;
4138 log_error("Unkown unit type or load state '%s'.",
4144 if (!(l = strv_append(arg_property, optarg)))
4147 strv_free(arg_property);
4150 /* If the user asked for a particular
4151 * property, show it to him, even if it is
4162 arg_job_mode = "fail";
4165 case ARG_IGNORE_DEPENDENCIES:
4166 arg_job_mode = "ignore-dependencies";
4170 arg_scope = UNIT_FILE_USER;
4174 arg_scope = UNIT_FILE_SYSTEM;
4178 arg_scope = UNIT_FILE_GLOBAL;
4182 arg_no_block = true;
4186 arg_no_legend = true;
4190 arg_no_pager = true;
4198 arg_dot = DOT_ORDER;
4202 arg_dot = DOT_REQUIRE;
4230 arg_no_reload = true;
4234 arg_kill_who = optarg;
4238 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4239 log_error("Failed to parse signal string %s.", optarg);
4244 case ARG_NO_ASK_PASSWORD:
4245 arg_ask_password = false;
4249 arg_transport = TRANSPORT_POLKIT;
4253 arg_transport = TRANSPORT_SSH;
4262 if (safe_atou(optarg, &arg_lines) < 0) {
4263 log_error("Failed to parse lines '%s'", optarg);
4269 arg_output = output_mode_from_string(optarg);
4270 if (arg_output < 0) {
4271 log_error("Unknown output '%s'.", optarg);
4280 log_error("Unknown option code '%c'.", c);
4285 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4286 log_error("Cannot access user instance remotely.");
4293 static int halt_parse_argv(int argc, char *argv[]) {
4302 static const struct option options[] = {
4303 { "help", no_argument, NULL, ARG_HELP },
4304 { "halt", no_argument, NULL, ARG_HALT },
4305 { "poweroff", no_argument, NULL, 'p' },
4306 { "reboot", no_argument, NULL, ARG_REBOOT },
4307 { "force", no_argument, NULL, 'f' },
4308 { "wtmp-only", no_argument, NULL, 'w' },
4309 { "no-wtmp", no_argument, NULL, 'd' },
4310 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4311 { NULL, 0, NULL, 0 }
4319 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4320 if (runlevel == '0' || runlevel == '6')
4323 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4331 arg_action = ACTION_HALT;
4335 if (arg_action != ACTION_REBOOT)
4336 arg_action = ACTION_POWEROFF;
4340 arg_action = ACTION_REBOOT;
4362 /* Compatibility nops */
4369 log_error("Unknown option code '%c'.", c);
4374 if (optind < argc) {
4375 log_error("Too many arguments.");
4382 static int parse_time_spec(const char *t, usec_t *_u) {
4386 if (streq(t, "now"))
4388 else if (!strchr(t, ':')) {
4391 if (safe_atou64(t, &u) < 0)
4394 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4403 hour = strtol(t, &e, 10);
4404 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4407 minute = strtol(e+1, &e, 10);
4408 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4411 n = now(CLOCK_REALTIME);
4412 s = (time_t) (n / USEC_PER_SEC);
4415 assert_se(localtime_r(&s, &tm));
4417 tm.tm_hour = (int) hour;
4418 tm.tm_min = (int) minute;
4421 assert_se(s = mktime(&tm));
4423 *_u = (usec_t) s * USEC_PER_SEC;
4426 *_u += USEC_PER_DAY;
4432 static int shutdown_parse_argv(int argc, char *argv[]) {
4439 static const struct option options[] = {
4440 { "help", no_argument, NULL, ARG_HELP },
4441 { "halt", no_argument, NULL, 'H' },
4442 { "poweroff", no_argument, NULL, 'P' },
4443 { "reboot", no_argument, NULL, 'r' },
4444 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4445 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4446 { NULL, 0, NULL, 0 }
4454 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4462 arg_action = ACTION_HALT;
4466 arg_action = ACTION_POWEROFF;
4471 arg_action = ACTION_KEXEC;
4473 arg_action = ACTION_REBOOT;
4477 arg_action = ACTION_KEXEC;
4481 if (arg_action != ACTION_HALT)
4482 arg_action = ACTION_POWEROFF;
4495 /* Compatibility nops */
4499 arg_action = ACTION_CANCEL_SHUTDOWN;
4506 log_error("Unknown option code '%c'.", c);
4511 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4512 r = parse_time_spec(argv[optind], &arg_when);
4514 log_error("Failed to parse time specification: %s", argv[optind]);
4518 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4520 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4521 /* No time argument for shutdown cancel */
4522 arg_wall = argv + optind;
4523 else if (argc > optind + 1)
4524 /* We skip the time argument */
4525 arg_wall = argv + optind + 1;
4532 static int telinit_parse_argv(int argc, char *argv[]) {
4539 static const struct option options[] = {
4540 { "help", no_argument, NULL, ARG_HELP },
4541 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4542 { NULL, 0, NULL, 0 }
4545 static const struct {
4549 { '0', ACTION_POWEROFF },
4550 { '6', ACTION_REBOOT },
4551 { '1', ACTION_RESCUE },
4552 { '2', ACTION_RUNLEVEL2 },
4553 { '3', ACTION_RUNLEVEL3 },
4554 { '4', ACTION_RUNLEVEL4 },
4555 { '5', ACTION_RUNLEVEL5 },
4556 { 's', ACTION_RESCUE },
4557 { 'S', ACTION_RESCUE },
4558 { 'q', ACTION_RELOAD },
4559 { 'Q', ACTION_RELOAD },
4560 { 'u', ACTION_REEXEC },
4561 { 'U', ACTION_REEXEC }
4570 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4585 log_error("Unknown option code '%c'.", c);
4590 if (optind >= argc) {
4595 if (optind + 1 < argc) {
4596 log_error("Too many arguments.");
4600 if (strlen(argv[optind]) != 1) {
4601 log_error("Expected single character argument.");
4605 for (i = 0; i < ELEMENTSOF(table); i++)
4606 if (table[i].from == argv[optind][0])
4609 if (i >= ELEMENTSOF(table)) {
4610 log_error("Unknown command '%s'.", argv[optind]);
4614 arg_action = table[i].to;
4621 static int runlevel_parse_argv(int argc, char *argv[]) {
4627 static const struct option options[] = {
4628 { "help", no_argument, NULL, ARG_HELP },
4629 { NULL, 0, NULL, 0 }
4637 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4648 log_error("Unknown option code '%c'.", c);
4653 if (optind < argc) {
4654 log_error("Too many arguments.");
4661 static int parse_argv(int argc, char *argv[]) {
4665 if (program_invocation_short_name) {
4667 if (strstr(program_invocation_short_name, "halt")) {
4668 arg_action = ACTION_HALT;
4669 return halt_parse_argv(argc, argv);
4670 } else if (strstr(program_invocation_short_name, "poweroff")) {
4671 arg_action = ACTION_POWEROFF;
4672 return halt_parse_argv(argc, argv);
4673 } else if (strstr(program_invocation_short_name, "reboot")) {
4675 arg_action = ACTION_KEXEC;
4677 arg_action = ACTION_REBOOT;
4678 return halt_parse_argv(argc, argv);
4679 } else if (strstr(program_invocation_short_name, "shutdown")) {
4680 arg_action = ACTION_POWEROFF;
4681 return shutdown_parse_argv(argc, argv);
4682 } else if (strstr(program_invocation_short_name, "init")) {
4684 if (sd_booted() > 0) {
4685 arg_action = ACTION_INVALID;
4686 return telinit_parse_argv(argc, argv);
4688 /* Hmm, so some other init system is
4689 * running, we need to forward this
4690 * request to it. For now we simply
4691 * guess that it is Upstart. */
4693 execv("/lib/upstart/telinit", argv);
4695 log_error("Couldn't find an alternative telinit implementation to spawn.");
4699 } else if (strstr(program_invocation_short_name, "runlevel")) {
4700 arg_action = ACTION_RUNLEVEL;
4701 return runlevel_parse_argv(argc, argv);
4705 arg_action = ACTION_SYSTEMCTL;
4706 return systemctl_parse_argv(argc, argv);
4709 static int action_to_runlevel(void) {
4711 static const char table[_ACTION_MAX] = {
4712 [ACTION_HALT] = '0',
4713 [ACTION_POWEROFF] = '0',
4714 [ACTION_REBOOT] = '6',
4715 [ACTION_RUNLEVEL2] = '2',
4716 [ACTION_RUNLEVEL3] = '3',
4717 [ACTION_RUNLEVEL4] = '4',
4718 [ACTION_RUNLEVEL5] = '5',
4719 [ACTION_RESCUE] = '1'
4722 assert(arg_action < _ACTION_MAX);
4724 return table[arg_action];
4727 static int talk_upstart(void) {
4728 DBusMessage *m = NULL, *reply = NULL;
4730 int previous, rl, r;
4732 env1_buf[] = "RUNLEVEL=X",
4733 env2_buf[] = "PREVLEVEL=X";
4734 char *env1 = env1_buf, *env2 = env2_buf;
4735 const char *emit = "runlevel";
4736 dbus_bool_t b_false = FALSE;
4737 DBusMessageIter iter, sub;
4738 DBusConnection *bus;
4740 dbus_error_init(&error);
4742 if (!(rl = action_to_runlevel()))
4745 if (utmp_get_runlevel(&previous, NULL) < 0)
4748 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4749 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4754 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4759 if ((r = bus_check_peercred(bus)) < 0) {
4760 log_error("Failed to verify owner of bus.");
4764 if (!(m = dbus_message_new_method_call(
4765 "com.ubuntu.Upstart",
4766 "/com/ubuntu/Upstart",
4767 "com.ubuntu.Upstart0_6",
4770 log_error("Could not allocate message.");
4775 dbus_message_iter_init_append(m, &iter);
4777 env1_buf[sizeof(env1_buf)-2] = rl;
4778 env2_buf[sizeof(env2_buf)-2] = previous;
4780 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4781 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4782 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4783 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4784 !dbus_message_iter_close_container(&iter, &sub) ||
4785 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4786 log_error("Could not append arguments to message.");
4791 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4793 if (bus_error_is_no_service(&error)) {
4798 log_error("Failed to issue method call: %s", bus_error_message(&error));
4807 dbus_message_unref(m);
4810 dbus_message_unref(reply);
4813 dbus_connection_flush(bus);
4814 dbus_connection_close(bus);
4815 dbus_connection_unref(bus);
4818 dbus_error_free(&error);
4823 static int talk_initctl(void) {
4824 struct init_request request;
4828 if (!(rl = action_to_runlevel()))
4832 request.magic = INIT_MAGIC;
4833 request.sleeptime = 0;
4834 request.cmd = INIT_CMD_RUNLVL;
4835 request.runlevel = rl;
4837 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4839 if (errno == ENOENT)
4842 log_error("Failed to open "INIT_FIFO": %m");
4847 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
4848 close_nointr_nofail(fd);
4851 log_error("Failed to write to "INIT_FIFO": %m");
4852 return errno ? -errno : -EIO;
4858 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
4860 static const struct {
4868 int (* const dispatch)(DBusConnection *bus, char **args);
4870 { "list-units", LESS, 1, list_units },
4871 { "list-unit-files", EQUAL, 1, list_unit_files },
4872 { "list-jobs", EQUAL, 1, list_jobs },
4873 { "clear-jobs", EQUAL, 1, daemon_reload },
4874 { "load", MORE, 2, load_unit },
4875 { "cancel", MORE, 2, cancel_job },
4876 { "start", MORE, 2, start_unit },
4877 { "stop", MORE, 2, start_unit },
4878 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4879 { "reload", MORE, 2, start_unit },
4880 { "restart", MORE, 2, start_unit },
4881 { "try-restart", MORE, 2, start_unit },
4882 { "reload-or-restart", MORE, 2, start_unit },
4883 { "reload-or-try-restart", MORE, 2, start_unit },
4884 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
4885 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4886 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
4887 { "isolate", EQUAL, 2, start_unit },
4888 { "kill", MORE, 2, kill_unit },
4889 { "is-active", MORE, 2, check_unit },
4890 { "check", MORE, 2, check_unit },
4891 { "show", MORE, 1, show },
4892 { "status", MORE, 2, show },
4893 { "help", MORE, 2, show },
4894 { "dump", EQUAL, 1, dump },
4895 { "dot", EQUAL, 1, dot },
4896 { "snapshot", LESS, 2, snapshot },
4897 { "delete", MORE, 2, delete_snapshot },
4898 { "daemon-reload", EQUAL, 1, daemon_reload },
4899 { "daemon-reexec", EQUAL, 1, daemon_reload },
4900 { "show-environment", EQUAL, 1, show_enviroment },
4901 { "set-environment", MORE, 2, set_environment },
4902 { "unset-environment", MORE, 2, set_environment },
4903 { "halt", EQUAL, 1, start_special },
4904 { "poweroff", EQUAL, 1, start_special },
4905 { "reboot", EQUAL, 1, start_special },
4906 { "kexec", EQUAL, 1, start_special },
4907 { "suspend", EQUAL, 1, start_special },
4908 { "hibernate", EQUAL, 1, start_special },
4909 { "hybrid-sleep", EQUAL, 1, start_special },
4910 { "default", EQUAL, 1, start_special },
4911 { "rescue", EQUAL, 1, start_special },
4912 { "emergency", EQUAL, 1, start_special },
4913 { "exit", EQUAL, 1, start_special },
4914 { "reset-failed", MORE, 1, reset_failed },
4915 { "enable", MORE, 2, enable_unit },
4916 { "disable", MORE, 2, enable_unit },
4917 { "is-enabled", MORE, 2, unit_is_enabled },
4918 { "reenable", MORE, 2, enable_unit },
4919 { "preset", MORE, 2, enable_unit },
4920 { "mask", MORE, 2, enable_unit },
4921 { "unmask", MORE, 2, enable_unit },
4922 { "link", MORE, 2, enable_unit },
4923 { "switch-root", MORE, 2, switch_root },
4933 left = argc - optind;
4936 /* Special rule: no arguments means "list-units" */
4939 if (streq(argv[optind], "help") && !argv[optind+1]) {
4940 log_error("This command expects one or more "
4941 "unit names. Did you mean --help?");
4945 for (i = 0; i < ELEMENTSOF(verbs); i++)
4946 if (streq(argv[optind], verbs[i].verb))
4949 if (i >= ELEMENTSOF(verbs)) {
4950 log_error("Unknown operation '%s'.", argv[optind]);
4955 switch (verbs[i].argc_cmp) {
4958 if (left != verbs[i].argc) {
4959 log_error("Invalid number of arguments.");
4966 if (left < verbs[i].argc) {
4967 log_error("Too few arguments.");
4974 if (left > verbs[i].argc) {
4975 log_error("Too many arguments.");
4982 assert_not_reached("Unknown comparison operator.");
4985 /* Require a bus connection for all operations but
4987 if (!streq(verbs[i].verb, "enable") &&
4988 !streq(verbs[i].verb, "disable") &&
4989 !streq(verbs[i].verb, "is-enabled") &&
4990 !streq(verbs[i].verb, "list-unit-files") &&
4991 !streq(verbs[i].verb, "reenable") &&
4992 !streq(verbs[i].verb, "preset") &&
4993 !streq(verbs[i].verb, "mask") &&
4994 !streq(verbs[i].verb, "unmask") &&
4995 !streq(verbs[i].verb, "link")) {
4997 if (running_in_chroot() > 0) {
4998 log_info("Running in chroot, ignoring request.");
5002 if (((!streq(verbs[i].verb, "reboot") &&
5003 !streq(verbs[i].verb, "halt") &&
5004 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5005 log_error("Failed to get D-Bus connection: %s",
5006 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5012 if (!bus && !avoid_bus()) {
5013 log_error("Failed to get D-Bus connection: %s",
5014 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5019 return verbs[i].dispatch(bus, argv + optind);
5022 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5024 struct msghdr msghdr;
5025 struct iovec iovec[2];
5026 union sockaddr_union sockaddr;
5027 struct sd_shutdown_command c;
5029 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5036 c.dry_run = dry_run;
5040 sockaddr.sa.sa_family = AF_UNIX;
5041 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5044 msghdr.msg_name = &sockaddr;
5045 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5048 iovec[0].iov_base = (char*) &c;
5049 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5051 if (isempty(message))
5052 msghdr.msg_iovlen = 1;
5054 iovec[1].iov_base = (char*) message;
5055 iovec[1].iov_len = strlen(message);
5056 msghdr.msg_iovlen = 2;
5058 msghdr.msg_iov = iovec;
5060 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5061 close_nointr_nofail(fd);
5065 close_nointr_nofail(fd);
5069 static int reload_with_fallback(DBusConnection *bus) {
5072 /* First, try systemd via D-Bus. */
5073 if (daemon_reload(bus, NULL) >= 0)
5077 /* Nothing else worked, so let's try signals */
5078 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5080 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5081 log_error("kill() failed: %m");
5088 static int start_with_fallback(DBusConnection *bus) {
5091 /* First, try systemd via D-Bus. */
5092 if (start_unit(bus, NULL) >= 0)
5096 /* Hmm, talking to systemd via D-Bus didn't work. Then
5097 * let's try to talk to Upstart via D-Bus. */
5098 if (talk_upstart() > 0)
5101 /* Nothing else worked, so let's try
5103 if (talk_initctl() > 0)
5106 log_error("Failed to talk to init daemon.");
5110 warn_wall(arg_action);
5114 static _noreturn_ void halt_now(enum action a) {
5116 /* Make sure C-A-D is handled by the kernel from this
5118 reboot(RB_ENABLE_CAD);
5123 log_info("Halting.");
5124 reboot(RB_HALT_SYSTEM);
5127 case ACTION_POWEROFF:
5128 log_info("Powering off.");
5129 reboot(RB_POWER_OFF);
5133 log_info("Rebooting.");
5134 reboot(RB_AUTOBOOT);
5138 assert_not_reached("Unknown halt action.");
5141 assert_not_reached("Uh? This shouldn't happen.");
5144 static int halt_main(DBusConnection *bus) {
5147 if (geteuid() != 0) {
5148 /* Try logind if we are a normal user and no special
5149 * mode applies. Maybe PolicyKit allows us to shutdown
5152 if (arg_when <= 0 &&
5155 (arg_action == ACTION_POWEROFF ||
5156 arg_action == ACTION_REBOOT)) {
5157 r = reboot_with_logind(bus, arg_action);
5162 log_error("Must be root.");
5169 m = strv_join(arg_wall, " ");
5170 r = send_shutdownd(arg_when,
5171 arg_action == ACTION_HALT ? 'H' :
5172 arg_action == ACTION_POWEROFF ? 'P' :
5173 arg_action == ACTION_KEXEC ? 'K' :
5181 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5183 char date[FORMAT_TIMESTAMP_MAX];
5185 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5186 format_timestamp(date, sizeof(date), arg_when));
5191 if (!arg_dry && !arg_force)
5192 return start_with_fallback(bus);
5195 if (sd_booted() > 0)
5196 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5198 r = utmp_put_shutdown();
5200 log_warning("Failed to write utmp record: %s", strerror(-r));
5207 halt_now(arg_action);
5208 /* We should never reach this. */
5212 static int runlevel_main(void) {
5213 int r, runlevel, previous;
5215 r = utmp_get_runlevel(&runlevel, &previous);
5222 previous <= 0 ? 'N' : previous,
5223 runlevel <= 0 ? 'N' : runlevel);
5228 int main(int argc, char*argv[]) {
5229 int r, retval = EXIT_FAILURE;
5230 DBusConnection *bus = NULL;
5233 dbus_error_init(&error);
5235 log_parse_environment();
5238 r = parse_argv(argc, argv);
5242 retval = EXIT_SUCCESS;
5246 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5247 * let's shortcut this */
5248 if (arg_action == ACTION_RUNLEVEL) {
5249 r = runlevel_main();
5250 retval = r < 0 ? EXIT_FAILURE : r;
5254 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5255 log_info("Running in chroot, ignoring request.");
5261 if (arg_transport == TRANSPORT_NORMAL)
5262 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5263 else if (arg_transport == TRANSPORT_POLKIT) {
5264 bus_connect_system_polkit(&bus, &error);
5265 private_bus = false;
5266 } else if (arg_transport == TRANSPORT_SSH) {
5267 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5268 private_bus = false;
5270 assert_not_reached("Uh, invalid transport...");
5273 switch (arg_action) {
5275 case ACTION_SYSTEMCTL:
5276 r = systemctl_main(bus, argc, argv, &error);
5280 case ACTION_POWEROFF:
5286 case ACTION_RUNLEVEL2:
5287 case ACTION_RUNLEVEL3:
5288 case ACTION_RUNLEVEL4:
5289 case ACTION_RUNLEVEL5:
5291 case ACTION_EMERGENCY:
5292 case ACTION_DEFAULT:
5293 r = start_with_fallback(bus);
5298 r = reload_with_fallback(bus);
5301 case ACTION_CANCEL_SHUTDOWN: {
5305 m = strv_join(arg_wall, " ");
5307 retval = EXIT_FAILURE;
5311 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5313 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5318 case ACTION_INVALID:
5319 case ACTION_RUNLEVEL:
5321 assert_not_reached("Unknown action");
5324 retval = r < 0 ? EXIT_FAILURE : r;
5328 dbus_connection_flush(bus);
5329 dbus_connection_close(bus);
5330 dbus_connection_unref(bus);
5333 dbus_error_free(&error);
5337 strv_free(arg_property);
5340 ask_password_agent_close();
5341 polkit_agent_close();