1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/reboot.h>
28 #include <sys/ioctl.h>
32 #include <sys/socket.h>
35 #include <sys/prctl.h>
36 #include <dbus/dbus.h>
38 #include <systemd/sd-daemon.h>
39 #include <systemd/sd-shutdown.h>
45 #include "utmp-wtmp.h"
48 #include "path-util.h"
50 #include "dbus-common.h"
51 #include "cgroup-show.h"
52 #include "cgroup-util.h"
54 #include "path-lookup.h"
55 #include "conf-parser.h"
56 #include "exit-status.h"
57 #include "bus-errors.h"
59 #include "unit-name.h"
61 #include "spawn-ask-password-agent.h"
62 #include "spawn-polkit-agent.h"
64 #include "logs-show.h"
65 #include "path-util.h"
66 #include "socket-util.h"
68 static const char *arg_type = NULL;
69 static const char *arg_load_state = NULL;
70 static char **arg_property = NULL;
71 static bool arg_all = false;
72 static const char *arg_job_mode = "replace";
73 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
74 static bool arg_no_block = false;
75 static bool arg_no_legend = false;
76 static bool arg_no_pager = false;
77 static bool arg_no_wtmp = false;
78 static bool arg_no_wall = false;
79 static bool arg_no_reload = false;
80 static bool arg_dry = false;
81 static bool arg_quiet = false;
82 static bool arg_full = false;
83 static int arg_force = 0;
84 static bool arg_ask_password = true;
85 static bool arg_failed = false;
86 static bool arg_runtime = false;
87 static char **arg_wall = NULL;
88 static const char *arg_kill_who = NULL;
89 static int arg_signal = SIGTERM;
90 static const char *arg_root = NULL;
91 static usec_t arg_when = 0;
112 ACTION_CANCEL_SHUTDOWN,
114 } arg_action = ACTION_SYSTEMCTL;
120 static enum transport {
124 } arg_transport = TRANSPORT_NORMAL;
125 static const char *arg_host = NULL;
126 static bool arg_follow = false;
127 static unsigned arg_lines = 10;
128 static OutputMode arg_output = OUTPUT_SHORT;
130 static bool private_bus = false;
132 static int daemon_reload(DBusConnection *bus, char **args);
133 static void halt_now(enum action a);
135 static bool on_tty(void) {
138 /* Note that this is invoked relatively early, before we start
139 * the pager. That means the value we return reflects whether
140 * we originally were started on a tty, not if we currently
141 * are. But this is intended, since we want colour and so on
142 * when run in our own pager. */
144 if (_unlikely_(t < 0))
145 t = isatty(STDOUT_FILENO) > 0;
150 static void pager_open_if_enabled(void) {
152 /* Cache result before we open the pager */
161 static void ask_password_agent_open_if_enabled(void) {
163 /* Open the password agent as a child process if necessary */
165 if (!arg_ask_password)
168 if (arg_scope != UNIT_FILE_SYSTEM)
171 ask_password_agent_open();
175 static void polkit_agent_open_if_enabled(void) {
177 /* Open the polkit agent as a child process if necessary */
179 if (!arg_ask_password)
182 if (arg_scope != UNIT_FILE_SYSTEM)
189 static const char *ansi_highlight_red(bool b) {
194 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
197 static const char *ansi_highlight_green(bool b) {
202 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
205 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
208 if (!dbus_error_is_set(error))
211 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
212 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
213 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
214 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
215 return EXIT_NOPERMISSION;
217 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
218 return EXIT_NOTINSTALLED;
220 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
221 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
222 return EXIT_NOTIMPLEMENTED;
224 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
225 return EXIT_NOTCONFIGURED;
233 static void warn_wall(enum action a) {
234 static const char *table[_ACTION_MAX] = {
235 [ACTION_HALT] = "The system is going down for system halt NOW!",
236 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
237 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
238 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
239 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
240 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
241 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
250 p = strv_join(arg_wall, " ");
252 log_error("Failed to join strings.");
268 utmp_wall(table[a], NULL);
271 static bool avoid_bus(void) {
273 if (running_in_chroot() > 0)
276 if (sd_booted() <= 0)
279 if (!isempty(arg_root))
282 if (arg_scope == UNIT_FILE_GLOBAL)
290 const char *description;
291 const char *load_state;
292 const char *active_state;
293 const char *sub_state;
294 const char *following;
295 const char *unit_path;
297 const char *job_type;
298 const char *job_path;
301 static int compare_unit_info(const void *a, const void *b) {
303 const struct unit_info *u = a, *v = b;
305 d1 = strrchr(u->id, '.');
306 d2 = strrchr(v->id, '.');
311 if ((r = strcasecmp(d1, d2)) != 0)
315 return strcasecmp(u->id, v->id);
318 static bool output_show_unit(const struct unit_info *u) {
322 return streq(u->active_state, "failed");
324 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
325 streq(dot+1, arg_type))) &&
326 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
327 (arg_all || !(streq(u->active_state, "inactive")
328 || u->following[0]) || u->job_id > 0);
331 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
332 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
333 const struct unit_info *u;
335 max_id_len = sizeof("UNIT")-1;
336 active_len = sizeof("ACTIVE")-1;
337 sub_len = sizeof("SUB")-1;
338 job_len = sizeof("JOB")-1;
341 for (u = unit_infos; u < unit_infos + c; u++) {
342 if (!output_show_unit(u))
345 max_id_len = MAX(max_id_len, strlen(u->id));
346 active_len = MAX(active_len, strlen(u->active_state));
347 sub_len = MAX(sub_len, strlen(u->sub_state));
349 job_len = MAX(job_len, strlen(u->job_type));
354 id_len = MIN(max_id_len, 25);
355 basic_len = 5 + id_len + 6 + active_len + sub_len + job_len;
356 if (basic_len < (unsigned) columns()) {
357 unsigned extra_len, incr;
358 extra_len = columns() - basic_len;
359 /* Either UNIT already got 25, or is fully satisfied.
360 * Grant up to 25 to DESC now. */
361 incr = MIN(extra_len, 25);
364 /* split the remaining space between UNIT and DESC,
365 * but do not give UNIT more than it needs. */
367 incr = MIN(extra_len / 2, max_id_len - id_len);
369 desc_len += extra_len - incr;
375 if (!arg_no_legend) {
376 printf("%-*s %-6s %-*s %-*s %-*s ", id_len, "UNIT", "LOAD",
377 active_len, "ACTIVE", sub_len, "SUB", job_len, "JOB");
378 if (!arg_full && arg_no_pager)
379 printf("%.*s\n", desc_len, "DESCRIPTION");
381 printf("%s\n", "DESCRIPTION");
384 for (u = unit_infos; u < unit_infos + c; u++) {
386 const char *on_loaded, *off_loaded;
387 const char *on_active, *off_active;
389 if (!output_show_unit(u))
394 if (streq(u->load_state, "error")) {
395 on_loaded = ansi_highlight_red(true);
396 off_loaded = ansi_highlight_red(false);
398 on_loaded = off_loaded = "";
400 if (streq(u->active_state, "failed")) {
401 on_active = ansi_highlight_red(true);
402 off_active = ansi_highlight_red(false);
404 on_active = off_active = "";
406 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
408 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s ",
409 id_len, e ? e : u->id,
410 on_loaded, u->load_state, off_loaded,
411 on_active, active_len, u->active_state,
412 sub_len, u->sub_state, off_active,
413 job_len, u->job_id ? u->job_type : "");
414 if (!arg_full && arg_no_pager)
415 printf("%.*s\n", desc_len, u->description);
417 printf("%s\n", u->description);
422 if (!arg_no_legend) {
423 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
424 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
425 "SUB = The low-level unit activation state, values depend on unit type.\n"
426 "JOB = Pending job for the unit.\n");
429 printf("\n%u loaded units listed.\n"
430 "To show all installed unit files use 'systemctl list-unit-files'.\n", n_shown);
432 printf("\n%u loaded units listed. Pass --all to see loaded but inactive units, too.\n"
433 "To show all installed unit files use 'systemctl list-unit-files'.\n", n_shown);
437 static int list_units(DBusConnection *bus, char **args) {
438 DBusMessage *reply = NULL;
440 DBusMessageIter iter, sub, sub2;
441 unsigned c = 0, n_units = 0;
442 struct unit_info *unit_infos = NULL;
444 pager_open_if_enabled();
446 r = bus_method_call_with_reply (
448 "org.freedesktop.systemd1",
449 "/org/freedesktop/systemd1",
450 "org.freedesktop.systemd1.Manager",
458 if (!dbus_message_iter_init(reply, &iter) ||
459 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
460 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
461 log_error("Failed to parse reply.");
466 dbus_message_iter_recurse(&iter, &sub);
468 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
471 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
472 log_error("Failed to parse reply.");
480 n_units = MAX(2*c, 16);
481 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
484 log_error("Failed to allocate unit array.");
494 dbus_message_iter_recurse(&sub, &sub2);
496 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
497 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
498 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
499 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
500 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
501 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
502 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
503 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
504 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
505 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
506 log_error("Failed to parse reply.");
511 dbus_message_iter_next(&sub);
516 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
517 output_units_list(unit_infos, c);
522 dbus_message_unref(reply);
529 static int compare_unit_file_list(const void *a, const void *b) {
531 const UnitFileList *u = a, *v = b;
533 d1 = strrchr(u->path, '.');
534 d2 = strrchr(v->path, '.');
539 r = strcasecmp(d1, d2);
544 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
547 static bool output_show_unit_file(const UnitFileList *u) {
550 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
553 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
554 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
555 const UnitFileList *u;
557 max_id_len = sizeof("UNIT FILE")-1;
558 state_cols = sizeof("STATE")-1;
559 for (u = units; u < units + c; u++) {
560 if (!output_show_unit_file(u))
563 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
564 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
569 id_cols = MIN(max_id_len, 25);
570 basic_cols = 1 + id_cols + state_cols;
571 if (basic_cols < (unsigned) columns())
572 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
574 id_cols = max_id_len;
577 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
579 for (u = units; u < units + c; u++) {
581 const char *on, *off;
584 if (!output_show_unit_file(u))
589 if (u->state == UNIT_FILE_MASKED ||
590 u->state == UNIT_FILE_MASKED_RUNTIME ||
591 u->state == UNIT_FILE_DISABLED ||
592 u->state == UNIT_FILE_INVALID) {
593 on = ansi_highlight_red(true);
594 off = ansi_highlight_red(false);
595 } else if (u->state == UNIT_FILE_ENABLED) {
596 on = ansi_highlight_green(true);
597 off = ansi_highlight_green(false);
601 id = path_get_file_name(u->path);
603 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
605 printf("%-*s %s%-*s%s\n",
607 on, state_cols, unit_file_state_to_string(u->state), off);
613 printf("\n%u unit files listed.\n", n_shown);
616 static int list_unit_files(DBusConnection *bus, char **args) {
617 DBusMessage *reply = NULL;
619 DBusMessageIter iter, sub, sub2;
620 unsigned c = 0, n_units = 0;
621 UnitFileList *units = NULL;
623 pager_open_if_enabled();
630 h = hashmap_new(string_hash_func, string_compare_func);
634 r = unit_file_get_list(arg_scope, arg_root, h);
636 unit_file_list_free(h);
637 log_error("Failed to get unit file list: %s", strerror(-r));
641 n_units = hashmap_size(h);
642 units = new(UnitFileList, n_units);
644 unit_file_list_free(h);
648 HASHMAP_FOREACH(u, h, i) {
649 memcpy(units + c++, u, sizeof(UnitFileList));
655 r = bus_method_call_with_reply (
657 "org.freedesktop.systemd1",
658 "/org/freedesktop/systemd1",
659 "org.freedesktop.systemd1.Manager",
667 if (!dbus_message_iter_init(reply, &iter) ||
668 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
669 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
670 log_error("Failed to parse reply.");
675 dbus_message_iter_recurse(&iter, &sub);
677 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
681 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
682 log_error("Failed to parse reply.");
690 n_units = MAX(2*c, 16);
691 w = realloc(units, sizeof(struct UnitFileList) * n_units);
694 log_error("Failed to allocate unit array.");
704 dbus_message_iter_recurse(&sub, &sub2);
706 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
707 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
708 log_error("Failed to parse reply.");
713 u->state = unit_file_state_from_string(state);
715 dbus_message_iter_next(&sub);
721 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
722 output_unit_file_list(units, c);
729 dbus_message_unref(reply);
736 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
737 static const char * const colors[] = {
738 "Requires", "[color=\"black\"]",
739 "RequiresOverridable", "[color=\"black\"]",
740 "Requisite", "[color=\"darkblue\"]",
741 "RequisiteOverridable", "[color=\"darkblue\"]",
742 "Wants", "[color=\"grey66\"]",
743 "Conflicts", "[color=\"red\"]",
744 "ConflictedBy", "[color=\"red\"]",
745 "After", "[color=\"green\"]"
748 const char *c = NULL;
755 for (i = 0; i < ELEMENTSOF(colors); i += 2)
756 if (streq(colors[i], prop)) {
764 if (arg_dot != DOT_ALL)
765 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
768 switch (dbus_message_iter_get_arg_type(iter)) {
770 case DBUS_TYPE_ARRAY:
772 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
775 dbus_message_iter_recurse(iter, &sub);
777 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
780 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
781 dbus_message_iter_get_basic(&sub, &s);
782 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
784 dbus_message_iter_next(&sub);
794 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
795 DBusMessage *reply = NULL;
796 const char *interface = "org.freedesktop.systemd1.Unit";
798 DBusMessageIter iter, sub, sub2, sub3;
802 r = bus_method_call_with_reply (
804 "org.freedesktop.systemd1",
806 "org.freedesktop.DBus.Properties",
810 DBUS_TYPE_STRING, &interface,
815 if (!dbus_message_iter_init(reply, &iter) ||
816 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
817 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
818 log_error("Failed to parse reply.");
823 dbus_message_iter_recurse(&iter, &sub);
825 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
828 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
829 log_error("Failed to parse reply.");
834 dbus_message_iter_recurse(&sub, &sub2);
836 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
837 log_error("Failed to parse reply.");
842 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
843 log_error("Failed to parse reply.");
848 dbus_message_iter_recurse(&sub2, &sub3);
850 if (dot_one_property(name, prop, &sub3)) {
851 log_error("Failed to parse reply.");
856 dbus_message_iter_next(&sub);
861 dbus_message_unref(reply);
866 static int dot(DBusConnection *bus, char **args) {
867 DBusMessage *reply = NULL;
869 DBusMessageIter iter, sub, sub2;
871 r = bus_method_call_with_reply (
873 "org.freedesktop.systemd1",
874 "/org/freedesktop/systemd1",
875 "org.freedesktop.systemd1.Manager",
883 if (!dbus_message_iter_init(reply, &iter) ||
884 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
885 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
886 log_error("Failed to parse reply.");
891 printf("digraph systemd {\n");
893 dbus_message_iter_recurse(&iter, &sub);
894 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
895 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
897 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
898 log_error("Failed to parse reply.");
903 dbus_message_iter_recurse(&sub, &sub2);
905 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
906 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
907 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
908 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
909 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
910 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
911 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
912 log_error("Failed to parse reply.");
917 if ((r = dot_one(bus, id, unit_path)) < 0)
920 /* printf("\t\"%s\";\n", id); */
921 dbus_message_iter_next(&sub);
926 log_info(" Color legend: black = Requires\n"
927 " dark blue = Requisite\n"
928 " dark grey = Wants\n"
933 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
934 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
940 dbus_message_unref(reply);
945 static int list_jobs(DBusConnection *bus, char **args) {
946 DBusMessage *reply = NULL;
948 DBusMessageIter iter, sub, sub2;
951 pager_open_if_enabled();
953 r = bus_method_call_with_reply (
955 "org.freedesktop.systemd1",
956 "/org/freedesktop/systemd1",
957 "org.freedesktop.systemd1.Manager",
965 if (!dbus_message_iter_init(reply, &iter) ||
966 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
967 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
968 log_error("Failed to parse reply.");
973 dbus_message_iter_recurse(&iter, &sub);
976 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
978 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
979 const char *name, *type, *state, *job_path, *unit_path;
983 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
984 log_error("Failed to parse reply.");
989 dbus_message_iter_recurse(&sub, &sub2);
991 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
992 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
993 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
994 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
995 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
996 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
997 log_error("Failed to parse reply.");
1002 e = arg_full ? NULL : ellipsize(name, 25, 33);
1003 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1008 dbus_message_iter_next(&sub);
1012 printf("\n%u jobs listed.\n", k);
1018 dbus_message_unref(reply);
1023 static int load_unit(DBusConnection *bus, char **args) {
1029 STRV_FOREACH(name, args+1) {
1030 n = unit_name_mangle(*name);
1031 r = bus_method_call_with_reply (
1033 "org.freedesktop.systemd1",
1034 "/org/freedesktop/systemd1",
1035 "org.freedesktop.systemd1.Manager",
1039 DBUS_TYPE_STRING, n ? &n : name,
1050 static int cancel_job(DBusConnection *bus, char **args) {
1051 DBusMessage *reply = NULL;
1057 if (strv_length(args) <= 1)
1058 return daemon_reload(bus, args);
1060 STRV_FOREACH(name, args+1) {
1064 r = safe_atou(*name, &id);
1066 log_error("Failed to parse job id: %s", strerror(-r));
1069 assert_cc(sizeof(uint32_t) == sizeof(id));
1071 r = bus_method_call_with_reply (
1073 "org.freedesktop.systemd1",
1074 "/org/freedesktop/systemd1",
1075 "org.freedesktop.systemd1.Manager",
1079 DBUS_TYPE_UINT32, &id,
1084 if (!dbus_message_get_args(reply, NULL,
1085 DBUS_TYPE_OBJECT_PATH, &path,
1086 DBUS_TYPE_INVALID)) {
1087 log_error("Failed to parse reply");
1088 dbus_message_unref(reply);
1092 dbus_message_unref(reply);
1094 r = bus_method_call_with_reply (
1096 "org.freedesktop.systemd1",
1098 "org.freedesktop.systemd1.Job",
1111 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1112 DBusMessage *reply = NULL;
1113 dbus_bool_t b = FALSE;
1114 DBusMessageIter iter, sub;
1116 *interface = "org.freedesktop.systemd1.Unit",
1117 *property = "NeedDaemonReload",
1122 /* We ignore all errors here, since this is used to show a warning only */
1124 n = unit_name_mangle(unit);
1125 r = bus_method_call_with_reply (
1127 "org.freedesktop.systemd1",
1128 "/org/freedesktop/systemd1",
1129 "org.freedesktop.systemd1.Manager",
1133 DBUS_TYPE_STRING, n ? (const char**) &n : &unit,
1139 if (!dbus_message_get_args(reply, NULL,
1140 DBUS_TYPE_OBJECT_PATH, &path,
1144 dbus_message_unref(reply);
1145 r = bus_method_call_with_reply (
1147 "org.freedesktop.systemd1",
1149 "org.freedesktop.DBus.Properties",
1153 DBUS_TYPE_STRING, &interface,
1154 DBUS_TYPE_STRING, &property,
1159 if (!dbus_message_iter_init(reply, &iter) ||
1160 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1163 dbus_message_iter_recurse(&iter, &sub);
1165 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1168 dbus_message_iter_get_basic(&sub, &b);
1172 dbus_message_unref(reply);
1177 typedef struct WaitData {
1184 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1192 dbus_error_init(&error);
1194 log_debug("Got D-Bus request: %s.%s() on %s",
1195 dbus_message_get_interface(message),
1196 dbus_message_get_member(message),
1197 dbus_message_get_path(message));
1199 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1200 log_error("Warning! D-Bus connection terminated.");
1201 dbus_connection_close(connection);
1203 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1205 const char *path, *result, *unit;
1206 dbus_bool_t success = true;
1208 if (dbus_message_get_args(message, &error,
1209 DBUS_TYPE_UINT32, &id,
1210 DBUS_TYPE_OBJECT_PATH, &path,
1211 DBUS_TYPE_STRING, &unit,
1212 DBUS_TYPE_STRING, &result,
1213 DBUS_TYPE_INVALID)) {
1216 p = set_remove(d->set, (char*) path);
1219 if (!isempty(result))
1220 d->result = strdup(result);
1223 d->name = strdup(unit);
1228 dbus_error_free(&error);
1229 if (dbus_message_get_args(message, &error,
1230 DBUS_TYPE_UINT32, &id,
1231 DBUS_TYPE_OBJECT_PATH, &path,
1232 DBUS_TYPE_STRING, &result,
1233 DBUS_TYPE_INVALID)) {
1236 /* Compatibility with older systemd versions <
1237 * 183 during upgrades. This should be dropped
1239 p = set_remove(d->set, (char*) path);
1243 d->result = strdup(result);
1248 dbus_error_free(&error);
1249 if (dbus_message_get_args(message, &error,
1250 DBUS_TYPE_UINT32, &id,
1251 DBUS_TYPE_OBJECT_PATH, &path,
1252 DBUS_TYPE_BOOLEAN, &success,
1253 DBUS_TYPE_INVALID)) {
1256 /* Compatibility with older systemd versions <
1257 * 19 during upgrades. This should be dropped
1260 p = set_remove(d->set, (char*) path);
1264 d->result = strdup("failed");
1270 log_error("Failed to parse message: %s", bus_error_message(&error));
1274 dbus_error_free(&error);
1275 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1278 static int enable_wait_for_jobs(DBusConnection *bus) {
1286 dbus_error_init(&error);
1287 dbus_bus_add_match(bus,
1289 "sender='org.freedesktop.systemd1',"
1290 "interface='org.freedesktop.systemd1.Manager',"
1291 "member='JobRemoved',"
1292 "path='/org/freedesktop/systemd1'",
1295 if (dbus_error_is_set(&error)) {
1296 log_error("Failed to add match: %s", bus_error_message(&error));
1297 dbus_error_free(&error);
1301 /* This is slightly dirty, since we don't undo the match registrations. */
1305 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1315 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1318 while (!set_isempty(s)) {
1320 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1321 log_error("Disconnected from bus.");
1322 return -ECONNREFUSED;
1325 if (!arg_quiet && d.result) {
1326 if (streq(d.result, "timeout"))
1327 log_error("Job for %s timed out.", strna(d.name));
1328 else if (streq(d.result, "canceled"))
1329 log_error("Job for %s canceled.", strna(d.name));
1330 else if (streq(d.result, "dependency"))
1331 log_error("A dependency job for %s failed. See 'journalctl' for details.", strna(d.name));
1332 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1333 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl' for details.", strna(d.name), strna(d.name));
1336 if (streq_ptr(d.result, "timeout"))
1338 else if (streq_ptr(d.result, "canceled"))
1340 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1350 /* This is slightly dirty, since we don't undo the filter registration. */
1354 static int check_one_unit(DBusConnection *bus, char *name, bool quiet) {
1355 DBusMessage *reply = NULL;
1356 DBusMessageIter iter, sub;
1358 *interface = "org.freedesktop.systemd1.Unit",
1359 *property = "ActiveState";
1360 const char *path = NULL;
1367 n = unit_name_mangle(name);
1368 r = bus_method_call_with_reply (
1370 "org.freedesktop.systemd1",
1371 "/org/freedesktop/systemd1",
1372 "org.freedesktop.systemd1.Manager",
1376 DBUS_TYPE_STRING, n ? &n : &name,
1380 if ((r != -ENOMEM) && (!quiet))
1385 if (!dbus_message_get_args(reply, NULL,
1386 DBUS_TYPE_OBJECT_PATH, &path,
1387 DBUS_TYPE_INVALID)) {
1388 log_error("Failed to parse reply.");
1393 dbus_message_unref(reply);
1394 r = bus_method_call_with_reply (
1396 "org.freedesktop.systemd1",
1398 "org.freedesktop.DBus.Properties",
1402 DBUS_TYPE_STRING, &interface,
1403 DBUS_TYPE_STRING, &property,
1408 if (!dbus_message_iter_init(reply, &iter) ||
1409 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1410 log_error("Failed to parse reply.");
1415 dbus_message_iter_recurse(&iter, &sub);
1417 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1418 log_error("Failed to parse reply.");
1423 dbus_message_iter_get_basic(&sub, &state);
1428 if (streq(state, "active") || streq(state, "reloading"))
1431 r = 3; /* According to LSB: "program is not running" */
1435 dbus_message_unref(reply);
1440 static void check_triggering_units(
1441 DBusConnection *bus,
1442 const char *unit_name) {
1444 DBusMessage _cleanup_dbus_msg_unref_ *reply = NULL;
1445 DBusMessageIter iter, sub;
1446 char *service_trigger = NULL;
1447 const char *interface = "org.freedesktop.systemd1.Unit",
1448 *triggered_by_property = "TriggeredBy";
1450 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1451 bool print_warning_label = true;
1454 n = unit_name_mangle(unit_name);
1455 unit_path = unit_dbus_path_from_name(n ? n : unit_name);
1458 log_error("Could not allocate dbus path.");
1462 r = bus_method_call_with_reply (
1464 "org.freedesktop.systemd1",
1466 "org.freedesktop.DBus.Properties",
1470 DBUS_TYPE_STRING, &interface,
1471 DBUS_TYPE_STRING, &triggered_by_property,
1476 if (!dbus_message_iter_init(reply, &iter) ||
1477 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1478 log_error("Failed to parse reply.");
1482 dbus_message_iter_recurse(&iter, &sub);
1483 dbus_message_iter_recurse(&sub, &iter);
1486 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1488 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1489 log_error("Failed to parse reply.");
1493 dbus_message_iter_get_basic(&sub, &service_trigger);
1495 r = check_one_unit(bus, service_trigger, true);
1499 if (print_warning_label) {
1500 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1501 print_warning_label = false;
1503 log_warning(" %s", service_trigger);
1506 dbus_message_iter_next(&sub);
1510 static int start_unit_one(
1511 DBusConnection *bus,
1518 DBusMessage *reply = NULL;
1521 _cleanup_free_ char *n, *p = NULL;
1528 n = unit_name_mangle(name);
1532 r = bus_method_call_with_reply(
1534 "org.freedesktop.systemd1",
1535 "/org/freedesktop/systemd1",
1536 "org.freedesktop.systemd1.Manager",
1540 DBUS_TYPE_STRING, &n,
1541 DBUS_TYPE_STRING, &mode,
1544 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1545 /* There's always a fallback possible for
1546 * legacy actions. */
1549 log_error("Failed to issue method call: %s", bus_error_message(error));
1554 if (!dbus_message_get_args(reply, error,
1555 DBUS_TYPE_OBJECT_PATH, &path,
1556 DBUS_TYPE_INVALID)) {
1557 log_error("Failed to parse reply: %s", bus_error_message(error));
1562 if (need_daemon_reload(bus, n))
1563 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1564 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1575 log_error("Failed to add path to set.");
1582 /* When stopping a unit warn if it can still be triggered by
1583 * another active unit (socket, path, timer) */
1584 if (!arg_quiet && streq(method, "StopUnit"))
1585 check_triggering_units(bus, name);
1591 dbus_message_unref(reply);
1596 static enum action verb_to_action(const char *verb) {
1597 if (streq(verb, "halt"))
1599 else if (streq(verb, "poweroff"))
1600 return ACTION_POWEROFF;
1601 else if (streq(verb, "reboot"))
1602 return ACTION_REBOOT;
1603 else if (streq(verb, "kexec"))
1604 return ACTION_KEXEC;
1605 else if (streq(verb, "rescue"))
1606 return ACTION_RESCUE;
1607 else if (streq(verb, "emergency"))
1608 return ACTION_EMERGENCY;
1609 else if (streq(verb, "default"))
1610 return ACTION_DEFAULT;
1611 else if (streq(verb, "exit"))
1613 else if (streq(verb, "suspend"))
1614 return ACTION_SUSPEND;
1615 else if (streq(verb, "hibernate"))
1616 return ACTION_HIBERNATE;
1618 return ACTION_INVALID;
1621 static int start_unit(DBusConnection *bus, char **args) {
1623 static const char * const table[_ACTION_MAX] = {
1624 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1625 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1626 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1627 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1628 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1629 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1630 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1631 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1632 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1633 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1634 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1635 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1636 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1637 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET
1641 const char *method, *mode, *one_name;
1646 dbus_error_init(&error);
1650 ask_password_agent_open_if_enabled();
1652 if (arg_action == ACTION_SYSTEMCTL) {
1654 streq(args[0], "stop") ||
1655 streq(args[0], "condstop") ? "StopUnit" :
1656 streq(args[0], "reload") ? "ReloadUnit" :
1657 streq(args[0], "restart") ? "RestartUnit" :
1659 streq(args[0], "try-restart") ||
1660 streq(args[0], "condrestart") ? "TryRestartUnit" :
1662 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1664 streq(args[0], "reload-or-try-restart") ||
1665 streq(args[0], "condreload") ||
1667 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1671 (streq(args[0], "isolate") ||
1672 streq(args[0], "rescue") ||
1673 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1675 one_name = table[verb_to_action(args[0])];
1678 assert(arg_action < ELEMENTSOF(table));
1679 assert(table[arg_action]);
1681 method = "StartUnit";
1683 mode = (arg_action == ACTION_EMERGENCY ||
1684 arg_action == ACTION_RESCUE ||
1685 arg_action == ACTION_RUNLEVEL2 ||
1686 arg_action == ACTION_RUNLEVEL3 ||
1687 arg_action == ACTION_RUNLEVEL4 ||
1688 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1690 one_name = table[arg_action];
1693 if (!arg_no_block) {
1694 ret = enable_wait_for_jobs(bus);
1696 log_error("Could not watch jobs: %s", strerror(-ret));
1700 s = set_new(string_hash_func, string_compare_func);
1708 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1710 ret = translate_bus_error_to_exit_status(ret, &error);
1712 STRV_FOREACH(name, args+1) {
1713 r = start_unit_one(bus, method, *name, mode, &error, s);
1715 ret = translate_bus_error_to_exit_status(r, &error);
1716 dbus_error_free(&error);
1721 if (!arg_no_block) {
1722 r = wait_for_jobs(bus, s);
1731 dbus_error_free(&error);
1736 /* Ask systemd-logind, which might grant access to unprivileged users
1737 * through PolicyKit */
1738 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1741 dbus_bool_t interactive = true;
1743 polkit_agent_open_if_enabled();
1751 case ACTION_POWEROFF:
1752 method = "PowerOff";
1755 case ACTION_SUSPEND:
1759 case ACTION_HIBERNATE:
1760 method = "Hibernate";
1767 return bus_method_call_with_reply (
1769 "org.freedesktop.login1",
1770 "/org/freedesktop/login1",
1771 "org.freedesktop.login1.Manager",
1775 DBUS_TYPE_BOOLEAN, &interactive,
1782 static int start_special(DBusConnection *bus, char **args) {
1788 a = verb_to_action(args[0]);
1790 if (arg_force >= 2 && geteuid() != 0) {
1791 log_error("Must be root.");
1795 if (arg_force >= 2 &&
1796 (a == ACTION_HALT ||
1797 a == ACTION_POWEROFF ||
1798 a == ACTION_REBOOT))
1801 if (arg_force >= 1 &&
1802 (a == ACTION_HALT ||
1803 a == ACTION_POWEROFF ||
1804 a == ACTION_REBOOT ||
1805 a == ACTION_KEXEC ||
1807 return daemon_reload(bus, args);
1809 /* first try logind, to allow authentication with polkit */
1810 if (geteuid() != 0 &&
1811 (a == ACTION_POWEROFF ||
1812 a == ACTION_REBOOT ||
1813 a == ACTION_SUSPEND ||
1814 a == ACTION_HIBERNATE)) {
1815 r = reboot_with_logind(bus, a);
1820 r = start_unit(bus, args);
1827 static int check_unit(DBusConnection *bus, char **args) {
1829 int r = 3; /* According to LSB: "program is not running" */
1834 STRV_FOREACH(name, args+1) {
1835 int state = check_one_unit(bus, *name, arg_quiet);
1845 static int kill_unit(DBusConnection *bus, char **args) {
1852 arg_kill_who = "all";
1854 STRV_FOREACH(name, args+1) {
1855 n = unit_name_mangle(*name);
1856 r = bus_method_call_with_reply (
1858 "org.freedesktop.systemd1",
1859 "/org/freedesktop/systemd1",
1860 "org.freedesktop.systemd1.Manager",
1864 DBUS_TYPE_STRING, n ? &n : name,
1865 DBUS_TYPE_STRING, &arg_kill_who,
1866 DBUS_TYPE_INT32, &arg_signal,
1875 typedef struct ExecStatusInfo {
1883 usec_t start_timestamp;
1884 usec_t exit_timestamp;
1889 LIST_FIELDS(struct ExecStatusInfo, exec);
1892 static void exec_status_info_free(ExecStatusInfo *i) {
1901 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
1902 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
1903 DBusMessageIter sub2, sub3;
1907 int32_t code, status;
1913 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
1916 dbus_message_iter_recurse(sub, &sub2);
1918 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
1921 if (!(i->path = strdup(path)))
1924 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
1925 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
1929 dbus_message_iter_recurse(&sub2, &sub3);
1930 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1931 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1932 dbus_message_iter_next(&sub3);
1937 if (!(i->argv = new0(char*, n+1)))
1941 dbus_message_iter_recurse(&sub2, &sub3);
1942 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1945 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1946 dbus_message_iter_get_basic(&sub3, &s);
1947 dbus_message_iter_next(&sub3);
1949 if (!(i->argv[n++] = strdup(s)))
1953 if (!dbus_message_iter_next(&sub2) ||
1954 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
1955 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
1956 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
1957 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
1958 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
1959 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
1960 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
1961 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
1965 i->start_timestamp = (usec_t) start_timestamp;
1966 i->exit_timestamp = (usec_t) exit_timestamp;
1967 i->pid = (pid_t) pid;
1974 typedef struct UnitStatusInfo {
1976 const char *load_state;
1977 const char *active_state;
1978 const char *sub_state;
1979 const char *unit_file_state;
1981 const char *description;
1982 const char *following;
1984 char **documentation;
1986 const char *fragment_path;
1987 const char *source_path;
1988 const char *default_control_group;
1990 const char *load_error;
1993 usec_t inactive_exit_timestamp;
1994 usec_t inactive_exit_timestamp_monotonic;
1995 usec_t active_enter_timestamp;
1996 usec_t active_exit_timestamp;
1997 usec_t inactive_enter_timestamp;
1999 bool need_daemon_reload;
2004 const char *status_text;
2007 usec_t start_timestamp;
2008 usec_t exit_timestamp;
2010 int exit_code, exit_status;
2012 usec_t condition_timestamp;
2013 bool condition_result;
2016 unsigned n_accepted;
2017 unsigned n_connections;
2021 const char *sysfs_path;
2023 /* Mount, Automount */
2029 LIST_HEAD(ExecStatusInfo, exec);
2032 static void print_status_info(UnitStatusInfo *i) {
2034 const char *on, *off, *ss;
2036 char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
2037 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2042 /* This shows pretty information about a unit. See
2043 * print_property() for a low-level property printer */
2045 printf("%s", strna(i->id));
2047 if (i->description && !streq_ptr(i->id, i->description))
2048 printf(" - %s", i->description);
2053 printf("\t Follow: unit currently follows state of %s\n", i->following);
2055 if (streq_ptr(i->load_state, "error")) {
2056 on = ansi_highlight_red(true);
2057 off = ansi_highlight_red(false);
2061 path = i->source_path ? i->source_path : i->fragment_path;
2064 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2065 else if (path && i->unit_file_state)
2066 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2068 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2070 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2072 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2074 if (streq_ptr(i->active_state, "failed")) {
2075 on = ansi_highlight_red(true);
2076 off = ansi_highlight_red(false);
2077 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2078 on = ansi_highlight_green(true);
2079 off = ansi_highlight_green(false);
2084 printf("\t Active: %s%s (%s)%s",
2086 strna(i->active_state),
2090 printf("\t Active: %s%s%s",
2092 strna(i->active_state),
2095 if (!isempty(i->result) && !streq(i->result, "success"))
2096 printf(" (Result: %s)", i->result);
2098 timestamp = (streq_ptr(i->active_state, "active") ||
2099 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2100 (streq_ptr(i->active_state, "inactive") ||
2101 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2102 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2103 i->active_exit_timestamp;
2105 s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
2106 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2109 printf(" since %s; %s\n", s2, s1);
2111 printf(" since %s\n", s2);
2115 if (!i->condition_result && i->condition_timestamp > 0) {
2116 s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
2117 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2120 printf("\t start condition failed at %s; %s\n", s2, s1);
2122 printf("\t start condition failed at %s\n", s2);
2126 printf("\t Device: %s\n", i->sysfs_path);
2128 printf("\t Where: %s\n", i->where);
2130 printf("\t What: %s\n", i->what);
2132 if (!strv_isempty(i->documentation)) {
2136 STRV_FOREACH(t, i->documentation) {
2138 printf("\t Docs: %s\n", *t);
2141 printf("\t %s\n", *t);
2146 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2148 LIST_FOREACH(exec, p, i->exec) {
2152 /* Only show exited processes here */
2156 t = strv_join(p->argv, " ");
2157 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2160 good = is_clean_exit_lsb(p->code, p->status, NULL);
2162 on = ansi_highlight_red(true);
2163 off = ansi_highlight_red(false);
2167 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2169 if (p->code == CLD_EXITED) {
2172 printf("status=%i", p->status);
2174 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2179 printf("signal=%s", signal_to_string(p->status));
2181 printf(")%s\n", off);
2183 if (i->main_pid == p->pid &&
2184 i->start_timestamp == p->start_timestamp &&
2185 i->exit_timestamp == p->start_timestamp)
2186 /* Let's not show this twice */
2189 if (p->pid == i->control_pid)
2193 if (i->main_pid > 0 || i->control_pid > 0) {
2196 if (i->main_pid > 0) {
2197 printf("Main PID: %u", (unsigned) i->main_pid);
2201 get_process_comm(i->main_pid, &t);
2206 } else if (i->exit_code > 0) {
2207 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2209 if (i->exit_code == CLD_EXITED) {
2212 printf("status=%i", i->exit_status);
2214 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2219 printf("signal=%s", signal_to_string(i->exit_status));
2224 if (i->main_pid > 0 && i->control_pid > 0)
2227 if (i->control_pid > 0) {
2230 printf(" Control: %u", (unsigned) i->control_pid);
2232 get_process_comm(i->control_pid, &t);
2243 printf("\t Status: \"%s\"\n", i->status_text);
2245 if (i->default_control_group) {
2248 printf("\t CGroup: %s\n", i->default_control_group);
2250 if (arg_transport != TRANSPORT_SSH) {
2260 if (i->main_pid > 0)
2261 extra[k++] = i->main_pid;
2263 if (i->control_pid > 0)
2264 extra[k++] = i->control_pid;
2266 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2270 if (i->id && arg_transport != TRANSPORT_SSH) {
2272 arg_all * OUTPUT_SHOW_ALL |
2273 arg_follow * OUTPUT_FOLLOW |
2274 !arg_quiet * OUTPUT_WARN_CUTOFF |
2275 on_tty() * OUTPUT_COLOR;
2278 show_journal_by_unit(i->id, arg_output, 0,
2279 i->inactive_exit_timestamp_monotonic,
2283 if (i->need_daemon_reload)
2284 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2285 ansi_highlight_red(true),
2286 ansi_highlight_red(false),
2287 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2290 static void show_unit_help(UnitStatusInfo *i) {
2295 if (!i->documentation) {
2296 log_info("Documentation for %s not known.", i->id);
2300 STRV_FOREACH(p, i->documentation) {
2302 if (startswith(*p, "man:")) {
2305 char *page = NULL, *section = NULL;
2306 const char *args[4] = { "man", NULL, NULL, NULL };
2311 if ((*p)[k-1] == ')')
2312 e = strrchr(*p, '(');
2315 page = strndup((*p) + 4, e - *p - 4);
2321 section = strndup(e + 1, *p + k - e - 2);
2335 log_error("Failed to fork: %m");
2343 execvp(args[0], (char**) args);
2344 log_error("Failed to execute man: %m");
2345 _exit(EXIT_FAILURE);
2351 wait_for_terminate(pid, NULL);
2353 log_info("Can't show: %s", *p);
2357 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2363 switch (dbus_message_iter_get_arg_type(iter)) {
2365 case DBUS_TYPE_STRING: {
2368 dbus_message_iter_get_basic(iter, &s);
2371 if (streq(name, "Id"))
2373 else if (streq(name, "LoadState"))
2375 else if (streq(name, "ActiveState"))
2376 i->active_state = s;
2377 else if (streq(name, "SubState"))
2379 else if (streq(name, "Description"))
2381 else if (streq(name, "FragmentPath"))
2382 i->fragment_path = s;
2383 else if (streq(name, "SourcePath"))
2385 else if (streq(name, "DefaultControlGroup"))
2386 i->default_control_group = s;
2387 else if (streq(name, "StatusText"))
2389 else if (streq(name, "SysFSPath"))
2391 else if (streq(name, "Where"))
2393 else if (streq(name, "What"))
2395 else if (streq(name, "Following"))
2397 else if (streq(name, "UnitFileState"))
2398 i->unit_file_state = s;
2399 else if (streq(name, "Result"))
2406 case DBUS_TYPE_BOOLEAN: {
2409 dbus_message_iter_get_basic(iter, &b);
2411 if (streq(name, "Accept"))
2413 else if (streq(name, "NeedDaemonReload"))
2414 i->need_daemon_reload = b;
2415 else if (streq(name, "ConditionResult"))
2416 i->condition_result = b;
2421 case DBUS_TYPE_UINT32: {
2424 dbus_message_iter_get_basic(iter, &u);
2426 if (streq(name, "MainPID")) {
2428 i->main_pid = (pid_t) u;
2431 } else if (streq(name, "ControlPID"))
2432 i->control_pid = (pid_t) u;
2433 else if (streq(name, "ExecMainPID")) {
2435 i->main_pid = (pid_t) u;
2436 } else if (streq(name, "NAccepted"))
2438 else if (streq(name, "NConnections"))
2439 i->n_connections = u;
2444 case DBUS_TYPE_INT32: {
2447 dbus_message_iter_get_basic(iter, &j);
2449 if (streq(name, "ExecMainCode"))
2450 i->exit_code = (int) j;
2451 else if (streq(name, "ExecMainStatus"))
2452 i->exit_status = (int) j;
2457 case DBUS_TYPE_UINT64: {
2460 dbus_message_iter_get_basic(iter, &u);
2462 if (streq(name, "ExecMainStartTimestamp"))
2463 i->start_timestamp = (usec_t) u;
2464 else if (streq(name, "ExecMainExitTimestamp"))
2465 i->exit_timestamp = (usec_t) u;
2466 else if (streq(name, "ActiveEnterTimestamp"))
2467 i->active_enter_timestamp = (usec_t) u;
2468 else if (streq(name, "InactiveEnterTimestamp"))
2469 i->inactive_enter_timestamp = (usec_t) u;
2470 else if (streq(name, "InactiveExitTimestamp"))
2471 i->inactive_exit_timestamp = (usec_t) u;
2472 else if (streq(name, "InactiveExitTimestampMonotonic"))
2473 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2474 else if (streq(name, "ActiveExitTimestamp"))
2475 i->active_exit_timestamp = (usec_t) u;
2476 else if (streq(name, "ConditionTimestamp"))
2477 i->condition_timestamp = (usec_t) u;
2482 case DBUS_TYPE_ARRAY: {
2484 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2485 startswith(name, "Exec")) {
2486 DBusMessageIter sub;
2488 dbus_message_iter_recurse(iter, &sub);
2489 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2490 ExecStatusInfo *info;
2493 if (!(info = new0(ExecStatusInfo, 1)))
2496 if (!(info->name = strdup(name))) {
2501 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2506 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2508 dbus_message_iter_next(&sub);
2510 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2511 streq(name, "Documentation")) {
2513 DBusMessageIter sub;
2515 dbus_message_iter_recurse(iter, &sub);
2516 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2520 dbus_message_iter_get_basic(&sub, &s);
2522 l = strv_append(i->documentation, s);
2526 strv_free(i->documentation);
2527 i->documentation = l;
2529 dbus_message_iter_next(&sub);
2536 case DBUS_TYPE_STRUCT: {
2538 if (streq(name, "LoadError")) {
2539 DBusMessageIter sub;
2540 const char *n, *message;
2543 dbus_message_iter_recurse(iter, &sub);
2545 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2549 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2553 if (!isempty(message))
2554 i->load_error = message;
2564 static int print_property(const char *name, DBusMessageIter *iter) {
2568 /* This is a low-level property printer, see
2569 * print_status_info() for the nicer output */
2571 if (arg_property && !strv_find(arg_property, name))
2574 switch (dbus_message_iter_get_arg_type(iter)) {
2576 case DBUS_TYPE_STRUCT: {
2577 DBusMessageIter sub;
2578 dbus_message_iter_recurse(iter, &sub);
2580 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2583 dbus_message_iter_get_basic(&sub, &u);
2586 printf("%s=%u\n", name, (unsigned) u);
2588 printf("%s=\n", name);
2591 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2594 dbus_message_iter_get_basic(&sub, &s);
2596 if (arg_all || s[0])
2597 printf("%s=%s\n", name, s);
2600 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2601 const char *a = NULL, *b = NULL;
2603 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2604 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2606 if (arg_all || !isempty(a) || !isempty(b))
2607 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2615 case DBUS_TYPE_ARRAY:
2617 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2618 DBusMessageIter sub, sub2;
2620 dbus_message_iter_recurse(iter, &sub);
2621 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2625 dbus_message_iter_recurse(&sub, &sub2);
2627 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2628 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2629 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2631 dbus_message_iter_next(&sub);
2636 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2637 DBusMessageIter sub, sub2;
2639 dbus_message_iter_recurse(iter, &sub);
2640 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2641 const char *type, *path;
2643 dbus_message_iter_recurse(&sub, &sub2);
2645 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2646 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2647 printf("%s=%s\n", type, path);
2649 dbus_message_iter_next(&sub);
2654 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2655 DBusMessageIter sub, sub2;
2657 dbus_message_iter_recurse(iter, &sub);
2658 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2660 uint64_t value, next_elapse;
2662 dbus_message_iter_recurse(&sub, &sub2);
2664 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2665 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2666 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2667 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2669 printf("%s={ value=%s ; next_elapse=%s }\n",
2671 format_timespan(timespan1, sizeof(timespan1), value),
2672 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2675 dbus_message_iter_next(&sub);
2680 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2681 DBusMessageIter sub, sub2;
2683 dbus_message_iter_recurse(iter, &sub);
2684 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2685 const char *controller, *attr, *value;
2687 dbus_message_iter_recurse(&sub, &sub2);
2689 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2690 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2691 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2693 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2699 dbus_message_iter_next(&sub);
2704 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2705 DBusMessageIter sub;
2707 dbus_message_iter_recurse(iter, &sub);
2708 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2709 ExecStatusInfo info;
2712 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2713 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2716 t = strv_join(info.argv, " ");
2718 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2722 yes_no(info.ignore),
2723 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2724 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2725 (unsigned) info. pid,
2726 sigchld_code_to_string(info.code),
2728 info.code == CLD_EXITED ? "" : "/",
2729 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2735 strv_free(info.argv);
2737 dbus_message_iter_next(&sub);
2746 if (generic_print_property(name, iter, arg_all) > 0)
2750 printf("%s=[unprintable]\n", name);
2755 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2756 DBusMessage *reply = NULL;
2757 const char *interface = "";
2759 DBusMessageIter iter, sub, sub2, sub3;
2760 UnitStatusInfo info;
2768 r = bus_method_call_with_reply (
2770 "org.freedesktop.systemd1",
2772 "org.freedesktop.DBus.Properties",
2776 DBUS_TYPE_STRING, &interface,
2781 if (!dbus_message_iter_init(reply, &iter) ||
2782 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2783 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2784 log_error("Failed to parse reply.");
2789 dbus_message_iter_recurse(&iter, &sub);
2796 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2799 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2800 log_error("Failed to parse reply.");
2805 dbus_message_iter_recurse(&sub, &sub2);
2807 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2808 log_error("Failed to parse reply.");
2813 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2814 log_error("Failed to parse reply.");
2819 dbus_message_iter_recurse(&sub2, &sub3);
2821 if (show_properties)
2822 r = print_property(name, &sub3);
2824 r = status_property(name, &sub3, &info);
2827 log_error("Failed to parse reply.");
2832 dbus_message_iter_next(&sub);
2837 if (!show_properties) {
2838 if (streq(verb, "help"))
2839 show_unit_help(&info);
2841 print_status_info(&info);
2844 strv_free(info.documentation);
2846 if (!streq_ptr(info.active_state, "active") &&
2847 !streq_ptr(info.active_state, "reloading") &&
2848 streq(verb, "status"))
2849 /* According to LSB: "program not running" */
2852 while ((p = info.exec)) {
2853 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2854 exec_status_info_free(p);
2859 dbus_message_unref(reply);
2864 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
2865 DBusMessage *reply = NULL;
2866 const char *path = NULL;
2870 dbus_error_init(&error);
2872 r = bus_method_call_with_reply (
2874 "org.freedesktop.systemd1",
2875 "/org/freedesktop/systemd1",
2876 "org.freedesktop.systemd1.Manager",
2880 DBUS_TYPE_UINT32, &pid,
2885 if (!dbus_message_get_args(reply, &error,
2886 DBUS_TYPE_OBJECT_PATH, &path,
2887 DBUS_TYPE_INVALID)) {
2888 log_error("Failed to parse reply: %s", bus_error_message(&error));
2893 r = show_one(verb, bus, path, false, new_line);
2897 dbus_message_unref(reply);
2899 dbus_error_free(&error);
2904 static int show(DBusConnection *bus, char **args) {
2906 bool show_properties, new_line = false;
2912 show_properties = streq(args[0], "show");
2914 if (show_properties)
2915 pager_open_if_enabled();
2917 if (show_properties && strv_length(args) <= 1) {
2918 /* If not argument is specified inspect the manager
2921 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2924 STRV_FOREACH(name, args+1) {
2927 if (safe_atou32(*name, &id) < 0) {
2929 /* Interpret as unit name */
2931 n = unit_name_mangle(*name);
2932 p = unit_dbus_path_from_name(n ? n : *name);
2937 r = show_one(args[0], bus, p, show_properties, &new_line);
2943 } else if (show_properties) {
2945 /* Interpret as job id */
2948 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
2951 r = show_one(args[0], bus, p, show_properties, &new_line);
2959 /* Interpret as PID */
2961 r = show_one_by_pid(args[0], bus, id, &new_line);
2970 static int dump(DBusConnection *bus, char **args) {
2971 DBusMessage *reply = NULL;
2976 dbus_error_init(&error);
2978 pager_open_if_enabled();
2980 r = bus_method_call_with_reply (
2982 "org.freedesktop.systemd1",
2983 "/org/freedesktop/systemd1",
2984 "org.freedesktop.systemd1.Manager",
2992 if (!dbus_message_get_args(reply, &error,
2993 DBUS_TYPE_STRING, &text,
2994 DBUS_TYPE_INVALID)) {
2995 log_error("Failed to parse reply: %s", bus_error_message(&error));
3000 fputs(text, stdout);
3004 dbus_message_unref(reply);
3006 dbus_error_free(&error);
3011 static int snapshot(DBusConnection *bus, char **args) {
3012 DBusMessage *reply = NULL;
3015 dbus_bool_t cleanup = FALSE;
3016 DBusMessageIter iter, sub;
3018 *name = "", *path, *id,
3019 *interface = "org.freedesktop.systemd1.Unit",
3023 dbus_error_init(&error);
3025 if (strv_length(args) > 1)
3028 n = unit_name_mangle(name);
3029 r = bus_method_call_with_reply (
3031 "org.freedesktop.systemd1",
3032 "/org/freedesktop/systemd1",
3033 "org.freedesktop.systemd1.Manager",
3037 DBUS_TYPE_STRING, n ? (const char**) &n : &name,
3038 DBUS_TYPE_BOOLEAN, &cleanup,
3044 if (!dbus_message_get_args(reply, &error,
3045 DBUS_TYPE_OBJECT_PATH, &path,
3046 DBUS_TYPE_INVALID)) {
3047 log_error("Failed to parse reply: %s", bus_error_message(&error));
3052 dbus_message_unref(reply);
3053 r = bus_method_call_with_reply (
3055 "org.freedesktop.systemd1",
3057 "org.freedesktop.DBus.Properties",
3061 DBUS_TYPE_STRING, &interface,
3062 DBUS_TYPE_STRING, &property,
3067 if (!dbus_message_iter_init(reply, &iter) ||
3068 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3069 log_error("Failed to parse reply.");
3074 dbus_message_iter_recurse(&iter, &sub);
3076 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3077 log_error("Failed to parse reply.");
3082 dbus_message_iter_get_basic(&sub, &id);
3089 dbus_message_unref(reply);
3091 dbus_error_free(&error);
3096 static int delete_snapshot(DBusConnection *bus, char **args) {
3097 DBusMessage *reply = NULL;
3104 dbus_error_init(&error);
3106 STRV_FOREACH(name, args+1) {
3107 const char *path = NULL;
3110 n = unit_name_mangle(*name);
3111 r = bus_method_call_with_reply (
3113 "org.freedesktop.systemd1",
3114 "/org/freedesktop/systemd1",
3115 "org.freedesktop.systemd1.Manager",
3119 DBUS_TYPE_STRING, n ? &n : name,
3125 if (!dbus_message_get_args(reply, &error,
3126 DBUS_TYPE_OBJECT_PATH, &path,
3127 DBUS_TYPE_INVALID)) {
3128 log_error("Failed to parse reply: %s", bus_error_message(&error));
3130 dbus_message_unref(reply);
3131 dbus_error_free(&error);
3134 dbus_message_unref(reply);
3136 r = bus_method_call_with_reply (
3138 "org.freedesktop.systemd1",
3140 "org.freedesktop.systemd1.Snapshot",
3153 static int daemon_reload(DBusConnection *bus, char **args) {
3158 if (arg_action == ACTION_RELOAD)
3160 else if (arg_action == ACTION_REEXEC)
3161 method = "Reexecute";
3163 assert(arg_action == ACTION_SYSTEMCTL);
3166 streq(args[0], "clear-jobs") ||
3167 streq(args[0], "cancel") ? "ClearJobs" :
3168 streq(args[0], "daemon-reexec") ? "Reexecute" :
3169 streq(args[0], "reset-failed") ? "ResetFailed" :
3170 streq(args[0], "halt") ? "Halt" :
3171 streq(args[0], "poweroff") ? "PowerOff" :
3172 streq(args[0], "reboot") ? "Reboot" :
3173 streq(args[0], "kexec") ? "KExec" :
3174 streq(args[0], "exit") ? "Exit" :
3175 /* "daemon-reload" */ "Reload";
3178 r = bus_method_call_with_reply (
3180 "org.freedesktop.systemd1",
3181 "/org/freedesktop/systemd1",
3182 "org.freedesktop.systemd1.Manager",
3188 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3189 /* There's always a fallback possible for
3190 * legacy actions. */
3192 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3193 /* On reexecution, we expect a disconnect, not
3197 log_error("Failed to issue method call: %s", bus_error_message(&error));
3198 dbus_error_free(&error);
3203 static int reset_failed(DBusConnection *bus, char **args) {
3207 if (strv_length(args) <= 1)
3208 return daemon_reload(bus, args);
3210 STRV_FOREACH(name, args+1) {
3211 n = unit_name_mangle(*name);
3212 r = bus_method_call_with_reply (
3214 "org.freedesktop.systemd1",
3215 "/org/freedesktop/systemd1",
3216 "org.freedesktop.systemd1.Manager",
3220 DBUS_TYPE_STRING, n ? &n : name,
3231 static int show_enviroment(DBusConnection *bus, char **args) {
3232 DBusMessage *reply = NULL;
3233 DBusMessageIter iter, sub, sub2;
3236 *interface = "org.freedesktop.systemd1.Manager",
3237 *property = "Environment";
3239 pager_open_if_enabled();
3241 r = bus_method_call_with_reply (
3243 "org.freedesktop.systemd1",
3244 "/org/freedesktop/systemd1",
3245 "org.freedesktop.DBus.Properties",
3249 DBUS_TYPE_STRING, &interface,
3250 DBUS_TYPE_STRING, &property,
3255 if (!dbus_message_iter_init(reply, &iter) ||
3256 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3257 log_error("Failed to parse reply.");
3262 dbus_message_iter_recurse(&iter, &sub);
3264 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3265 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3266 log_error("Failed to parse reply.");
3271 dbus_message_iter_recurse(&sub, &sub2);
3273 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3276 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3277 log_error("Failed to parse reply.");
3282 dbus_message_iter_get_basic(&sub2, &text);
3283 printf("%s\n", text);
3285 dbus_message_iter_next(&sub2);
3292 dbus_message_unref(reply);
3297 static int switch_root(DBusConnection *bus, char **args) {
3299 const char *root, *init;
3301 l = strv_length(args);
3302 if (l < 2 || l > 3) {
3303 log_error("Wrong number of arguments.");
3308 init = l >= 3 ? args[2] : "";
3310 return bus_method_call_with_reply (
3312 "org.freedesktop.systemd1",
3313 "/org/freedesktop/systemd1",
3314 "org.freedesktop.systemd1.Manager",
3318 DBUS_TYPE_STRING, &root,
3319 DBUS_TYPE_STRING, &init,
3323 static int set_environment(DBusConnection *bus, char **args) {
3324 DBusMessage *m = NULL, *reply = NULL;
3328 DBusMessageIter iter, sub;
3331 dbus_error_init(&error);
3333 method = streq(args[0], "set-environment")
3335 : "UnsetEnvironment";
3337 if (!(m = dbus_message_new_method_call(
3338 "org.freedesktop.systemd1",
3339 "/org/freedesktop/systemd1",
3340 "org.freedesktop.systemd1.Manager",
3343 log_error("Could not allocate message.");
3347 dbus_message_iter_init_append(m, &iter);
3349 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
3350 log_error("Could not append arguments to message.");
3355 STRV_FOREACH(name, args+1)
3356 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, name)) {
3357 log_error("Could not append arguments to message.");
3362 if (!dbus_message_iter_close_container(&iter, &sub)) {
3363 log_error("Could not append arguments to message.");
3368 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3369 log_error("Failed to issue method call: %s", bus_error_message(&error));
3378 dbus_message_unref(m);
3381 dbus_message_unref(reply);
3383 dbus_error_free(&error);
3388 static int enable_sysv_units(char **args) {
3391 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3392 const char *verb = args[0];
3393 unsigned f = 1, t = 1;
3396 if (arg_scope != UNIT_FILE_SYSTEM)
3399 if (!streq(verb, "enable") &&
3400 !streq(verb, "disable") &&
3401 !streq(verb, "is-enabled"))
3404 /* Processes all SysV units, and reshuffles the array so that
3405 * afterwards only the native units remain */
3408 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3413 for (f = 1; args[f]; f++) {
3416 bool found_native = false, found_sysv;
3418 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3419 char **k, *l, *q = NULL;
3426 if (!endswith(name, ".service"))
3429 if (path_is_absolute(name))
3432 STRV_FOREACH(k, paths.unit_path) {
3435 if (!isempty(arg_root))
3436 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3438 asprintf(&p, "%s/%s", *k, name);
3445 found_native = access(p, F_OK) >= 0;
3456 if (!isempty(arg_root))
3457 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3459 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3465 p[strlen(p) - sizeof(".service") + 1] = 0;
3466 found_sysv = access(p, F_OK) >= 0;
3473 /* Mark this entry, so that we don't try enabling it as native unit */
3474 args[f] = (char*) "";
3476 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3478 if (!isempty(arg_root))
3479 argv[c++] = q = strappend("--root=", arg_root);
3481 argv[c++] = path_get_file_name(p);
3483 streq(verb, "enable") ? "on" :
3484 streq(verb, "disable") ? "off" : "--level=5";
3487 l = strv_join((char**)argv, " ");
3495 log_info("Executing %s", l);
3500 log_error("Failed to fork: %m");
3505 } else if (pid == 0) {
3508 execv(argv[0], (char**) argv);
3509 _exit(EXIT_FAILURE);
3515 j = wait_for_terminate(pid, &status);
3517 log_error("Failed to wait for child: %s", strerror(-r));
3522 if (status.si_code == CLD_EXITED) {
3523 if (streq(verb, "is-enabled")) {
3524 if (status.si_status == 0) {
3533 } else if (status.si_status != 0) {
3544 lookup_paths_free(&paths);
3546 /* Drop all SysV units */
3547 for (f = 1, t = 1; args[f]; f++) {
3549 if (isempty(args[f]))
3552 args[t++] = args[f];
3561 static int mangle_names(char **original_names, char ***mangled_names) {
3562 char **i, **l, **name;
3564 l = new(char*, strv_length(original_names) + 1);
3569 STRV_FOREACH(name, original_names) {
3570 *i = unit_name_mangle(*name);
3585 static int enable_unit(DBusConnection *bus, char **args) {
3586 const char *verb = args[0];
3587 UnitFileChange *changes = NULL;
3588 unsigned n_changes = 0, i;
3589 int carries_install_info = -1;
3590 DBusMessage *m = NULL, *reply = NULL;
3593 char **mangled_names = NULL;
3595 r = enable_sysv_units(args);
3602 dbus_error_init(&error);
3604 if (!bus || avoid_bus()) {
3605 if (streq(verb, "enable")) {
3606 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3607 carries_install_info = r;
3608 } else if (streq(verb, "disable"))
3609 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3610 else if (streq(verb, "reenable")) {
3611 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3612 carries_install_info = r;
3613 } else if (streq(verb, "link"))
3614 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3615 else if (streq(verb, "preset")) {
3616 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3617 carries_install_info = r;
3618 } else if (streq(verb, "mask"))
3619 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3620 else if (streq(verb, "unmask"))
3621 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3623 assert_not_reached("Unknown verb");
3626 log_error("Operation failed: %s", strerror(-r));
3631 for (i = 0; i < n_changes; i++) {
3632 if (changes[i].type == UNIT_FILE_SYMLINK)
3633 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3635 log_info("rm '%s'", changes[i].path);
3641 bool send_force = true, expect_carries_install_info = false;
3643 DBusMessageIter iter, sub, sub2;
3645 if (streq(verb, "enable")) {
3646 method = "EnableUnitFiles";
3647 expect_carries_install_info = true;
3648 } else if (streq(verb, "disable")) {
3649 method = "DisableUnitFiles";
3651 } else if (streq(verb, "reenable")) {
3652 method = "ReenableUnitFiles";
3653 expect_carries_install_info = true;
3654 } else if (streq(verb, "link"))
3655 method = "LinkUnitFiles";
3656 else if (streq(verb, "preset")) {
3657 method = "PresetUnitFiles";
3658 expect_carries_install_info = true;
3659 } else if (streq(verb, "mask"))
3660 method = "MaskUnitFiles";
3661 else if (streq(verb, "unmask")) {
3662 method = "UnmaskUnitFiles";
3665 assert_not_reached("Unknown verb");
3667 m = dbus_message_new_method_call(
3668 "org.freedesktop.systemd1",
3669 "/org/freedesktop/systemd1",
3670 "org.freedesktop.systemd1.Manager",
3677 dbus_message_iter_init_append(m, &iter);
3679 r = mangle_names(args+1, &mangled_names);
3683 r = bus_append_strv_iter(&iter, mangled_names);
3685 log_error("Failed to append unit files.");
3690 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3691 log_error("Failed to append runtime boolean.");
3699 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3700 log_error("Failed to append force boolean.");
3706 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3708 log_error("Failed to issue method call: %s", bus_error_message(&error));
3713 if (!dbus_message_iter_init(reply, &iter)) {
3714 log_error("Failed to initialize iterator.");
3718 if (expect_carries_install_info) {
3719 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3721 log_error("Failed to parse reply.");
3725 carries_install_info = b;
3728 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3729 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3730 log_error("Failed to parse reply.");
3735 dbus_message_iter_recurse(&iter, &sub);
3736 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3737 const char *type, *path, *source;
3739 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3740 log_error("Failed to parse reply.");
3745 dbus_message_iter_recurse(&sub, &sub2);
3747 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3748 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3749 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3750 log_error("Failed to parse reply.");
3756 if (streq(type, "symlink"))
3757 log_info("ln -s '%s' '%s'", source, path);
3759 log_info("rm '%s'", path);
3762 dbus_message_iter_next(&sub);
3765 /* Try to reload if enabeld */
3767 r = daemon_reload(bus, args);
3770 if (carries_install_info == 0)
3771 log_warning("The unit files have no [Install] section. They are not meant to be enabled using systemctl.");
3775 dbus_message_unref(m);
3778 dbus_message_unref(reply);
3780 unit_file_changes_free(changes, n_changes);
3782 dbus_error_free(&error);
3784 strv_free(mangled_names);
3789 static int unit_is_enabled(DBusConnection *bus, char **args) {
3792 DBusMessage *reply = NULL;
3796 dbus_error_init(&error);
3798 r = enable_sysv_units(args);
3804 if (!bus || avoid_bus()) {
3806 STRV_FOREACH(name, args+1) {
3807 UnitFileState state;
3809 state = unit_file_get_state(arg_scope, arg_root, *name);
3815 if (state == UNIT_FILE_ENABLED ||
3816 state == UNIT_FILE_ENABLED_RUNTIME ||
3817 state == UNIT_FILE_STATIC)
3821 puts(unit_file_state_to_string(state));
3825 STRV_FOREACH(name, args+1) {
3828 r = bus_method_call_with_reply (
3830 "org.freedesktop.systemd1",
3831 "/org/freedesktop/systemd1",
3832 "org.freedesktop.systemd1.Manager",
3836 DBUS_TYPE_STRING, name,
3841 if (!dbus_message_get_args(reply, &error,
3842 DBUS_TYPE_STRING, &s,
3843 DBUS_TYPE_INVALID)) {
3844 log_error("Failed to parse reply: %s", bus_error_message(&error));
3849 dbus_message_unref(reply);
3852 if (streq(s, "enabled") ||
3853 streq(s, "enabled-runtime") ||
3862 r = enabled ? 0 : 1;
3866 dbus_message_unref(reply);
3868 dbus_error_free(&error);
3872 static int systemctl_help(void) {
3874 pager_open_if_enabled();
3876 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
3877 "Query or send control commands to the systemd manager.\n\n"
3878 " -h --help Show this help\n"
3879 " --version Show package version\n"
3880 " -t --type=TYPE List only units of a particular type\n"
3881 " -p --property=NAME Show only properties by this name\n"
3882 " -a --all Show all units/properties, including dead/empty ones\n"
3883 " --failed Show only failed units\n"
3884 " --full Don't ellipsize unit names on output\n"
3885 " --fail When queueing a new job, fail if conflicting jobs are\n"
3887 " --ignore-dependencies\n"
3888 " When queueing a new job, ignore all its dependencies\n"
3889 " --kill-who=WHO Who to send signal to\n"
3890 " -s --signal=SIGNAL Which signal to send\n"
3891 " -H --host=[USER@]HOST\n"
3892 " Show information for remote host\n"
3893 " -P --privileged Acquire privileges before execution\n"
3894 " -q --quiet Suppress output\n"
3895 " --no-block Do not wait until operation finished\n"
3896 " --no-wall Don't send wall message before halt/power-off/reboot\n"
3897 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
3899 " --no-legend Do not print a legend (column headers and hints)\n"
3900 " --no-pager Do not pipe output into a pager\n"
3901 " --no-ask-password\n"
3902 " Do not ask for system passwords\n"
3903 " --order When generating graph for dot, show only order\n"
3904 " --require When generating graph for dot, show only requirement\n"
3905 " --system Connect to system manager\n"
3906 " --user Connect to user service manager\n"
3907 " --global Enable/disable unit files globally\n"
3908 " -f --force When enabling unit files, override existing symlinks\n"
3909 " When shutting down, execute action immediately\n"
3910 " --root=PATH Enable unit files in the specified root directory\n"
3911 " --runtime Enable unit files only temporarily until next reboot\n"
3912 " -n --lines=INTEGER Journal entries to show\n"
3913 " --follow Follow journal\n"
3914 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
3915 " verbose, export, json, json-pretty, cat)\n\n"
3917 " list-units List loaded units\n"
3918 " start [NAME...] Start (activate) one or more units\n"
3919 " stop [NAME...] Stop (deactivate) one or more units\n"
3920 " reload [NAME...] Reload one or more units\n"
3921 " restart [NAME...] Start or restart one or more units\n"
3922 " try-restart [NAME...] Restart one or more units if active\n"
3923 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
3924 " otherwise start or restart\n"
3925 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
3926 " otherwise restart if active\n"
3927 " isolate [NAME] Start one unit and stop all others\n"
3928 " kill [NAME...] Send signal to processes of a unit\n"
3929 " is-active [NAME...] Check whether units are active\n"
3930 " status [NAME...|PID...] Show runtime status of one or more units\n"
3931 " show [NAME...|JOB...] Show properties of one or more\n"
3932 " units/jobs or the manager\n"
3933 " help [NAME...|PID...] Show manual for one or more units\n"
3934 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
3936 " load [NAME...] Load one or more units\n\n"
3937 "Unit File Commands:\n"
3938 " list-unit-files List installed unit files\n"
3939 " enable [NAME...] Enable one or more unit files\n"
3940 " disable [NAME...] Disable one or more unit files\n"
3941 " reenable [NAME...] Reenable one or more unit files\n"
3942 " preset [NAME...] Enable/disable one or more unit files\n"
3943 " based on preset configuration\n"
3944 " mask [NAME...] Mask one or more units\n"
3945 " unmask [NAME...] Unmask one or more units\n"
3946 " link [PATH...] Link one or more units files into\n"
3947 " the search path\n"
3948 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
3950 " list-jobs List jobs\n"
3951 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
3952 "Status Commands:\n"
3953 " dump Dump server status\n"
3954 " dot Dump dependency graph for dot(1)\n\n"
3955 "Snapshot Commands:\n"
3956 " snapshot [NAME] Create a snapshot\n"
3957 " delete [NAME...] Remove one or more snapshots\n\n"
3958 "Environment Commands:\n"
3959 " show-environment Dump environment\n"
3960 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
3961 " unset-environment [NAME...] Unset one or more environment variables\n\n"
3962 "Manager Lifecycle Commands:\n"
3963 " daemon-reload Reload systemd manager configuration\n"
3964 " daemon-reexec Reexecute systemd manager\n\n"
3965 "System Commands:\n"
3966 " default Enter system default mode\n"
3967 " rescue Enter system rescue mode\n"
3968 " emergency Enter system emergency mode\n"
3969 " halt Shut down and halt the system\n"
3970 " poweroff Shut down and power-off the system\n"
3971 " reboot Shut down and reboot the system\n"
3972 " kexec Shut down and reboot the system with kexec\n"
3973 " exit Request user instance exit\n"
3974 " switch-root [ROOT] [INIT] Change to a different root file system\n"
3975 " suspend Suspend the system\n"
3976 " hibernate Hibernate the system\n",
3977 program_invocation_short_name);
3982 static int halt_help(void) {
3984 printf("%s [OPTIONS...]\n\n"
3985 "%s the system.\n\n"
3986 " --help Show this help\n"
3987 " --halt Halt the machine\n"
3988 " -p --poweroff Switch off the machine\n"
3989 " --reboot Reboot the machine\n"
3990 " -f --force Force immediate halt/power-off/reboot\n"
3991 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
3992 " -d --no-wtmp Don't write wtmp record\n"
3993 " --no-wall Don't send wall message before halt/power-off/reboot\n",
3994 program_invocation_short_name,
3995 arg_action == ACTION_REBOOT ? "Reboot" :
3996 arg_action == ACTION_POWEROFF ? "Power off" :
4002 static int shutdown_help(void) {
4004 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4005 "Shut down the system.\n\n"
4006 " --help Show this help\n"
4007 " -H --halt Halt the machine\n"
4008 " -P --poweroff Power-off the machine\n"
4009 " -r --reboot Reboot the machine\n"
4010 " -h Equivalent to --poweroff, overridden by --halt\n"
4011 " -k Don't halt/power-off/reboot, just send warnings\n"
4012 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4013 " -c Cancel a pending shutdown\n",
4014 program_invocation_short_name);
4019 static int telinit_help(void) {
4021 printf("%s [OPTIONS...] {COMMAND}\n\n"
4022 "Send control commands to the init daemon.\n\n"
4023 " --help Show this help\n"
4024 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4026 " 0 Power-off the machine\n"
4027 " 6 Reboot the machine\n"
4028 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4029 " 1, s, S Enter rescue mode\n"
4030 " q, Q Reload init daemon configuration\n"
4031 " u, U Reexecute init daemon\n",
4032 program_invocation_short_name);
4037 static int runlevel_help(void) {
4039 printf("%s [OPTIONS...]\n\n"
4040 "Prints the previous and current runlevel of the init system.\n\n"
4041 " --help Show this help\n",
4042 program_invocation_short_name);
4047 static int systemctl_parse_argv(int argc, char *argv[]) {
4051 ARG_IGNORE_DEPENDENCIES,
4066 ARG_NO_ASK_PASSWORD,
4073 static const struct option options[] = {
4074 { "help", no_argument, NULL, 'h' },
4075 { "version", no_argument, NULL, ARG_VERSION },
4076 { "type", required_argument, NULL, 't' },
4077 { "property", required_argument, NULL, 'p' },
4078 { "all", no_argument, NULL, 'a' },
4079 { "failed", no_argument, NULL, ARG_FAILED },
4080 { "full", no_argument, NULL, ARG_FULL },
4081 { "fail", no_argument, NULL, ARG_FAIL },
4082 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4083 { "user", no_argument, NULL, ARG_USER },
4084 { "system", no_argument, NULL, ARG_SYSTEM },
4085 { "global", no_argument, NULL, ARG_GLOBAL },
4086 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4087 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4088 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4089 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4090 { "quiet", no_argument, NULL, 'q' },
4091 { "order", no_argument, NULL, ARG_ORDER },
4092 { "require", no_argument, NULL, ARG_REQUIRE },
4093 { "root", required_argument, NULL, ARG_ROOT },
4094 { "force", no_argument, NULL, ARG_FORCE },
4095 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4096 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4097 { "signal", required_argument, NULL, 's' },
4098 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4099 { "host", required_argument, NULL, 'H' },
4100 { "privileged",no_argument, NULL, 'P' },
4101 { "runtime", no_argument, NULL, ARG_RUNTIME },
4102 { "lines", required_argument, NULL, 'n' },
4103 { "follow", no_argument, NULL, ARG_FOLLOW },
4104 { "output", required_argument, NULL, 'o' },
4105 { NULL, 0, NULL, 0 }
4113 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4122 puts(PACKAGE_STRING);
4124 puts(SYSTEMD_FEATURES);
4128 if (unit_type_from_string(optarg) >= 0) {
4132 if (unit_load_state_from_string(optarg) >= 0) {
4133 arg_load_state = optarg;
4136 log_error("Unkown unit type or load state '%s'.",
4142 if (!(l = strv_append(arg_property, optarg)))
4145 strv_free(arg_property);
4148 /* If the user asked for a particular
4149 * property, show it to him, even if it is
4160 arg_job_mode = "fail";
4163 case ARG_IGNORE_DEPENDENCIES:
4164 arg_job_mode = "ignore-dependencies";
4168 arg_scope = UNIT_FILE_USER;
4172 arg_scope = UNIT_FILE_SYSTEM;
4176 arg_scope = UNIT_FILE_GLOBAL;
4180 arg_no_block = true;
4184 arg_no_legend = true;
4188 arg_no_pager = true;
4196 arg_dot = DOT_ORDER;
4200 arg_dot = DOT_REQUIRE;
4228 /* -f is short for both --follow and --force! */
4234 arg_no_reload = true;
4238 arg_kill_who = optarg;
4242 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4243 log_error("Failed to parse signal string %s.", optarg);
4248 case ARG_NO_ASK_PASSWORD:
4249 arg_ask_password = false;
4253 arg_transport = TRANSPORT_POLKIT;
4257 arg_transport = TRANSPORT_SSH;
4266 if (safe_atou(optarg, &arg_lines) < 0) {
4267 log_error("Failed to parse lines '%s'", optarg);
4273 arg_output = output_mode_from_string(optarg);
4274 if (arg_output < 0) {
4275 log_error("Unknown output '%s'.", optarg);
4284 log_error("Unknown option code '%c'.", c);
4289 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4290 log_error("Cannot access user instance remotely.");
4297 static int halt_parse_argv(int argc, char *argv[]) {
4306 static const struct option options[] = {
4307 { "help", no_argument, NULL, ARG_HELP },
4308 { "halt", no_argument, NULL, ARG_HALT },
4309 { "poweroff", no_argument, NULL, 'p' },
4310 { "reboot", no_argument, NULL, ARG_REBOOT },
4311 { "force", no_argument, NULL, 'f' },
4312 { "wtmp-only", no_argument, NULL, 'w' },
4313 { "no-wtmp", no_argument, NULL, 'd' },
4314 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4315 { NULL, 0, NULL, 0 }
4323 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4324 if (runlevel == '0' || runlevel == '6')
4327 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4335 arg_action = ACTION_HALT;
4339 if (arg_action != ACTION_REBOOT)
4340 arg_action = ACTION_POWEROFF;
4344 arg_action = ACTION_REBOOT;
4366 /* Compatibility nops */
4373 log_error("Unknown option code '%c'.", c);
4378 if (optind < argc) {
4379 log_error("Too many arguments.");
4386 static int parse_time_spec(const char *t, usec_t *_u) {
4390 if (streq(t, "now"))
4392 else if (!strchr(t, ':')) {
4395 if (safe_atou64(t, &u) < 0)
4398 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4407 hour = strtol(t, &e, 10);
4408 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4411 minute = strtol(e+1, &e, 10);
4412 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4415 n = now(CLOCK_REALTIME);
4416 s = (time_t) (n / USEC_PER_SEC);
4419 assert_se(localtime_r(&s, &tm));
4421 tm.tm_hour = (int) hour;
4422 tm.tm_min = (int) minute;
4425 assert_se(s = mktime(&tm));
4427 *_u = (usec_t) s * USEC_PER_SEC;
4430 *_u += USEC_PER_DAY;
4436 static int shutdown_parse_argv(int argc, char *argv[]) {
4443 static const struct option options[] = {
4444 { "help", no_argument, NULL, ARG_HELP },
4445 { "halt", no_argument, NULL, 'H' },
4446 { "poweroff", no_argument, NULL, 'P' },
4447 { "reboot", no_argument, NULL, 'r' },
4448 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4449 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4450 { NULL, 0, NULL, 0 }
4458 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4466 arg_action = ACTION_HALT;
4470 arg_action = ACTION_POWEROFF;
4475 arg_action = ACTION_KEXEC;
4477 arg_action = ACTION_REBOOT;
4481 arg_action = ACTION_KEXEC;
4485 if (arg_action != ACTION_HALT)
4486 arg_action = ACTION_POWEROFF;
4499 /* Compatibility nops */
4503 arg_action = ACTION_CANCEL_SHUTDOWN;
4510 log_error("Unknown option code '%c'.", c);
4515 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4516 r = parse_time_spec(argv[optind], &arg_when);
4518 log_error("Failed to parse time specification: %s", argv[optind]);
4522 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4524 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4525 /* No time argument for shutdown cancel */
4526 arg_wall = argv + optind;
4527 else if (argc > optind + 1)
4528 /* We skip the time argument */
4529 arg_wall = argv + optind + 1;
4536 static int telinit_parse_argv(int argc, char *argv[]) {
4543 static const struct option options[] = {
4544 { "help", no_argument, NULL, ARG_HELP },
4545 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4546 { NULL, 0, NULL, 0 }
4549 static const struct {
4553 { '0', ACTION_POWEROFF },
4554 { '6', ACTION_REBOOT },
4555 { '1', ACTION_RESCUE },
4556 { '2', ACTION_RUNLEVEL2 },
4557 { '3', ACTION_RUNLEVEL3 },
4558 { '4', ACTION_RUNLEVEL4 },
4559 { '5', ACTION_RUNLEVEL5 },
4560 { 's', ACTION_RESCUE },
4561 { 'S', ACTION_RESCUE },
4562 { 'q', ACTION_RELOAD },
4563 { 'Q', ACTION_RELOAD },
4564 { 'u', ACTION_REEXEC },
4565 { 'U', ACTION_REEXEC }
4574 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4589 log_error("Unknown option code '%c'.", c);
4594 if (optind >= argc) {
4599 if (optind + 1 < argc) {
4600 log_error("Too many arguments.");
4604 if (strlen(argv[optind]) != 1) {
4605 log_error("Expected single character argument.");
4609 for (i = 0; i < ELEMENTSOF(table); i++)
4610 if (table[i].from == argv[optind][0])
4613 if (i >= ELEMENTSOF(table)) {
4614 log_error("Unknown command '%s'.", argv[optind]);
4618 arg_action = table[i].to;
4625 static int runlevel_parse_argv(int argc, char *argv[]) {
4631 static const struct option options[] = {
4632 { "help", no_argument, NULL, ARG_HELP },
4633 { NULL, 0, NULL, 0 }
4641 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4652 log_error("Unknown option code '%c'.", c);
4657 if (optind < argc) {
4658 log_error("Too many arguments.");
4665 static int parse_argv(int argc, char *argv[]) {
4669 if (program_invocation_short_name) {
4671 if (strstr(program_invocation_short_name, "halt")) {
4672 arg_action = ACTION_HALT;
4673 return halt_parse_argv(argc, argv);
4674 } else if (strstr(program_invocation_short_name, "poweroff")) {
4675 arg_action = ACTION_POWEROFF;
4676 return halt_parse_argv(argc, argv);
4677 } else if (strstr(program_invocation_short_name, "reboot")) {
4679 arg_action = ACTION_KEXEC;
4681 arg_action = ACTION_REBOOT;
4682 return halt_parse_argv(argc, argv);
4683 } else if (strstr(program_invocation_short_name, "shutdown")) {
4684 arg_action = ACTION_POWEROFF;
4685 return shutdown_parse_argv(argc, argv);
4686 } else if (strstr(program_invocation_short_name, "init")) {
4688 if (sd_booted() > 0) {
4689 arg_action = ACTION_INVALID;
4690 return telinit_parse_argv(argc, argv);
4692 /* Hmm, so some other init system is
4693 * running, we need to forward this
4694 * request to it. For now we simply
4695 * guess that it is Upstart. */
4697 execv("/lib/upstart/telinit", argv);
4699 log_error("Couldn't find an alternative telinit implementation to spawn.");
4703 } else if (strstr(program_invocation_short_name, "runlevel")) {
4704 arg_action = ACTION_RUNLEVEL;
4705 return runlevel_parse_argv(argc, argv);
4709 arg_action = ACTION_SYSTEMCTL;
4710 return systemctl_parse_argv(argc, argv);
4713 static int action_to_runlevel(void) {
4715 static const char table[_ACTION_MAX] = {
4716 [ACTION_HALT] = '0',
4717 [ACTION_POWEROFF] = '0',
4718 [ACTION_REBOOT] = '6',
4719 [ACTION_RUNLEVEL2] = '2',
4720 [ACTION_RUNLEVEL3] = '3',
4721 [ACTION_RUNLEVEL4] = '4',
4722 [ACTION_RUNLEVEL5] = '5',
4723 [ACTION_RESCUE] = '1'
4726 assert(arg_action < _ACTION_MAX);
4728 return table[arg_action];
4731 static int talk_upstart(void) {
4732 DBusMessage *m = NULL, *reply = NULL;
4734 int previous, rl, r;
4736 env1_buf[] = "RUNLEVEL=X",
4737 env2_buf[] = "PREVLEVEL=X";
4738 char *env1 = env1_buf, *env2 = env2_buf;
4739 const char *emit = "runlevel";
4740 dbus_bool_t b_false = FALSE;
4741 DBusMessageIter iter, sub;
4742 DBusConnection *bus;
4744 dbus_error_init(&error);
4746 if (!(rl = action_to_runlevel()))
4749 if (utmp_get_runlevel(&previous, NULL) < 0)
4752 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4753 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4758 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4763 if ((r = bus_check_peercred(bus)) < 0) {
4764 log_error("Failed to verify owner of bus.");
4768 if (!(m = dbus_message_new_method_call(
4769 "com.ubuntu.Upstart",
4770 "/com/ubuntu/Upstart",
4771 "com.ubuntu.Upstart0_6",
4774 log_error("Could not allocate message.");
4779 dbus_message_iter_init_append(m, &iter);
4781 env1_buf[sizeof(env1_buf)-2] = rl;
4782 env2_buf[sizeof(env2_buf)-2] = previous;
4784 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4785 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4786 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4787 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4788 !dbus_message_iter_close_container(&iter, &sub) ||
4789 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4790 log_error("Could not append arguments to message.");
4795 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4797 if (bus_error_is_no_service(&error)) {
4802 log_error("Failed to issue method call: %s", bus_error_message(&error));
4811 dbus_message_unref(m);
4814 dbus_message_unref(reply);
4817 dbus_connection_flush(bus);
4818 dbus_connection_close(bus);
4819 dbus_connection_unref(bus);
4822 dbus_error_free(&error);
4827 static int talk_initctl(void) {
4828 struct init_request request;
4832 if (!(rl = action_to_runlevel()))
4836 request.magic = INIT_MAGIC;
4837 request.sleeptime = 0;
4838 request.cmd = INIT_CMD_RUNLVL;
4839 request.runlevel = rl;
4841 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4843 if (errno == ENOENT)
4846 log_error("Failed to open "INIT_FIFO": %m");
4851 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
4852 close_nointr_nofail(fd);
4855 log_error("Failed to write to "INIT_FIFO": %m");
4856 return errno ? -errno : -EIO;
4862 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
4864 static const struct {
4872 int (* const dispatch)(DBusConnection *bus, char **args);
4874 { "list-units", LESS, 1, list_units },
4875 { "list-unit-files", EQUAL, 1, list_unit_files },
4876 { "list-jobs", EQUAL, 1, list_jobs },
4877 { "clear-jobs", EQUAL, 1, daemon_reload },
4878 { "load", MORE, 2, load_unit },
4879 { "cancel", MORE, 2, cancel_job },
4880 { "start", MORE, 2, start_unit },
4881 { "stop", MORE, 2, start_unit },
4882 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4883 { "reload", MORE, 2, start_unit },
4884 { "restart", MORE, 2, start_unit },
4885 { "try-restart", MORE, 2, start_unit },
4886 { "reload-or-restart", MORE, 2, start_unit },
4887 { "reload-or-try-restart", MORE, 2, start_unit },
4888 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
4889 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4890 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
4891 { "isolate", EQUAL, 2, start_unit },
4892 { "kill", MORE, 2, kill_unit },
4893 { "is-active", MORE, 2, check_unit },
4894 { "check", MORE, 2, check_unit },
4895 { "show", MORE, 1, show },
4896 { "status", MORE, 2, show },
4897 { "help", MORE, 2, show },
4898 { "dump", EQUAL, 1, dump },
4899 { "dot", EQUAL, 1, dot },
4900 { "snapshot", LESS, 2, snapshot },
4901 { "delete", MORE, 2, delete_snapshot },
4902 { "daemon-reload", EQUAL, 1, daemon_reload },
4903 { "daemon-reexec", EQUAL, 1, daemon_reload },
4904 { "show-environment", EQUAL, 1, show_enviroment },
4905 { "set-environment", MORE, 2, set_environment },
4906 { "unset-environment", MORE, 2, set_environment },
4907 { "halt", EQUAL, 1, start_special },
4908 { "poweroff", EQUAL, 1, start_special },
4909 { "reboot", EQUAL, 1, start_special },
4910 { "kexec", EQUAL, 1, start_special },
4911 { "suspend", EQUAL, 1, start_special },
4912 { "hibernate", EQUAL, 1, start_special },
4913 { "default", EQUAL, 1, start_special },
4914 { "rescue", EQUAL, 1, start_special },
4915 { "emergency", EQUAL, 1, start_special },
4916 { "exit", EQUAL, 1, start_special },
4917 { "reset-failed", MORE, 1, reset_failed },
4918 { "enable", MORE, 2, enable_unit },
4919 { "disable", MORE, 2, enable_unit },
4920 { "is-enabled", MORE, 2, unit_is_enabled },
4921 { "reenable", MORE, 2, enable_unit },
4922 { "preset", MORE, 2, enable_unit },
4923 { "mask", MORE, 2, enable_unit },
4924 { "unmask", MORE, 2, enable_unit },
4925 { "link", MORE, 2, enable_unit },
4926 { "switch-root", MORE, 2, switch_root },
4936 left = argc - optind;
4939 /* Special rule: no arguments means "list-units" */
4942 if (streq(argv[optind], "help") && !argv[optind+1]) {
4943 log_error("This command expects one or more "
4944 "unit names. Did you mean --help?");
4948 for (i = 0; i < ELEMENTSOF(verbs); i++)
4949 if (streq(argv[optind], verbs[i].verb))
4952 if (i >= ELEMENTSOF(verbs)) {
4953 log_error("Unknown operation '%s'.", argv[optind]);
4958 switch (verbs[i].argc_cmp) {
4961 if (left != verbs[i].argc) {
4962 log_error("Invalid number of arguments.");
4969 if (left < verbs[i].argc) {
4970 log_error("Too few arguments.");
4977 if (left > verbs[i].argc) {
4978 log_error("Too many arguments.");
4985 assert_not_reached("Unknown comparison operator.");
4988 /* Require a bus connection for all operations but
4990 if (!streq(verbs[i].verb, "enable") &&
4991 !streq(verbs[i].verb, "disable") &&
4992 !streq(verbs[i].verb, "is-enabled") &&
4993 !streq(verbs[i].verb, "list-unit-files") &&
4994 !streq(verbs[i].verb, "reenable") &&
4995 !streq(verbs[i].verb, "preset") &&
4996 !streq(verbs[i].verb, "mask") &&
4997 !streq(verbs[i].verb, "unmask") &&
4998 !streq(verbs[i].verb, "link")) {
5000 if (running_in_chroot() > 0) {
5001 log_info("Running in chroot, ignoring request.");
5005 if (((!streq(verbs[i].verb, "reboot") &&
5006 !streq(verbs[i].verb, "halt") &&
5007 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5008 log_error("Failed to get D-Bus connection: %s",
5009 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5015 if (!bus && !avoid_bus()) {
5016 log_error("Failed to get D-Bus connection: %s",
5017 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5022 return verbs[i].dispatch(bus, argv + optind);
5025 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5027 struct msghdr msghdr;
5028 struct iovec iovec[2];
5029 union sockaddr_union sockaddr;
5030 struct sd_shutdown_command c;
5032 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5039 c.dry_run = dry_run;
5043 sockaddr.sa.sa_family = AF_UNIX;
5044 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5047 msghdr.msg_name = &sockaddr;
5048 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5051 iovec[0].iov_base = (char*) &c;
5052 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5054 if (isempty(message))
5055 msghdr.msg_iovlen = 1;
5057 iovec[1].iov_base = (char*) message;
5058 iovec[1].iov_len = strlen(message);
5059 msghdr.msg_iovlen = 2;
5061 msghdr.msg_iov = iovec;
5063 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5064 close_nointr_nofail(fd);
5068 close_nointr_nofail(fd);
5072 static int reload_with_fallback(DBusConnection *bus) {
5075 /* First, try systemd via D-Bus. */
5076 if (daemon_reload(bus, NULL) >= 0)
5080 /* Nothing else worked, so let's try signals */
5081 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5083 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5084 log_error("kill() failed: %m");
5091 static int start_with_fallback(DBusConnection *bus) {
5094 /* First, try systemd via D-Bus. */
5095 if (start_unit(bus, NULL) >= 0)
5099 /* Hmm, talking to systemd via D-Bus didn't work. Then
5100 * let's try to talk to Upstart via D-Bus. */
5101 if (talk_upstart() > 0)
5104 /* Nothing else worked, so let's try
5106 if (talk_initctl() > 0)
5109 log_error("Failed to talk to init daemon.");
5113 warn_wall(arg_action);
5117 static _noreturn_ void halt_now(enum action a) {
5119 /* Make sure C-A-D is handled by the kernel from this
5121 reboot(RB_ENABLE_CAD);
5126 log_info("Halting.");
5127 reboot(RB_HALT_SYSTEM);
5130 case ACTION_POWEROFF:
5131 log_info("Powering off.");
5132 reboot(RB_POWER_OFF);
5136 log_info("Rebooting.");
5137 reboot(RB_AUTOBOOT);
5141 assert_not_reached("Unknown halt action.");
5144 assert_not_reached("Uh? This shouldn't happen.");
5147 static int halt_main(DBusConnection *bus) {
5150 if (geteuid() != 0) {
5151 /* Try logind if we are a normal user and no special
5152 * mode applies. Maybe PolicyKit allows us to shutdown
5155 if (arg_when <= 0 &&
5158 (arg_action == ACTION_POWEROFF ||
5159 arg_action == ACTION_REBOOT)) {
5160 r = reboot_with_logind(bus, arg_action);
5165 log_error("Must be root.");
5172 m = strv_join(arg_wall, " ");
5173 r = send_shutdownd(arg_when,
5174 arg_action == ACTION_HALT ? 'H' :
5175 arg_action == ACTION_POWEROFF ? 'P' :
5176 arg_action == ACTION_KEXEC ? 'K' :
5184 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5186 char date[FORMAT_TIMESTAMP_MAX];
5188 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5189 format_timestamp(date, sizeof(date), arg_when));
5194 if (!arg_dry && !arg_force)
5195 return start_with_fallback(bus);
5198 if (sd_booted() > 0)
5199 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5201 r = utmp_put_shutdown();
5203 log_warning("Failed to write utmp record: %s", strerror(-r));
5210 halt_now(arg_action);
5211 /* We should never reach this. */
5215 static int runlevel_main(void) {
5216 int r, runlevel, previous;
5218 r = utmp_get_runlevel(&runlevel, &previous);
5225 previous <= 0 ? 'N' : previous,
5226 runlevel <= 0 ? 'N' : runlevel);
5231 int main(int argc, char*argv[]) {
5232 int r, retval = EXIT_FAILURE;
5233 DBusConnection *bus = NULL;
5236 dbus_error_init(&error);
5238 log_parse_environment();
5241 r = parse_argv(argc, argv);
5245 retval = EXIT_SUCCESS;
5249 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5250 * let's shortcut this */
5251 if (arg_action == ACTION_RUNLEVEL) {
5252 r = runlevel_main();
5253 retval = r < 0 ? EXIT_FAILURE : r;
5257 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5258 log_info("Running in chroot, ignoring request.");
5264 if (arg_transport == TRANSPORT_NORMAL)
5265 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5266 else if (arg_transport == TRANSPORT_POLKIT) {
5267 bus_connect_system_polkit(&bus, &error);
5268 private_bus = false;
5269 } else if (arg_transport == TRANSPORT_SSH) {
5270 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5271 private_bus = false;
5273 assert_not_reached("Uh, invalid transport...");
5276 switch (arg_action) {
5278 case ACTION_SYSTEMCTL:
5279 r = systemctl_main(bus, argc, argv, &error);
5283 case ACTION_POWEROFF:
5289 case ACTION_RUNLEVEL2:
5290 case ACTION_RUNLEVEL3:
5291 case ACTION_RUNLEVEL4:
5292 case ACTION_RUNLEVEL5:
5294 case ACTION_EMERGENCY:
5295 case ACTION_DEFAULT:
5296 r = start_with_fallback(bus);
5301 r = reload_with_fallback(bus);
5304 case ACTION_CANCEL_SHUTDOWN: {
5308 m = strv_join(arg_wall, " ");
5310 retval = EXIT_FAILURE;
5314 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5316 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5321 case ACTION_INVALID:
5322 case ACTION_RUNLEVEL:
5324 assert_not_reached("Unknown action");
5327 retval = r < 0 ? EXIT_FAILURE : r;
5331 dbus_connection_flush(bus);
5332 dbus_connection_close(bus);
5333 dbus_connection_unref(bus);
5336 dbus_error_free(&error);
5340 strv_free(arg_property);
5343 ask_password_agent_close();
5344 polkit_agent_close();