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 void pager_open_if_enabled(void) {
143 static void ask_password_agent_open_if_enabled(void) {
145 /* Open the password agent as a child process if necessary */
147 if (!arg_ask_password)
150 if (arg_scope != UNIT_FILE_SYSTEM)
153 ask_password_agent_open();
157 static void polkit_agent_open_if_enabled(void) {
159 /* Open the polkit agent as a child process if necessary */
161 if (!arg_ask_password)
164 if (arg_scope != UNIT_FILE_SYSTEM)
171 static const char *ansi_highlight(bool b) {
176 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
179 static const char *ansi_highlight_red(bool b) {
184 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
187 static const char *ansi_highlight_green(bool b) {
192 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
195 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
198 if (!dbus_error_is_set(error))
201 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
202 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
203 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
204 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
205 return EXIT_NOPERMISSION;
207 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
208 return EXIT_NOTINSTALLED;
210 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
211 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
212 return EXIT_NOTIMPLEMENTED;
214 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
215 return EXIT_NOTCONFIGURED;
223 static void warn_wall(enum action a) {
224 static const char *table[_ACTION_MAX] = {
225 [ACTION_HALT] = "The system is going down for system halt NOW!",
226 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
227 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
228 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
229 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
230 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
231 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
240 p = strv_join(arg_wall, " ");
242 log_error("Failed to join strings.");
258 utmp_wall(table[a], NULL);
261 static bool avoid_bus(void) {
263 if (running_in_chroot() > 0)
266 if (sd_booted() <= 0)
269 if (!isempty(arg_root))
272 if (arg_scope == UNIT_FILE_GLOBAL)
280 const char *description;
281 const char *load_state;
282 const char *active_state;
283 const char *sub_state;
284 const char *following;
285 const char *unit_path;
287 const char *job_type;
288 const char *job_path;
291 static int compare_unit_info(const void *a, const void *b) {
293 const struct unit_info *u = a, *v = b;
295 d1 = strrchr(u->id, '.');
296 d2 = strrchr(v->id, '.');
301 if ((r = strcasecmp(d1, d2)) != 0)
305 return strcasecmp(u->id, v->id);
308 static bool output_show_unit(const struct unit_info *u) {
312 return streq(u->active_state, "failed");
314 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
315 streq(dot+1, arg_type))) &&
316 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
317 (arg_all || !(streq(u->active_state, "inactive")
318 || u->following[0]) || u->job_id > 0);
321 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
322 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
323 const struct unit_info *u;
325 max_id_len = sizeof("UNIT")-1;
326 active_len = sizeof("ACTIVE")-1;
327 sub_len = sizeof("SUB")-1;
328 job_len = sizeof("JOB")-1;
331 for (u = unit_infos; u < unit_infos + c; u++) {
332 if (!output_show_unit(u))
335 max_id_len = MAX(max_id_len, strlen(u->id));
336 active_len = MAX(active_len, strlen(u->active_state));
337 sub_len = MAX(sub_len, strlen(u->sub_state));
339 job_len = MAX(job_len, strlen(u->job_type));
344 id_len = MIN(max_id_len, 25);
345 basic_len = 5 + id_len + 6 + active_len + sub_len + job_len;
346 if (basic_len < (unsigned) columns()) {
347 unsigned extra_len, incr;
348 extra_len = columns() - basic_len;
349 /* Either UNIT already got 25, or is fully satisfied.
350 * Grant up to 25 to DESC now. */
351 incr = MIN(extra_len, 25);
354 /* split the remaining space between UNIT and DESC,
355 * but do not give UNIT more than it needs. */
357 incr = MIN(extra_len / 2, max_id_len - id_len);
359 desc_len += extra_len - incr;
365 for (u = unit_infos; u < unit_infos + c; u++) {
367 const char *on_loaded, *off_loaded;
368 const char *on_active, *off_active;
370 if (!output_show_unit(u))
373 if (!n_shown && !arg_no_legend) {
374 printf("%-*s %-6s %-*s %-*s %-*s ", id_len, "UNIT", "LOAD",
375 active_len, "ACTIVE", sub_len, "SUB", job_len, "JOB");
376 if (!arg_full && arg_no_pager)
377 printf("%.*s\n", desc_len, "DESCRIPTION");
379 printf("%s\n", "DESCRIPTION");
384 if (streq(u->load_state, "error")) {
385 on_loaded = ansi_highlight_red(true);
386 off_loaded = ansi_highlight_red(false);
388 on_loaded = off_loaded = "";
390 if (streq(u->active_state, "failed")) {
391 on_active = ansi_highlight_red(true);
392 off_active = ansi_highlight_red(false);
394 on_active = off_active = "";
396 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
398 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s ",
399 id_len, e ? e : u->id,
400 on_loaded, u->load_state, off_loaded,
401 on_active, active_len, u->active_state,
402 sub_len, u->sub_state, off_active,
403 job_len, u->job_id ? u->job_type : "");
404 if (!arg_full && arg_no_pager)
405 printf("%.*s\n", desc_len, u->description);
407 printf("%s\n", u->description);
412 if (!arg_no_legend) {
413 const char *on, *off;
416 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
417 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
418 "SUB = The low-level unit activation state, values depend on unit type.\n"
419 "JOB = Pending job for the unit.\n\n");
420 on = ansi_highlight(true);
421 off = ansi_highlight(false);
423 on = ansi_highlight_red(true);
424 off = ansi_highlight_red(false);
428 printf("%s%u loaded units listed.%s\n"
429 "To show all installed unit files use 'systemctl list-unit-files'.\n",
432 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
433 "To show all installed unit files use 'systemctl list-unit-files'.\n",
438 static int list_units(DBusConnection *bus, char **args) {
439 DBusMessage *reply = NULL;
441 DBusMessageIter iter, sub, sub2;
442 unsigned c = 0, n_units = 0;
443 struct unit_info *unit_infos = NULL;
445 pager_open_if_enabled();
447 r = bus_method_call_with_reply (
449 "org.freedesktop.systemd1",
450 "/org/freedesktop/systemd1",
451 "org.freedesktop.systemd1.Manager",
459 if (!dbus_message_iter_init(reply, &iter) ||
460 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
461 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
462 log_error("Failed to parse reply.");
467 dbus_message_iter_recurse(&iter, &sub);
469 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
472 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
473 log_error("Failed to parse reply.");
481 n_units = MAX(2*c, 16);
482 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
485 log_error("Failed to allocate unit array.");
495 dbus_message_iter_recurse(&sub, &sub2);
497 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
498 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
499 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
500 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
501 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
502 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
503 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
504 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
505 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
506 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
507 log_error("Failed to parse reply.");
512 dbus_message_iter_next(&sub);
517 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
518 output_units_list(unit_infos, c);
523 dbus_message_unref(reply);
530 static int compare_unit_file_list(const void *a, const void *b) {
532 const UnitFileList *u = a, *v = b;
534 d1 = strrchr(u->path, '.');
535 d2 = strrchr(v->path, '.');
540 r = strcasecmp(d1, d2);
545 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
548 static bool output_show_unit_file(const UnitFileList *u) {
551 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
554 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
555 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
556 const UnitFileList *u;
558 max_id_len = sizeof("UNIT FILE")-1;
559 state_cols = sizeof("STATE")-1;
560 for (u = units; u < units + c; u++) {
561 if (!output_show_unit_file(u))
564 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
565 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
570 id_cols = MIN(max_id_len, 25);
571 basic_cols = 1 + id_cols + state_cols;
572 if (basic_cols < (unsigned) columns())
573 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
575 id_cols = max_id_len;
578 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
580 for (u = units; u < units + c; u++) {
582 const char *on, *off;
585 if (!output_show_unit_file(u))
590 if (u->state == UNIT_FILE_MASKED ||
591 u->state == UNIT_FILE_MASKED_RUNTIME ||
592 u->state == UNIT_FILE_DISABLED ||
593 u->state == UNIT_FILE_INVALID) {
594 on = ansi_highlight_red(true);
595 off = ansi_highlight_red(false);
596 } else if (u->state == UNIT_FILE_ENABLED) {
597 on = ansi_highlight_green(true);
598 off = ansi_highlight_green(false);
602 id = path_get_file_name(u->path);
604 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
606 printf("%-*s %s%-*s%s\n",
608 on, state_cols, unit_file_state_to_string(u->state), off);
614 printf("\n%u unit files listed.\n", n_shown);
617 static int list_unit_files(DBusConnection *bus, char **args) {
618 DBusMessage *reply = NULL;
620 DBusMessageIter iter, sub, sub2;
621 unsigned c = 0, n_units = 0;
622 UnitFileList *units = NULL;
624 pager_open_if_enabled();
631 h = hashmap_new(string_hash_func, string_compare_func);
635 r = unit_file_get_list(arg_scope, arg_root, h);
637 unit_file_list_free(h);
638 log_error("Failed to get unit file list: %s", strerror(-r));
642 n_units = hashmap_size(h);
643 units = new(UnitFileList, n_units);
645 unit_file_list_free(h);
649 HASHMAP_FOREACH(u, h, i) {
650 memcpy(units + c++, u, sizeof(UnitFileList));
656 r = bus_method_call_with_reply (
658 "org.freedesktop.systemd1",
659 "/org/freedesktop/systemd1",
660 "org.freedesktop.systemd1.Manager",
668 if (!dbus_message_iter_init(reply, &iter) ||
669 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
670 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
671 log_error("Failed to parse reply.");
676 dbus_message_iter_recurse(&iter, &sub);
678 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
682 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
683 log_error("Failed to parse reply.");
691 n_units = MAX(2*c, 16);
692 w = realloc(units, sizeof(struct UnitFileList) * n_units);
695 log_error("Failed to allocate unit array.");
705 dbus_message_iter_recurse(&sub, &sub2);
707 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
708 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
709 log_error("Failed to parse reply.");
714 u->state = unit_file_state_from_string(state);
716 dbus_message_iter_next(&sub);
722 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
723 output_unit_file_list(units, c);
730 dbus_message_unref(reply);
737 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
738 static const char * const colors[] = {
739 "Requires", "[color=\"black\"]",
740 "RequiresOverridable", "[color=\"black\"]",
741 "Requisite", "[color=\"darkblue\"]",
742 "RequisiteOverridable", "[color=\"darkblue\"]",
743 "Wants", "[color=\"grey66\"]",
744 "Conflicts", "[color=\"red\"]",
745 "ConflictedBy", "[color=\"red\"]",
746 "After", "[color=\"green\"]"
749 const char *c = NULL;
756 for (i = 0; i < ELEMENTSOF(colors); i += 2)
757 if (streq(colors[i], prop)) {
765 if (arg_dot != DOT_ALL)
766 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
769 switch (dbus_message_iter_get_arg_type(iter)) {
771 case DBUS_TYPE_ARRAY:
773 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
776 dbus_message_iter_recurse(iter, &sub);
778 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
781 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
782 dbus_message_iter_get_basic(&sub, &s);
783 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
785 dbus_message_iter_next(&sub);
795 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
796 DBusMessage *reply = NULL;
797 const char *interface = "org.freedesktop.systemd1.Unit";
799 DBusMessageIter iter, sub, sub2, sub3;
803 r = bus_method_call_with_reply (
805 "org.freedesktop.systemd1",
807 "org.freedesktop.DBus.Properties",
811 DBUS_TYPE_STRING, &interface,
816 if (!dbus_message_iter_init(reply, &iter) ||
817 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
818 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
819 log_error("Failed to parse reply.");
824 dbus_message_iter_recurse(&iter, &sub);
826 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
829 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
830 log_error("Failed to parse reply.");
835 dbus_message_iter_recurse(&sub, &sub2);
837 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
838 log_error("Failed to parse reply.");
843 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
844 log_error("Failed to parse reply.");
849 dbus_message_iter_recurse(&sub2, &sub3);
851 if (dot_one_property(name, prop, &sub3)) {
852 log_error("Failed to parse reply.");
857 dbus_message_iter_next(&sub);
862 dbus_message_unref(reply);
867 static int dot(DBusConnection *bus, char **args) {
868 DBusMessage *reply = NULL;
870 DBusMessageIter iter, sub, sub2;
872 r = bus_method_call_with_reply (
874 "org.freedesktop.systemd1",
875 "/org/freedesktop/systemd1",
876 "org.freedesktop.systemd1.Manager",
884 if (!dbus_message_iter_init(reply, &iter) ||
885 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
886 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
887 log_error("Failed to parse reply.");
892 printf("digraph systemd {\n");
894 dbus_message_iter_recurse(&iter, &sub);
895 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
896 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
898 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
899 log_error("Failed to parse reply.");
904 dbus_message_iter_recurse(&sub, &sub2);
906 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
907 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
908 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
909 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
910 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
911 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
912 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
913 log_error("Failed to parse reply.");
918 if ((r = dot_one(bus, id, unit_path)) < 0)
921 /* printf("\t\"%s\";\n", id); */
922 dbus_message_iter_next(&sub);
927 log_info(" Color legend: black = Requires\n"
928 " dark blue = Requisite\n"
929 " dark grey = Wants\n"
934 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
935 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
941 dbus_message_unref(reply);
946 static int list_jobs(DBusConnection *bus, char **args) {
947 DBusMessage *reply = NULL;
949 DBusMessageIter iter, sub, sub2;
952 pager_open_if_enabled();
954 r = bus_method_call_with_reply (
956 "org.freedesktop.systemd1",
957 "/org/freedesktop/systemd1",
958 "org.freedesktop.systemd1.Manager",
966 if (!dbus_message_iter_init(reply, &iter) ||
967 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
968 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
969 log_error("Failed to parse reply.");
974 dbus_message_iter_recurse(&iter, &sub);
977 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
979 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
980 const char *name, *type, *state, *job_path, *unit_path;
984 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
985 log_error("Failed to parse reply.");
990 dbus_message_iter_recurse(&sub, &sub2);
992 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
993 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
994 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
995 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
996 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
997 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
998 log_error("Failed to parse reply.");
1003 e = arg_full ? NULL : ellipsize(name, 25, 33);
1004 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1009 dbus_message_iter_next(&sub);
1013 printf("\n%u jobs listed.\n", k);
1019 dbus_message_unref(reply);
1024 static int load_unit(DBusConnection *bus, char **args) {
1030 STRV_FOREACH(name, args+1) {
1031 n = unit_name_mangle(*name);
1032 r = bus_method_call_with_reply (
1034 "org.freedesktop.systemd1",
1035 "/org/freedesktop/systemd1",
1036 "org.freedesktop.systemd1.Manager",
1040 DBUS_TYPE_STRING, n ? &n : name,
1051 static int cancel_job(DBusConnection *bus, char **args) {
1052 DBusMessage *reply = NULL;
1058 if (strv_length(args) <= 1)
1059 return daemon_reload(bus, args);
1061 STRV_FOREACH(name, args+1) {
1065 r = safe_atou(*name, &id);
1067 log_error("Failed to parse job id: %s", strerror(-r));
1070 assert_cc(sizeof(uint32_t) == sizeof(id));
1072 r = bus_method_call_with_reply (
1074 "org.freedesktop.systemd1",
1075 "/org/freedesktop/systemd1",
1076 "org.freedesktop.systemd1.Manager",
1080 DBUS_TYPE_UINT32, &id,
1085 if (!dbus_message_get_args(reply, NULL,
1086 DBUS_TYPE_OBJECT_PATH, &path,
1087 DBUS_TYPE_INVALID)) {
1088 log_error("Failed to parse reply");
1089 dbus_message_unref(reply);
1093 dbus_message_unref(reply);
1095 r = bus_method_call_with_reply (
1097 "org.freedesktop.systemd1",
1099 "org.freedesktop.systemd1.Job",
1112 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1113 DBusMessage *reply = NULL;
1114 dbus_bool_t b = FALSE;
1115 DBusMessageIter iter, sub;
1117 *interface = "org.freedesktop.systemd1.Unit",
1118 *property = "NeedDaemonReload",
1123 /* We ignore all errors here, since this is used to show a warning only */
1125 n = unit_name_mangle(unit);
1126 r = bus_method_call_with_reply (
1128 "org.freedesktop.systemd1",
1129 "/org/freedesktop/systemd1",
1130 "org.freedesktop.systemd1.Manager",
1134 DBUS_TYPE_STRING, n ? (const char**) &n : &unit,
1140 if (!dbus_message_get_args(reply, NULL,
1141 DBUS_TYPE_OBJECT_PATH, &path,
1145 dbus_message_unref(reply);
1146 r = bus_method_call_with_reply (
1148 "org.freedesktop.systemd1",
1150 "org.freedesktop.DBus.Properties",
1154 DBUS_TYPE_STRING, &interface,
1155 DBUS_TYPE_STRING, &property,
1160 if (!dbus_message_iter_init(reply, &iter) ||
1161 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1164 dbus_message_iter_recurse(&iter, &sub);
1166 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1169 dbus_message_iter_get_basic(&sub, &b);
1173 dbus_message_unref(reply);
1178 typedef struct WaitData {
1185 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1193 dbus_error_init(&error);
1195 log_debug("Got D-Bus request: %s.%s() on %s",
1196 dbus_message_get_interface(message),
1197 dbus_message_get_member(message),
1198 dbus_message_get_path(message));
1200 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1201 log_error("Warning! D-Bus connection terminated.");
1202 dbus_connection_close(connection);
1204 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1206 const char *path, *result, *unit;
1207 dbus_bool_t success = true;
1209 if (dbus_message_get_args(message, &error,
1210 DBUS_TYPE_UINT32, &id,
1211 DBUS_TYPE_OBJECT_PATH, &path,
1212 DBUS_TYPE_STRING, &unit,
1213 DBUS_TYPE_STRING, &result,
1214 DBUS_TYPE_INVALID)) {
1217 p = set_remove(d->set, (char*) path);
1220 if (!isempty(result))
1221 d->result = strdup(result);
1224 d->name = strdup(unit);
1229 dbus_error_free(&error);
1230 if (dbus_message_get_args(message, &error,
1231 DBUS_TYPE_UINT32, &id,
1232 DBUS_TYPE_OBJECT_PATH, &path,
1233 DBUS_TYPE_STRING, &result,
1234 DBUS_TYPE_INVALID)) {
1237 /* Compatibility with older systemd versions <
1238 * 183 during upgrades. This should be dropped
1240 p = set_remove(d->set, (char*) path);
1244 d->result = strdup(result);
1249 dbus_error_free(&error);
1250 if (dbus_message_get_args(message, &error,
1251 DBUS_TYPE_UINT32, &id,
1252 DBUS_TYPE_OBJECT_PATH, &path,
1253 DBUS_TYPE_BOOLEAN, &success,
1254 DBUS_TYPE_INVALID)) {
1257 /* Compatibility with older systemd versions <
1258 * 19 during upgrades. This should be dropped
1261 p = set_remove(d->set, (char*) path);
1265 d->result = strdup("failed");
1271 log_error("Failed to parse message: %s", bus_error_message(&error));
1275 dbus_error_free(&error);
1276 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1279 static int enable_wait_for_jobs(DBusConnection *bus) {
1287 dbus_error_init(&error);
1288 dbus_bus_add_match(bus,
1290 "sender='org.freedesktop.systemd1',"
1291 "interface='org.freedesktop.systemd1.Manager',"
1292 "member='JobRemoved',"
1293 "path='/org/freedesktop/systemd1'",
1296 if (dbus_error_is_set(&error)) {
1297 log_error("Failed to add match: %s", bus_error_message(&error));
1298 dbus_error_free(&error);
1302 /* This is slightly dirty, since we don't undo the match registrations. */
1306 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1316 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1319 while (!set_isempty(s)) {
1321 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1322 log_error("Disconnected from bus.");
1323 return -ECONNREFUSED;
1330 if (streq(d.result, "timeout"))
1331 log_error("Job for %s timed out.", strna(d.name));
1332 else if (streq(d.result, "canceled"))
1333 log_error("Job for %s canceled.", strna(d.name));
1334 else if (streq(d.result, "dependency"))
1335 log_error("A dependency job for %s failed. See 'journalctl' for details.", strna(d.name));
1336 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1337 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl' for details.", strna(d.name), strna(d.name));
1340 if (streq_ptr(d.result, "timeout"))
1342 else if (streq_ptr(d.result, "canceled"))
1344 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1355 dbus_connection_remove_filter(bus, wait_filter, &d);
1359 static int check_one_unit(DBusConnection *bus, char *name, bool quiet) {
1360 DBusMessage *reply = NULL;
1361 DBusMessageIter iter, sub;
1363 *interface = "org.freedesktop.systemd1.Unit",
1364 *property = "ActiveState";
1365 const char *path = NULL;
1372 n = unit_name_mangle(name);
1373 r = bus_method_call_with_reply (
1375 "org.freedesktop.systemd1",
1376 "/org/freedesktop/systemd1",
1377 "org.freedesktop.systemd1.Manager",
1381 DBUS_TYPE_STRING, n ? &n : &name,
1385 if ((r != -ENOMEM) && (!quiet))
1390 if (!dbus_message_get_args(reply, NULL,
1391 DBUS_TYPE_OBJECT_PATH, &path,
1392 DBUS_TYPE_INVALID)) {
1393 log_error("Failed to parse reply.");
1398 dbus_message_unref(reply);
1399 r = bus_method_call_with_reply (
1401 "org.freedesktop.systemd1",
1403 "org.freedesktop.DBus.Properties",
1407 DBUS_TYPE_STRING, &interface,
1408 DBUS_TYPE_STRING, &property,
1413 if (!dbus_message_iter_init(reply, &iter) ||
1414 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1415 log_error("Failed to parse reply.");
1420 dbus_message_iter_recurse(&iter, &sub);
1422 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1423 log_error("Failed to parse reply.");
1428 dbus_message_iter_get_basic(&sub, &state);
1433 if (streq(state, "active") || streq(state, "reloading"))
1436 r = 3; /* According to LSB: "program is not running" */
1440 dbus_message_unref(reply);
1445 static void check_triggering_units(
1446 DBusConnection *bus,
1447 const char *unit_name) {
1449 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1450 DBusMessageIter iter, sub;
1451 char *service_trigger = NULL;
1452 const char *interface = "org.freedesktop.systemd1.Unit",
1453 *triggered_by_property = "TriggeredBy";
1455 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1456 bool print_warning_label = true;
1459 n = unit_name_mangle(unit_name);
1465 unit_path = unit_dbus_path_from_name(n);
1471 r = bus_method_call_with_reply (
1473 "org.freedesktop.systemd1",
1475 "org.freedesktop.DBus.Properties",
1479 DBUS_TYPE_STRING, &interface,
1480 DBUS_TYPE_STRING, &triggered_by_property,
1485 if (!dbus_message_iter_init(reply, &iter) ||
1486 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1487 log_error("Failed to parse reply.");
1491 dbus_message_iter_recurse(&iter, &sub);
1492 dbus_message_iter_recurse(&sub, &iter);
1495 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1497 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1498 log_error("Failed to parse reply.");
1502 dbus_message_iter_get_basic(&sub, &service_trigger);
1504 r = check_one_unit(bus, service_trigger, true);
1508 if (print_warning_label) {
1509 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1510 print_warning_label = false;
1512 log_warning(" %s", service_trigger);
1515 dbus_message_iter_next(&sub);
1519 static int start_unit_one(
1520 DBusConnection *bus,
1527 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1530 _cleanup_free_ char *n, *p = NULL;
1537 n = unit_name_mangle(name);
1541 r = bus_method_call_with_reply(
1543 "org.freedesktop.systemd1",
1544 "/org/freedesktop/systemd1",
1545 "org.freedesktop.systemd1.Manager",
1549 DBUS_TYPE_STRING, &n,
1550 DBUS_TYPE_STRING, &mode,
1553 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1554 /* There's always a fallback possible for
1555 * legacy actions. */
1558 log_error("Failed to issue method call: %s", bus_error_message(error));
1563 if (!dbus_message_get_args(reply, error,
1564 DBUS_TYPE_OBJECT_PATH, &path,
1565 DBUS_TYPE_INVALID)) {
1566 log_error("Failed to parse reply: %s", bus_error_message(error));
1570 if (need_daemon_reload(bus, n))
1571 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1572 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1581 log_error("Failed to add path to set.");
1591 static enum action verb_to_action(const char *verb) {
1592 if (streq(verb, "halt"))
1594 else if (streq(verb, "poweroff"))
1595 return ACTION_POWEROFF;
1596 else if (streq(verb, "reboot"))
1597 return ACTION_REBOOT;
1598 else if (streq(verb, "kexec"))
1599 return ACTION_KEXEC;
1600 else if (streq(verb, "rescue"))
1601 return ACTION_RESCUE;
1602 else if (streq(verb, "emergency"))
1603 return ACTION_EMERGENCY;
1604 else if (streq(verb, "default"))
1605 return ACTION_DEFAULT;
1606 else if (streq(verb, "exit"))
1608 else if (streq(verb, "suspend"))
1609 return ACTION_SUSPEND;
1610 else if (streq(verb, "hibernate"))
1611 return ACTION_HIBERNATE;
1613 return ACTION_INVALID;
1616 static int start_unit(DBusConnection *bus, char **args) {
1618 static const char * const table[_ACTION_MAX] = {
1619 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1620 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1621 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1622 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1623 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1624 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1625 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1626 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1627 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1628 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1629 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1630 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1631 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1632 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET
1636 const char *method, *mode, *one_name;
1641 dbus_error_init(&error);
1645 ask_password_agent_open_if_enabled();
1647 if (arg_action == ACTION_SYSTEMCTL) {
1649 streq(args[0], "stop") ||
1650 streq(args[0], "condstop") ? "StopUnit" :
1651 streq(args[0], "reload") ? "ReloadUnit" :
1652 streq(args[0], "restart") ? "RestartUnit" :
1654 streq(args[0], "try-restart") ||
1655 streq(args[0], "condrestart") ? "TryRestartUnit" :
1657 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1659 streq(args[0], "reload-or-try-restart") ||
1660 streq(args[0], "condreload") ||
1662 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1666 (streq(args[0], "isolate") ||
1667 streq(args[0], "rescue") ||
1668 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1670 one_name = table[verb_to_action(args[0])];
1673 assert(arg_action < ELEMENTSOF(table));
1674 assert(table[arg_action]);
1676 method = "StartUnit";
1678 mode = (arg_action == ACTION_EMERGENCY ||
1679 arg_action == ACTION_RESCUE ||
1680 arg_action == ACTION_RUNLEVEL2 ||
1681 arg_action == ACTION_RUNLEVEL3 ||
1682 arg_action == ACTION_RUNLEVEL4 ||
1683 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1685 one_name = table[arg_action];
1688 if (!arg_no_block) {
1689 ret = enable_wait_for_jobs(bus);
1691 log_error("Could not watch jobs: %s", strerror(-ret));
1695 s = set_new(string_hash_func, string_compare_func);
1703 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1705 ret = translate_bus_error_to_exit_status(ret, &error);
1707 STRV_FOREACH(name, args+1) {
1708 r = start_unit_one(bus, method, *name, mode, &error, s);
1710 ret = translate_bus_error_to_exit_status(r, &error);
1711 dbus_error_free(&error);
1716 if (!arg_no_block) {
1717 r = wait_for_jobs(bus, s);
1723 /* When stopping units, warn if they can still be triggered by
1724 * another active unit (socket, path, timer) */
1725 if (!arg_quiet && streq(method, "StopUnit")) {
1727 check_triggering_units(bus, one_name);
1729 STRV_FOREACH(name, args+1)
1730 check_triggering_units(bus, *name);
1736 dbus_error_free(&error);
1741 /* Ask systemd-logind, which might grant access to unprivileged users
1742 * through PolicyKit */
1743 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1746 dbus_bool_t interactive = true;
1748 polkit_agent_open_if_enabled();
1756 case ACTION_POWEROFF:
1757 method = "PowerOff";
1760 case ACTION_SUSPEND:
1764 case ACTION_HIBERNATE:
1765 method = "Hibernate";
1772 return bus_method_call_with_reply (
1774 "org.freedesktop.login1",
1775 "/org/freedesktop/login1",
1776 "org.freedesktop.login1.Manager",
1780 DBUS_TYPE_BOOLEAN, &interactive,
1787 static int start_special(DBusConnection *bus, char **args) {
1793 a = verb_to_action(args[0]);
1795 if (arg_force >= 2 && geteuid() != 0) {
1796 log_error("Must be root.");
1800 if (arg_force >= 2 &&
1801 (a == ACTION_HALT ||
1802 a == ACTION_POWEROFF ||
1803 a == ACTION_REBOOT))
1806 if (arg_force >= 1 &&
1807 (a == ACTION_HALT ||
1808 a == ACTION_POWEROFF ||
1809 a == ACTION_REBOOT ||
1810 a == ACTION_KEXEC ||
1812 return daemon_reload(bus, args);
1814 /* first try logind, to allow authentication with polkit */
1815 if (geteuid() != 0 &&
1816 (a == ACTION_POWEROFF ||
1817 a == ACTION_REBOOT ||
1818 a == ACTION_SUSPEND ||
1819 a == ACTION_HIBERNATE)) {
1820 r = reboot_with_logind(bus, a);
1825 r = start_unit(bus, args);
1832 static int check_unit(DBusConnection *bus, char **args) {
1834 int r = 3; /* According to LSB: "program is not running" */
1839 STRV_FOREACH(name, args+1) {
1840 int state = check_one_unit(bus, *name, arg_quiet);
1850 static int kill_unit(DBusConnection *bus, char **args) {
1857 arg_kill_who = "all";
1859 STRV_FOREACH(name, args+1) {
1860 n = unit_name_mangle(*name);
1861 r = bus_method_call_with_reply (
1863 "org.freedesktop.systemd1",
1864 "/org/freedesktop/systemd1",
1865 "org.freedesktop.systemd1.Manager",
1869 DBUS_TYPE_STRING, n ? &n : name,
1870 DBUS_TYPE_STRING, &arg_kill_who,
1871 DBUS_TYPE_INT32, &arg_signal,
1880 typedef struct ExecStatusInfo {
1888 usec_t start_timestamp;
1889 usec_t exit_timestamp;
1894 LIST_FIELDS(struct ExecStatusInfo, exec);
1897 static void exec_status_info_free(ExecStatusInfo *i) {
1906 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
1907 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
1908 DBusMessageIter sub2, sub3;
1912 int32_t code, status;
1918 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
1921 dbus_message_iter_recurse(sub, &sub2);
1923 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
1926 if (!(i->path = strdup(path)))
1929 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
1930 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
1934 dbus_message_iter_recurse(&sub2, &sub3);
1935 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1936 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1937 dbus_message_iter_next(&sub3);
1942 if (!(i->argv = new0(char*, n+1)))
1946 dbus_message_iter_recurse(&sub2, &sub3);
1947 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1950 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1951 dbus_message_iter_get_basic(&sub3, &s);
1952 dbus_message_iter_next(&sub3);
1954 if (!(i->argv[n++] = strdup(s)))
1958 if (!dbus_message_iter_next(&sub2) ||
1959 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
1960 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
1961 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
1962 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
1963 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
1964 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
1965 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
1966 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
1970 i->start_timestamp = (usec_t) start_timestamp;
1971 i->exit_timestamp = (usec_t) exit_timestamp;
1972 i->pid = (pid_t) pid;
1979 typedef struct UnitStatusInfo {
1981 const char *load_state;
1982 const char *active_state;
1983 const char *sub_state;
1984 const char *unit_file_state;
1986 const char *description;
1987 const char *following;
1989 char **documentation;
1991 const char *fragment_path;
1992 const char *source_path;
1993 const char *default_control_group;
1995 const char *load_error;
1998 usec_t inactive_exit_timestamp;
1999 usec_t inactive_exit_timestamp_monotonic;
2000 usec_t active_enter_timestamp;
2001 usec_t active_exit_timestamp;
2002 usec_t inactive_enter_timestamp;
2004 bool need_daemon_reload;
2009 const char *status_text;
2012 usec_t start_timestamp;
2013 usec_t exit_timestamp;
2015 int exit_code, exit_status;
2017 usec_t condition_timestamp;
2018 bool condition_result;
2021 unsigned n_accepted;
2022 unsigned n_connections;
2026 const char *sysfs_path;
2028 /* Mount, Automount */
2034 LIST_HEAD(ExecStatusInfo, exec);
2037 static void print_status_info(UnitStatusInfo *i) {
2039 const char *on, *off, *ss;
2041 char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
2042 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2047 /* This shows pretty information about a unit. See
2048 * print_property() for a low-level property printer */
2050 printf("%s", strna(i->id));
2052 if (i->description && !streq_ptr(i->id, i->description))
2053 printf(" - %s", i->description);
2058 printf("\t Follow: unit currently follows state of %s\n", i->following);
2060 if (streq_ptr(i->load_state, "error")) {
2061 on = ansi_highlight_red(true);
2062 off = ansi_highlight_red(false);
2066 path = i->source_path ? i->source_path : i->fragment_path;
2069 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2070 else if (path && i->unit_file_state)
2071 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2073 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2075 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2077 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2079 if (streq_ptr(i->active_state, "failed")) {
2080 on = ansi_highlight_red(true);
2081 off = ansi_highlight_red(false);
2082 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2083 on = ansi_highlight_green(true);
2084 off = ansi_highlight_green(false);
2089 printf("\t Active: %s%s (%s)%s",
2091 strna(i->active_state),
2095 printf("\t Active: %s%s%s",
2097 strna(i->active_state),
2100 if (!isempty(i->result) && !streq(i->result, "success"))
2101 printf(" (Result: %s)", i->result);
2103 timestamp = (streq_ptr(i->active_state, "active") ||
2104 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2105 (streq_ptr(i->active_state, "inactive") ||
2106 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2107 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2108 i->active_exit_timestamp;
2110 s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
2111 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2114 printf(" since %s; %s\n", s2, s1);
2116 printf(" since %s\n", s2);
2120 if (!i->condition_result && i->condition_timestamp > 0) {
2121 s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
2122 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2125 printf("\t start condition failed at %s; %s\n", s2, s1);
2127 printf("\t start condition failed at %s\n", s2);
2131 printf("\t Device: %s\n", i->sysfs_path);
2133 printf("\t Where: %s\n", i->where);
2135 printf("\t What: %s\n", i->what);
2137 if (!strv_isempty(i->documentation)) {
2141 STRV_FOREACH(t, i->documentation) {
2143 printf("\t Docs: %s\n", *t);
2146 printf("\t %s\n", *t);
2151 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2153 LIST_FOREACH(exec, p, i->exec) {
2157 /* Only show exited processes here */
2161 t = strv_join(p->argv, " ");
2162 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2165 good = is_clean_exit_lsb(p->code, p->status, NULL);
2167 on = ansi_highlight_red(true);
2168 off = ansi_highlight_red(false);
2172 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2174 if (p->code == CLD_EXITED) {
2177 printf("status=%i", p->status);
2179 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2184 printf("signal=%s", signal_to_string(p->status));
2186 printf(")%s\n", off);
2188 if (i->main_pid == p->pid &&
2189 i->start_timestamp == p->start_timestamp &&
2190 i->exit_timestamp == p->start_timestamp)
2191 /* Let's not show this twice */
2194 if (p->pid == i->control_pid)
2198 if (i->main_pid > 0 || i->control_pid > 0) {
2201 if (i->main_pid > 0) {
2202 printf("Main PID: %u", (unsigned) i->main_pid);
2206 get_process_comm(i->main_pid, &t);
2211 } else if (i->exit_code > 0) {
2212 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2214 if (i->exit_code == CLD_EXITED) {
2217 printf("status=%i", i->exit_status);
2219 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2224 printf("signal=%s", signal_to_string(i->exit_status));
2229 if (i->main_pid > 0 && i->control_pid > 0)
2232 if (i->control_pid > 0) {
2235 printf(" Control: %u", (unsigned) i->control_pid);
2237 get_process_comm(i->control_pid, &t);
2248 printf("\t Status: \"%s\"\n", i->status_text);
2250 if (i->default_control_group) {
2253 printf("\t CGroup: %s\n", i->default_control_group);
2255 if (arg_transport != TRANSPORT_SSH) {
2265 if (i->main_pid > 0)
2266 extra[k++] = i->main_pid;
2268 if (i->control_pid > 0)
2269 extra[k++] = i->control_pid;
2271 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2275 if (i->id && arg_transport != TRANSPORT_SSH) {
2277 arg_all * OUTPUT_SHOW_ALL |
2278 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2279 on_tty() * OUTPUT_COLOR |
2280 arg_follow * OUTPUT_FOLLOW |
2281 !arg_quiet * OUTPUT_WARN_CUTOFF;
2284 show_journal_by_unit(stdout,
2288 i->inactive_exit_timestamp_monotonic,
2293 if (i->need_daemon_reload)
2294 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2295 ansi_highlight_red(true),
2296 ansi_highlight_red(false),
2297 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2300 static void show_unit_help(UnitStatusInfo *i) {
2305 if (!i->documentation) {
2306 log_info("Documentation for %s not known.", i->id);
2310 STRV_FOREACH(p, i->documentation) {
2312 if (startswith(*p, "man:")) {
2315 char *page = NULL, *section = NULL;
2316 const char *args[4] = { "man", NULL, NULL, NULL };
2321 if ((*p)[k-1] == ')')
2322 e = strrchr(*p, '(');
2325 page = strndup((*p) + 4, e - *p - 4);
2331 section = strndup(e + 1, *p + k - e - 2);
2345 log_error("Failed to fork: %m");
2353 execvp(args[0], (char**) args);
2354 log_error("Failed to execute man: %m");
2355 _exit(EXIT_FAILURE);
2361 wait_for_terminate(pid, NULL);
2363 log_info("Can't show: %s", *p);
2367 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2373 switch (dbus_message_iter_get_arg_type(iter)) {
2375 case DBUS_TYPE_STRING: {
2378 dbus_message_iter_get_basic(iter, &s);
2381 if (streq(name, "Id"))
2383 else if (streq(name, "LoadState"))
2385 else if (streq(name, "ActiveState"))
2386 i->active_state = s;
2387 else if (streq(name, "SubState"))
2389 else if (streq(name, "Description"))
2391 else if (streq(name, "FragmentPath"))
2392 i->fragment_path = s;
2393 else if (streq(name, "SourcePath"))
2395 else if (streq(name, "DefaultControlGroup"))
2396 i->default_control_group = s;
2397 else if (streq(name, "StatusText"))
2399 else if (streq(name, "SysFSPath"))
2401 else if (streq(name, "Where"))
2403 else if (streq(name, "What"))
2405 else if (streq(name, "Following"))
2407 else if (streq(name, "UnitFileState"))
2408 i->unit_file_state = s;
2409 else if (streq(name, "Result"))
2416 case DBUS_TYPE_BOOLEAN: {
2419 dbus_message_iter_get_basic(iter, &b);
2421 if (streq(name, "Accept"))
2423 else if (streq(name, "NeedDaemonReload"))
2424 i->need_daemon_reload = b;
2425 else if (streq(name, "ConditionResult"))
2426 i->condition_result = b;
2431 case DBUS_TYPE_UINT32: {
2434 dbus_message_iter_get_basic(iter, &u);
2436 if (streq(name, "MainPID")) {
2438 i->main_pid = (pid_t) u;
2441 } else if (streq(name, "ControlPID"))
2442 i->control_pid = (pid_t) u;
2443 else if (streq(name, "ExecMainPID")) {
2445 i->main_pid = (pid_t) u;
2446 } else if (streq(name, "NAccepted"))
2448 else if (streq(name, "NConnections"))
2449 i->n_connections = u;
2454 case DBUS_TYPE_INT32: {
2457 dbus_message_iter_get_basic(iter, &j);
2459 if (streq(name, "ExecMainCode"))
2460 i->exit_code = (int) j;
2461 else if (streq(name, "ExecMainStatus"))
2462 i->exit_status = (int) j;
2467 case DBUS_TYPE_UINT64: {
2470 dbus_message_iter_get_basic(iter, &u);
2472 if (streq(name, "ExecMainStartTimestamp"))
2473 i->start_timestamp = (usec_t) u;
2474 else if (streq(name, "ExecMainExitTimestamp"))
2475 i->exit_timestamp = (usec_t) u;
2476 else if (streq(name, "ActiveEnterTimestamp"))
2477 i->active_enter_timestamp = (usec_t) u;
2478 else if (streq(name, "InactiveEnterTimestamp"))
2479 i->inactive_enter_timestamp = (usec_t) u;
2480 else if (streq(name, "InactiveExitTimestamp"))
2481 i->inactive_exit_timestamp = (usec_t) u;
2482 else if (streq(name, "InactiveExitTimestampMonotonic"))
2483 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2484 else if (streq(name, "ActiveExitTimestamp"))
2485 i->active_exit_timestamp = (usec_t) u;
2486 else if (streq(name, "ConditionTimestamp"))
2487 i->condition_timestamp = (usec_t) u;
2492 case DBUS_TYPE_ARRAY: {
2494 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2495 startswith(name, "Exec")) {
2496 DBusMessageIter sub;
2498 dbus_message_iter_recurse(iter, &sub);
2499 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2500 ExecStatusInfo *info;
2503 if (!(info = new0(ExecStatusInfo, 1)))
2506 if (!(info->name = strdup(name))) {
2511 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2516 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2518 dbus_message_iter_next(&sub);
2520 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2521 streq(name, "Documentation")) {
2523 DBusMessageIter sub;
2525 dbus_message_iter_recurse(iter, &sub);
2526 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2530 dbus_message_iter_get_basic(&sub, &s);
2532 l = strv_append(i->documentation, s);
2536 strv_free(i->documentation);
2537 i->documentation = l;
2539 dbus_message_iter_next(&sub);
2546 case DBUS_TYPE_STRUCT: {
2548 if (streq(name, "LoadError")) {
2549 DBusMessageIter sub;
2550 const char *n, *message;
2553 dbus_message_iter_recurse(iter, &sub);
2555 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2559 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2563 if (!isempty(message))
2564 i->load_error = message;
2574 static int print_property(const char *name, DBusMessageIter *iter) {
2578 /* This is a low-level property printer, see
2579 * print_status_info() for the nicer output */
2581 if (arg_property && !strv_find(arg_property, name))
2584 switch (dbus_message_iter_get_arg_type(iter)) {
2586 case DBUS_TYPE_STRUCT: {
2587 DBusMessageIter sub;
2588 dbus_message_iter_recurse(iter, &sub);
2590 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2593 dbus_message_iter_get_basic(&sub, &u);
2596 printf("%s=%u\n", name, (unsigned) u);
2598 printf("%s=\n", name);
2601 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2604 dbus_message_iter_get_basic(&sub, &s);
2606 if (arg_all || s[0])
2607 printf("%s=%s\n", name, s);
2610 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2611 const char *a = NULL, *b = NULL;
2613 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2614 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2616 if (arg_all || !isempty(a) || !isempty(b))
2617 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2625 case DBUS_TYPE_ARRAY:
2627 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2628 DBusMessageIter sub, sub2;
2630 dbus_message_iter_recurse(iter, &sub);
2631 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2635 dbus_message_iter_recurse(&sub, &sub2);
2637 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2638 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2639 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2641 dbus_message_iter_next(&sub);
2646 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2647 DBusMessageIter sub, sub2;
2649 dbus_message_iter_recurse(iter, &sub);
2650 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2651 const char *type, *path;
2653 dbus_message_iter_recurse(&sub, &sub2);
2655 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2656 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2657 printf("%s=%s\n", type, path);
2659 dbus_message_iter_next(&sub);
2664 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2665 DBusMessageIter sub, sub2;
2667 dbus_message_iter_recurse(iter, &sub);
2668 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2670 uint64_t value, next_elapse;
2672 dbus_message_iter_recurse(&sub, &sub2);
2674 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2675 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2676 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2677 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2679 printf("%s={ value=%s ; next_elapse=%s }\n",
2681 format_timespan(timespan1, sizeof(timespan1), value),
2682 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2685 dbus_message_iter_next(&sub);
2690 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2691 DBusMessageIter sub, sub2;
2693 dbus_message_iter_recurse(iter, &sub);
2694 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2695 const char *controller, *attr, *value;
2697 dbus_message_iter_recurse(&sub, &sub2);
2699 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2700 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2701 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2703 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2709 dbus_message_iter_next(&sub);
2714 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2715 DBusMessageIter sub;
2717 dbus_message_iter_recurse(iter, &sub);
2718 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2719 ExecStatusInfo info;
2722 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2723 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2726 t = strv_join(info.argv, " ");
2728 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2732 yes_no(info.ignore),
2733 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2734 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2735 (unsigned) info. pid,
2736 sigchld_code_to_string(info.code),
2738 info.code == CLD_EXITED ? "" : "/",
2739 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2745 strv_free(info.argv);
2747 dbus_message_iter_next(&sub);
2756 if (generic_print_property(name, iter, arg_all) > 0)
2760 printf("%s=[unprintable]\n", name);
2765 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2766 DBusMessage *reply = NULL;
2767 const char *interface = "";
2769 DBusMessageIter iter, sub, sub2, sub3;
2770 UnitStatusInfo info;
2778 r = bus_method_call_with_reply (
2780 "org.freedesktop.systemd1",
2782 "org.freedesktop.DBus.Properties",
2786 DBUS_TYPE_STRING, &interface,
2791 if (!dbus_message_iter_init(reply, &iter) ||
2792 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2793 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2794 log_error("Failed to parse reply.");
2799 dbus_message_iter_recurse(&iter, &sub);
2806 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2809 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2810 log_error("Failed to parse reply.");
2815 dbus_message_iter_recurse(&sub, &sub2);
2817 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2818 log_error("Failed to parse reply.");
2823 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2824 log_error("Failed to parse reply.");
2829 dbus_message_iter_recurse(&sub2, &sub3);
2831 if (show_properties)
2832 r = print_property(name, &sub3);
2834 r = status_property(name, &sub3, &info);
2837 log_error("Failed to parse reply.");
2842 dbus_message_iter_next(&sub);
2847 if (!show_properties) {
2848 if (streq(verb, "help"))
2849 show_unit_help(&info);
2851 print_status_info(&info);
2854 strv_free(info.documentation);
2856 if (!streq_ptr(info.active_state, "active") &&
2857 !streq_ptr(info.active_state, "reloading") &&
2858 streq(verb, "status"))
2859 /* According to LSB: "program not running" */
2862 while ((p = info.exec)) {
2863 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2864 exec_status_info_free(p);
2869 dbus_message_unref(reply);
2874 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
2875 DBusMessage *reply = NULL;
2876 const char *path = NULL;
2880 dbus_error_init(&error);
2882 r = bus_method_call_with_reply (
2884 "org.freedesktop.systemd1",
2885 "/org/freedesktop/systemd1",
2886 "org.freedesktop.systemd1.Manager",
2890 DBUS_TYPE_UINT32, &pid,
2895 if (!dbus_message_get_args(reply, &error,
2896 DBUS_TYPE_OBJECT_PATH, &path,
2897 DBUS_TYPE_INVALID)) {
2898 log_error("Failed to parse reply: %s", bus_error_message(&error));
2903 r = show_one(verb, bus, path, false, new_line);
2907 dbus_message_unref(reply);
2909 dbus_error_free(&error);
2914 static int show(DBusConnection *bus, char **args) {
2916 bool show_properties, new_line = false;
2922 show_properties = streq(args[0], "show");
2924 if (show_properties)
2925 pager_open_if_enabled();
2927 if (show_properties && strv_length(args) <= 1) {
2928 /* If not argument is specified inspect the manager
2931 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2934 STRV_FOREACH(name, args+1) {
2937 if (safe_atou32(*name, &id) < 0) {
2939 /* Interpret as unit name */
2941 n = unit_name_mangle(*name);
2942 p = unit_dbus_path_from_name(n ? n : *name);
2947 r = show_one(args[0], bus, p, show_properties, &new_line);
2953 } else if (show_properties) {
2955 /* Interpret as job id */
2958 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
2961 r = show_one(args[0], bus, p, show_properties, &new_line);
2969 /* Interpret as PID */
2971 r = show_one_by_pid(args[0], bus, id, &new_line);
2980 static int dump(DBusConnection *bus, char **args) {
2981 DBusMessage *reply = NULL;
2986 dbus_error_init(&error);
2988 pager_open_if_enabled();
2990 r = bus_method_call_with_reply (
2992 "org.freedesktop.systemd1",
2993 "/org/freedesktop/systemd1",
2994 "org.freedesktop.systemd1.Manager",
3002 if (!dbus_message_get_args(reply, &error,
3003 DBUS_TYPE_STRING, &text,
3004 DBUS_TYPE_INVALID)) {
3005 log_error("Failed to parse reply: %s", bus_error_message(&error));
3010 fputs(text, stdout);
3014 dbus_message_unref(reply);
3016 dbus_error_free(&error);
3021 static int snapshot(DBusConnection *bus, char **args) {
3022 DBusMessage *reply = NULL;
3025 dbus_bool_t cleanup = FALSE;
3026 DBusMessageIter iter, sub;
3028 *name = "", *path, *id,
3029 *interface = "org.freedesktop.systemd1.Unit",
3033 dbus_error_init(&error);
3035 if (strv_length(args) > 1)
3038 n = unit_name_mangle(name);
3039 r = bus_method_call_with_reply (
3041 "org.freedesktop.systemd1",
3042 "/org/freedesktop/systemd1",
3043 "org.freedesktop.systemd1.Manager",
3047 DBUS_TYPE_STRING, n ? (const char**) &n : &name,
3048 DBUS_TYPE_BOOLEAN, &cleanup,
3054 if (!dbus_message_get_args(reply, &error,
3055 DBUS_TYPE_OBJECT_PATH, &path,
3056 DBUS_TYPE_INVALID)) {
3057 log_error("Failed to parse reply: %s", bus_error_message(&error));
3062 dbus_message_unref(reply);
3063 r = bus_method_call_with_reply (
3065 "org.freedesktop.systemd1",
3067 "org.freedesktop.DBus.Properties",
3071 DBUS_TYPE_STRING, &interface,
3072 DBUS_TYPE_STRING, &property,
3077 if (!dbus_message_iter_init(reply, &iter) ||
3078 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3079 log_error("Failed to parse reply.");
3084 dbus_message_iter_recurse(&iter, &sub);
3086 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3087 log_error("Failed to parse reply.");
3092 dbus_message_iter_get_basic(&sub, &id);
3099 dbus_message_unref(reply);
3101 dbus_error_free(&error);
3106 static int delete_snapshot(DBusConnection *bus, char **args) {
3107 DBusMessage *reply = NULL;
3114 dbus_error_init(&error);
3116 STRV_FOREACH(name, args+1) {
3117 const char *path = NULL;
3120 n = unit_name_mangle(*name);
3121 r = bus_method_call_with_reply (
3123 "org.freedesktop.systemd1",
3124 "/org/freedesktop/systemd1",
3125 "org.freedesktop.systemd1.Manager",
3129 DBUS_TYPE_STRING, n ? &n : name,
3135 if (!dbus_message_get_args(reply, &error,
3136 DBUS_TYPE_OBJECT_PATH, &path,
3137 DBUS_TYPE_INVALID)) {
3138 log_error("Failed to parse reply: %s", bus_error_message(&error));
3140 dbus_message_unref(reply);
3141 dbus_error_free(&error);
3144 dbus_message_unref(reply);
3146 r = bus_method_call_with_reply (
3148 "org.freedesktop.systemd1",
3150 "org.freedesktop.systemd1.Snapshot",
3163 static int daemon_reload(DBusConnection *bus, char **args) {
3168 if (arg_action == ACTION_RELOAD)
3170 else if (arg_action == ACTION_REEXEC)
3171 method = "Reexecute";
3173 assert(arg_action == ACTION_SYSTEMCTL);
3176 streq(args[0], "clear-jobs") ||
3177 streq(args[0], "cancel") ? "ClearJobs" :
3178 streq(args[0], "daemon-reexec") ? "Reexecute" :
3179 streq(args[0], "reset-failed") ? "ResetFailed" :
3180 streq(args[0], "halt") ? "Halt" :
3181 streq(args[0], "poweroff") ? "PowerOff" :
3182 streq(args[0], "reboot") ? "Reboot" :
3183 streq(args[0], "kexec") ? "KExec" :
3184 streq(args[0], "exit") ? "Exit" :
3185 /* "daemon-reload" */ "Reload";
3188 r = bus_method_call_with_reply (
3190 "org.freedesktop.systemd1",
3191 "/org/freedesktop/systemd1",
3192 "org.freedesktop.systemd1.Manager",
3198 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3199 /* There's always a fallback possible for
3200 * legacy actions. */
3202 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3203 /* On reexecution, we expect a disconnect, not
3207 log_error("Failed to issue method call: %s", bus_error_message(&error));
3208 dbus_error_free(&error);
3213 static int reset_failed(DBusConnection *bus, char **args) {
3217 if (strv_length(args) <= 1)
3218 return daemon_reload(bus, args);
3220 STRV_FOREACH(name, args+1) {
3221 n = unit_name_mangle(*name);
3222 r = bus_method_call_with_reply (
3224 "org.freedesktop.systemd1",
3225 "/org/freedesktop/systemd1",
3226 "org.freedesktop.systemd1.Manager",
3230 DBUS_TYPE_STRING, n ? &n : name,
3241 static int show_enviroment(DBusConnection *bus, char **args) {
3242 DBusMessage *reply = NULL;
3243 DBusMessageIter iter, sub, sub2;
3246 *interface = "org.freedesktop.systemd1.Manager",
3247 *property = "Environment";
3249 pager_open_if_enabled();
3251 r = bus_method_call_with_reply (
3253 "org.freedesktop.systemd1",
3254 "/org/freedesktop/systemd1",
3255 "org.freedesktop.DBus.Properties",
3259 DBUS_TYPE_STRING, &interface,
3260 DBUS_TYPE_STRING, &property,
3265 if (!dbus_message_iter_init(reply, &iter) ||
3266 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3267 log_error("Failed to parse reply.");
3272 dbus_message_iter_recurse(&iter, &sub);
3274 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3275 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3276 log_error("Failed to parse reply.");
3281 dbus_message_iter_recurse(&sub, &sub2);
3283 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3286 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3287 log_error("Failed to parse reply.");
3292 dbus_message_iter_get_basic(&sub2, &text);
3293 printf("%s\n", text);
3295 dbus_message_iter_next(&sub2);
3302 dbus_message_unref(reply);
3307 static int switch_root(DBusConnection *bus, char **args) {
3309 const char *root, *init;
3311 l = strv_length(args);
3312 if (l < 2 || l > 3) {
3313 log_error("Wrong number of arguments.");
3318 init = l >= 3 ? args[2] : "";
3320 return bus_method_call_with_reply (
3322 "org.freedesktop.systemd1",
3323 "/org/freedesktop/systemd1",
3324 "org.freedesktop.systemd1.Manager",
3328 DBUS_TYPE_STRING, &root,
3329 DBUS_TYPE_STRING, &init,
3333 static int set_environment(DBusConnection *bus, char **args) {
3334 DBusMessage *m = NULL, *reply = NULL;
3338 DBusMessageIter iter, sub;
3341 dbus_error_init(&error);
3343 method = streq(args[0], "set-environment")
3345 : "UnsetEnvironment";
3347 if (!(m = dbus_message_new_method_call(
3348 "org.freedesktop.systemd1",
3349 "/org/freedesktop/systemd1",
3350 "org.freedesktop.systemd1.Manager",
3353 log_error("Could not allocate message.");
3357 dbus_message_iter_init_append(m, &iter);
3359 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
3360 log_error("Could not append arguments to message.");
3365 STRV_FOREACH(name, args+1)
3366 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, name)) {
3367 log_error("Could not append arguments to message.");
3372 if (!dbus_message_iter_close_container(&iter, &sub)) {
3373 log_error("Could not append arguments to message.");
3378 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3379 log_error("Failed to issue method call: %s", bus_error_message(&error));
3388 dbus_message_unref(m);
3391 dbus_message_unref(reply);
3393 dbus_error_free(&error);
3398 static int enable_sysv_units(char **args) {
3401 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3402 const char *verb = args[0];
3403 unsigned f = 1, t = 1;
3406 if (arg_scope != UNIT_FILE_SYSTEM)
3409 if (!streq(verb, "enable") &&
3410 !streq(verb, "disable") &&
3411 !streq(verb, "is-enabled"))
3414 /* Processes all SysV units, and reshuffles the array so that
3415 * afterwards only the native units remain */
3418 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3423 for (f = 1; args[f]; f++) {
3426 bool found_native = false, found_sysv;
3428 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3429 char **k, *l, *q = NULL;
3436 if (!endswith(name, ".service"))
3439 if (path_is_absolute(name))
3442 STRV_FOREACH(k, paths.unit_path) {
3445 if (!isempty(arg_root))
3446 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3448 asprintf(&p, "%s/%s", *k, name);
3455 found_native = access(p, F_OK) >= 0;
3466 if (!isempty(arg_root))
3467 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3469 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3475 p[strlen(p) - sizeof(".service") + 1] = 0;
3476 found_sysv = access(p, F_OK) >= 0;
3483 /* Mark this entry, so that we don't try enabling it as native unit */
3484 args[f] = (char*) "";
3486 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3488 if (!isempty(arg_root))
3489 argv[c++] = q = strappend("--root=", arg_root);
3491 argv[c++] = path_get_file_name(p);
3493 streq(verb, "enable") ? "on" :
3494 streq(verb, "disable") ? "off" : "--level=5";
3497 l = strv_join((char**)argv, " ");
3505 log_info("Executing %s", l);
3510 log_error("Failed to fork: %m");
3515 } else if (pid == 0) {
3518 execv(argv[0], (char**) argv);
3519 _exit(EXIT_FAILURE);
3525 j = wait_for_terminate(pid, &status);
3527 log_error("Failed to wait for child: %s", strerror(-r));
3532 if (status.si_code == CLD_EXITED) {
3533 if (streq(verb, "is-enabled")) {
3534 if (status.si_status == 0) {
3543 } else if (status.si_status != 0) {
3554 lookup_paths_free(&paths);
3556 /* Drop all SysV units */
3557 for (f = 1, t = 1; args[f]; f++) {
3559 if (isempty(args[f]))
3562 args[t++] = args[f];
3571 static int mangle_names(char **original_names, char ***mangled_names) {
3572 char **i, **l, **name;
3574 l = new(char*, strv_length(original_names) + 1);
3579 STRV_FOREACH(name, original_names) {
3581 /* When enabling units qualified path names are OK,
3582 * too, hence allow them explicitly. */
3587 *i = unit_name_mangle(*name);
3603 static int enable_unit(DBusConnection *bus, char **args) {
3604 const char *verb = args[0];
3605 UnitFileChange *changes = NULL;
3606 unsigned n_changes = 0, i;
3607 int carries_install_info = -1;
3608 DBusMessage *m = NULL, *reply = NULL;
3611 char **mangled_names = NULL;
3613 r = enable_sysv_units(args);
3620 dbus_error_init(&error);
3622 if (!bus || avoid_bus()) {
3623 if (streq(verb, "enable")) {
3624 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3625 carries_install_info = r;
3626 } else if (streq(verb, "disable"))
3627 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3628 else if (streq(verb, "reenable")) {
3629 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3630 carries_install_info = r;
3631 } else if (streq(verb, "link"))
3632 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3633 else if (streq(verb, "preset")) {
3634 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3635 carries_install_info = r;
3636 } else if (streq(verb, "mask"))
3637 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3638 else if (streq(verb, "unmask"))
3639 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3641 assert_not_reached("Unknown verb");
3644 log_error("Operation failed: %s", strerror(-r));
3649 for (i = 0; i < n_changes; i++) {
3650 if (changes[i].type == UNIT_FILE_SYMLINK)
3651 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3653 log_info("rm '%s'", changes[i].path);
3659 bool send_force = true, expect_carries_install_info = false;
3661 DBusMessageIter iter, sub, sub2;
3663 if (streq(verb, "enable")) {
3664 method = "EnableUnitFiles";
3665 expect_carries_install_info = true;
3666 } else if (streq(verb, "disable")) {
3667 method = "DisableUnitFiles";
3669 } else if (streq(verb, "reenable")) {
3670 method = "ReenableUnitFiles";
3671 expect_carries_install_info = true;
3672 } else if (streq(verb, "link"))
3673 method = "LinkUnitFiles";
3674 else if (streq(verb, "preset")) {
3675 method = "PresetUnitFiles";
3676 expect_carries_install_info = true;
3677 } else if (streq(verb, "mask"))
3678 method = "MaskUnitFiles";
3679 else if (streq(verb, "unmask")) {
3680 method = "UnmaskUnitFiles";
3683 assert_not_reached("Unknown verb");
3685 m = dbus_message_new_method_call(
3686 "org.freedesktop.systemd1",
3687 "/org/freedesktop/systemd1",
3688 "org.freedesktop.systemd1.Manager",
3695 dbus_message_iter_init_append(m, &iter);
3697 r = mangle_names(args+1, &mangled_names);
3701 r = bus_append_strv_iter(&iter, mangled_names);
3703 log_error("Failed to append unit files.");
3708 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3709 log_error("Failed to append runtime boolean.");
3717 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3718 log_error("Failed to append force boolean.");
3724 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3726 log_error("Failed to issue method call: %s", bus_error_message(&error));
3731 if (!dbus_message_iter_init(reply, &iter)) {
3732 log_error("Failed to initialize iterator.");
3736 if (expect_carries_install_info) {
3737 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3739 log_error("Failed to parse reply.");
3743 carries_install_info = b;
3746 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3747 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3748 log_error("Failed to parse reply.");
3753 dbus_message_iter_recurse(&iter, &sub);
3754 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3755 const char *type, *path, *source;
3757 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3758 log_error("Failed to parse reply.");
3763 dbus_message_iter_recurse(&sub, &sub2);
3765 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3766 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3767 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3768 log_error("Failed to parse reply.");
3774 if (streq(type, "symlink"))
3775 log_info("ln -s '%s' '%s'", source, path);
3777 log_info("rm '%s'", path);
3780 dbus_message_iter_next(&sub);
3783 /* Try to reload if enabeld */
3785 r = daemon_reload(bus, args);
3788 if (carries_install_info == 0)
3789 log_warning("The unit files have no [Install] section. They are not meant to be enabled using systemctl.");
3793 dbus_message_unref(m);
3796 dbus_message_unref(reply);
3798 unit_file_changes_free(changes, n_changes);
3800 dbus_error_free(&error);
3802 strv_free(mangled_names);
3807 static int unit_is_enabled(DBusConnection *bus, char **args) {
3810 DBusMessage *reply = NULL;
3814 dbus_error_init(&error);
3816 r = enable_sysv_units(args);
3822 if (!bus || avoid_bus()) {
3824 STRV_FOREACH(name, args+1) {
3825 UnitFileState state;
3827 state = unit_file_get_state(arg_scope, arg_root, *name);
3833 if (state == UNIT_FILE_ENABLED ||
3834 state == UNIT_FILE_ENABLED_RUNTIME ||
3835 state == UNIT_FILE_STATIC)
3839 puts(unit_file_state_to_string(state));
3843 STRV_FOREACH(name, args+1) {
3846 r = bus_method_call_with_reply (
3848 "org.freedesktop.systemd1",
3849 "/org/freedesktop/systemd1",
3850 "org.freedesktop.systemd1.Manager",
3854 DBUS_TYPE_STRING, name,
3859 if (!dbus_message_get_args(reply, &error,
3860 DBUS_TYPE_STRING, &s,
3861 DBUS_TYPE_INVALID)) {
3862 log_error("Failed to parse reply: %s", bus_error_message(&error));
3867 dbus_message_unref(reply);
3870 if (streq(s, "enabled") ||
3871 streq(s, "enabled-runtime") ||
3880 r = enabled ? 0 : 1;
3884 dbus_message_unref(reply);
3886 dbus_error_free(&error);
3890 static int systemctl_help(void) {
3892 pager_open_if_enabled();
3894 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
3895 "Query or send control commands to the systemd manager.\n\n"
3896 " -h --help Show this help\n"
3897 " --version Show package version\n"
3898 " -t --type=TYPE List only units of a particular type\n"
3899 " -p --property=NAME Show only properties by this name\n"
3900 " -a --all Show all units/properties, including dead/empty ones\n"
3901 " --failed Show only failed units\n"
3902 " --full Don't ellipsize unit names on output\n"
3903 " --fail When queueing a new job, fail if conflicting jobs are\n"
3905 " --ignore-dependencies\n"
3906 " When queueing a new job, ignore all its dependencies\n"
3907 " --kill-who=WHO Who to send signal to\n"
3908 " -s --signal=SIGNAL Which signal to send\n"
3909 " -H --host=[USER@]HOST\n"
3910 " Show information for remote host\n"
3911 " -P --privileged Acquire privileges before execution\n"
3912 " -q --quiet Suppress output\n"
3913 " --no-block Do not wait until operation finished\n"
3914 " --no-wall Don't send wall message before halt/power-off/reboot\n"
3915 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
3917 " --no-legend Do not print a legend (column headers and hints)\n"
3918 " --no-pager Do not pipe output into a pager\n"
3919 " --no-ask-password\n"
3920 " Do not ask for system passwords\n"
3921 " --order When generating graph for dot, show only order\n"
3922 " --require When generating graph for dot, show only requirement\n"
3923 " --system Connect to system manager\n"
3924 " --user Connect to user service manager\n"
3925 " --global Enable/disable unit files globally\n"
3926 " -f --force When enabling unit files, override existing symlinks\n"
3927 " When shutting down, execute action immediately\n"
3928 " --root=PATH Enable unit files in the specified root directory\n"
3929 " --runtime Enable unit files only temporarily until next reboot\n"
3930 " -n --lines=INTEGER Journal entries to show\n"
3931 " --follow Follow journal\n"
3932 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
3933 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
3935 " list-units List loaded units\n"
3936 " start [NAME...] Start (activate) one or more units\n"
3937 " stop [NAME...] Stop (deactivate) one or more units\n"
3938 " reload [NAME...] Reload one or more units\n"
3939 " restart [NAME...] Start or restart one or more units\n"
3940 " try-restart [NAME...] Restart one or more units if active\n"
3941 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
3942 " otherwise start or restart\n"
3943 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
3944 " otherwise restart if active\n"
3945 " isolate [NAME] Start one unit and stop all others\n"
3946 " kill [NAME...] Send signal to processes of a unit\n"
3947 " is-active [NAME...] Check whether units are active\n"
3948 " status [NAME...|PID...] Show runtime status of one or more units\n"
3949 " show [NAME...|JOB...] Show properties of one or more\n"
3950 " units/jobs or the manager\n"
3951 " help [NAME...|PID...] Show manual for one or more units\n"
3952 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
3954 " load [NAME...] Load one or more units\n\n"
3955 "Unit File Commands:\n"
3956 " list-unit-files List installed unit files\n"
3957 " enable [NAME...] Enable one or more unit files\n"
3958 " disable [NAME...] Disable one or more unit files\n"
3959 " reenable [NAME...] Reenable one or more unit files\n"
3960 " preset [NAME...] Enable/disable one or more unit files\n"
3961 " based on preset configuration\n"
3962 " mask [NAME...] Mask one or more units\n"
3963 " unmask [NAME...] Unmask one or more units\n"
3964 " link [PATH...] Link one or more units files into\n"
3965 " the search path\n"
3966 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
3968 " list-jobs List jobs\n"
3969 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
3970 "Status Commands:\n"
3971 " dump Dump server status\n"
3972 " dot Dump dependency graph for dot(1)\n\n"
3973 "Snapshot Commands:\n"
3974 " snapshot [NAME] Create a snapshot\n"
3975 " delete [NAME...] Remove one or more snapshots\n\n"
3976 "Environment Commands:\n"
3977 " show-environment Dump environment\n"
3978 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
3979 " unset-environment [NAME...] Unset one or more environment variables\n\n"
3980 "Manager Lifecycle Commands:\n"
3981 " daemon-reload Reload systemd manager configuration\n"
3982 " daemon-reexec Reexecute systemd manager\n\n"
3983 "System Commands:\n"
3984 " default Enter system default mode\n"
3985 " rescue Enter system rescue mode\n"
3986 " emergency Enter system emergency mode\n"
3987 " halt Shut down and halt the system\n"
3988 " poweroff Shut down and power-off the system\n"
3989 " reboot Shut down and reboot the system\n"
3990 " kexec Shut down and reboot the system with kexec\n"
3991 " exit Request user instance exit\n"
3992 " switch-root [ROOT] [INIT] Change to a different root file system\n"
3993 " suspend Suspend the system\n"
3994 " hibernate Hibernate the system\n",
3995 program_invocation_short_name);
4000 static int halt_help(void) {
4002 printf("%s [OPTIONS...]\n\n"
4003 "%s the system.\n\n"
4004 " --help Show this help\n"
4005 " --halt Halt the machine\n"
4006 " -p --poweroff Switch off the machine\n"
4007 " --reboot Reboot the machine\n"
4008 " -f --force Force immediate halt/power-off/reboot\n"
4009 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4010 " -d --no-wtmp Don't write wtmp record\n"
4011 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4012 program_invocation_short_name,
4013 arg_action == ACTION_REBOOT ? "Reboot" :
4014 arg_action == ACTION_POWEROFF ? "Power off" :
4020 static int shutdown_help(void) {
4022 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4023 "Shut down the system.\n\n"
4024 " --help Show this help\n"
4025 " -H --halt Halt the machine\n"
4026 " -P --poweroff Power-off the machine\n"
4027 " -r --reboot Reboot the machine\n"
4028 " -h Equivalent to --poweroff, overridden by --halt\n"
4029 " -k Don't halt/power-off/reboot, just send warnings\n"
4030 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4031 " -c Cancel a pending shutdown\n",
4032 program_invocation_short_name);
4037 static int telinit_help(void) {
4039 printf("%s [OPTIONS...] {COMMAND}\n\n"
4040 "Send control commands to the init daemon.\n\n"
4041 " --help Show this help\n"
4042 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4044 " 0 Power-off the machine\n"
4045 " 6 Reboot the machine\n"
4046 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4047 " 1, s, S Enter rescue mode\n"
4048 " q, Q Reload init daemon configuration\n"
4049 " u, U Reexecute init daemon\n",
4050 program_invocation_short_name);
4055 static int runlevel_help(void) {
4057 printf("%s [OPTIONS...]\n\n"
4058 "Prints the previous and current runlevel of the init system.\n\n"
4059 " --help Show this help\n",
4060 program_invocation_short_name);
4065 static int systemctl_parse_argv(int argc, char *argv[]) {
4069 ARG_IGNORE_DEPENDENCIES,
4084 ARG_NO_ASK_PASSWORD,
4091 static const struct option options[] = {
4092 { "help", no_argument, NULL, 'h' },
4093 { "version", no_argument, NULL, ARG_VERSION },
4094 { "type", required_argument, NULL, 't' },
4095 { "property", required_argument, NULL, 'p' },
4096 { "all", no_argument, NULL, 'a' },
4097 { "failed", no_argument, NULL, ARG_FAILED },
4098 { "full", no_argument, NULL, ARG_FULL },
4099 { "fail", no_argument, NULL, ARG_FAIL },
4100 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4101 { "user", no_argument, NULL, ARG_USER },
4102 { "system", no_argument, NULL, ARG_SYSTEM },
4103 { "global", no_argument, NULL, ARG_GLOBAL },
4104 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4105 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4106 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4107 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4108 { "quiet", no_argument, NULL, 'q' },
4109 { "order", no_argument, NULL, ARG_ORDER },
4110 { "require", no_argument, NULL, ARG_REQUIRE },
4111 { "root", required_argument, NULL, ARG_ROOT },
4112 { "force", no_argument, NULL, ARG_FORCE },
4113 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4114 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4115 { "signal", required_argument, NULL, 's' },
4116 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4117 { "host", required_argument, NULL, 'H' },
4118 { "privileged",no_argument, NULL, 'P' },
4119 { "runtime", no_argument, NULL, ARG_RUNTIME },
4120 { "lines", required_argument, NULL, 'n' },
4121 { "follow", no_argument, NULL, ARG_FOLLOW },
4122 { "output", required_argument, NULL, 'o' },
4123 { NULL, 0, NULL, 0 }
4131 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4140 puts(PACKAGE_STRING);
4142 puts(SYSTEMD_FEATURES);
4146 if (unit_type_from_string(optarg) >= 0) {
4150 if (unit_load_state_from_string(optarg) >= 0) {
4151 arg_load_state = optarg;
4154 log_error("Unkown unit type or load state '%s'.",
4160 if (!(l = strv_append(arg_property, optarg)))
4163 strv_free(arg_property);
4166 /* If the user asked for a particular
4167 * property, show it to him, even if it is
4178 arg_job_mode = "fail";
4181 case ARG_IGNORE_DEPENDENCIES:
4182 arg_job_mode = "ignore-dependencies";
4186 arg_scope = UNIT_FILE_USER;
4190 arg_scope = UNIT_FILE_SYSTEM;
4194 arg_scope = UNIT_FILE_GLOBAL;
4198 arg_no_block = true;
4202 arg_no_legend = true;
4206 arg_no_pager = true;
4214 arg_dot = DOT_ORDER;
4218 arg_dot = DOT_REQUIRE;
4246 /* -f is short for both --follow and --force! */
4252 arg_no_reload = true;
4256 arg_kill_who = optarg;
4260 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4261 log_error("Failed to parse signal string %s.", optarg);
4266 case ARG_NO_ASK_PASSWORD:
4267 arg_ask_password = false;
4271 arg_transport = TRANSPORT_POLKIT;
4275 arg_transport = TRANSPORT_SSH;
4284 if (safe_atou(optarg, &arg_lines) < 0) {
4285 log_error("Failed to parse lines '%s'", optarg);
4291 arg_output = output_mode_from_string(optarg);
4292 if (arg_output < 0) {
4293 log_error("Unknown output '%s'.", optarg);
4302 log_error("Unknown option code '%c'.", c);
4307 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4308 log_error("Cannot access user instance remotely.");
4315 static int halt_parse_argv(int argc, char *argv[]) {
4324 static const struct option options[] = {
4325 { "help", no_argument, NULL, ARG_HELP },
4326 { "halt", no_argument, NULL, ARG_HALT },
4327 { "poweroff", no_argument, NULL, 'p' },
4328 { "reboot", no_argument, NULL, ARG_REBOOT },
4329 { "force", no_argument, NULL, 'f' },
4330 { "wtmp-only", no_argument, NULL, 'w' },
4331 { "no-wtmp", no_argument, NULL, 'd' },
4332 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4333 { NULL, 0, NULL, 0 }
4341 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4342 if (runlevel == '0' || runlevel == '6')
4345 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4353 arg_action = ACTION_HALT;
4357 if (arg_action != ACTION_REBOOT)
4358 arg_action = ACTION_POWEROFF;
4362 arg_action = ACTION_REBOOT;
4384 /* Compatibility nops */
4391 log_error("Unknown option code '%c'.", c);
4396 if (optind < argc) {
4397 log_error("Too many arguments.");
4404 static int parse_time_spec(const char *t, usec_t *_u) {
4408 if (streq(t, "now"))
4410 else if (!strchr(t, ':')) {
4413 if (safe_atou64(t, &u) < 0)
4416 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4425 hour = strtol(t, &e, 10);
4426 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4429 minute = strtol(e+1, &e, 10);
4430 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4433 n = now(CLOCK_REALTIME);
4434 s = (time_t) (n / USEC_PER_SEC);
4437 assert_se(localtime_r(&s, &tm));
4439 tm.tm_hour = (int) hour;
4440 tm.tm_min = (int) minute;
4443 assert_se(s = mktime(&tm));
4445 *_u = (usec_t) s * USEC_PER_SEC;
4448 *_u += USEC_PER_DAY;
4454 static int shutdown_parse_argv(int argc, char *argv[]) {
4461 static const struct option options[] = {
4462 { "help", no_argument, NULL, ARG_HELP },
4463 { "halt", no_argument, NULL, 'H' },
4464 { "poweroff", no_argument, NULL, 'P' },
4465 { "reboot", no_argument, NULL, 'r' },
4466 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4467 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4468 { NULL, 0, NULL, 0 }
4476 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4484 arg_action = ACTION_HALT;
4488 arg_action = ACTION_POWEROFF;
4493 arg_action = ACTION_KEXEC;
4495 arg_action = ACTION_REBOOT;
4499 arg_action = ACTION_KEXEC;
4503 if (arg_action != ACTION_HALT)
4504 arg_action = ACTION_POWEROFF;
4517 /* Compatibility nops */
4521 arg_action = ACTION_CANCEL_SHUTDOWN;
4528 log_error("Unknown option code '%c'.", c);
4533 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4534 r = parse_time_spec(argv[optind], &arg_when);
4536 log_error("Failed to parse time specification: %s", argv[optind]);
4540 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4542 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4543 /* No time argument for shutdown cancel */
4544 arg_wall = argv + optind;
4545 else if (argc > optind + 1)
4546 /* We skip the time argument */
4547 arg_wall = argv + optind + 1;
4554 static int telinit_parse_argv(int argc, char *argv[]) {
4561 static const struct option options[] = {
4562 { "help", no_argument, NULL, ARG_HELP },
4563 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4564 { NULL, 0, NULL, 0 }
4567 static const struct {
4571 { '0', ACTION_POWEROFF },
4572 { '6', ACTION_REBOOT },
4573 { '1', ACTION_RESCUE },
4574 { '2', ACTION_RUNLEVEL2 },
4575 { '3', ACTION_RUNLEVEL3 },
4576 { '4', ACTION_RUNLEVEL4 },
4577 { '5', ACTION_RUNLEVEL5 },
4578 { 's', ACTION_RESCUE },
4579 { 'S', ACTION_RESCUE },
4580 { 'q', ACTION_RELOAD },
4581 { 'Q', ACTION_RELOAD },
4582 { 'u', ACTION_REEXEC },
4583 { 'U', ACTION_REEXEC }
4592 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4607 log_error("Unknown option code '%c'.", c);
4612 if (optind >= argc) {
4617 if (optind + 1 < argc) {
4618 log_error("Too many arguments.");
4622 if (strlen(argv[optind]) != 1) {
4623 log_error("Expected single character argument.");
4627 for (i = 0; i < ELEMENTSOF(table); i++)
4628 if (table[i].from == argv[optind][0])
4631 if (i >= ELEMENTSOF(table)) {
4632 log_error("Unknown command '%s'.", argv[optind]);
4636 arg_action = table[i].to;
4643 static int runlevel_parse_argv(int argc, char *argv[]) {
4649 static const struct option options[] = {
4650 { "help", no_argument, NULL, ARG_HELP },
4651 { NULL, 0, NULL, 0 }
4659 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4670 log_error("Unknown option code '%c'.", c);
4675 if (optind < argc) {
4676 log_error("Too many arguments.");
4683 static int parse_argv(int argc, char *argv[]) {
4687 if (program_invocation_short_name) {
4689 if (strstr(program_invocation_short_name, "halt")) {
4690 arg_action = ACTION_HALT;
4691 return halt_parse_argv(argc, argv);
4692 } else if (strstr(program_invocation_short_name, "poweroff")) {
4693 arg_action = ACTION_POWEROFF;
4694 return halt_parse_argv(argc, argv);
4695 } else if (strstr(program_invocation_short_name, "reboot")) {
4697 arg_action = ACTION_KEXEC;
4699 arg_action = ACTION_REBOOT;
4700 return halt_parse_argv(argc, argv);
4701 } else if (strstr(program_invocation_short_name, "shutdown")) {
4702 arg_action = ACTION_POWEROFF;
4703 return shutdown_parse_argv(argc, argv);
4704 } else if (strstr(program_invocation_short_name, "init")) {
4706 if (sd_booted() > 0) {
4707 arg_action = ACTION_INVALID;
4708 return telinit_parse_argv(argc, argv);
4710 /* Hmm, so some other init system is
4711 * running, we need to forward this
4712 * request to it. For now we simply
4713 * guess that it is Upstart. */
4715 execv("/lib/upstart/telinit", argv);
4717 log_error("Couldn't find an alternative telinit implementation to spawn.");
4721 } else if (strstr(program_invocation_short_name, "runlevel")) {
4722 arg_action = ACTION_RUNLEVEL;
4723 return runlevel_parse_argv(argc, argv);
4727 arg_action = ACTION_SYSTEMCTL;
4728 return systemctl_parse_argv(argc, argv);
4731 static int action_to_runlevel(void) {
4733 static const char table[_ACTION_MAX] = {
4734 [ACTION_HALT] = '0',
4735 [ACTION_POWEROFF] = '0',
4736 [ACTION_REBOOT] = '6',
4737 [ACTION_RUNLEVEL2] = '2',
4738 [ACTION_RUNLEVEL3] = '3',
4739 [ACTION_RUNLEVEL4] = '4',
4740 [ACTION_RUNLEVEL5] = '5',
4741 [ACTION_RESCUE] = '1'
4744 assert(arg_action < _ACTION_MAX);
4746 return table[arg_action];
4749 static int talk_upstart(void) {
4750 DBusMessage *m = NULL, *reply = NULL;
4752 int previous, rl, r;
4754 env1_buf[] = "RUNLEVEL=X",
4755 env2_buf[] = "PREVLEVEL=X";
4756 char *env1 = env1_buf, *env2 = env2_buf;
4757 const char *emit = "runlevel";
4758 dbus_bool_t b_false = FALSE;
4759 DBusMessageIter iter, sub;
4760 DBusConnection *bus;
4762 dbus_error_init(&error);
4764 if (!(rl = action_to_runlevel()))
4767 if (utmp_get_runlevel(&previous, NULL) < 0)
4770 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4771 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4776 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4781 if ((r = bus_check_peercred(bus)) < 0) {
4782 log_error("Failed to verify owner of bus.");
4786 if (!(m = dbus_message_new_method_call(
4787 "com.ubuntu.Upstart",
4788 "/com/ubuntu/Upstart",
4789 "com.ubuntu.Upstart0_6",
4792 log_error("Could not allocate message.");
4797 dbus_message_iter_init_append(m, &iter);
4799 env1_buf[sizeof(env1_buf)-2] = rl;
4800 env2_buf[sizeof(env2_buf)-2] = previous;
4802 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4803 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4804 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4805 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4806 !dbus_message_iter_close_container(&iter, &sub) ||
4807 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4808 log_error("Could not append arguments to message.");
4813 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4815 if (bus_error_is_no_service(&error)) {
4820 log_error("Failed to issue method call: %s", bus_error_message(&error));
4829 dbus_message_unref(m);
4832 dbus_message_unref(reply);
4835 dbus_connection_flush(bus);
4836 dbus_connection_close(bus);
4837 dbus_connection_unref(bus);
4840 dbus_error_free(&error);
4845 static int talk_initctl(void) {
4846 struct init_request request;
4850 if (!(rl = action_to_runlevel()))
4854 request.magic = INIT_MAGIC;
4855 request.sleeptime = 0;
4856 request.cmd = INIT_CMD_RUNLVL;
4857 request.runlevel = rl;
4859 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4861 if (errno == ENOENT)
4864 log_error("Failed to open "INIT_FIFO": %m");
4869 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
4870 close_nointr_nofail(fd);
4873 log_error("Failed to write to "INIT_FIFO": %m");
4874 return errno ? -errno : -EIO;
4880 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
4882 static const struct {
4890 int (* const dispatch)(DBusConnection *bus, char **args);
4892 { "list-units", LESS, 1, list_units },
4893 { "list-unit-files", EQUAL, 1, list_unit_files },
4894 { "list-jobs", EQUAL, 1, list_jobs },
4895 { "clear-jobs", EQUAL, 1, daemon_reload },
4896 { "load", MORE, 2, load_unit },
4897 { "cancel", MORE, 2, cancel_job },
4898 { "start", MORE, 2, start_unit },
4899 { "stop", MORE, 2, start_unit },
4900 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4901 { "reload", MORE, 2, start_unit },
4902 { "restart", MORE, 2, start_unit },
4903 { "try-restart", MORE, 2, start_unit },
4904 { "reload-or-restart", MORE, 2, start_unit },
4905 { "reload-or-try-restart", MORE, 2, start_unit },
4906 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
4907 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4908 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
4909 { "isolate", EQUAL, 2, start_unit },
4910 { "kill", MORE, 2, kill_unit },
4911 { "is-active", MORE, 2, check_unit },
4912 { "check", MORE, 2, check_unit },
4913 { "show", MORE, 1, show },
4914 { "status", MORE, 2, show },
4915 { "help", MORE, 2, show },
4916 { "dump", EQUAL, 1, dump },
4917 { "dot", EQUAL, 1, dot },
4918 { "snapshot", LESS, 2, snapshot },
4919 { "delete", MORE, 2, delete_snapshot },
4920 { "daemon-reload", EQUAL, 1, daemon_reload },
4921 { "daemon-reexec", EQUAL, 1, daemon_reload },
4922 { "show-environment", EQUAL, 1, show_enviroment },
4923 { "set-environment", MORE, 2, set_environment },
4924 { "unset-environment", MORE, 2, set_environment },
4925 { "halt", EQUAL, 1, start_special },
4926 { "poweroff", EQUAL, 1, start_special },
4927 { "reboot", EQUAL, 1, start_special },
4928 { "kexec", EQUAL, 1, start_special },
4929 { "suspend", EQUAL, 1, start_special },
4930 { "hibernate", EQUAL, 1, start_special },
4931 { "default", EQUAL, 1, start_special },
4932 { "rescue", EQUAL, 1, start_special },
4933 { "emergency", EQUAL, 1, start_special },
4934 { "exit", EQUAL, 1, start_special },
4935 { "reset-failed", MORE, 1, reset_failed },
4936 { "enable", MORE, 2, enable_unit },
4937 { "disable", MORE, 2, enable_unit },
4938 { "is-enabled", MORE, 2, unit_is_enabled },
4939 { "reenable", MORE, 2, enable_unit },
4940 { "preset", MORE, 2, enable_unit },
4941 { "mask", MORE, 2, enable_unit },
4942 { "unmask", MORE, 2, enable_unit },
4943 { "link", MORE, 2, enable_unit },
4944 { "switch-root", MORE, 2, switch_root },
4954 left = argc - optind;
4957 /* Special rule: no arguments means "list-units" */
4960 if (streq(argv[optind], "help") && !argv[optind+1]) {
4961 log_error("This command expects one or more "
4962 "unit names. Did you mean --help?");
4966 for (i = 0; i < ELEMENTSOF(verbs); i++)
4967 if (streq(argv[optind], verbs[i].verb))
4970 if (i >= ELEMENTSOF(verbs)) {
4971 log_error("Unknown operation '%s'.", argv[optind]);
4976 switch (verbs[i].argc_cmp) {
4979 if (left != verbs[i].argc) {
4980 log_error("Invalid number of arguments.");
4987 if (left < verbs[i].argc) {
4988 log_error("Too few arguments.");
4995 if (left > verbs[i].argc) {
4996 log_error("Too many arguments.");
5003 assert_not_reached("Unknown comparison operator.");
5006 /* Require a bus connection for all operations but
5008 if (!streq(verbs[i].verb, "enable") &&
5009 !streq(verbs[i].verb, "disable") &&
5010 !streq(verbs[i].verb, "is-enabled") &&
5011 !streq(verbs[i].verb, "list-unit-files") &&
5012 !streq(verbs[i].verb, "reenable") &&
5013 !streq(verbs[i].verb, "preset") &&
5014 !streq(verbs[i].verb, "mask") &&
5015 !streq(verbs[i].verb, "unmask") &&
5016 !streq(verbs[i].verb, "link")) {
5018 if (running_in_chroot() > 0) {
5019 log_info("Running in chroot, ignoring request.");
5023 if (((!streq(verbs[i].verb, "reboot") &&
5024 !streq(verbs[i].verb, "halt") &&
5025 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5026 log_error("Failed to get D-Bus connection: %s",
5027 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5033 if (!bus && !avoid_bus()) {
5034 log_error("Failed to get D-Bus connection: %s",
5035 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5040 return verbs[i].dispatch(bus, argv + optind);
5043 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5045 struct msghdr msghdr;
5046 struct iovec iovec[2];
5047 union sockaddr_union sockaddr;
5048 struct sd_shutdown_command c;
5050 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5057 c.dry_run = dry_run;
5061 sockaddr.sa.sa_family = AF_UNIX;
5062 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5065 msghdr.msg_name = &sockaddr;
5066 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5069 iovec[0].iov_base = (char*) &c;
5070 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5072 if (isempty(message))
5073 msghdr.msg_iovlen = 1;
5075 iovec[1].iov_base = (char*) message;
5076 iovec[1].iov_len = strlen(message);
5077 msghdr.msg_iovlen = 2;
5079 msghdr.msg_iov = iovec;
5081 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5082 close_nointr_nofail(fd);
5086 close_nointr_nofail(fd);
5090 static int reload_with_fallback(DBusConnection *bus) {
5093 /* First, try systemd via D-Bus. */
5094 if (daemon_reload(bus, NULL) >= 0)
5098 /* Nothing else worked, so let's try signals */
5099 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5101 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5102 log_error("kill() failed: %m");
5109 static int start_with_fallback(DBusConnection *bus) {
5112 /* First, try systemd via D-Bus. */
5113 if (start_unit(bus, NULL) >= 0)
5117 /* Hmm, talking to systemd via D-Bus didn't work. Then
5118 * let's try to talk to Upstart via D-Bus. */
5119 if (talk_upstart() > 0)
5122 /* Nothing else worked, so let's try
5124 if (talk_initctl() > 0)
5127 log_error("Failed to talk to init daemon.");
5131 warn_wall(arg_action);
5135 static _noreturn_ void halt_now(enum action a) {
5137 /* Make sure C-A-D is handled by the kernel from this
5139 reboot(RB_ENABLE_CAD);
5144 log_info("Halting.");
5145 reboot(RB_HALT_SYSTEM);
5148 case ACTION_POWEROFF:
5149 log_info("Powering off.");
5150 reboot(RB_POWER_OFF);
5154 log_info("Rebooting.");
5155 reboot(RB_AUTOBOOT);
5159 assert_not_reached("Unknown halt action.");
5162 assert_not_reached("Uh? This shouldn't happen.");
5165 static int halt_main(DBusConnection *bus) {
5168 if (geteuid() != 0) {
5169 /* Try logind if we are a normal user and no special
5170 * mode applies. Maybe PolicyKit allows us to shutdown
5173 if (arg_when <= 0 &&
5176 (arg_action == ACTION_POWEROFF ||
5177 arg_action == ACTION_REBOOT)) {
5178 r = reboot_with_logind(bus, arg_action);
5183 log_error("Must be root.");
5190 m = strv_join(arg_wall, " ");
5191 r = send_shutdownd(arg_when,
5192 arg_action == ACTION_HALT ? 'H' :
5193 arg_action == ACTION_POWEROFF ? 'P' :
5194 arg_action == ACTION_KEXEC ? 'K' :
5202 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5204 char date[FORMAT_TIMESTAMP_MAX];
5206 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5207 format_timestamp(date, sizeof(date), arg_when));
5212 if (!arg_dry && !arg_force)
5213 return start_with_fallback(bus);
5216 if (sd_booted() > 0)
5217 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5219 r = utmp_put_shutdown();
5221 log_warning("Failed to write utmp record: %s", strerror(-r));
5228 halt_now(arg_action);
5229 /* We should never reach this. */
5233 static int runlevel_main(void) {
5234 int r, runlevel, previous;
5236 r = utmp_get_runlevel(&runlevel, &previous);
5243 previous <= 0 ? 'N' : previous,
5244 runlevel <= 0 ? 'N' : runlevel);
5249 int main(int argc, char*argv[]) {
5250 int r, retval = EXIT_FAILURE;
5251 DBusConnection *bus = NULL;
5254 dbus_error_init(&error);
5256 log_parse_environment();
5259 r = parse_argv(argc, argv);
5263 retval = EXIT_SUCCESS;
5267 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5268 * let's shortcut this */
5269 if (arg_action == ACTION_RUNLEVEL) {
5270 r = runlevel_main();
5271 retval = r < 0 ? EXIT_FAILURE : r;
5275 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5276 log_info("Running in chroot, ignoring request.");
5282 if (arg_transport == TRANSPORT_NORMAL)
5283 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5284 else if (arg_transport == TRANSPORT_POLKIT) {
5285 bus_connect_system_polkit(&bus, &error);
5286 private_bus = false;
5287 } else if (arg_transport == TRANSPORT_SSH) {
5288 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5289 private_bus = false;
5291 assert_not_reached("Uh, invalid transport...");
5294 switch (arg_action) {
5296 case ACTION_SYSTEMCTL:
5297 r = systemctl_main(bus, argc, argv, &error);
5301 case ACTION_POWEROFF:
5307 case ACTION_RUNLEVEL2:
5308 case ACTION_RUNLEVEL3:
5309 case ACTION_RUNLEVEL4:
5310 case ACTION_RUNLEVEL5:
5312 case ACTION_EMERGENCY:
5313 case ACTION_DEFAULT:
5314 r = start_with_fallback(bus);
5319 r = reload_with_fallback(bus);
5322 case ACTION_CANCEL_SHUTDOWN: {
5326 m = strv_join(arg_wall, " ");
5328 retval = EXIT_FAILURE;
5332 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5334 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5339 case ACTION_INVALID:
5340 case ACTION_RUNLEVEL:
5342 assert_not_reached("Unknown action");
5345 retval = r < 0 ? EXIT_FAILURE : r;
5349 dbus_connection_flush(bus);
5350 dbus_connection_close(bus);
5351 dbus_connection_unref(bus);
5354 dbus_error_free(&error);
5358 strv_free(arg_property);
5361 ask_password_agent_close();
5362 polkit_agent_close();