1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/reboot.h>
28 #include <sys/ioctl.h>
32 #include <sys/socket.h>
35 #include <sys/prctl.h>
36 #include <dbus/dbus.h>
38 #include <systemd/sd-daemon.h>
39 #include <systemd/sd-shutdown.h>
45 #include "utmp-wtmp.h"
48 #include "path-util.h"
50 #include "dbus-common.h"
51 #include "cgroup-show.h"
52 #include "cgroup-util.h"
54 #include "path-lookup.h"
55 #include "conf-parser.h"
56 #include "exit-status.h"
57 #include "bus-errors.h"
59 #include "unit-name.h"
61 #include "spawn-ask-password-agent.h"
62 #include "spawn-polkit-agent.h"
64 #include "logs-show.h"
65 #include "path-util.h"
66 #include "socket-util.h"
68 static const char *arg_type = NULL;
69 static const char *arg_load_state = NULL;
70 static char **arg_property = NULL;
71 static bool arg_all = false;
72 static const char *arg_job_mode = "replace";
73 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
74 static bool arg_no_block = false;
75 static bool arg_no_legend = false;
76 static bool arg_no_pager = false;
77 static bool arg_no_wtmp = false;
78 static bool arg_no_wall = false;
79 static bool arg_no_reload = false;
80 static bool arg_dry = false;
81 static bool arg_quiet = false;
82 static bool arg_full = false;
83 static int arg_force = 0;
84 static bool arg_ask_password = true;
85 static bool arg_failed = false;
86 static bool arg_runtime = false;
87 static char **arg_wall = NULL;
88 static const char *arg_kill_who = NULL;
89 static int arg_signal = SIGTERM;
90 static const char *arg_root = NULL;
91 static usec_t arg_when = 0;
112 ACTION_CANCEL_SHUTDOWN,
114 } arg_action = ACTION_SYSTEMCTL;
120 static enum transport {
124 } arg_transport = TRANSPORT_NORMAL;
125 static const char *arg_host = NULL;
126 static bool arg_follow = false;
127 static unsigned arg_lines = 10;
128 static OutputMode arg_output = OUTPUT_SHORT;
130 static bool private_bus = false;
132 static int daemon_reload(DBusConnection *bus, char **args);
133 static void halt_now(enum action a);
135 static bool on_tty(void) {
138 /* Note that this is invoked relatively early, before we start
139 * the pager. That means the value we return reflects whether
140 * we originally were started on a tty, not if we currently
141 * are. But this is intended, since we want colour and so on
142 * when run in our own pager. */
144 if (_unlikely_(t < 0))
145 t = isatty(STDOUT_FILENO) > 0;
150 static void pager_open_if_enabled(void) {
152 /* Cache result before we open the pager */
161 static void ask_password_agent_open_if_enabled(void) {
163 /* Open the password agent as a child process if necessary */
165 if (!arg_ask_password)
168 if (arg_scope != UNIT_FILE_SYSTEM)
171 ask_password_agent_open();
175 static void polkit_agent_open_if_enabled(void) {
177 /* Open the polkit agent as a child process if necessary */
179 if (!arg_ask_password)
182 if (arg_scope != UNIT_FILE_SYSTEM)
189 static const char *ansi_highlight_red(bool b) {
194 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
197 static const char *ansi_highlight_green(bool b) {
202 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
205 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
208 if (!dbus_error_is_set(error))
211 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
212 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
213 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
214 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
215 return EXIT_NOPERMISSION;
217 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
218 return EXIT_NOTINSTALLED;
220 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
221 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
222 return EXIT_NOTIMPLEMENTED;
224 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
225 return EXIT_NOTCONFIGURED;
233 static void warn_wall(enum action a) {
234 static const char *table[_ACTION_MAX] = {
235 [ACTION_HALT] = "The system is going down for system halt NOW!",
236 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
237 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
238 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
239 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
240 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
241 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
250 p = strv_join(arg_wall, " ");
252 log_error("Failed to join strings.");
268 utmp_wall(table[a], NULL);
271 static bool avoid_bus(void) {
273 if (running_in_chroot() > 0)
276 if (sd_booted() <= 0)
279 if (!isempty(arg_root))
282 if (arg_scope == UNIT_FILE_GLOBAL)
290 const char *description;
291 const char *load_state;
292 const char *active_state;
293 const char *sub_state;
294 const char *following;
295 const char *unit_path;
297 const char *job_type;
298 const char *job_path;
301 static int compare_unit_info(const void *a, const void *b) {
303 const struct unit_info *u = a, *v = b;
305 d1 = strrchr(u->id, '.');
306 d2 = strrchr(v->id, '.');
311 if ((r = strcasecmp(d1, d2)) != 0)
315 return strcasecmp(u->id, v->id);
318 static bool output_show_unit(const struct unit_info *u) {
322 return streq(u->active_state, "failed");
324 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
325 streq(dot+1, arg_type))) &&
326 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
327 (arg_all || !(streq(u->active_state, "inactive")
328 || u->following[0]) || u->job_id > 0);
331 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
332 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
333 const struct unit_info *u;
335 max_id_len = sizeof("UNIT")-1;
336 active_len = sizeof("ACTIVE")-1;
337 sub_len = sizeof("SUB")-1;
338 job_len = sizeof("JOB")-1;
341 for (u = unit_infos; u < unit_infos + c; u++) {
342 if (!output_show_unit(u))
345 max_id_len = MAX(max_id_len, strlen(u->id));
346 active_len = MAX(active_len, strlen(u->active_state));
347 sub_len = MAX(sub_len, strlen(u->sub_state));
349 job_len = MAX(job_len, strlen(u->job_type));
354 id_len = MIN(max_id_len, 25);
355 basic_len = 5 + id_len + 6 + active_len + sub_len + job_len;
356 if (basic_len < (unsigned) columns()) {
357 unsigned extra_len, incr;
358 extra_len = columns() - basic_len;
359 /* Either UNIT already got 25, or is fully satisfied.
360 * Grant up to 25 to DESC now. */
361 incr = MIN(extra_len, 25);
364 /* split the remaining space between UNIT and DESC,
365 * but do not give UNIT more than it needs. */
367 incr = MIN(extra_len / 2, max_id_len - id_len);
369 desc_len += extra_len - incr;
375 for (u = unit_infos; u < unit_infos + c; u++) {
377 const char *on_loaded, *off_loaded;
378 const char *on_active, *off_active;
380 if (!output_show_unit(u))
383 if (!n_shown && !arg_no_legend) {
384 printf("%-*s %-6s %-*s %-*s %-*s ", id_len, "UNIT", "LOAD",
385 active_len, "ACTIVE", sub_len, "SUB", job_len, "JOB");
386 if (!arg_full && arg_no_pager)
387 printf("%.*s\n", desc_len, "DESCRIPTION");
389 printf("%s\n", "DESCRIPTION");
394 if (streq(u->load_state, "error")) {
395 on_loaded = ansi_highlight_red(true);
396 off_loaded = ansi_highlight_red(false);
398 on_loaded = off_loaded = "";
400 if (streq(u->active_state, "failed")) {
401 on_active = ansi_highlight_red(true);
402 off_active = ansi_highlight_red(false);
404 on_active = off_active = "";
406 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
408 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s ",
409 id_len, e ? e : u->id,
410 on_loaded, u->load_state, off_loaded,
411 on_active, active_len, u->active_state,
412 sub_len, u->sub_state, off_active,
413 job_len, u->job_id ? u->job_type : "");
414 if (!arg_full && arg_no_pager)
415 printf("%.*s\n", desc_len, u->description);
417 printf("%s\n", u->description);
422 if (!arg_no_legend) {
424 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
425 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
426 "SUB = The low-level unit activation state, values depend on unit type.\n"
427 "JOB = Pending job for the unit.\n\n");
430 printf("%u loaded units listed.\n"
431 "To show all installed unit files use 'systemctl list-unit-files'.\n", n_shown);
433 printf("%u loaded units listed. Pass --all to see loaded but inactive units, too.\n"
434 "To show all installed unit files use 'systemctl list-unit-files'.\n", n_shown);
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 arg_follow * OUTPUT_FOLLOW |
2279 !arg_quiet * OUTPUT_WARN_CUTOFF |
2280 on_tty() * OUTPUT_COLOR;
2283 show_journal_by_unit(stdout,
2287 i->inactive_exit_timestamp_monotonic,
2292 if (i->need_daemon_reload)
2293 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2294 ansi_highlight_red(true),
2295 ansi_highlight_red(false),
2296 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2299 static void show_unit_help(UnitStatusInfo *i) {
2304 if (!i->documentation) {
2305 log_info("Documentation for %s not known.", i->id);
2309 STRV_FOREACH(p, i->documentation) {
2311 if (startswith(*p, "man:")) {
2314 char *page = NULL, *section = NULL;
2315 const char *args[4] = { "man", NULL, NULL, NULL };
2320 if ((*p)[k-1] == ')')
2321 e = strrchr(*p, '(');
2324 page = strndup((*p) + 4, e - *p - 4);
2330 section = strndup(e + 1, *p + k - e - 2);
2344 log_error("Failed to fork: %m");
2352 execvp(args[0], (char**) args);
2353 log_error("Failed to execute man: %m");
2354 _exit(EXIT_FAILURE);
2360 wait_for_terminate(pid, NULL);
2362 log_info("Can't show: %s", *p);
2366 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2372 switch (dbus_message_iter_get_arg_type(iter)) {
2374 case DBUS_TYPE_STRING: {
2377 dbus_message_iter_get_basic(iter, &s);
2380 if (streq(name, "Id"))
2382 else if (streq(name, "LoadState"))
2384 else if (streq(name, "ActiveState"))
2385 i->active_state = s;
2386 else if (streq(name, "SubState"))
2388 else if (streq(name, "Description"))
2390 else if (streq(name, "FragmentPath"))
2391 i->fragment_path = s;
2392 else if (streq(name, "SourcePath"))
2394 else if (streq(name, "DefaultControlGroup"))
2395 i->default_control_group = s;
2396 else if (streq(name, "StatusText"))
2398 else if (streq(name, "SysFSPath"))
2400 else if (streq(name, "Where"))
2402 else if (streq(name, "What"))
2404 else if (streq(name, "Following"))
2406 else if (streq(name, "UnitFileState"))
2407 i->unit_file_state = s;
2408 else if (streq(name, "Result"))
2415 case DBUS_TYPE_BOOLEAN: {
2418 dbus_message_iter_get_basic(iter, &b);
2420 if (streq(name, "Accept"))
2422 else if (streq(name, "NeedDaemonReload"))
2423 i->need_daemon_reload = b;
2424 else if (streq(name, "ConditionResult"))
2425 i->condition_result = b;
2430 case DBUS_TYPE_UINT32: {
2433 dbus_message_iter_get_basic(iter, &u);
2435 if (streq(name, "MainPID")) {
2437 i->main_pid = (pid_t) u;
2440 } else if (streq(name, "ControlPID"))
2441 i->control_pid = (pid_t) u;
2442 else if (streq(name, "ExecMainPID")) {
2444 i->main_pid = (pid_t) u;
2445 } else if (streq(name, "NAccepted"))
2447 else if (streq(name, "NConnections"))
2448 i->n_connections = u;
2453 case DBUS_TYPE_INT32: {
2456 dbus_message_iter_get_basic(iter, &j);
2458 if (streq(name, "ExecMainCode"))
2459 i->exit_code = (int) j;
2460 else if (streq(name, "ExecMainStatus"))
2461 i->exit_status = (int) j;
2466 case DBUS_TYPE_UINT64: {
2469 dbus_message_iter_get_basic(iter, &u);
2471 if (streq(name, "ExecMainStartTimestamp"))
2472 i->start_timestamp = (usec_t) u;
2473 else if (streq(name, "ExecMainExitTimestamp"))
2474 i->exit_timestamp = (usec_t) u;
2475 else if (streq(name, "ActiveEnterTimestamp"))
2476 i->active_enter_timestamp = (usec_t) u;
2477 else if (streq(name, "InactiveEnterTimestamp"))
2478 i->inactive_enter_timestamp = (usec_t) u;
2479 else if (streq(name, "InactiveExitTimestamp"))
2480 i->inactive_exit_timestamp = (usec_t) u;
2481 else if (streq(name, "InactiveExitTimestampMonotonic"))
2482 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2483 else if (streq(name, "ActiveExitTimestamp"))
2484 i->active_exit_timestamp = (usec_t) u;
2485 else if (streq(name, "ConditionTimestamp"))
2486 i->condition_timestamp = (usec_t) u;
2491 case DBUS_TYPE_ARRAY: {
2493 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2494 startswith(name, "Exec")) {
2495 DBusMessageIter sub;
2497 dbus_message_iter_recurse(iter, &sub);
2498 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2499 ExecStatusInfo *info;
2502 if (!(info = new0(ExecStatusInfo, 1)))
2505 if (!(info->name = strdup(name))) {
2510 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2515 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2517 dbus_message_iter_next(&sub);
2519 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2520 streq(name, "Documentation")) {
2522 DBusMessageIter sub;
2524 dbus_message_iter_recurse(iter, &sub);
2525 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2529 dbus_message_iter_get_basic(&sub, &s);
2531 l = strv_append(i->documentation, s);
2535 strv_free(i->documentation);
2536 i->documentation = l;
2538 dbus_message_iter_next(&sub);
2545 case DBUS_TYPE_STRUCT: {
2547 if (streq(name, "LoadError")) {
2548 DBusMessageIter sub;
2549 const char *n, *message;
2552 dbus_message_iter_recurse(iter, &sub);
2554 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2558 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2562 if (!isempty(message))
2563 i->load_error = message;
2573 static int print_property(const char *name, DBusMessageIter *iter) {
2577 /* This is a low-level property printer, see
2578 * print_status_info() for the nicer output */
2580 if (arg_property && !strv_find(arg_property, name))
2583 switch (dbus_message_iter_get_arg_type(iter)) {
2585 case DBUS_TYPE_STRUCT: {
2586 DBusMessageIter sub;
2587 dbus_message_iter_recurse(iter, &sub);
2589 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2592 dbus_message_iter_get_basic(&sub, &u);
2595 printf("%s=%u\n", name, (unsigned) u);
2597 printf("%s=\n", name);
2600 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2603 dbus_message_iter_get_basic(&sub, &s);
2605 if (arg_all || s[0])
2606 printf("%s=%s\n", name, s);
2609 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2610 const char *a = NULL, *b = NULL;
2612 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2613 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2615 if (arg_all || !isempty(a) || !isempty(b))
2616 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2624 case DBUS_TYPE_ARRAY:
2626 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2627 DBusMessageIter sub, sub2;
2629 dbus_message_iter_recurse(iter, &sub);
2630 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2634 dbus_message_iter_recurse(&sub, &sub2);
2636 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2637 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2638 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2640 dbus_message_iter_next(&sub);
2645 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2646 DBusMessageIter sub, sub2;
2648 dbus_message_iter_recurse(iter, &sub);
2649 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2650 const char *type, *path;
2652 dbus_message_iter_recurse(&sub, &sub2);
2654 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2655 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2656 printf("%s=%s\n", type, path);
2658 dbus_message_iter_next(&sub);
2663 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2664 DBusMessageIter sub, sub2;
2666 dbus_message_iter_recurse(iter, &sub);
2667 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2669 uint64_t value, next_elapse;
2671 dbus_message_iter_recurse(&sub, &sub2);
2673 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2674 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2675 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2676 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2678 printf("%s={ value=%s ; next_elapse=%s }\n",
2680 format_timespan(timespan1, sizeof(timespan1), value),
2681 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2684 dbus_message_iter_next(&sub);
2689 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2690 DBusMessageIter sub, sub2;
2692 dbus_message_iter_recurse(iter, &sub);
2693 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2694 const char *controller, *attr, *value;
2696 dbus_message_iter_recurse(&sub, &sub2);
2698 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2699 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2700 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2702 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2708 dbus_message_iter_next(&sub);
2713 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2714 DBusMessageIter sub;
2716 dbus_message_iter_recurse(iter, &sub);
2717 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2718 ExecStatusInfo info;
2721 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2722 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2725 t = strv_join(info.argv, " ");
2727 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2731 yes_no(info.ignore),
2732 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2733 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2734 (unsigned) info. pid,
2735 sigchld_code_to_string(info.code),
2737 info.code == CLD_EXITED ? "" : "/",
2738 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2744 strv_free(info.argv);
2746 dbus_message_iter_next(&sub);
2755 if (generic_print_property(name, iter, arg_all) > 0)
2759 printf("%s=[unprintable]\n", name);
2764 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2765 DBusMessage *reply = NULL;
2766 const char *interface = "";
2768 DBusMessageIter iter, sub, sub2, sub3;
2769 UnitStatusInfo info;
2777 r = bus_method_call_with_reply (
2779 "org.freedesktop.systemd1",
2781 "org.freedesktop.DBus.Properties",
2785 DBUS_TYPE_STRING, &interface,
2790 if (!dbus_message_iter_init(reply, &iter) ||
2791 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2792 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2793 log_error("Failed to parse reply.");
2798 dbus_message_iter_recurse(&iter, &sub);
2805 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2808 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2809 log_error("Failed to parse reply.");
2814 dbus_message_iter_recurse(&sub, &sub2);
2816 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2817 log_error("Failed to parse reply.");
2822 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2823 log_error("Failed to parse reply.");
2828 dbus_message_iter_recurse(&sub2, &sub3);
2830 if (show_properties)
2831 r = print_property(name, &sub3);
2833 r = status_property(name, &sub3, &info);
2836 log_error("Failed to parse reply.");
2841 dbus_message_iter_next(&sub);
2846 if (!show_properties) {
2847 if (streq(verb, "help"))
2848 show_unit_help(&info);
2850 print_status_info(&info);
2853 strv_free(info.documentation);
2855 if (!streq_ptr(info.active_state, "active") &&
2856 !streq_ptr(info.active_state, "reloading") &&
2857 streq(verb, "status"))
2858 /* According to LSB: "program not running" */
2861 while ((p = info.exec)) {
2862 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2863 exec_status_info_free(p);
2868 dbus_message_unref(reply);
2873 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
2874 DBusMessage *reply = NULL;
2875 const char *path = NULL;
2879 dbus_error_init(&error);
2881 r = bus_method_call_with_reply (
2883 "org.freedesktop.systemd1",
2884 "/org/freedesktop/systemd1",
2885 "org.freedesktop.systemd1.Manager",
2889 DBUS_TYPE_UINT32, &pid,
2894 if (!dbus_message_get_args(reply, &error,
2895 DBUS_TYPE_OBJECT_PATH, &path,
2896 DBUS_TYPE_INVALID)) {
2897 log_error("Failed to parse reply: %s", bus_error_message(&error));
2902 r = show_one(verb, bus, path, false, new_line);
2906 dbus_message_unref(reply);
2908 dbus_error_free(&error);
2913 static int show(DBusConnection *bus, char **args) {
2915 bool show_properties, new_line = false;
2921 show_properties = streq(args[0], "show");
2923 if (show_properties)
2924 pager_open_if_enabled();
2926 if (show_properties && strv_length(args) <= 1) {
2927 /* If not argument is specified inspect the manager
2930 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2933 STRV_FOREACH(name, args+1) {
2936 if (safe_atou32(*name, &id) < 0) {
2938 /* Interpret as unit name */
2940 n = unit_name_mangle(*name);
2941 p = unit_dbus_path_from_name(n ? n : *name);
2946 r = show_one(args[0], bus, p, show_properties, &new_line);
2952 } else if (show_properties) {
2954 /* Interpret as job id */
2957 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
2960 r = show_one(args[0], bus, p, show_properties, &new_line);
2968 /* Interpret as PID */
2970 r = show_one_by_pid(args[0], bus, id, &new_line);
2979 static int dump(DBusConnection *bus, char **args) {
2980 DBusMessage *reply = NULL;
2985 dbus_error_init(&error);
2987 pager_open_if_enabled();
2989 r = bus_method_call_with_reply (
2991 "org.freedesktop.systemd1",
2992 "/org/freedesktop/systemd1",
2993 "org.freedesktop.systemd1.Manager",
3001 if (!dbus_message_get_args(reply, &error,
3002 DBUS_TYPE_STRING, &text,
3003 DBUS_TYPE_INVALID)) {
3004 log_error("Failed to parse reply: %s", bus_error_message(&error));
3009 fputs(text, stdout);
3013 dbus_message_unref(reply);
3015 dbus_error_free(&error);
3020 static int snapshot(DBusConnection *bus, char **args) {
3021 DBusMessage *reply = NULL;
3024 dbus_bool_t cleanup = FALSE;
3025 DBusMessageIter iter, sub;
3027 *name = "", *path, *id,
3028 *interface = "org.freedesktop.systemd1.Unit",
3032 dbus_error_init(&error);
3034 if (strv_length(args) > 1)
3037 n = unit_name_mangle(name);
3038 r = bus_method_call_with_reply (
3040 "org.freedesktop.systemd1",
3041 "/org/freedesktop/systemd1",
3042 "org.freedesktop.systemd1.Manager",
3046 DBUS_TYPE_STRING, n ? (const char**) &n : &name,
3047 DBUS_TYPE_BOOLEAN, &cleanup,
3053 if (!dbus_message_get_args(reply, &error,
3054 DBUS_TYPE_OBJECT_PATH, &path,
3055 DBUS_TYPE_INVALID)) {
3056 log_error("Failed to parse reply: %s", bus_error_message(&error));
3061 dbus_message_unref(reply);
3062 r = bus_method_call_with_reply (
3064 "org.freedesktop.systemd1",
3066 "org.freedesktop.DBus.Properties",
3070 DBUS_TYPE_STRING, &interface,
3071 DBUS_TYPE_STRING, &property,
3076 if (!dbus_message_iter_init(reply, &iter) ||
3077 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3078 log_error("Failed to parse reply.");
3083 dbus_message_iter_recurse(&iter, &sub);
3085 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3086 log_error("Failed to parse reply.");
3091 dbus_message_iter_get_basic(&sub, &id);
3098 dbus_message_unref(reply);
3100 dbus_error_free(&error);
3105 static int delete_snapshot(DBusConnection *bus, char **args) {
3106 DBusMessage *reply = NULL;
3113 dbus_error_init(&error);
3115 STRV_FOREACH(name, args+1) {
3116 const char *path = NULL;
3119 n = unit_name_mangle(*name);
3120 r = bus_method_call_with_reply (
3122 "org.freedesktop.systemd1",
3123 "/org/freedesktop/systemd1",
3124 "org.freedesktop.systemd1.Manager",
3128 DBUS_TYPE_STRING, n ? &n : name,
3134 if (!dbus_message_get_args(reply, &error,
3135 DBUS_TYPE_OBJECT_PATH, &path,
3136 DBUS_TYPE_INVALID)) {
3137 log_error("Failed to parse reply: %s", bus_error_message(&error));
3139 dbus_message_unref(reply);
3140 dbus_error_free(&error);
3143 dbus_message_unref(reply);
3145 r = bus_method_call_with_reply (
3147 "org.freedesktop.systemd1",
3149 "org.freedesktop.systemd1.Snapshot",
3162 static int daemon_reload(DBusConnection *bus, char **args) {
3167 if (arg_action == ACTION_RELOAD)
3169 else if (arg_action == ACTION_REEXEC)
3170 method = "Reexecute";
3172 assert(arg_action == ACTION_SYSTEMCTL);
3175 streq(args[0], "clear-jobs") ||
3176 streq(args[0], "cancel") ? "ClearJobs" :
3177 streq(args[0], "daemon-reexec") ? "Reexecute" :
3178 streq(args[0], "reset-failed") ? "ResetFailed" :
3179 streq(args[0], "halt") ? "Halt" :
3180 streq(args[0], "poweroff") ? "PowerOff" :
3181 streq(args[0], "reboot") ? "Reboot" :
3182 streq(args[0], "kexec") ? "KExec" :
3183 streq(args[0], "exit") ? "Exit" :
3184 /* "daemon-reload" */ "Reload";
3187 r = bus_method_call_with_reply (
3189 "org.freedesktop.systemd1",
3190 "/org/freedesktop/systemd1",
3191 "org.freedesktop.systemd1.Manager",
3197 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3198 /* There's always a fallback possible for
3199 * legacy actions. */
3201 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3202 /* On reexecution, we expect a disconnect, not
3206 log_error("Failed to issue method call: %s", bus_error_message(&error));
3207 dbus_error_free(&error);
3212 static int reset_failed(DBusConnection *bus, char **args) {
3216 if (strv_length(args) <= 1)
3217 return daemon_reload(bus, args);
3219 STRV_FOREACH(name, args+1) {
3220 n = unit_name_mangle(*name);
3221 r = bus_method_call_with_reply (
3223 "org.freedesktop.systemd1",
3224 "/org/freedesktop/systemd1",
3225 "org.freedesktop.systemd1.Manager",
3229 DBUS_TYPE_STRING, n ? &n : name,
3240 static int show_enviroment(DBusConnection *bus, char **args) {
3241 DBusMessage *reply = NULL;
3242 DBusMessageIter iter, sub, sub2;
3245 *interface = "org.freedesktop.systemd1.Manager",
3246 *property = "Environment";
3248 pager_open_if_enabled();
3250 r = bus_method_call_with_reply (
3252 "org.freedesktop.systemd1",
3253 "/org/freedesktop/systemd1",
3254 "org.freedesktop.DBus.Properties",
3258 DBUS_TYPE_STRING, &interface,
3259 DBUS_TYPE_STRING, &property,
3264 if (!dbus_message_iter_init(reply, &iter) ||
3265 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3266 log_error("Failed to parse reply.");
3271 dbus_message_iter_recurse(&iter, &sub);
3273 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3274 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3275 log_error("Failed to parse reply.");
3280 dbus_message_iter_recurse(&sub, &sub2);
3282 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3285 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3286 log_error("Failed to parse reply.");
3291 dbus_message_iter_get_basic(&sub2, &text);
3292 printf("%s\n", text);
3294 dbus_message_iter_next(&sub2);
3301 dbus_message_unref(reply);
3306 static int switch_root(DBusConnection *bus, char **args) {
3308 const char *root, *init;
3310 l = strv_length(args);
3311 if (l < 2 || l > 3) {
3312 log_error("Wrong number of arguments.");
3317 init = l >= 3 ? args[2] : "";
3319 return bus_method_call_with_reply (
3321 "org.freedesktop.systemd1",
3322 "/org/freedesktop/systemd1",
3323 "org.freedesktop.systemd1.Manager",
3327 DBUS_TYPE_STRING, &root,
3328 DBUS_TYPE_STRING, &init,
3332 static int set_environment(DBusConnection *bus, char **args) {
3333 DBusMessage *m = NULL, *reply = NULL;
3337 DBusMessageIter iter, sub;
3340 dbus_error_init(&error);
3342 method = streq(args[0], "set-environment")
3344 : "UnsetEnvironment";
3346 if (!(m = dbus_message_new_method_call(
3347 "org.freedesktop.systemd1",
3348 "/org/freedesktop/systemd1",
3349 "org.freedesktop.systemd1.Manager",
3352 log_error("Could not allocate message.");
3356 dbus_message_iter_init_append(m, &iter);
3358 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
3359 log_error("Could not append arguments to message.");
3364 STRV_FOREACH(name, args+1)
3365 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, name)) {
3366 log_error("Could not append arguments to message.");
3371 if (!dbus_message_iter_close_container(&iter, &sub)) {
3372 log_error("Could not append arguments to message.");
3377 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3378 log_error("Failed to issue method call: %s", bus_error_message(&error));
3387 dbus_message_unref(m);
3390 dbus_message_unref(reply);
3392 dbus_error_free(&error);
3397 static int enable_sysv_units(char **args) {
3400 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3401 const char *verb = args[0];
3402 unsigned f = 1, t = 1;
3405 if (arg_scope != UNIT_FILE_SYSTEM)
3408 if (!streq(verb, "enable") &&
3409 !streq(verb, "disable") &&
3410 !streq(verb, "is-enabled"))
3413 /* Processes all SysV units, and reshuffles the array so that
3414 * afterwards only the native units remain */
3417 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3422 for (f = 1; args[f]; f++) {
3425 bool found_native = false, found_sysv;
3427 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3428 char **k, *l, *q = NULL;
3435 if (!endswith(name, ".service"))
3438 if (path_is_absolute(name))
3441 STRV_FOREACH(k, paths.unit_path) {
3444 if (!isempty(arg_root))
3445 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3447 asprintf(&p, "%s/%s", *k, name);
3454 found_native = access(p, F_OK) >= 0;
3465 if (!isempty(arg_root))
3466 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3468 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3474 p[strlen(p) - sizeof(".service") + 1] = 0;
3475 found_sysv = access(p, F_OK) >= 0;
3482 /* Mark this entry, so that we don't try enabling it as native unit */
3483 args[f] = (char*) "";
3485 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3487 if (!isempty(arg_root))
3488 argv[c++] = q = strappend("--root=", arg_root);
3490 argv[c++] = path_get_file_name(p);
3492 streq(verb, "enable") ? "on" :
3493 streq(verb, "disable") ? "off" : "--level=5";
3496 l = strv_join((char**)argv, " ");
3504 log_info("Executing %s", l);
3509 log_error("Failed to fork: %m");
3514 } else if (pid == 0) {
3517 execv(argv[0], (char**) argv);
3518 _exit(EXIT_FAILURE);
3524 j = wait_for_terminate(pid, &status);
3526 log_error("Failed to wait for child: %s", strerror(-r));
3531 if (status.si_code == CLD_EXITED) {
3532 if (streq(verb, "is-enabled")) {
3533 if (status.si_status == 0) {
3542 } else if (status.si_status != 0) {
3553 lookup_paths_free(&paths);
3555 /* Drop all SysV units */
3556 for (f = 1, t = 1; args[f]; f++) {
3558 if (isempty(args[f]))
3561 args[t++] = args[f];
3570 static int mangle_names(char **original_names, char ***mangled_names) {
3571 char **i, **l, **name;
3573 l = new(char*, strv_length(original_names) + 1);
3578 STRV_FOREACH(name, original_names) {
3579 *i = unit_name_mangle(*name);
3594 static int enable_unit(DBusConnection *bus, char **args) {
3595 const char *verb = args[0];
3596 UnitFileChange *changes = NULL;
3597 unsigned n_changes = 0, i;
3598 int carries_install_info = -1;
3599 DBusMessage *m = NULL, *reply = NULL;
3602 char **mangled_names = NULL;
3604 r = enable_sysv_units(args);
3611 dbus_error_init(&error);
3613 if (!bus || avoid_bus()) {
3614 if (streq(verb, "enable")) {
3615 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3616 carries_install_info = r;
3617 } else if (streq(verb, "disable"))
3618 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3619 else if (streq(verb, "reenable")) {
3620 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3621 carries_install_info = r;
3622 } else if (streq(verb, "link"))
3623 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3624 else if (streq(verb, "preset")) {
3625 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3626 carries_install_info = r;
3627 } else if (streq(verb, "mask"))
3628 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3629 else if (streq(verb, "unmask"))
3630 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3632 assert_not_reached("Unknown verb");
3635 log_error("Operation failed: %s", strerror(-r));
3640 for (i = 0; i < n_changes; i++) {
3641 if (changes[i].type == UNIT_FILE_SYMLINK)
3642 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3644 log_info("rm '%s'", changes[i].path);
3650 bool send_force = true, expect_carries_install_info = false;
3652 DBusMessageIter iter, sub, sub2;
3654 if (streq(verb, "enable")) {
3655 method = "EnableUnitFiles";
3656 expect_carries_install_info = true;
3657 } else if (streq(verb, "disable")) {
3658 method = "DisableUnitFiles";
3660 } else if (streq(verb, "reenable")) {
3661 method = "ReenableUnitFiles";
3662 expect_carries_install_info = true;
3663 } else if (streq(verb, "link"))
3664 method = "LinkUnitFiles";
3665 else if (streq(verb, "preset")) {
3666 method = "PresetUnitFiles";
3667 expect_carries_install_info = true;
3668 } else if (streq(verb, "mask"))
3669 method = "MaskUnitFiles";
3670 else if (streq(verb, "unmask")) {
3671 method = "UnmaskUnitFiles";
3674 assert_not_reached("Unknown verb");
3676 m = dbus_message_new_method_call(
3677 "org.freedesktop.systemd1",
3678 "/org/freedesktop/systemd1",
3679 "org.freedesktop.systemd1.Manager",
3686 dbus_message_iter_init_append(m, &iter);
3688 r = mangle_names(args+1, &mangled_names);
3692 r = bus_append_strv_iter(&iter, mangled_names);
3694 log_error("Failed to append unit files.");
3699 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3700 log_error("Failed to append runtime boolean.");
3708 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3709 log_error("Failed to append force boolean.");
3715 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3717 log_error("Failed to issue method call: %s", bus_error_message(&error));
3722 if (!dbus_message_iter_init(reply, &iter)) {
3723 log_error("Failed to initialize iterator.");
3727 if (expect_carries_install_info) {
3728 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3730 log_error("Failed to parse reply.");
3734 carries_install_info = b;
3737 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3738 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3739 log_error("Failed to parse reply.");
3744 dbus_message_iter_recurse(&iter, &sub);
3745 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3746 const char *type, *path, *source;
3748 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3749 log_error("Failed to parse reply.");
3754 dbus_message_iter_recurse(&sub, &sub2);
3756 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3757 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3758 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3759 log_error("Failed to parse reply.");
3765 if (streq(type, "symlink"))
3766 log_info("ln -s '%s' '%s'", source, path);
3768 log_info("rm '%s'", path);
3771 dbus_message_iter_next(&sub);
3774 /* Try to reload if enabeld */
3776 r = daemon_reload(bus, args);
3779 if (carries_install_info == 0)
3780 log_warning("The unit files have no [Install] section. They are not meant to be enabled using systemctl.");
3784 dbus_message_unref(m);
3787 dbus_message_unref(reply);
3789 unit_file_changes_free(changes, n_changes);
3791 dbus_error_free(&error);
3793 strv_free(mangled_names);
3798 static int unit_is_enabled(DBusConnection *bus, char **args) {
3801 DBusMessage *reply = NULL;
3805 dbus_error_init(&error);
3807 r = enable_sysv_units(args);
3813 if (!bus || avoid_bus()) {
3815 STRV_FOREACH(name, args+1) {
3816 UnitFileState state;
3818 state = unit_file_get_state(arg_scope, arg_root, *name);
3824 if (state == UNIT_FILE_ENABLED ||
3825 state == UNIT_FILE_ENABLED_RUNTIME ||
3826 state == UNIT_FILE_STATIC)
3830 puts(unit_file_state_to_string(state));
3834 STRV_FOREACH(name, args+1) {
3837 r = bus_method_call_with_reply (
3839 "org.freedesktop.systemd1",
3840 "/org/freedesktop/systemd1",
3841 "org.freedesktop.systemd1.Manager",
3845 DBUS_TYPE_STRING, name,
3850 if (!dbus_message_get_args(reply, &error,
3851 DBUS_TYPE_STRING, &s,
3852 DBUS_TYPE_INVALID)) {
3853 log_error("Failed to parse reply: %s", bus_error_message(&error));
3858 dbus_message_unref(reply);
3861 if (streq(s, "enabled") ||
3862 streq(s, "enabled-runtime") ||
3871 r = enabled ? 0 : 1;
3875 dbus_message_unref(reply);
3877 dbus_error_free(&error);
3881 static int systemctl_help(void) {
3883 pager_open_if_enabled();
3885 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
3886 "Query or send control commands to the systemd manager.\n\n"
3887 " -h --help Show this help\n"
3888 " --version Show package version\n"
3889 " -t --type=TYPE List only units of a particular type\n"
3890 " -p --property=NAME Show only properties by this name\n"
3891 " -a --all Show all units/properties, including dead/empty ones\n"
3892 " --failed Show only failed units\n"
3893 " --full Don't ellipsize unit names on output\n"
3894 " --fail When queueing a new job, fail if conflicting jobs are\n"
3896 " --ignore-dependencies\n"
3897 " When queueing a new job, ignore all its dependencies\n"
3898 " --kill-who=WHO Who to send signal to\n"
3899 " -s --signal=SIGNAL Which signal to send\n"
3900 " -H --host=[USER@]HOST\n"
3901 " Show information for remote host\n"
3902 " -P --privileged Acquire privileges before execution\n"
3903 " -q --quiet Suppress output\n"
3904 " --no-block Do not wait until operation finished\n"
3905 " --no-wall Don't send wall message before halt/power-off/reboot\n"
3906 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
3908 " --no-legend Do not print a legend (column headers and hints)\n"
3909 " --no-pager Do not pipe output into a pager\n"
3910 " --no-ask-password\n"
3911 " Do not ask for system passwords\n"
3912 " --order When generating graph for dot, show only order\n"
3913 " --require When generating graph for dot, show only requirement\n"
3914 " --system Connect to system manager\n"
3915 " --user Connect to user service manager\n"
3916 " --global Enable/disable unit files globally\n"
3917 " -f --force When enabling unit files, override existing symlinks\n"
3918 " When shutting down, execute action immediately\n"
3919 " --root=PATH Enable unit files in the specified root directory\n"
3920 " --runtime Enable unit files only temporarily until next reboot\n"
3921 " -n --lines=INTEGER Journal entries to show\n"
3922 " --follow Follow journal\n"
3923 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
3924 " verbose, export, json, json-pretty, cat)\n\n"
3926 " list-units List loaded units\n"
3927 " start [NAME...] Start (activate) one or more units\n"
3928 " stop [NAME...] Stop (deactivate) one or more units\n"
3929 " reload [NAME...] Reload one or more units\n"
3930 " restart [NAME...] Start or restart one or more units\n"
3931 " try-restart [NAME...] Restart one or more units if active\n"
3932 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
3933 " otherwise start or restart\n"
3934 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
3935 " otherwise restart if active\n"
3936 " isolate [NAME] Start one unit and stop all others\n"
3937 " kill [NAME...] Send signal to processes of a unit\n"
3938 " is-active [NAME...] Check whether units are active\n"
3939 " status [NAME...|PID...] Show runtime status of one or more units\n"
3940 " show [NAME...|JOB...] Show properties of one or more\n"
3941 " units/jobs or the manager\n"
3942 " help [NAME...|PID...] Show manual for one or more units\n"
3943 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
3945 " load [NAME...] Load one or more units\n\n"
3946 "Unit File Commands:\n"
3947 " list-unit-files List installed unit files\n"
3948 " enable [NAME...] Enable one or more unit files\n"
3949 " disable [NAME...] Disable one or more unit files\n"
3950 " reenable [NAME...] Reenable one or more unit files\n"
3951 " preset [NAME...] Enable/disable one or more unit files\n"
3952 " based on preset configuration\n"
3953 " mask [NAME...] Mask one or more units\n"
3954 " unmask [NAME...] Unmask one or more units\n"
3955 " link [PATH...] Link one or more units files into\n"
3956 " the search path\n"
3957 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
3959 " list-jobs List jobs\n"
3960 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
3961 "Status Commands:\n"
3962 " dump Dump server status\n"
3963 " dot Dump dependency graph for dot(1)\n\n"
3964 "Snapshot Commands:\n"
3965 " snapshot [NAME] Create a snapshot\n"
3966 " delete [NAME...] Remove one or more snapshots\n\n"
3967 "Environment Commands:\n"
3968 " show-environment Dump environment\n"
3969 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
3970 " unset-environment [NAME...] Unset one or more environment variables\n\n"
3971 "Manager Lifecycle Commands:\n"
3972 " daemon-reload Reload systemd manager configuration\n"
3973 " daemon-reexec Reexecute systemd manager\n\n"
3974 "System Commands:\n"
3975 " default Enter system default mode\n"
3976 " rescue Enter system rescue mode\n"
3977 " emergency Enter system emergency mode\n"
3978 " halt Shut down and halt the system\n"
3979 " poweroff Shut down and power-off the system\n"
3980 " reboot Shut down and reboot the system\n"
3981 " kexec Shut down and reboot the system with kexec\n"
3982 " exit Request user instance exit\n"
3983 " switch-root [ROOT] [INIT] Change to a different root file system\n"
3984 " suspend Suspend the system\n"
3985 " hibernate Hibernate the system\n",
3986 program_invocation_short_name);
3991 static int halt_help(void) {
3993 printf("%s [OPTIONS...]\n\n"
3994 "%s the system.\n\n"
3995 " --help Show this help\n"
3996 " --halt Halt the machine\n"
3997 " -p --poweroff Switch off the machine\n"
3998 " --reboot Reboot the machine\n"
3999 " -f --force Force immediate halt/power-off/reboot\n"
4000 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4001 " -d --no-wtmp Don't write wtmp record\n"
4002 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4003 program_invocation_short_name,
4004 arg_action == ACTION_REBOOT ? "Reboot" :
4005 arg_action == ACTION_POWEROFF ? "Power off" :
4011 static int shutdown_help(void) {
4013 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4014 "Shut down the system.\n\n"
4015 " --help Show this help\n"
4016 " -H --halt Halt the machine\n"
4017 " -P --poweroff Power-off the machine\n"
4018 " -r --reboot Reboot the machine\n"
4019 " -h Equivalent to --poweroff, overridden by --halt\n"
4020 " -k Don't halt/power-off/reboot, just send warnings\n"
4021 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4022 " -c Cancel a pending shutdown\n",
4023 program_invocation_short_name);
4028 static int telinit_help(void) {
4030 printf("%s [OPTIONS...] {COMMAND}\n\n"
4031 "Send control commands to the init daemon.\n\n"
4032 " --help Show this help\n"
4033 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4035 " 0 Power-off the machine\n"
4036 " 6 Reboot the machine\n"
4037 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4038 " 1, s, S Enter rescue mode\n"
4039 " q, Q Reload init daemon configuration\n"
4040 " u, U Reexecute init daemon\n",
4041 program_invocation_short_name);
4046 static int runlevel_help(void) {
4048 printf("%s [OPTIONS...]\n\n"
4049 "Prints the previous and current runlevel of the init system.\n\n"
4050 " --help Show this help\n",
4051 program_invocation_short_name);
4056 static int systemctl_parse_argv(int argc, char *argv[]) {
4060 ARG_IGNORE_DEPENDENCIES,
4075 ARG_NO_ASK_PASSWORD,
4082 static const struct option options[] = {
4083 { "help", no_argument, NULL, 'h' },
4084 { "version", no_argument, NULL, ARG_VERSION },
4085 { "type", required_argument, NULL, 't' },
4086 { "property", required_argument, NULL, 'p' },
4087 { "all", no_argument, NULL, 'a' },
4088 { "failed", no_argument, NULL, ARG_FAILED },
4089 { "full", no_argument, NULL, ARG_FULL },
4090 { "fail", no_argument, NULL, ARG_FAIL },
4091 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4092 { "user", no_argument, NULL, ARG_USER },
4093 { "system", no_argument, NULL, ARG_SYSTEM },
4094 { "global", no_argument, NULL, ARG_GLOBAL },
4095 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4096 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4097 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4098 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4099 { "quiet", no_argument, NULL, 'q' },
4100 { "order", no_argument, NULL, ARG_ORDER },
4101 { "require", no_argument, NULL, ARG_REQUIRE },
4102 { "root", required_argument, NULL, ARG_ROOT },
4103 { "force", no_argument, NULL, ARG_FORCE },
4104 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4105 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4106 { "signal", required_argument, NULL, 's' },
4107 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4108 { "host", required_argument, NULL, 'H' },
4109 { "privileged",no_argument, NULL, 'P' },
4110 { "runtime", no_argument, NULL, ARG_RUNTIME },
4111 { "lines", required_argument, NULL, 'n' },
4112 { "follow", no_argument, NULL, ARG_FOLLOW },
4113 { "output", required_argument, NULL, 'o' },
4114 { NULL, 0, NULL, 0 }
4122 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4131 puts(PACKAGE_STRING);
4133 puts(SYSTEMD_FEATURES);
4137 if (unit_type_from_string(optarg) >= 0) {
4141 if (unit_load_state_from_string(optarg) >= 0) {
4142 arg_load_state = optarg;
4145 log_error("Unkown unit type or load state '%s'.",
4151 if (!(l = strv_append(arg_property, optarg)))
4154 strv_free(arg_property);
4157 /* If the user asked for a particular
4158 * property, show it to him, even if it is
4169 arg_job_mode = "fail";
4172 case ARG_IGNORE_DEPENDENCIES:
4173 arg_job_mode = "ignore-dependencies";
4177 arg_scope = UNIT_FILE_USER;
4181 arg_scope = UNIT_FILE_SYSTEM;
4185 arg_scope = UNIT_FILE_GLOBAL;
4189 arg_no_block = true;
4193 arg_no_legend = true;
4197 arg_no_pager = true;
4205 arg_dot = DOT_ORDER;
4209 arg_dot = DOT_REQUIRE;
4237 /* -f is short for both --follow and --force! */
4243 arg_no_reload = true;
4247 arg_kill_who = optarg;
4251 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4252 log_error("Failed to parse signal string %s.", optarg);
4257 case ARG_NO_ASK_PASSWORD:
4258 arg_ask_password = false;
4262 arg_transport = TRANSPORT_POLKIT;
4266 arg_transport = TRANSPORT_SSH;
4275 if (safe_atou(optarg, &arg_lines) < 0) {
4276 log_error("Failed to parse lines '%s'", optarg);
4282 arg_output = output_mode_from_string(optarg);
4283 if (arg_output < 0) {
4284 log_error("Unknown output '%s'.", optarg);
4293 log_error("Unknown option code '%c'.", c);
4298 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4299 log_error("Cannot access user instance remotely.");
4306 static int halt_parse_argv(int argc, char *argv[]) {
4315 static const struct option options[] = {
4316 { "help", no_argument, NULL, ARG_HELP },
4317 { "halt", no_argument, NULL, ARG_HALT },
4318 { "poweroff", no_argument, NULL, 'p' },
4319 { "reboot", no_argument, NULL, ARG_REBOOT },
4320 { "force", no_argument, NULL, 'f' },
4321 { "wtmp-only", no_argument, NULL, 'w' },
4322 { "no-wtmp", no_argument, NULL, 'd' },
4323 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4324 { NULL, 0, NULL, 0 }
4332 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4333 if (runlevel == '0' || runlevel == '6')
4336 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4344 arg_action = ACTION_HALT;
4348 if (arg_action != ACTION_REBOOT)
4349 arg_action = ACTION_POWEROFF;
4353 arg_action = ACTION_REBOOT;
4375 /* Compatibility nops */
4382 log_error("Unknown option code '%c'.", c);
4387 if (optind < argc) {
4388 log_error("Too many arguments.");
4395 static int parse_time_spec(const char *t, usec_t *_u) {
4399 if (streq(t, "now"))
4401 else if (!strchr(t, ':')) {
4404 if (safe_atou64(t, &u) < 0)
4407 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4416 hour = strtol(t, &e, 10);
4417 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4420 minute = strtol(e+1, &e, 10);
4421 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4424 n = now(CLOCK_REALTIME);
4425 s = (time_t) (n / USEC_PER_SEC);
4428 assert_se(localtime_r(&s, &tm));
4430 tm.tm_hour = (int) hour;
4431 tm.tm_min = (int) minute;
4434 assert_se(s = mktime(&tm));
4436 *_u = (usec_t) s * USEC_PER_SEC;
4439 *_u += USEC_PER_DAY;
4445 static int shutdown_parse_argv(int argc, char *argv[]) {
4452 static const struct option options[] = {
4453 { "help", no_argument, NULL, ARG_HELP },
4454 { "halt", no_argument, NULL, 'H' },
4455 { "poweroff", no_argument, NULL, 'P' },
4456 { "reboot", no_argument, NULL, 'r' },
4457 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4458 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4459 { NULL, 0, NULL, 0 }
4467 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4475 arg_action = ACTION_HALT;
4479 arg_action = ACTION_POWEROFF;
4484 arg_action = ACTION_KEXEC;
4486 arg_action = ACTION_REBOOT;
4490 arg_action = ACTION_KEXEC;
4494 if (arg_action != ACTION_HALT)
4495 arg_action = ACTION_POWEROFF;
4508 /* Compatibility nops */
4512 arg_action = ACTION_CANCEL_SHUTDOWN;
4519 log_error("Unknown option code '%c'.", c);
4524 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4525 r = parse_time_spec(argv[optind], &arg_when);
4527 log_error("Failed to parse time specification: %s", argv[optind]);
4531 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4533 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4534 /* No time argument for shutdown cancel */
4535 arg_wall = argv + optind;
4536 else if (argc > optind + 1)
4537 /* We skip the time argument */
4538 arg_wall = argv + optind + 1;
4545 static int telinit_parse_argv(int argc, char *argv[]) {
4552 static const struct option options[] = {
4553 { "help", no_argument, NULL, ARG_HELP },
4554 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4555 { NULL, 0, NULL, 0 }
4558 static const struct {
4562 { '0', ACTION_POWEROFF },
4563 { '6', ACTION_REBOOT },
4564 { '1', ACTION_RESCUE },
4565 { '2', ACTION_RUNLEVEL2 },
4566 { '3', ACTION_RUNLEVEL3 },
4567 { '4', ACTION_RUNLEVEL4 },
4568 { '5', ACTION_RUNLEVEL5 },
4569 { 's', ACTION_RESCUE },
4570 { 'S', ACTION_RESCUE },
4571 { 'q', ACTION_RELOAD },
4572 { 'Q', ACTION_RELOAD },
4573 { 'u', ACTION_REEXEC },
4574 { 'U', ACTION_REEXEC }
4583 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4598 log_error("Unknown option code '%c'.", c);
4603 if (optind >= argc) {
4608 if (optind + 1 < argc) {
4609 log_error("Too many arguments.");
4613 if (strlen(argv[optind]) != 1) {
4614 log_error("Expected single character argument.");
4618 for (i = 0; i < ELEMENTSOF(table); i++)
4619 if (table[i].from == argv[optind][0])
4622 if (i >= ELEMENTSOF(table)) {
4623 log_error("Unknown command '%s'.", argv[optind]);
4627 arg_action = table[i].to;
4634 static int runlevel_parse_argv(int argc, char *argv[]) {
4640 static const struct option options[] = {
4641 { "help", no_argument, NULL, ARG_HELP },
4642 { NULL, 0, NULL, 0 }
4650 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4661 log_error("Unknown option code '%c'.", c);
4666 if (optind < argc) {
4667 log_error("Too many arguments.");
4674 static int parse_argv(int argc, char *argv[]) {
4678 if (program_invocation_short_name) {
4680 if (strstr(program_invocation_short_name, "halt")) {
4681 arg_action = ACTION_HALT;
4682 return halt_parse_argv(argc, argv);
4683 } else if (strstr(program_invocation_short_name, "poweroff")) {
4684 arg_action = ACTION_POWEROFF;
4685 return halt_parse_argv(argc, argv);
4686 } else if (strstr(program_invocation_short_name, "reboot")) {
4688 arg_action = ACTION_KEXEC;
4690 arg_action = ACTION_REBOOT;
4691 return halt_parse_argv(argc, argv);
4692 } else if (strstr(program_invocation_short_name, "shutdown")) {
4693 arg_action = ACTION_POWEROFF;
4694 return shutdown_parse_argv(argc, argv);
4695 } else if (strstr(program_invocation_short_name, "init")) {
4697 if (sd_booted() > 0) {
4698 arg_action = ACTION_INVALID;
4699 return telinit_parse_argv(argc, argv);
4701 /* Hmm, so some other init system is
4702 * running, we need to forward this
4703 * request to it. For now we simply
4704 * guess that it is Upstart. */
4706 execv("/lib/upstart/telinit", argv);
4708 log_error("Couldn't find an alternative telinit implementation to spawn.");
4712 } else if (strstr(program_invocation_short_name, "runlevel")) {
4713 arg_action = ACTION_RUNLEVEL;
4714 return runlevel_parse_argv(argc, argv);
4718 arg_action = ACTION_SYSTEMCTL;
4719 return systemctl_parse_argv(argc, argv);
4722 static int action_to_runlevel(void) {
4724 static const char table[_ACTION_MAX] = {
4725 [ACTION_HALT] = '0',
4726 [ACTION_POWEROFF] = '0',
4727 [ACTION_REBOOT] = '6',
4728 [ACTION_RUNLEVEL2] = '2',
4729 [ACTION_RUNLEVEL3] = '3',
4730 [ACTION_RUNLEVEL4] = '4',
4731 [ACTION_RUNLEVEL5] = '5',
4732 [ACTION_RESCUE] = '1'
4735 assert(arg_action < _ACTION_MAX);
4737 return table[arg_action];
4740 static int talk_upstart(void) {
4741 DBusMessage *m = NULL, *reply = NULL;
4743 int previous, rl, r;
4745 env1_buf[] = "RUNLEVEL=X",
4746 env2_buf[] = "PREVLEVEL=X";
4747 char *env1 = env1_buf, *env2 = env2_buf;
4748 const char *emit = "runlevel";
4749 dbus_bool_t b_false = FALSE;
4750 DBusMessageIter iter, sub;
4751 DBusConnection *bus;
4753 dbus_error_init(&error);
4755 if (!(rl = action_to_runlevel()))
4758 if (utmp_get_runlevel(&previous, NULL) < 0)
4761 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4762 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4767 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4772 if ((r = bus_check_peercred(bus)) < 0) {
4773 log_error("Failed to verify owner of bus.");
4777 if (!(m = dbus_message_new_method_call(
4778 "com.ubuntu.Upstart",
4779 "/com/ubuntu/Upstart",
4780 "com.ubuntu.Upstart0_6",
4783 log_error("Could not allocate message.");
4788 dbus_message_iter_init_append(m, &iter);
4790 env1_buf[sizeof(env1_buf)-2] = rl;
4791 env2_buf[sizeof(env2_buf)-2] = previous;
4793 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4794 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4795 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4796 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4797 !dbus_message_iter_close_container(&iter, &sub) ||
4798 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4799 log_error("Could not append arguments to message.");
4804 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4806 if (bus_error_is_no_service(&error)) {
4811 log_error("Failed to issue method call: %s", bus_error_message(&error));
4820 dbus_message_unref(m);
4823 dbus_message_unref(reply);
4826 dbus_connection_flush(bus);
4827 dbus_connection_close(bus);
4828 dbus_connection_unref(bus);
4831 dbus_error_free(&error);
4836 static int talk_initctl(void) {
4837 struct init_request request;
4841 if (!(rl = action_to_runlevel()))
4845 request.magic = INIT_MAGIC;
4846 request.sleeptime = 0;
4847 request.cmd = INIT_CMD_RUNLVL;
4848 request.runlevel = rl;
4850 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4852 if (errno == ENOENT)
4855 log_error("Failed to open "INIT_FIFO": %m");
4860 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
4861 close_nointr_nofail(fd);
4864 log_error("Failed to write to "INIT_FIFO": %m");
4865 return errno ? -errno : -EIO;
4871 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
4873 static const struct {
4881 int (* const dispatch)(DBusConnection *bus, char **args);
4883 { "list-units", LESS, 1, list_units },
4884 { "list-unit-files", EQUAL, 1, list_unit_files },
4885 { "list-jobs", EQUAL, 1, list_jobs },
4886 { "clear-jobs", EQUAL, 1, daemon_reload },
4887 { "load", MORE, 2, load_unit },
4888 { "cancel", MORE, 2, cancel_job },
4889 { "start", MORE, 2, start_unit },
4890 { "stop", MORE, 2, start_unit },
4891 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4892 { "reload", MORE, 2, start_unit },
4893 { "restart", MORE, 2, start_unit },
4894 { "try-restart", MORE, 2, start_unit },
4895 { "reload-or-restart", MORE, 2, start_unit },
4896 { "reload-or-try-restart", MORE, 2, start_unit },
4897 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
4898 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4899 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
4900 { "isolate", EQUAL, 2, start_unit },
4901 { "kill", MORE, 2, kill_unit },
4902 { "is-active", MORE, 2, check_unit },
4903 { "check", MORE, 2, check_unit },
4904 { "show", MORE, 1, show },
4905 { "status", MORE, 2, show },
4906 { "help", MORE, 2, show },
4907 { "dump", EQUAL, 1, dump },
4908 { "dot", EQUAL, 1, dot },
4909 { "snapshot", LESS, 2, snapshot },
4910 { "delete", MORE, 2, delete_snapshot },
4911 { "daemon-reload", EQUAL, 1, daemon_reload },
4912 { "daemon-reexec", EQUAL, 1, daemon_reload },
4913 { "show-environment", EQUAL, 1, show_enviroment },
4914 { "set-environment", MORE, 2, set_environment },
4915 { "unset-environment", MORE, 2, set_environment },
4916 { "halt", EQUAL, 1, start_special },
4917 { "poweroff", EQUAL, 1, start_special },
4918 { "reboot", EQUAL, 1, start_special },
4919 { "kexec", EQUAL, 1, start_special },
4920 { "suspend", EQUAL, 1, start_special },
4921 { "hibernate", EQUAL, 1, start_special },
4922 { "default", EQUAL, 1, start_special },
4923 { "rescue", EQUAL, 1, start_special },
4924 { "emergency", EQUAL, 1, start_special },
4925 { "exit", EQUAL, 1, start_special },
4926 { "reset-failed", MORE, 1, reset_failed },
4927 { "enable", MORE, 2, enable_unit },
4928 { "disable", MORE, 2, enable_unit },
4929 { "is-enabled", MORE, 2, unit_is_enabled },
4930 { "reenable", MORE, 2, enable_unit },
4931 { "preset", MORE, 2, enable_unit },
4932 { "mask", MORE, 2, enable_unit },
4933 { "unmask", MORE, 2, enable_unit },
4934 { "link", MORE, 2, enable_unit },
4935 { "switch-root", MORE, 2, switch_root },
4945 left = argc - optind;
4948 /* Special rule: no arguments means "list-units" */
4951 if (streq(argv[optind], "help") && !argv[optind+1]) {
4952 log_error("This command expects one or more "
4953 "unit names. Did you mean --help?");
4957 for (i = 0; i < ELEMENTSOF(verbs); i++)
4958 if (streq(argv[optind], verbs[i].verb))
4961 if (i >= ELEMENTSOF(verbs)) {
4962 log_error("Unknown operation '%s'.", argv[optind]);
4967 switch (verbs[i].argc_cmp) {
4970 if (left != verbs[i].argc) {
4971 log_error("Invalid number of arguments.");
4978 if (left < verbs[i].argc) {
4979 log_error("Too few arguments.");
4986 if (left > verbs[i].argc) {
4987 log_error("Too many arguments.");
4994 assert_not_reached("Unknown comparison operator.");
4997 /* Require a bus connection for all operations but
4999 if (!streq(verbs[i].verb, "enable") &&
5000 !streq(verbs[i].verb, "disable") &&
5001 !streq(verbs[i].verb, "is-enabled") &&
5002 !streq(verbs[i].verb, "list-unit-files") &&
5003 !streq(verbs[i].verb, "reenable") &&
5004 !streq(verbs[i].verb, "preset") &&
5005 !streq(verbs[i].verb, "mask") &&
5006 !streq(verbs[i].verb, "unmask") &&
5007 !streq(verbs[i].verb, "link")) {
5009 if (running_in_chroot() > 0) {
5010 log_info("Running in chroot, ignoring request.");
5014 if (((!streq(verbs[i].verb, "reboot") &&
5015 !streq(verbs[i].verb, "halt") &&
5016 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5017 log_error("Failed to get D-Bus connection: %s",
5018 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5024 if (!bus && !avoid_bus()) {
5025 log_error("Failed to get D-Bus connection: %s",
5026 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5031 return verbs[i].dispatch(bus, argv + optind);
5034 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5036 struct msghdr msghdr;
5037 struct iovec iovec[2];
5038 union sockaddr_union sockaddr;
5039 struct sd_shutdown_command c;
5041 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5048 c.dry_run = dry_run;
5052 sockaddr.sa.sa_family = AF_UNIX;
5053 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5056 msghdr.msg_name = &sockaddr;
5057 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5060 iovec[0].iov_base = (char*) &c;
5061 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5063 if (isempty(message))
5064 msghdr.msg_iovlen = 1;
5066 iovec[1].iov_base = (char*) message;
5067 iovec[1].iov_len = strlen(message);
5068 msghdr.msg_iovlen = 2;
5070 msghdr.msg_iov = iovec;
5072 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5073 close_nointr_nofail(fd);
5077 close_nointr_nofail(fd);
5081 static int reload_with_fallback(DBusConnection *bus) {
5084 /* First, try systemd via D-Bus. */
5085 if (daemon_reload(bus, NULL) >= 0)
5089 /* Nothing else worked, so let's try signals */
5090 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5092 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5093 log_error("kill() failed: %m");
5100 static int start_with_fallback(DBusConnection *bus) {
5103 /* First, try systemd via D-Bus. */
5104 if (start_unit(bus, NULL) >= 0)
5108 /* Hmm, talking to systemd via D-Bus didn't work. Then
5109 * let's try to talk to Upstart via D-Bus. */
5110 if (talk_upstart() > 0)
5113 /* Nothing else worked, so let's try
5115 if (talk_initctl() > 0)
5118 log_error("Failed to talk to init daemon.");
5122 warn_wall(arg_action);
5126 static _noreturn_ void halt_now(enum action a) {
5128 /* Make sure C-A-D is handled by the kernel from this
5130 reboot(RB_ENABLE_CAD);
5135 log_info("Halting.");
5136 reboot(RB_HALT_SYSTEM);
5139 case ACTION_POWEROFF:
5140 log_info("Powering off.");
5141 reboot(RB_POWER_OFF);
5145 log_info("Rebooting.");
5146 reboot(RB_AUTOBOOT);
5150 assert_not_reached("Unknown halt action.");
5153 assert_not_reached("Uh? This shouldn't happen.");
5156 static int halt_main(DBusConnection *bus) {
5159 if (geteuid() != 0) {
5160 /* Try logind if we are a normal user and no special
5161 * mode applies. Maybe PolicyKit allows us to shutdown
5164 if (arg_when <= 0 &&
5167 (arg_action == ACTION_POWEROFF ||
5168 arg_action == ACTION_REBOOT)) {
5169 r = reboot_with_logind(bus, arg_action);
5174 log_error("Must be root.");
5181 m = strv_join(arg_wall, " ");
5182 r = send_shutdownd(arg_when,
5183 arg_action == ACTION_HALT ? 'H' :
5184 arg_action == ACTION_POWEROFF ? 'P' :
5185 arg_action == ACTION_KEXEC ? 'K' :
5193 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5195 char date[FORMAT_TIMESTAMP_MAX];
5197 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5198 format_timestamp(date, sizeof(date), arg_when));
5203 if (!arg_dry && !arg_force)
5204 return start_with_fallback(bus);
5207 if (sd_booted() > 0)
5208 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5210 r = utmp_put_shutdown();
5212 log_warning("Failed to write utmp record: %s", strerror(-r));
5219 halt_now(arg_action);
5220 /* We should never reach this. */
5224 static int runlevel_main(void) {
5225 int r, runlevel, previous;
5227 r = utmp_get_runlevel(&runlevel, &previous);
5234 previous <= 0 ? 'N' : previous,
5235 runlevel <= 0 ? 'N' : runlevel);
5240 int main(int argc, char*argv[]) {
5241 int r, retval = EXIT_FAILURE;
5242 DBusConnection *bus = NULL;
5245 dbus_error_init(&error);
5247 log_parse_environment();
5250 r = parse_argv(argc, argv);
5254 retval = EXIT_SUCCESS;
5258 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5259 * let's shortcut this */
5260 if (arg_action == ACTION_RUNLEVEL) {
5261 r = runlevel_main();
5262 retval = r < 0 ? EXIT_FAILURE : r;
5266 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5267 log_info("Running in chroot, ignoring request.");
5273 if (arg_transport == TRANSPORT_NORMAL)
5274 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5275 else if (arg_transport == TRANSPORT_POLKIT) {
5276 bus_connect_system_polkit(&bus, &error);
5277 private_bus = false;
5278 } else if (arg_transport == TRANSPORT_SSH) {
5279 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5280 private_bus = false;
5282 assert_not_reached("Uh, invalid transport...");
5285 switch (arg_action) {
5287 case ACTION_SYSTEMCTL:
5288 r = systemctl_main(bus, argc, argv, &error);
5292 case ACTION_POWEROFF:
5298 case ACTION_RUNLEVEL2:
5299 case ACTION_RUNLEVEL3:
5300 case ACTION_RUNLEVEL4:
5301 case ACTION_RUNLEVEL5:
5303 case ACTION_EMERGENCY:
5304 case ACTION_DEFAULT:
5305 r = start_with_fallback(bus);
5310 r = reload_with_fallback(bus);
5313 case ACTION_CANCEL_SHUTDOWN: {
5317 m = strv_join(arg_wall, " ");
5319 retval = EXIT_FAILURE;
5323 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5325 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5330 case ACTION_INVALID:
5331 case ACTION_RUNLEVEL:
5333 assert_not_reached("Unknown action");
5336 retval = r < 0 ? EXIT_FAILURE : r;
5340 dbus_connection_flush(bus);
5341 dbus_connection_close(bus);
5342 dbus_connection_unref(bus);
5345 dbus_error_free(&error);
5349 strv_free(arg_property);
5352 ask_password_agent_close();
5353 polkit_agent_close();