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(bool b) {
194 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
197 static const char *ansi_highlight_red(bool b) {
202 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
205 static const char *ansi_highlight_green(bool b) {
210 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
213 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
216 if (!dbus_error_is_set(error))
219 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
220 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
221 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
222 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
223 return EXIT_NOPERMISSION;
225 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
226 return EXIT_NOTINSTALLED;
228 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
229 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
230 return EXIT_NOTIMPLEMENTED;
232 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
233 return EXIT_NOTCONFIGURED;
241 static void warn_wall(enum action a) {
242 static const char *table[_ACTION_MAX] = {
243 [ACTION_HALT] = "The system is going down for system halt NOW!",
244 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
245 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
246 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
247 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
248 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
249 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
258 p = strv_join(arg_wall, " ");
260 log_error("Failed to join strings.");
276 utmp_wall(table[a], NULL);
279 static bool avoid_bus(void) {
281 if (running_in_chroot() > 0)
284 if (sd_booted() <= 0)
287 if (!isempty(arg_root))
290 if (arg_scope == UNIT_FILE_GLOBAL)
298 const char *description;
299 const char *load_state;
300 const char *active_state;
301 const char *sub_state;
302 const char *following;
303 const char *unit_path;
305 const char *job_type;
306 const char *job_path;
309 static int compare_unit_info(const void *a, const void *b) {
311 const struct unit_info *u = a, *v = b;
313 d1 = strrchr(u->id, '.');
314 d2 = strrchr(v->id, '.');
319 if ((r = strcasecmp(d1, d2)) != 0)
323 return strcasecmp(u->id, v->id);
326 static bool output_show_unit(const struct unit_info *u) {
330 return streq(u->active_state, "failed");
332 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
333 streq(dot+1, arg_type))) &&
334 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
335 (arg_all || !(streq(u->active_state, "inactive")
336 || u->following[0]) || u->job_id > 0);
339 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
340 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
341 const struct unit_info *u;
343 max_id_len = sizeof("UNIT")-1;
344 active_len = sizeof("ACTIVE")-1;
345 sub_len = sizeof("SUB")-1;
346 job_len = sizeof("JOB")-1;
349 for (u = unit_infos; u < unit_infos + c; u++) {
350 if (!output_show_unit(u))
353 max_id_len = MAX(max_id_len, strlen(u->id));
354 active_len = MAX(active_len, strlen(u->active_state));
355 sub_len = MAX(sub_len, strlen(u->sub_state));
357 job_len = MAX(job_len, strlen(u->job_type));
362 id_len = MIN(max_id_len, 25);
363 basic_len = 5 + id_len + 6 + active_len + sub_len + job_len;
364 if (basic_len < (unsigned) columns()) {
365 unsigned extra_len, incr;
366 extra_len = columns() - basic_len;
367 /* Either UNIT already got 25, or is fully satisfied.
368 * Grant up to 25 to DESC now. */
369 incr = MIN(extra_len, 25);
372 /* split the remaining space between UNIT and DESC,
373 * but do not give UNIT more than it needs. */
375 incr = MIN(extra_len / 2, max_id_len - id_len);
377 desc_len += extra_len - incr;
383 for (u = unit_infos; u < unit_infos + c; u++) {
385 const char *on_loaded, *off_loaded;
386 const char *on_active, *off_active;
388 if (!output_show_unit(u))
391 if (!n_shown && !arg_no_legend) {
392 printf("%-*s %-6s %-*s %-*s %-*s ", id_len, "UNIT", "LOAD",
393 active_len, "ACTIVE", sub_len, "SUB", job_len, "JOB");
394 if (!arg_full && arg_no_pager)
395 printf("%.*s\n", desc_len, "DESCRIPTION");
397 printf("%s\n", "DESCRIPTION");
402 if (streq(u->load_state, "error")) {
403 on_loaded = ansi_highlight_red(true);
404 off_loaded = ansi_highlight_red(false);
406 on_loaded = off_loaded = "";
408 if (streq(u->active_state, "failed")) {
409 on_active = ansi_highlight_red(true);
410 off_active = ansi_highlight_red(false);
412 on_active = off_active = "";
414 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
416 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s ",
417 id_len, e ? e : u->id,
418 on_loaded, u->load_state, off_loaded,
419 on_active, active_len, u->active_state,
420 sub_len, u->sub_state, off_active,
421 job_len, u->job_id ? u->job_type : "");
422 if (!arg_full && arg_no_pager)
423 printf("%.*s\n", desc_len, u->description);
425 printf("%s\n", u->description);
430 if (!arg_no_legend) {
431 const char *on, *off;
434 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
435 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
436 "SUB = The low-level unit activation state, values depend on unit type.\n"
437 "JOB = Pending job for the unit.\n\n");
438 on = ansi_highlight(true);
439 off = ansi_highlight(false);
441 on = ansi_highlight_red(true);
442 off = ansi_highlight_red(false);
446 printf("%s%u loaded units listed.%s\n"
447 "To show all installed unit files use 'systemctl list-unit-files'.\n",
450 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
451 "To show all installed unit files use 'systemctl list-unit-files'.\n",
456 static int list_units(DBusConnection *bus, char **args) {
457 DBusMessage *reply = NULL;
459 DBusMessageIter iter, sub, sub2;
460 unsigned c = 0, n_units = 0;
461 struct unit_info *unit_infos = NULL;
463 pager_open_if_enabled();
465 r = bus_method_call_with_reply (
467 "org.freedesktop.systemd1",
468 "/org/freedesktop/systemd1",
469 "org.freedesktop.systemd1.Manager",
477 if (!dbus_message_iter_init(reply, &iter) ||
478 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
479 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
480 log_error("Failed to parse reply.");
485 dbus_message_iter_recurse(&iter, &sub);
487 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
490 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
491 log_error("Failed to parse reply.");
499 n_units = MAX(2*c, 16);
500 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
503 log_error("Failed to allocate unit array.");
513 dbus_message_iter_recurse(&sub, &sub2);
515 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
516 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
517 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
518 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
519 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
520 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
521 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
522 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
523 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
524 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
525 log_error("Failed to parse reply.");
530 dbus_message_iter_next(&sub);
535 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
536 output_units_list(unit_infos, c);
541 dbus_message_unref(reply);
548 static int compare_unit_file_list(const void *a, const void *b) {
550 const UnitFileList *u = a, *v = b;
552 d1 = strrchr(u->path, '.');
553 d2 = strrchr(v->path, '.');
558 r = strcasecmp(d1, d2);
563 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
566 static bool output_show_unit_file(const UnitFileList *u) {
569 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
572 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
573 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
574 const UnitFileList *u;
576 max_id_len = sizeof("UNIT FILE")-1;
577 state_cols = sizeof("STATE")-1;
578 for (u = units; u < units + c; u++) {
579 if (!output_show_unit_file(u))
582 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
583 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
588 id_cols = MIN(max_id_len, 25);
589 basic_cols = 1 + id_cols + state_cols;
590 if (basic_cols < (unsigned) columns())
591 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
593 id_cols = max_id_len;
596 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
598 for (u = units; u < units + c; u++) {
600 const char *on, *off;
603 if (!output_show_unit_file(u))
608 if (u->state == UNIT_FILE_MASKED ||
609 u->state == UNIT_FILE_MASKED_RUNTIME ||
610 u->state == UNIT_FILE_DISABLED ||
611 u->state == UNIT_FILE_INVALID) {
612 on = ansi_highlight_red(true);
613 off = ansi_highlight_red(false);
614 } else if (u->state == UNIT_FILE_ENABLED) {
615 on = ansi_highlight_green(true);
616 off = ansi_highlight_green(false);
620 id = path_get_file_name(u->path);
622 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
624 printf("%-*s %s%-*s%s\n",
626 on, state_cols, unit_file_state_to_string(u->state), off);
632 printf("\n%u unit files listed.\n", n_shown);
635 static int list_unit_files(DBusConnection *bus, char **args) {
636 DBusMessage *reply = NULL;
638 DBusMessageIter iter, sub, sub2;
639 unsigned c = 0, n_units = 0;
640 UnitFileList *units = NULL;
642 pager_open_if_enabled();
649 h = hashmap_new(string_hash_func, string_compare_func);
653 r = unit_file_get_list(arg_scope, arg_root, h);
655 unit_file_list_free(h);
656 log_error("Failed to get unit file list: %s", strerror(-r));
660 n_units = hashmap_size(h);
661 units = new(UnitFileList, n_units);
663 unit_file_list_free(h);
667 HASHMAP_FOREACH(u, h, i) {
668 memcpy(units + c++, u, sizeof(UnitFileList));
674 r = bus_method_call_with_reply (
676 "org.freedesktop.systemd1",
677 "/org/freedesktop/systemd1",
678 "org.freedesktop.systemd1.Manager",
686 if (!dbus_message_iter_init(reply, &iter) ||
687 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
688 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
689 log_error("Failed to parse reply.");
694 dbus_message_iter_recurse(&iter, &sub);
696 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
700 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
701 log_error("Failed to parse reply.");
709 n_units = MAX(2*c, 16);
710 w = realloc(units, sizeof(struct UnitFileList) * n_units);
713 log_error("Failed to allocate unit array.");
723 dbus_message_iter_recurse(&sub, &sub2);
725 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
726 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
727 log_error("Failed to parse reply.");
732 u->state = unit_file_state_from_string(state);
734 dbus_message_iter_next(&sub);
740 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
741 output_unit_file_list(units, c);
748 dbus_message_unref(reply);
755 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
756 static const char * const colors[] = {
757 "Requires", "[color=\"black\"]",
758 "RequiresOverridable", "[color=\"black\"]",
759 "Requisite", "[color=\"darkblue\"]",
760 "RequisiteOverridable", "[color=\"darkblue\"]",
761 "Wants", "[color=\"grey66\"]",
762 "Conflicts", "[color=\"red\"]",
763 "ConflictedBy", "[color=\"red\"]",
764 "After", "[color=\"green\"]"
767 const char *c = NULL;
774 for (i = 0; i < ELEMENTSOF(colors); i += 2)
775 if (streq(colors[i], prop)) {
783 if (arg_dot != DOT_ALL)
784 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
787 switch (dbus_message_iter_get_arg_type(iter)) {
789 case DBUS_TYPE_ARRAY:
791 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
794 dbus_message_iter_recurse(iter, &sub);
796 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
799 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
800 dbus_message_iter_get_basic(&sub, &s);
801 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
803 dbus_message_iter_next(&sub);
813 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
814 DBusMessage *reply = NULL;
815 const char *interface = "org.freedesktop.systemd1.Unit";
817 DBusMessageIter iter, sub, sub2, sub3;
821 r = bus_method_call_with_reply (
823 "org.freedesktop.systemd1",
825 "org.freedesktop.DBus.Properties",
829 DBUS_TYPE_STRING, &interface,
834 if (!dbus_message_iter_init(reply, &iter) ||
835 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
836 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
837 log_error("Failed to parse reply.");
842 dbus_message_iter_recurse(&iter, &sub);
844 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
847 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
848 log_error("Failed to parse reply.");
853 dbus_message_iter_recurse(&sub, &sub2);
855 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
856 log_error("Failed to parse reply.");
861 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
862 log_error("Failed to parse reply.");
867 dbus_message_iter_recurse(&sub2, &sub3);
869 if (dot_one_property(name, prop, &sub3)) {
870 log_error("Failed to parse reply.");
875 dbus_message_iter_next(&sub);
880 dbus_message_unref(reply);
885 static int dot(DBusConnection *bus, char **args) {
886 DBusMessage *reply = NULL;
888 DBusMessageIter iter, sub, sub2;
890 r = bus_method_call_with_reply (
892 "org.freedesktop.systemd1",
893 "/org/freedesktop/systemd1",
894 "org.freedesktop.systemd1.Manager",
902 if (!dbus_message_iter_init(reply, &iter) ||
903 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
904 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
905 log_error("Failed to parse reply.");
910 printf("digraph systemd {\n");
912 dbus_message_iter_recurse(&iter, &sub);
913 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
914 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
916 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
917 log_error("Failed to parse reply.");
922 dbus_message_iter_recurse(&sub, &sub2);
924 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
925 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
926 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
927 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
928 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
929 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
930 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
931 log_error("Failed to parse reply.");
936 if ((r = dot_one(bus, id, unit_path)) < 0)
939 /* printf("\t\"%s\";\n", id); */
940 dbus_message_iter_next(&sub);
945 log_info(" Color legend: black = Requires\n"
946 " dark blue = Requisite\n"
947 " dark grey = Wants\n"
952 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
953 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
959 dbus_message_unref(reply);
964 static int list_jobs(DBusConnection *bus, char **args) {
965 DBusMessage *reply = NULL;
967 DBusMessageIter iter, sub, sub2;
970 pager_open_if_enabled();
972 r = bus_method_call_with_reply (
974 "org.freedesktop.systemd1",
975 "/org/freedesktop/systemd1",
976 "org.freedesktop.systemd1.Manager",
984 if (!dbus_message_iter_init(reply, &iter) ||
985 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
986 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
987 log_error("Failed to parse reply.");
992 dbus_message_iter_recurse(&iter, &sub);
995 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
997 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
998 const char *name, *type, *state, *job_path, *unit_path;
1002 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1003 log_error("Failed to parse reply.");
1008 dbus_message_iter_recurse(&sub, &sub2);
1010 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1011 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1012 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1013 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1014 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1015 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1016 log_error("Failed to parse reply.");
1021 e = arg_full ? NULL : ellipsize(name, 25, 33);
1022 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1027 dbus_message_iter_next(&sub);
1031 printf("\n%u jobs listed.\n", k);
1037 dbus_message_unref(reply);
1042 static int load_unit(DBusConnection *bus, char **args) {
1048 STRV_FOREACH(name, args+1) {
1049 n = unit_name_mangle(*name);
1050 r = bus_method_call_with_reply (
1052 "org.freedesktop.systemd1",
1053 "/org/freedesktop/systemd1",
1054 "org.freedesktop.systemd1.Manager",
1058 DBUS_TYPE_STRING, n ? &n : name,
1069 static int cancel_job(DBusConnection *bus, char **args) {
1070 DBusMessage *reply = NULL;
1076 if (strv_length(args) <= 1)
1077 return daemon_reload(bus, args);
1079 STRV_FOREACH(name, args+1) {
1083 r = safe_atou(*name, &id);
1085 log_error("Failed to parse job id: %s", strerror(-r));
1088 assert_cc(sizeof(uint32_t) == sizeof(id));
1090 r = bus_method_call_with_reply (
1092 "org.freedesktop.systemd1",
1093 "/org/freedesktop/systemd1",
1094 "org.freedesktop.systemd1.Manager",
1098 DBUS_TYPE_UINT32, &id,
1103 if (!dbus_message_get_args(reply, NULL,
1104 DBUS_TYPE_OBJECT_PATH, &path,
1105 DBUS_TYPE_INVALID)) {
1106 log_error("Failed to parse reply");
1107 dbus_message_unref(reply);
1111 dbus_message_unref(reply);
1113 r = bus_method_call_with_reply (
1115 "org.freedesktop.systemd1",
1117 "org.freedesktop.systemd1.Job",
1130 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1131 DBusMessage *reply = NULL;
1132 dbus_bool_t b = FALSE;
1133 DBusMessageIter iter, sub;
1135 *interface = "org.freedesktop.systemd1.Unit",
1136 *property = "NeedDaemonReload",
1141 /* We ignore all errors here, since this is used to show a warning only */
1143 n = unit_name_mangle(unit);
1144 r = bus_method_call_with_reply (
1146 "org.freedesktop.systemd1",
1147 "/org/freedesktop/systemd1",
1148 "org.freedesktop.systemd1.Manager",
1152 DBUS_TYPE_STRING, n ? (const char**) &n : &unit,
1158 if (!dbus_message_get_args(reply, NULL,
1159 DBUS_TYPE_OBJECT_PATH, &path,
1163 dbus_message_unref(reply);
1164 r = bus_method_call_with_reply (
1166 "org.freedesktop.systemd1",
1168 "org.freedesktop.DBus.Properties",
1172 DBUS_TYPE_STRING, &interface,
1173 DBUS_TYPE_STRING, &property,
1178 if (!dbus_message_iter_init(reply, &iter) ||
1179 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1182 dbus_message_iter_recurse(&iter, &sub);
1184 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1187 dbus_message_iter_get_basic(&sub, &b);
1191 dbus_message_unref(reply);
1196 typedef struct WaitData {
1203 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1211 dbus_error_init(&error);
1213 log_debug("Got D-Bus request: %s.%s() on %s",
1214 dbus_message_get_interface(message),
1215 dbus_message_get_member(message),
1216 dbus_message_get_path(message));
1218 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1219 log_error("Warning! D-Bus connection terminated.");
1220 dbus_connection_close(connection);
1222 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1224 const char *path, *result, *unit;
1225 dbus_bool_t success = true;
1227 if (dbus_message_get_args(message, &error,
1228 DBUS_TYPE_UINT32, &id,
1229 DBUS_TYPE_OBJECT_PATH, &path,
1230 DBUS_TYPE_STRING, &unit,
1231 DBUS_TYPE_STRING, &result,
1232 DBUS_TYPE_INVALID)) {
1235 p = set_remove(d->set, (char*) path);
1238 if (!isempty(result))
1239 d->result = strdup(result);
1242 d->name = strdup(unit);
1247 dbus_error_free(&error);
1248 if (dbus_message_get_args(message, &error,
1249 DBUS_TYPE_UINT32, &id,
1250 DBUS_TYPE_OBJECT_PATH, &path,
1251 DBUS_TYPE_STRING, &result,
1252 DBUS_TYPE_INVALID)) {
1255 /* Compatibility with older systemd versions <
1256 * 183 during upgrades. This should be dropped
1258 p = set_remove(d->set, (char*) path);
1262 d->result = strdup(result);
1267 dbus_error_free(&error);
1268 if (dbus_message_get_args(message, &error,
1269 DBUS_TYPE_UINT32, &id,
1270 DBUS_TYPE_OBJECT_PATH, &path,
1271 DBUS_TYPE_BOOLEAN, &success,
1272 DBUS_TYPE_INVALID)) {
1275 /* Compatibility with older systemd versions <
1276 * 19 during upgrades. This should be dropped
1279 p = set_remove(d->set, (char*) path);
1283 d->result = strdup("failed");
1289 log_error("Failed to parse message: %s", bus_error_message(&error));
1293 dbus_error_free(&error);
1294 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1297 static int enable_wait_for_jobs(DBusConnection *bus) {
1305 dbus_error_init(&error);
1306 dbus_bus_add_match(bus,
1308 "sender='org.freedesktop.systemd1',"
1309 "interface='org.freedesktop.systemd1.Manager',"
1310 "member='JobRemoved',"
1311 "path='/org/freedesktop/systemd1'",
1314 if (dbus_error_is_set(&error)) {
1315 log_error("Failed to add match: %s", bus_error_message(&error));
1316 dbus_error_free(&error);
1320 /* This is slightly dirty, since we don't undo the match registrations. */
1324 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1334 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1337 while (!set_isempty(s)) {
1339 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1340 log_error("Disconnected from bus.");
1341 return -ECONNREFUSED;
1348 if (streq(d.result, "timeout"))
1349 log_error("Job for %s timed out.", strna(d.name));
1350 else if (streq(d.result, "canceled"))
1351 log_error("Job for %s canceled.", strna(d.name));
1352 else if (streq(d.result, "dependency"))
1353 log_error("A dependency job for %s failed. See 'journalctl' for details.", strna(d.name));
1354 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1355 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl' for details.", strna(d.name), strna(d.name));
1358 if (streq_ptr(d.result, "timeout"))
1360 else if (streq_ptr(d.result, "canceled"))
1362 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1373 dbus_connection_remove_filter(bus, wait_filter, &d);
1377 static int check_one_unit(DBusConnection *bus, char *name, bool quiet) {
1378 DBusMessage *reply = NULL;
1379 DBusMessageIter iter, sub;
1381 *interface = "org.freedesktop.systemd1.Unit",
1382 *property = "ActiveState";
1383 const char *path = NULL;
1390 n = unit_name_mangle(name);
1391 r = bus_method_call_with_reply (
1393 "org.freedesktop.systemd1",
1394 "/org/freedesktop/systemd1",
1395 "org.freedesktop.systemd1.Manager",
1399 DBUS_TYPE_STRING, n ? &n : &name,
1403 if ((r != -ENOMEM) && (!quiet))
1408 if (!dbus_message_get_args(reply, NULL,
1409 DBUS_TYPE_OBJECT_PATH, &path,
1410 DBUS_TYPE_INVALID)) {
1411 log_error("Failed to parse reply.");
1416 dbus_message_unref(reply);
1417 r = bus_method_call_with_reply (
1419 "org.freedesktop.systemd1",
1421 "org.freedesktop.DBus.Properties",
1425 DBUS_TYPE_STRING, &interface,
1426 DBUS_TYPE_STRING, &property,
1431 if (!dbus_message_iter_init(reply, &iter) ||
1432 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1433 log_error("Failed to parse reply.");
1438 dbus_message_iter_recurse(&iter, &sub);
1440 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1441 log_error("Failed to parse reply.");
1446 dbus_message_iter_get_basic(&sub, &state);
1451 if (streq(state, "active") || streq(state, "reloading"))
1454 r = 3; /* According to LSB: "program is not running" */
1458 dbus_message_unref(reply);
1463 static void check_triggering_units(
1464 DBusConnection *bus,
1465 const char *unit_name) {
1467 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1468 DBusMessageIter iter, sub;
1469 char *service_trigger = NULL;
1470 const char *interface = "org.freedesktop.systemd1.Unit",
1471 *triggered_by_property = "TriggeredBy";
1473 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1474 bool print_warning_label = true;
1477 n = unit_name_mangle(unit_name);
1483 unit_path = unit_dbus_path_from_name(n);
1489 r = bus_method_call_with_reply (
1491 "org.freedesktop.systemd1",
1493 "org.freedesktop.DBus.Properties",
1497 DBUS_TYPE_STRING, &interface,
1498 DBUS_TYPE_STRING, &triggered_by_property,
1503 if (!dbus_message_iter_init(reply, &iter) ||
1504 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1505 log_error("Failed to parse reply.");
1509 dbus_message_iter_recurse(&iter, &sub);
1510 dbus_message_iter_recurse(&sub, &iter);
1513 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1515 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1516 log_error("Failed to parse reply.");
1520 dbus_message_iter_get_basic(&sub, &service_trigger);
1522 r = check_one_unit(bus, service_trigger, true);
1526 if (print_warning_label) {
1527 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1528 print_warning_label = false;
1530 log_warning(" %s", service_trigger);
1533 dbus_message_iter_next(&sub);
1537 static int start_unit_one(
1538 DBusConnection *bus,
1545 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1548 _cleanup_free_ char *n, *p = NULL;
1555 n = unit_name_mangle(name);
1559 r = bus_method_call_with_reply(
1561 "org.freedesktop.systemd1",
1562 "/org/freedesktop/systemd1",
1563 "org.freedesktop.systemd1.Manager",
1567 DBUS_TYPE_STRING, &n,
1568 DBUS_TYPE_STRING, &mode,
1571 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1572 /* There's always a fallback possible for
1573 * legacy actions. */
1576 log_error("Failed to issue method call: %s", bus_error_message(error));
1581 if (!dbus_message_get_args(reply, error,
1582 DBUS_TYPE_OBJECT_PATH, &path,
1583 DBUS_TYPE_INVALID)) {
1584 log_error("Failed to parse reply: %s", bus_error_message(error));
1588 if (need_daemon_reload(bus, n))
1589 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1590 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1599 log_error("Failed to add path to set.");
1609 static enum action verb_to_action(const char *verb) {
1610 if (streq(verb, "halt"))
1612 else if (streq(verb, "poweroff"))
1613 return ACTION_POWEROFF;
1614 else if (streq(verb, "reboot"))
1615 return ACTION_REBOOT;
1616 else if (streq(verb, "kexec"))
1617 return ACTION_KEXEC;
1618 else if (streq(verb, "rescue"))
1619 return ACTION_RESCUE;
1620 else if (streq(verb, "emergency"))
1621 return ACTION_EMERGENCY;
1622 else if (streq(verb, "default"))
1623 return ACTION_DEFAULT;
1624 else if (streq(verb, "exit"))
1626 else if (streq(verb, "suspend"))
1627 return ACTION_SUSPEND;
1628 else if (streq(verb, "hibernate"))
1629 return ACTION_HIBERNATE;
1631 return ACTION_INVALID;
1634 static int start_unit(DBusConnection *bus, char **args) {
1636 static const char * const table[_ACTION_MAX] = {
1637 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1638 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1639 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1640 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1641 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1642 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1643 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1644 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1645 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1646 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1647 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1648 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1649 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1650 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET
1654 const char *method, *mode, *one_name;
1659 dbus_error_init(&error);
1663 ask_password_agent_open_if_enabled();
1665 if (arg_action == ACTION_SYSTEMCTL) {
1667 streq(args[0], "stop") ||
1668 streq(args[0], "condstop") ? "StopUnit" :
1669 streq(args[0], "reload") ? "ReloadUnit" :
1670 streq(args[0], "restart") ? "RestartUnit" :
1672 streq(args[0], "try-restart") ||
1673 streq(args[0], "condrestart") ? "TryRestartUnit" :
1675 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1677 streq(args[0], "reload-or-try-restart") ||
1678 streq(args[0], "condreload") ||
1680 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1684 (streq(args[0], "isolate") ||
1685 streq(args[0], "rescue") ||
1686 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1688 one_name = table[verb_to_action(args[0])];
1691 assert(arg_action < ELEMENTSOF(table));
1692 assert(table[arg_action]);
1694 method = "StartUnit";
1696 mode = (arg_action == ACTION_EMERGENCY ||
1697 arg_action == ACTION_RESCUE ||
1698 arg_action == ACTION_RUNLEVEL2 ||
1699 arg_action == ACTION_RUNLEVEL3 ||
1700 arg_action == ACTION_RUNLEVEL4 ||
1701 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1703 one_name = table[arg_action];
1706 if (!arg_no_block) {
1707 ret = enable_wait_for_jobs(bus);
1709 log_error("Could not watch jobs: %s", strerror(-ret));
1713 s = set_new(string_hash_func, string_compare_func);
1721 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1723 ret = translate_bus_error_to_exit_status(ret, &error);
1725 STRV_FOREACH(name, args+1) {
1726 r = start_unit_one(bus, method, *name, mode, &error, s);
1728 ret = translate_bus_error_to_exit_status(r, &error);
1729 dbus_error_free(&error);
1734 if (!arg_no_block) {
1735 r = wait_for_jobs(bus, s);
1741 /* When stopping units, warn if they can still be triggered by
1742 * another active unit (socket, path, timer) */
1743 if (!arg_quiet && streq(method, "StopUnit")) {
1745 check_triggering_units(bus, one_name);
1747 STRV_FOREACH(name, args+1)
1748 check_triggering_units(bus, *name);
1754 dbus_error_free(&error);
1759 /* Ask systemd-logind, which might grant access to unprivileged users
1760 * through PolicyKit */
1761 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1764 dbus_bool_t interactive = true;
1766 polkit_agent_open_if_enabled();
1774 case ACTION_POWEROFF:
1775 method = "PowerOff";
1778 case ACTION_SUSPEND:
1782 case ACTION_HIBERNATE:
1783 method = "Hibernate";
1790 return bus_method_call_with_reply (
1792 "org.freedesktop.login1",
1793 "/org/freedesktop/login1",
1794 "org.freedesktop.login1.Manager",
1798 DBUS_TYPE_BOOLEAN, &interactive,
1805 static int start_special(DBusConnection *bus, char **args) {
1811 a = verb_to_action(args[0]);
1813 if (arg_force >= 2 && geteuid() != 0) {
1814 log_error("Must be root.");
1818 if (arg_force >= 2 &&
1819 (a == ACTION_HALT ||
1820 a == ACTION_POWEROFF ||
1821 a == ACTION_REBOOT))
1824 if (arg_force >= 1 &&
1825 (a == ACTION_HALT ||
1826 a == ACTION_POWEROFF ||
1827 a == ACTION_REBOOT ||
1828 a == ACTION_KEXEC ||
1830 return daemon_reload(bus, args);
1832 /* first try logind, to allow authentication with polkit */
1833 if (geteuid() != 0 &&
1834 (a == ACTION_POWEROFF ||
1835 a == ACTION_REBOOT ||
1836 a == ACTION_SUSPEND ||
1837 a == ACTION_HIBERNATE)) {
1838 r = reboot_with_logind(bus, a);
1843 r = start_unit(bus, args);
1850 static int check_unit(DBusConnection *bus, char **args) {
1852 int r = 3; /* According to LSB: "program is not running" */
1857 STRV_FOREACH(name, args+1) {
1858 int state = check_one_unit(bus, *name, arg_quiet);
1868 static int kill_unit(DBusConnection *bus, char **args) {
1875 arg_kill_who = "all";
1877 STRV_FOREACH(name, args+1) {
1878 n = unit_name_mangle(*name);
1879 r = bus_method_call_with_reply (
1881 "org.freedesktop.systemd1",
1882 "/org/freedesktop/systemd1",
1883 "org.freedesktop.systemd1.Manager",
1887 DBUS_TYPE_STRING, n ? &n : name,
1888 DBUS_TYPE_STRING, &arg_kill_who,
1889 DBUS_TYPE_INT32, &arg_signal,
1898 typedef struct ExecStatusInfo {
1906 usec_t start_timestamp;
1907 usec_t exit_timestamp;
1912 LIST_FIELDS(struct ExecStatusInfo, exec);
1915 static void exec_status_info_free(ExecStatusInfo *i) {
1924 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
1925 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
1926 DBusMessageIter sub2, sub3;
1930 int32_t code, status;
1936 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
1939 dbus_message_iter_recurse(sub, &sub2);
1941 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
1944 if (!(i->path = strdup(path)))
1947 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
1948 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
1952 dbus_message_iter_recurse(&sub2, &sub3);
1953 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1954 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1955 dbus_message_iter_next(&sub3);
1960 if (!(i->argv = new0(char*, n+1)))
1964 dbus_message_iter_recurse(&sub2, &sub3);
1965 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1968 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1969 dbus_message_iter_get_basic(&sub3, &s);
1970 dbus_message_iter_next(&sub3);
1972 if (!(i->argv[n++] = strdup(s)))
1976 if (!dbus_message_iter_next(&sub2) ||
1977 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
1978 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
1979 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
1980 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
1981 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
1982 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
1983 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
1984 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
1988 i->start_timestamp = (usec_t) start_timestamp;
1989 i->exit_timestamp = (usec_t) exit_timestamp;
1990 i->pid = (pid_t) pid;
1997 typedef struct UnitStatusInfo {
1999 const char *load_state;
2000 const char *active_state;
2001 const char *sub_state;
2002 const char *unit_file_state;
2004 const char *description;
2005 const char *following;
2007 char **documentation;
2009 const char *fragment_path;
2010 const char *source_path;
2011 const char *default_control_group;
2013 const char *load_error;
2016 usec_t inactive_exit_timestamp;
2017 usec_t inactive_exit_timestamp_monotonic;
2018 usec_t active_enter_timestamp;
2019 usec_t active_exit_timestamp;
2020 usec_t inactive_enter_timestamp;
2022 bool need_daemon_reload;
2027 const char *status_text;
2030 usec_t start_timestamp;
2031 usec_t exit_timestamp;
2033 int exit_code, exit_status;
2035 usec_t condition_timestamp;
2036 bool condition_result;
2039 unsigned n_accepted;
2040 unsigned n_connections;
2044 const char *sysfs_path;
2046 /* Mount, Automount */
2052 LIST_HEAD(ExecStatusInfo, exec);
2055 static void print_status_info(UnitStatusInfo *i) {
2057 const char *on, *off, *ss;
2059 char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
2060 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2065 /* This shows pretty information about a unit. See
2066 * print_property() for a low-level property printer */
2068 printf("%s", strna(i->id));
2070 if (i->description && !streq_ptr(i->id, i->description))
2071 printf(" - %s", i->description);
2076 printf("\t Follow: unit currently follows state of %s\n", i->following);
2078 if (streq_ptr(i->load_state, "error")) {
2079 on = ansi_highlight_red(true);
2080 off = ansi_highlight_red(false);
2084 path = i->source_path ? i->source_path : i->fragment_path;
2087 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2088 else if (path && i->unit_file_state)
2089 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2091 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2093 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2095 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2097 if (streq_ptr(i->active_state, "failed")) {
2098 on = ansi_highlight_red(true);
2099 off = ansi_highlight_red(false);
2100 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2101 on = ansi_highlight_green(true);
2102 off = ansi_highlight_green(false);
2107 printf("\t Active: %s%s (%s)%s",
2109 strna(i->active_state),
2113 printf("\t Active: %s%s%s",
2115 strna(i->active_state),
2118 if (!isempty(i->result) && !streq(i->result, "success"))
2119 printf(" (Result: %s)", i->result);
2121 timestamp = (streq_ptr(i->active_state, "active") ||
2122 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2123 (streq_ptr(i->active_state, "inactive") ||
2124 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2125 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2126 i->active_exit_timestamp;
2128 s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
2129 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2132 printf(" since %s; %s\n", s2, s1);
2134 printf(" since %s\n", s2);
2138 if (!i->condition_result && i->condition_timestamp > 0) {
2139 s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
2140 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2143 printf("\t start condition failed at %s; %s\n", s2, s1);
2145 printf("\t start condition failed at %s\n", s2);
2149 printf("\t Device: %s\n", i->sysfs_path);
2151 printf("\t Where: %s\n", i->where);
2153 printf("\t What: %s\n", i->what);
2155 if (!strv_isempty(i->documentation)) {
2159 STRV_FOREACH(t, i->documentation) {
2161 printf("\t Docs: %s\n", *t);
2164 printf("\t %s\n", *t);
2169 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2171 LIST_FOREACH(exec, p, i->exec) {
2175 /* Only show exited processes here */
2179 t = strv_join(p->argv, " ");
2180 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2183 good = is_clean_exit_lsb(p->code, p->status, NULL);
2185 on = ansi_highlight_red(true);
2186 off = ansi_highlight_red(false);
2190 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2192 if (p->code == CLD_EXITED) {
2195 printf("status=%i", p->status);
2197 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2202 printf("signal=%s", signal_to_string(p->status));
2204 printf(")%s\n", off);
2206 if (i->main_pid == p->pid &&
2207 i->start_timestamp == p->start_timestamp &&
2208 i->exit_timestamp == p->start_timestamp)
2209 /* Let's not show this twice */
2212 if (p->pid == i->control_pid)
2216 if (i->main_pid > 0 || i->control_pid > 0) {
2219 if (i->main_pid > 0) {
2220 printf("Main PID: %u", (unsigned) i->main_pid);
2224 get_process_comm(i->main_pid, &t);
2229 } else if (i->exit_code > 0) {
2230 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2232 if (i->exit_code == CLD_EXITED) {
2235 printf("status=%i", i->exit_status);
2237 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2242 printf("signal=%s", signal_to_string(i->exit_status));
2247 if (i->main_pid > 0 && i->control_pid > 0)
2250 if (i->control_pid > 0) {
2253 printf(" Control: %u", (unsigned) i->control_pid);
2255 get_process_comm(i->control_pid, &t);
2266 printf("\t Status: \"%s\"\n", i->status_text);
2268 if (i->default_control_group) {
2271 printf("\t CGroup: %s\n", i->default_control_group);
2273 if (arg_transport != TRANSPORT_SSH) {
2283 if (i->main_pid > 0)
2284 extra[k++] = i->main_pid;
2286 if (i->control_pid > 0)
2287 extra[k++] = i->control_pid;
2289 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2293 if (i->id && arg_transport != TRANSPORT_SSH) {
2295 arg_all * OUTPUT_SHOW_ALL |
2296 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2297 on_tty() * OUTPUT_COLOR |
2298 arg_follow * OUTPUT_FOLLOW |
2299 !arg_quiet * OUTPUT_WARN_CUTOFF;
2302 show_journal_by_unit(stdout,
2306 i->inactive_exit_timestamp_monotonic,
2311 if (i->need_daemon_reload)
2312 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2313 ansi_highlight_red(true),
2314 ansi_highlight_red(false),
2315 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2318 static void show_unit_help(UnitStatusInfo *i) {
2323 if (!i->documentation) {
2324 log_info("Documentation for %s not known.", i->id);
2328 STRV_FOREACH(p, i->documentation) {
2330 if (startswith(*p, "man:")) {
2333 char *page = NULL, *section = NULL;
2334 const char *args[4] = { "man", NULL, NULL, NULL };
2339 if ((*p)[k-1] == ')')
2340 e = strrchr(*p, '(');
2343 page = strndup((*p) + 4, e - *p - 4);
2349 section = strndup(e + 1, *p + k - e - 2);
2363 log_error("Failed to fork: %m");
2371 execvp(args[0], (char**) args);
2372 log_error("Failed to execute man: %m");
2373 _exit(EXIT_FAILURE);
2379 wait_for_terminate(pid, NULL);
2381 log_info("Can't show: %s", *p);
2385 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2391 switch (dbus_message_iter_get_arg_type(iter)) {
2393 case DBUS_TYPE_STRING: {
2396 dbus_message_iter_get_basic(iter, &s);
2399 if (streq(name, "Id"))
2401 else if (streq(name, "LoadState"))
2403 else if (streq(name, "ActiveState"))
2404 i->active_state = s;
2405 else if (streq(name, "SubState"))
2407 else if (streq(name, "Description"))
2409 else if (streq(name, "FragmentPath"))
2410 i->fragment_path = s;
2411 else if (streq(name, "SourcePath"))
2413 else if (streq(name, "DefaultControlGroup"))
2414 i->default_control_group = s;
2415 else if (streq(name, "StatusText"))
2417 else if (streq(name, "SysFSPath"))
2419 else if (streq(name, "Where"))
2421 else if (streq(name, "What"))
2423 else if (streq(name, "Following"))
2425 else if (streq(name, "UnitFileState"))
2426 i->unit_file_state = s;
2427 else if (streq(name, "Result"))
2434 case DBUS_TYPE_BOOLEAN: {
2437 dbus_message_iter_get_basic(iter, &b);
2439 if (streq(name, "Accept"))
2441 else if (streq(name, "NeedDaemonReload"))
2442 i->need_daemon_reload = b;
2443 else if (streq(name, "ConditionResult"))
2444 i->condition_result = b;
2449 case DBUS_TYPE_UINT32: {
2452 dbus_message_iter_get_basic(iter, &u);
2454 if (streq(name, "MainPID")) {
2456 i->main_pid = (pid_t) u;
2459 } else if (streq(name, "ControlPID"))
2460 i->control_pid = (pid_t) u;
2461 else if (streq(name, "ExecMainPID")) {
2463 i->main_pid = (pid_t) u;
2464 } else if (streq(name, "NAccepted"))
2466 else if (streq(name, "NConnections"))
2467 i->n_connections = u;
2472 case DBUS_TYPE_INT32: {
2475 dbus_message_iter_get_basic(iter, &j);
2477 if (streq(name, "ExecMainCode"))
2478 i->exit_code = (int) j;
2479 else if (streq(name, "ExecMainStatus"))
2480 i->exit_status = (int) j;
2485 case DBUS_TYPE_UINT64: {
2488 dbus_message_iter_get_basic(iter, &u);
2490 if (streq(name, "ExecMainStartTimestamp"))
2491 i->start_timestamp = (usec_t) u;
2492 else if (streq(name, "ExecMainExitTimestamp"))
2493 i->exit_timestamp = (usec_t) u;
2494 else if (streq(name, "ActiveEnterTimestamp"))
2495 i->active_enter_timestamp = (usec_t) u;
2496 else if (streq(name, "InactiveEnterTimestamp"))
2497 i->inactive_enter_timestamp = (usec_t) u;
2498 else if (streq(name, "InactiveExitTimestamp"))
2499 i->inactive_exit_timestamp = (usec_t) u;
2500 else if (streq(name, "InactiveExitTimestampMonotonic"))
2501 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2502 else if (streq(name, "ActiveExitTimestamp"))
2503 i->active_exit_timestamp = (usec_t) u;
2504 else if (streq(name, "ConditionTimestamp"))
2505 i->condition_timestamp = (usec_t) u;
2510 case DBUS_TYPE_ARRAY: {
2512 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2513 startswith(name, "Exec")) {
2514 DBusMessageIter sub;
2516 dbus_message_iter_recurse(iter, &sub);
2517 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2518 ExecStatusInfo *info;
2521 if (!(info = new0(ExecStatusInfo, 1)))
2524 if (!(info->name = strdup(name))) {
2529 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2534 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2536 dbus_message_iter_next(&sub);
2538 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2539 streq(name, "Documentation")) {
2541 DBusMessageIter sub;
2543 dbus_message_iter_recurse(iter, &sub);
2544 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2548 dbus_message_iter_get_basic(&sub, &s);
2550 l = strv_append(i->documentation, s);
2554 strv_free(i->documentation);
2555 i->documentation = l;
2557 dbus_message_iter_next(&sub);
2564 case DBUS_TYPE_STRUCT: {
2566 if (streq(name, "LoadError")) {
2567 DBusMessageIter sub;
2568 const char *n, *message;
2571 dbus_message_iter_recurse(iter, &sub);
2573 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2577 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2581 if (!isempty(message))
2582 i->load_error = message;
2592 static int print_property(const char *name, DBusMessageIter *iter) {
2596 /* This is a low-level property printer, see
2597 * print_status_info() for the nicer output */
2599 if (arg_property && !strv_find(arg_property, name))
2602 switch (dbus_message_iter_get_arg_type(iter)) {
2604 case DBUS_TYPE_STRUCT: {
2605 DBusMessageIter sub;
2606 dbus_message_iter_recurse(iter, &sub);
2608 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2611 dbus_message_iter_get_basic(&sub, &u);
2614 printf("%s=%u\n", name, (unsigned) u);
2616 printf("%s=\n", name);
2619 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2622 dbus_message_iter_get_basic(&sub, &s);
2624 if (arg_all || s[0])
2625 printf("%s=%s\n", name, s);
2628 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2629 const char *a = NULL, *b = NULL;
2631 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2632 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2634 if (arg_all || !isempty(a) || !isempty(b))
2635 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2643 case DBUS_TYPE_ARRAY:
2645 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2646 DBusMessageIter sub, sub2;
2648 dbus_message_iter_recurse(iter, &sub);
2649 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2653 dbus_message_iter_recurse(&sub, &sub2);
2655 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2656 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2657 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2659 dbus_message_iter_next(&sub);
2664 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2665 DBusMessageIter sub, sub2;
2667 dbus_message_iter_recurse(iter, &sub);
2668 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2669 const char *type, *path;
2671 dbus_message_iter_recurse(&sub, &sub2);
2673 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2674 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2675 printf("%s=%s\n", type, path);
2677 dbus_message_iter_next(&sub);
2682 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2683 DBusMessageIter sub, sub2;
2685 dbus_message_iter_recurse(iter, &sub);
2686 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2688 uint64_t value, next_elapse;
2690 dbus_message_iter_recurse(&sub, &sub2);
2692 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2693 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2694 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2695 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2697 printf("%s={ value=%s ; next_elapse=%s }\n",
2699 format_timespan(timespan1, sizeof(timespan1), value),
2700 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2703 dbus_message_iter_next(&sub);
2708 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2709 DBusMessageIter sub, sub2;
2711 dbus_message_iter_recurse(iter, &sub);
2712 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2713 const char *controller, *attr, *value;
2715 dbus_message_iter_recurse(&sub, &sub2);
2717 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2718 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2719 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2721 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2727 dbus_message_iter_next(&sub);
2732 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2733 DBusMessageIter sub;
2735 dbus_message_iter_recurse(iter, &sub);
2736 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2737 ExecStatusInfo info;
2740 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2741 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2744 t = strv_join(info.argv, " ");
2746 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2750 yes_no(info.ignore),
2751 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2752 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2753 (unsigned) info. pid,
2754 sigchld_code_to_string(info.code),
2756 info.code == CLD_EXITED ? "" : "/",
2757 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2763 strv_free(info.argv);
2765 dbus_message_iter_next(&sub);
2774 if (generic_print_property(name, iter, arg_all) > 0)
2778 printf("%s=[unprintable]\n", name);
2783 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2784 DBusMessage *reply = NULL;
2785 const char *interface = "";
2787 DBusMessageIter iter, sub, sub2, sub3;
2788 UnitStatusInfo info;
2796 r = bus_method_call_with_reply (
2798 "org.freedesktop.systemd1",
2800 "org.freedesktop.DBus.Properties",
2804 DBUS_TYPE_STRING, &interface,
2809 if (!dbus_message_iter_init(reply, &iter) ||
2810 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2811 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2812 log_error("Failed to parse reply.");
2817 dbus_message_iter_recurse(&iter, &sub);
2824 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2827 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2828 log_error("Failed to parse reply.");
2833 dbus_message_iter_recurse(&sub, &sub2);
2835 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2836 log_error("Failed to parse reply.");
2841 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2842 log_error("Failed to parse reply.");
2847 dbus_message_iter_recurse(&sub2, &sub3);
2849 if (show_properties)
2850 r = print_property(name, &sub3);
2852 r = status_property(name, &sub3, &info);
2855 log_error("Failed to parse reply.");
2860 dbus_message_iter_next(&sub);
2865 if (!show_properties) {
2866 if (streq(verb, "help"))
2867 show_unit_help(&info);
2869 print_status_info(&info);
2872 strv_free(info.documentation);
2874 if (!streq_ptr(info.active_state, "active") &&
2875 !streq_ptr(info.active_state, "reloading") &&
2876 streq(verb, "status"))
2877 /* According to LSB: "program not running" */
2880 while ((p = info.exec)) {
2881 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2882 exec_status_info_free(p);
2887 dbus_message_unref(reply);
2892 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
2893 DBusMessage *reply = NULL;
2894 const char *path = NULL;
2898 dbus_error_init(&error);
2900 r = bus_method_call_with_reply (
2902 "org.freedesktop.systemd1",
2903 "/org/freedesktop/systemd1",
2904 "org.freedesktop.systemd1.Manager",
2908 DBUS_TYPE_UINT32, &pid,
2913 if (!dbus_message_get_args(reply, &error,
2914 DBUS_TYPE_OBJECT_PATH, &path,
2915 DBUS_TYPE_INVALID)) {
2916 log_error("Failed to parse reply: %s", bus_error_message(&error));
2921 r = show_one(verb, bus, path, false, new_line);
2925 dbus_message_unref(reply);
2927 dbus_error_free(&error);
2932 static int show(DBusConnection *bus, char **args) {
2934 bool show_properties, new_line = false;
2940 show_properties = streq(args[0], "show");
2942 if (show_properties)
2943 pager_open_if_enabled();
2945 if (show_properties && strv_length(args) <= 1) {
2946 /* If not argument is specified inspect the manager
2949 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2952 STRV_FOREACH(name, args+1) {
2955 if (safe_atou32(*name, &id) < 0) {
2957 /* Interpret as unit name */
2959 n = unit_name_mangle(*name);
2960 p = unit_dbus_path_from_name(n ? n : *name);
2965 r = show_one(args[0], bus, p, show_properties, &new_line);
2971 } else if (show_properties) {
2973 /* Interpret as job id */
2976 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
2979 r = show_one(args[0], bus, p, show_properties, &new_line);
2987 /* Interpret as PID */
2989 r = show_one_by_pid(args[0], bus, id, &new_line);
2998 static int dump(DBusConnection *bus, char **args) {
2999 DBusMessage *reply = NULL;
3004 dbus_error_init(&error);
3006 pager_open_if_enabled();
3008 r = bus_method_call_with_reply (
3010 "org.freedesktop.systemd1",
3011 "/org/freedesktop/systemd1",
3012 "org.freedesktop.systemd1.Manager",
3020 if (!dbus_message_get_args(reply, &error,
3021 DBUS_TYPE_STRING, &text,
3022 DBUS_TYPE_INVALID)) {
3023 log_error("Failed to parse reply: %s", bus_error_message(&error));
3028 fputs(text, stdout);
3032 dbus_message_unref(reply);
3034 dbus_error_free(&error);
3039 static int snapshot(DBusConnection *bus, char **args) {
3040 DBusMessage *reply = NULL;
3043 dbus_bool_t cleanup = FALSE;
3044 DBusMessageIter iter, sub;
3046 *name = "", *path, *id,
3047 *interface = "org.freedesktop.systemd1.Unit",
3051 dbus_error_init(&error);
3053 if (strv_length(args) > 1)
3056 n = unit_name_mangle(name);
3057 r = bus_method_call_with_reply (
3059 "org.freedesktop.systemd1",
3060 "/org/freedesktop/systemd1",
3061 "org.freedesktop.systemd1.Manager",
3065 DBUS_TYPE_STRING, n ? (const char**) &n : &name,
3066 DBUS_TYPE_BOOLEAN, &cleanup,
3072 if (!dbus_message_get_args(reply, &error,
3073 DBUS_TYPE_OBJECT_PATH, &path,
3074 DBUS_TYPE_INVALID)) {
3075 log_error("Failed to parse reply: %s", bus_error_message(&error));
3080 dbus_message_unref(reply);
3081 r = bus_method_call_with_reply (
3083 "org.freedesktop.systemd1",
3085 "org.freedesktop.DBus.Properties",
3089 DBUS_TYPE_STRING, &interface,
3090 DBUS_TYPE_STRING, &property,
3095 if (!dbus_message_iter_init(reply, &iter) ||
3096 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3097 log_error("Failed to parse reply.");
3102 dbus_message_iter_recurse(&iter, &sub);
3104 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3105 log_error("Failed to parse reply.");
3110 dbus_message_iter_get_basic(&sub, &id);
3117 dbus_message_unref(reply);
3119 dbus_error_free(&error);
3124 static int delete_snapshot(DBusConnection *bus, char **args) {
3125 DBusMessage *reply = NULL;
3132 dbus_error_init(&error);
3134 STRV_FOREACH(name, args+1) {
3135 const char *path = NULL;
3138 n = unit_name_mangle(*name);
3139 r = bus_method_call_with_reply (
3141 "org.freedesktop.systemd1",
3142 "/org/freedesktop/systemd1",
3143 "org.freedesktop.systemd1.Manager",
3147 DBUS_TYPE_STRING, n ? &n : name,
3153 if (!dbus_message_get_args(reply, &error,
3154 DBUS_TYPE_OBJECT_PATH, &path,
3155 DBUS_TYPE_INVALID)) {
3156 log_error("Failed to parse reply: %s", bus_error_message(&error));
3158 dbus_message_unref(reply);
3159 dbus_error_free(&error);
3162 dbus_message_unref(reply);
3164 r = bus_method_call_with_reply (
3166 "org.freedesktop.systemd1",
3168 "org.freedesktop.systemd1.Snapshot",
3181 static int daemon_reload(DBusConnection *bus, char **args) {
3186 if (arg_action == ACTION_RELOAD)
3188 else if (arg_action == ACTION_REEXEC)
3189 method = "Reexecute";
3191 assert(arg_action == ACTION_SYSTEMCTL);
3194 streq(args[0], "clear-jobs") ||
3195 streq(args[0], "cancel") ? "ClearJobs" :
3196 streq(args[0], "daemon-reexec") ? "Reexecute" :
3197 streq(args[0], "reset-failed") ? "ResetFailed" :
3198 streq(args[0], "halt") ? "Halt" :
3199 streq(args[0], "poweroff") ? "PowerOff" :
3200 streq(args[0], "reboot") ? "Reboot" :
3201 streq(args[0], "kexec") ? "KExec" :
3202 streq(args[0], "exit") ? "Exit" :
3203 /* "daemon-reload" */ "Reload";
3206 r = bus_method_call_with_reply (
3208 "org.freedesktop.systemd1",
3209 "/org/freedesktop/systemd1",
3210 "org.freedesktop.systemd1.Manager",
3216 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3217 /* There's always a fallback possible for
3218 * legacy actions. */
3220 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3221 /* On reexecution, we expect a disconnect, not
3225 log_error("Failed to issue method call: %s", bus_error_message(&error));
3226 dbus_error_free(&error);
3231 static int reset_failed(DBusConnection *bus, char **args) {
3235 if (strv_length(args) <= 1)
3236 return daemon_reload(bus, args);
3238 STRV_FOREACH(name, args+1) {
3239 n = unit_name_mangle(*name);
3240 r = bus_method_call_with_reply (
3242 "org.freedesktop.systemd1",
3243 "/org/freedesktop/systemd1",
3244 "org.freedesktop.systemd1.Manager",
3248 DBUS_TYPE_STRING, n ? &n : name,
3259 static int show_enviroment(DBusConnection *bus, char **args) {
3260 DBusMessage *reply = NULL;
3261 DBusMessageIter iter, sub, sub2;
3264 *interface = "org.freedesktop.systemd1.Manager",
3265 *property = "Environment";
3267 pager_open_if_enabled();
3269 r = bus_method_call_with_reply (
3271 "org.freedesktop.systemd1",
3272 "/org/freedesktop/systemd1",
3273 "org.freedesktop.DBus.Properties",
3277 DBUS_TYPE_STRING, &interface,
3278 DBUS_TYPE_STRING, &property,
3283 if (!dbus_message_iter_init(reply, &iter) ||
3284 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3285 log_error("Failed to parse reply.");
3290 dbus_message_iter_recurse(&iter, &sub);
3292 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3293 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3294 log_error("Failed to parse reply.");
3299 dbus_message_iter_recurse(&sub, &sub2);
3301 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3304 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3305 log_error("Failed to parse reply.");
3310 dbus_message_iter_get_basic(&sub2, &text);
3311 printf("%s\n", text);
3313 dbus_message_iter_next(&sub2);
3320 dbus_message_unref(reply);
3325 static int switch_root(DBusConnection *bus, char **args) {
3327 const char *root, *init;
3329 l = strv_length(args);
3330 if (l < 2 || l > 3) {
3331 log_error("Wrong number of arguments.");
3336 init = l >= 3 ? args[2] : "";
3338 return bus_method_call_with_reply (
3340 "org.freedesktop.systemd1",
3341 "/org/freedesktop/systemd1",
3342 "org.freedesktop.systemd1.Manager",
3346 DBUS_TYPE_STRING, &root,
3347 DBUS_TYPE_STRING, &init,
3351 static int set_environment(DBusConnection *bus, char **args) {
3352 DBusMessage *m = NULL, *reply = NULL;
3356 DBusMessageIter iter, sub;
3359 dbus_error_init(&error);
3361 method = streq(args[0], "set-environment")
3363 : "UnsetEnvironment";
3365 if (!(m = dbus_message_new_method_call(
3366 "org.freedesktop.systemd1",
3367 "/org/freedesktop/systemd1",
3368 "org.freedesktop.systemd1.Manager",
3371 log_error("Could not allocate message.");
3375 dbus_message_iter_init_append(m, &iter);
3377 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
3378 log_error("Could not append arguments to message.");
3383 STRV_FOREACH(name, args+1)
3384 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, name)) {
3385 log_error("Could not append arguments to message.");
3390 if (!dbus_message_iter_close_container(&iter, &sub)) {
3391 log_error("Could not append arguments to message.");
3396 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3397 log_error("Failed to issue method call: %s", bus_error_message(&error));
3406 dbus_message_unref(m);
3409 dbus_message_unref(reply);
3411 dbus_error_free(&error);
3416 static int enable_sysv_units(char **args) {
3419 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3420 const char *verb = args[0];
3421 unsigned f = 1, t = 1;
3424 if (arg_scope != UNIT_FILE_SYSTEM)
3427 if (!streq(verb, "enable") &&
3428 !streq(verb, "disable") &&
3429 !streq(verb, "is-enabled"))
3432 /* Processes all SysV units, and reshuffles the array so that
3433 * afterwards only the native units remain */
3436 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3441 for (f = 1; args[f]; f++) {
3444 bool found_native = false, found_sysv;
3446 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3447 char **k, *l, *q = NULL;
3454 if (!endswith(name, ".service"))
3457 if (path_is_absolute(name))
3460 STRV_FOREACH(k, paths.unit_path) {
3463 if (!isempty(arg_root))
3464 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3466 asprintf(&p, "%s/%s", *k, name);
3473 found_native = access(p, F_OK) >= 0;
3484 if (!isempty(arg_root))
3485 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3487 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3493 p[strlen(p) - sizeof(".service") + 1] = 0;
3494 found_sysv = access(p, F_OK) >= 0;
3501 /* Mark this entry, so that we don't try enabling it as native unit */
3502 args[f] = (char*) "";
3504 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3506 if (!isempty(arg_root))
3507 argv[c++] = q = strappend("--root=", arg_root);
3509 argv[c++] = path_get_file_name(p);
3511 streq(verb, "enable") ? "on" :
3512 streq(verb, "disable") ? "off" : "--level=5";
3515 l = strv_join((char**)argv, " ");
3523 log_info("Executing %s", l);
3528 log_error("Failed to fork: %m");
3533 } else if (pid == 0) {
3536 execv(argv[0], (char**) argv);
3537 _exit(EXIT_FAILURE);
3543 j = wait_for_terminate(pid, &status);
3545 log_error("Failed to wait for child: %s", strerror(-r));
3550 if (status.si_code == CLD_EXITED) {
3551 if (streq(verb, "is-enabled")) {
3552 if (status.si_status == 0) {
3561 } else if (status.si_status != 0) {
3572 lookup_paths_free(&paths);
3574 /* Drop all SysV units */
3575 for (f = 1, t = 1; args[f]; f++) {
3577 if (isempty(args[f]))
3580 args[t++] = args[f];
3589 static int mangle_names(char **original_names, char ***mangled_names) {
3590 char **i, **l, **name;
3592 l = new(char*, strv_length(original_names) + 1);
3597 STRV_FOREACH(name, original_names) {
3599 /* When enabling units qualified path names are OK,
3600 * too, hence allow them explicitly. */
3605 *i = unit_name_mangle(*name);
3621 static int enable_unit(DBusConnection *bus, char **args) {
3622 const char *verb = args[0];
3623 UnitFileChange *changes = NULL;
3624 unsigned n_changes = 0, i;
3625 int carries_install_info = -1;
3626 DBusMessage *m = NULL, *reply = NULL;
3629 char **mangled_names = NULL;
3631 r = enable_sysv_units(args);
3638 dbus_error_init(&error);
3640 if (!bus || avoid_bus()) {
3641 if (streq(verb, "enable")) {
3642 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3643 carries_install_info = r;
3644 } else if (streq(verb, "disable"))
3645 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3646 else if (streq(verb, "reenable")) {
3647 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3648 carries_install_info = r;
3649 } else if (streq(verb, "link"))
3650 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3651 else if (streq(verb, "preset")) {
3652 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3653 carries_install_info = r;
3654 } else if (streq(verb, "mask"))
3655 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3656 else if (streq(verb, "unmask"))
3657 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3659 assert_not_reached("Unknown verb");
3662 log_error("Operation failed: %s", strerror(-r));
3667 for (i = 0; i < n_changes; i++) {
3668 if (changes[i].type == UNIT_FILE_SYMLINK)
3669 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3671 log_info("rm '%s'", changes[i].path);
3677 bool send_force = true, expect_carries_install_info = false;
3679 DBusMessageIter iter, sub, sub2;
3681 if (streq(verb, "enable")) {
3682 method = "EnableUnitFiles";
3683 expect_carries_install_info = true;
3684 } else if (streq(verb, "disable")) {
3685 method = "DisableUnitFiles";
3687 } else if (streq(verb, "reenable")) {
3688 method = "ReenableUnitFiles";
3689 expect_carries_install_info = true;
3690 } else if (streq(verb, "link"))
3691 method = "LinkUnitFiles";
3692 else if (streq(verb, "preset")) {
3693 method = "PresetUnitFiles";
3694 expect_carries_install_info = true;
3695 } else if (streq(verb, "mask"))
3696 method = "MaskUnitFiles";
3697 else if (streq(verb, "unmask")) {
3698 method = "UnmaskUnitFiles";
3701 assert_not_reached("Unknown verb");
3703 m = dbus_message_new_method_call(
3704 "org.freedesktop.systemd1",
3705 "/org/freedesktop/systemd1",
3706 "org.freedesktop.systemd1.Manager",
3713 dbus_message_iter_init_append(m, &iter);
3715 r = mangle_names(args+1, &mangled_names);
3719 r = bus_append_strv_iter(&iter, mangled_names);
3721 log_error("Failed to append unit files.");
3726 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3727 log_error("Failed to append runtime boolean.");
3735 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3736 log_error("Failed to append force boolean.");
3742 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3744 log_error("Failed to issue method call: %s", bus_error_message(&error));
3749 if (!dbus_message_iter_init(reply, &iter)) {
3750 log_error("Failed to initialize iterator.");
3754 if (expect_carries_install_info) {
3755 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3757 log_error("Failed to parse reply.");
3761 carries_install_info = b;
3764 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3765 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3766 log_error("Failed to parse reply.");
3771 dbus_message_iter_recurse(&iter, &sub);
3772 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3773 const char *type, *path, *source;
3775 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3776 log_error("Failed to parse reply.");
3781 dbus_message_iter_recurse(&sub, &sub2);
3783 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3784 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3785 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3786 log_error("Failed to parse reply.");
3792 if (streq(type, "symlink"))
3793 log_info("ln -s '%s' '%s'", source, path);
3795 log_info("rm '%s'", path);
3798 dbus_message_iter_next(&sub);
3801 /* Try to reload if enabeld */
3803 r = daemon_reload(bus, args);
3806 if (carries_install_info == 0)
3807 log_warning("The unit files have no [Install] section. They are not meant to be enabled using systemctl.");
3811 dbus_message_unref(m);
3814 dbus_message_unref(reply);
3816 unit_file_changes_free(changes, n_changes);
3818 dbus_error_free(&error);
3820 strv_free(mangled_names);
3825 static int unit_is_enabled(DBusConnection *bus, char **args) {
3828 DBusMessage *reply = NULL;
3832 dbus_error_init(&error);
3834 r = enable_sysv_units(args);
3840 if (!bus || avoid_bus()) {
3842 STRV_FOREACH(name, args+1) {
3843 UnitFileState state;
3845 state = unit_file_get_state(arg_scope, arg_root, *name);
3851 if (state == UNIT_FILE_ENABLED ||
3852 state == UNIT_FILE_ENABLED_RUNTIME ||
3853 state == UNIT_FILE_STATIC)
3857 puts(unit_file_state_to_string(state));
3861 STRV_FOREACH(name, args+1) {
3864 r = bus_method_call_with_reply (
3866 "org.freedesktop.systemd1",
3867 "/org/freedesktop/systemd1",
3868 "org.freedesktop.systemd1.Manager",
3872 DBUS_TYPE_STRING, name,
3877 if (!dbus_message_get_args(reply, &error,
3878 DBUS_TYPE_STRING, &s,
3879 DBUS_TYPE_INVALID)) {
3880 log_error("Failed to parse reply: %s", bus_error_message(&error));
3885 dbus_message_unref(reply);
3888 if (streq(s, "enabled") ||
3889 streq(s, "enabled-runtime") ||
3898 r = enabled ? 0 : 1;
3902 dbus_message_unref(reply);
3904 dbus_error_free(&error);
3908 static int systemctl_help(void) {
3910 pager_open_if_enabled();
3912 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
3913 "Query or send control commands to the systemd manager.\n\n"
3914 " -h --help Show this help\n"
3915 " --version Show package version\n"
3916 " -t --type=TYPE List only units of a particular type\n"
3917 " -p --property=NAME Show only properties by this name\n"
3918 " -a --all Show all units/properties, including dead/empty ones\n"
3919 " --failed Show only failed units\n"
3920 " --full Don't ellipsize unit names on output\n"
3921 " --fail When queueing a new job, fail if conflicting jobs are\n"
3923 " --ignore-dependencies\n"
3924 " When queueing a new job, ignore all its dependencies\n"
3925 " --kill-who=WHO Who to send signal to\n"
3926 " -s --signal=SIGNAL Which signal to send\n"
3927 " -H --host=[USER@]HOST\n"
3928 " Show information for remote host\n"
3929 " -P --privileged Acquire privileges before execution\n"
3930 " -q --quiet Suppress output\n"
3931 " --no-block Do not wait until operation finished\n"
3932 " --no-wall Don't send wall message before halt/power-off/reboot\n"
3933 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
3935 " --no-legend Do not print a legend (column headers and hints)\n"
3936 " --no-pager Do not pipe output into a pager\n"
3937 " --no-ask-password\n"
3938 " Do not ask for system passwords\n"
3939 " --order When generating graph for dot, show only order\n"
3940 " --require When generating graph for dot, show only requirement\n"
3941 " --system Connect to system manager\n"
3942 " --user Connect to user service manager\n"
3943 " --global Enable/disable unit files globally\n"
3944 " -f --force When enabling unit files, override existing symlinks\n"
3945 " When shutting down, execute action immediately\n"
3946 " --root=PATH Enable unit files in the specified root directory\n"
3947 " --runtime Enable unit files only temporarily until next reboot\n"
3948 " -n --lines=INTEGER Journal entries to show\n"
3949 " --follow Follow journal\n"
3950 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
3951 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
3953 " list-units List loaded units\n"
3954 " start [NAME...] Start (activate) one or more units\n"
3955 " stop [NAME...] Stop (deactivate) one or more units\n"
3956 " reload [NAME...] Reload one or more units\n"
3957 " restart [NAME...] Start or restart one or more units\n"
3958 " try-restart [NAME...] Restart one or more units if active\n"
3959 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
3960 " otherwise start or restart\n"
3961 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
3962 " otherwise restart if active\n"
3963 " isolate [NAME] Start one unit and stop all others\n"
3964 " kill [NAME...] Send signal to processes of a unit\n"
3965 " is-active [NAME...] Check whether units are active\n"
3966 " status [NAME...|PID...] Show runtime status of one or more units\n"
3967 " show [NAME...|JOB...] Show properties of one or more\n"
3968 " units/jobs or the manager\n"
3969 " help [NAME...|PID...] Show manual for one or more units\n"
3970 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
3972 " load [NAME...] Load one or more units\n\n"
3973 "Unit File Commands:\n"
3974 " list-unit-files List installed unit files\n"
3975 " enable [NAME...] Enable one or more unit files\n"
3976 " disable [NAME...] Disable one or more unit files\n"
3977 " reenable [NAME...] Reenable one or more unit files\n"
3978 " preset [NAME...] Enable/disable one or more unit files\n"
3979 " based on preset configuration\n"
3980 " mask [NAME...] Mask one or more units\n"
3981 " unmask [NAME...] Unmask one or more units\n"
3982 " link [PATH...] Link one or more units files into\n"
3983 " the search path\n"
3984 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
3986 " list-jobs List jobs\n"
3987 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
3988 "Status Commands:\n"
3989 " dump Dump server status\n"
3990 " dot Dump dependency graph for dot(1)\n\n"
3991 "Snapshot Commands:\n"
3992 " snapshot [NAME] Create a snapshot\n"
3993 " delete [NAME...] Remove one or more snapshots\n\n"
3994 "Environment Commands:\n"
3995 " show-environment Dump environment\n"
3996 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
3997 " unset-environment [NAME...] Unset one or more environment variables\n\n"
3998 "Manager Lifecycle Commands:\n"
3999 " daemon-reload Reload systemd manager configuration\n"
4000 " daemon-reexec Reexecute systemd manager\n\n"
4001 "System Commands:\n"
4002 " default Enter system default mode\n"
4003 " rescue Enter system rescue mode\n"
4004 " emergency Enter system emergency mode\n"
4005 " halt Shut down and halt the system\n"
4006 " poweroff Shut down and power-off the system\n"
4007 " reboot Shut down and reboot the system\n"
4008 " kexec Shut down and reboot the system with kexec\n"
4009 " exit Request user instance exit\n"
4010 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4011 " suspend Suspend the system\n"
4012 " hibernate Hibernate the system\n",
4013 program_invocation_short_name);
4018 static int halt_help(void) {
4020 printf("%s [OPTIONS...]\n\n"
4021 "%s the system.\n\n"
4022 " --help Show this help\n"
4023 " --halt Halt the machine\n"
4024 " -p --poweroff Switch off the machine\n"
4025 " --reboot Reboot the machine\n"
4026 " -f --force Force immediate halt/power-off/reboot\n"
4027 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4028 " -d --no-wtmp Don't write wtmp record\n"
4029 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4030 program_invocation_short_name,
4031 arg_action == ACTION_REBOOT ? "Reboot" :
4032 arg_action == ACTION_POWEROFF ? "Power off" :
4038 static int shutdown_help(void) {
4040 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4041 "Shut down the system.\n\n"
4042 " --help Show this help\n"
4043 " -H --halt Halt the machine\n"
4044 " -P --poweroff Power-off the machine\n"
4045 " -r --reboot Reboot the machine\n"
4046 " -h Equivalent to --poweroff, overridden by --halt\n"
4047 " -k Don't halt/power-off/reboot, just send warnings\n"
4048 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4049 " -c Cancel a pending shutdown\n",
4050 program_invocation_short_name);
4055 static int telinit_help(void) {
4057 printf("%s [OPTIONS...] {COMMAND}\n\n"
4058 "Send control commands to the init daemon.\n\n"
4059 " --help Show this help\n"
4060 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4062 " 0 Power-off the machine\n"
4063 " 6 Reboot the machine\n"
4064 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4065 " 1, s, S Enter rescue mode\n"
4066 " q, Q Reload init daemon configuration\n"
4067 " u, U Reexecute init daemon\n",
4068 program_invocation_short_name);
4073 static int runlevel_help(void) {
4075 printf("%s [OPTIONS...]\n\n"
4076 "Prints the previous and current runlevel of the init system.\n\n"
4077 " --help Show this help\n",
4078 program_invocation_short_name);
4083 static int systemctl_parse_argv(int argc, char *argv[]) {
4087 ARG_IGNORE_DEPENDENCIES,
4102 ARG_NO_ASK_PASSWORD,
4109 static const struct option options[] = {
4110 { "help", no_argument, NULL, 'h' },
4111 { "version", no_argument, NULL, ARG_VERSION },
4112 { "type", required_argument, NULL, 't' },
4113 { "property", required_argument, NULL, 'p' },
4114 { "all", no_argument, NULL, 'a' },
4115 { "failed", no_argument, NULL, ARG_FAILED },
4116 { "full", no_argument, NULL, ARG_FULL },
4117 { "fail", no_argument, NULL, ARG_FAIL },
4118 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4119 { "user", no_argument, NULL, ARG_USER },
4120 { "system", no_argument, NULL, ARG_SYSTEM },
4121 { "global", no_argument, NULL, ARG_GLOBAL },
4122 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4123 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4124 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4125 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4126 { "quiet", no_argument, NULL, 'q' },
4127 { "order", no_argument, NULL, ARG_ORDER },
4128 { "require", no_argument, NULL, ARG_REQUIRE },
4129 { "root", required_argument, NULL, ARG_ROOT },
4130 { "force", no_argument, NULL, ARG_FORCE },
4131 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4132 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4133 { "signal", required_argument, NULL, 's' },
4134 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4135 { "host", required_argument, NULL, 'H' },
4136 { "privileged",no_argument, NULL, 'P' },
4137 { "runtime", no_argument, NULL, ARG_RUNTIME },
4138 { "lines", required_argument, NULL, 'n' },
4139 { "follow", no_argument, NULL, ARG_FOLLOW },
4140 { "output", required_argument, NULL, 'o' },
4141 { NULL, 0, NULL, 0 }
4149 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4158 puts(PACKAGE_STRING);
4160 puts(SYSTEMD_FEATURES);
4164 if (unit_type_from_string(optarg) >= 0) {
4168 if (unit_load_state_from_string(optarg) >= 0) {
4169 arg_load_state = optarg;
4172 log_error("Unkown unit type or load state '%s'.",
4178 if (!(l = strv_append(arg_property, optarg)))
4181 strv_free(arg_property);
4184 /* If the user asked for a particular
4185 * property, show it to him, even if it is
4196 arg_job_mode = "fail";
4199 case ARG_IGNORE_DEPENDENCIES:
4200 arg_job_mode = "ignore-dependencies";
4204 arg_scope = UNIT_FILE_USER;
4208 arg_scope = UNIT_FILE_SYSTEM;
4212 arg_scope = UNIT_FILE_GLOBAL;
4216 arg_no_block = true;
4220 arg_no_legend = true;
4224 arg_no_pager = true;
4232 arg_dot = DOT_ORDER;
4236 arg_dot = DOT_REQUIRE;
4264 /* -f is short for both --follow and --force! */
4270 arg_no_reload = true;
4274 arg_kill_who = optarg;
4278 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4279 log_error("Failed to parse signal string %s.", optarg);
4284 case ARG_NO_ASK_PASSWORD:
4285 arg_ask_password = false;
4289 arg_transport = TRANSPORT_POLKIT;
4293 arg_transport = TRANSPORT_SSH;
4302 if (safe_atou(optarg, &arg_lines) < 0) {
4303 log_error("Failed to parse lines '%s'", optarg);
4309 arg_output = output_mode_from_string(optarg);
4310 if (arg_output < 0) {
4311 log_error("Unknown output '%s'.", optarg);
4320 log_error("Unknown option code '%c'.", c);
4325 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4326 log_error("Cannot access user instance remotely.");
4333 static int halt_parse_argv(int argc, char *argv[]) {
4342 static const struct option options[] = {
4343 { "help", no_argument, NULL, ARG_HELP },
4344 { "halt", no_argument, NULL, ARG_HALT },
4345 { "poweroff", no_argument, NULL, 'p' },
4346 { "reboot", no_argument, NULL, ARG_REBOOT },
4347 { "force", no_argument, NULL, 'f' },
4348 { "wtmp-only", no_argument, NULL, 'w' },
4349 { "no-wtmp", no_argument, NULL, 'd' },
4350 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4351 { NULL, 0, NULL, 0 }
4359 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4360 if (runlevel == '0' || runlevel == '6')
4363 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4371 arg_action = ACTION_HALT;
4375 if (arg_action != ACTION_REBOOT)
4376 arg_action = ACTION_POWEROFF;
4380 arg_action = ACTION_REBOOT;
4402 /* Compatibility nops */
4409 log_error("Unknown option code '%c'.", c);
4414 if (optind < argc) {
4415 log_error("Too many arguments.");
4422 static int parse_time_spec(const char *t, usec_t *_u) {
4426 if (streq(t, "now"))
4428 else if (!strchr(t, ':')) {
4431 if (safe_atou64(t, &u) < 0)
4434 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4443 hour = strtol(t, &e, 10);
4444 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4447 minute = strtol(e+1, &e, 10);
4448 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4451 n = now(CLOCK_REALTIME);
4452 s = (time_t) (n / USEC_PER_SEC);
4455 assert_se(localtime_r(&s, &tm));
4457 tm.tm_hour = (int) hour;
4458 tm.tm_min = (int) minute;
4461 assert_se(s = mktime(&tm));
4463 *_u = (usec_t) s * USEC_PER_SEC;
4466 *_u += USEC_PER_DAY;
4472 static int shutdown_parse_argv(int argc, char *argv[]) {
4479 static const struct option options[] = {
4480 { "help", no_argument, NULL, ARG_HELP },
4481 { "halt", no_argument, NULL, 'H' },
4482 { "poweroff", no_argument, NULL, 'P' },
4483 { "reboot", no_argument, NULL, 'r' },
4484 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4485 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4486 { NULL, 0, NULL, 0 }
4494 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4502 arg_action = ACTION_HALT;
4506 arg_action = ACTION_POWEROFF;
4511 arg_action = ACTION_KEXEC;
4513 arg_action = ACTION_REBOOT;
4517 arg_action = ACTION_KEXEC;
4521 if (arg_action != ACTION_HALT)
4522 arg_action = ACTION_POWEROFF;
4535 /* Compatibility nops */
4539 arg_action = ACTION_CANCEL_SHUTDOWN;
4546 log_error("Unknown option code '%c'.", c);
4551 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4552 r = parse_time_spec(argv[optind], &arg_when);
4554 log_error("Failed to parse time specification: %s", argv[optind]);
4558 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4560 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4561 /* No time argument for shutdown cancel */
4562 arg_wall = argv + optind;
4563 else if (argc > optind + 1)
4564 /* We skip the time argument */
4565 arg_wall = argv + optind + 1;
4572 static int telinit_parse_argv(int argc, char *argv[]) {
4579 static const struct option options[] = {
4580 { "help", no_argument, NULL, ARG_HELP },
4581 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4582 { NULL, 0, NULL, 0 }
4585 static const struct {
4589 { '0', ACTION_POWEROFF },
4590 { '6', ACTION_REBOOT },
4591 { '1', ACTION_RESCUE },
4592 { '2', ACTION_RUNLEVEL2 },
4593 { '3', ACTION_RUNLEVEL3 },
4594 { '4', ACTION_RUNLEVEL4 },
4595 { '5', ACTION_RUNLEVEL5 },
4596 { 's', ACTION_RESCUE },
4597 { 'S', ACTION_RESCUE },
4598 { 'q', ACTION_RELOAD },
4599 { 'Q', ACTION_RELOAD },
4600 { 'u', ACTION_REEXEC },
4601 { 'U', ACTION_REEXEC }
4610 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4625 log_error("Unknown option code '%c'.", c);
4630 if (optind >= argc) {
4635 if (optind + 1 < argc) {
4636 log_error("Too many arguments.");
4640 if (strlen(argv[optind]) != 1) {
4641 log_error("Expected single character argument.");
4645 for (i = 0; i < ELEMENTSOF(table); i++)
4646 if (table[i].from == argv[optind][0])
4649 if (i >= ELEMENTSOF(table)) {
4650 log_error("Unknown command '%s'.", argv[optind]);
4654 arg_action = table[i].to;
4661 static int runlevel_parse_argv(int argc, char *argv[]) {
4667 static const struct option options[] = {
4668 { "help", no_argument, NULL, ARG_HELP },
4669 { NULL, 0, NULL, 0 }
4677 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4688 log_error("Unknown option code '%c'.", c);
4693 if (optind < argc) {
4694 log_error("Too many arguments.");
4701 static int parse_argv(int argc, char *argv[]) {
4705 if (program_invocation_short_name) {
4707 if (strstr(program_invocation_short_name, "halt")) {
4708 arg_action = ACTION_HALT;
4709 return halt_parse_argv(argc, argv);
4710 } else if (strstr(program_invocation_short_name, "poweroff")) {
4711 arg_action = ACTION_POWEROFF;
4712 return halt_parse_argv(argc, argv);
4713 } else if (strstr(program_invocation_short_name, "reboot")) {
4715 arg_action = ACTION_KEXEC;
4717 arg_action = ACTION_REBOOT;
4718 return halt_parse_argv(argc, argv);
4719 } else if (strstr(program_invocation_short_name, "shutdown")) {
4720 arg_action = ACTION_POWEROFF;
4721 return shutdown_parse_argv(argc, argv);
4722 } else if (strstr(program_invocation_short_name, "init")) {
4724 if (sd_booted() > 0) {
4725 arg_action = ACTION_INVALID;
4726 return telinit_parse_argv(argc, argv);
4728 /* Hmm, so some other init system is
4729 * running, we need to forward this
4730 * request to it. For now we simply
4731 * guess that it is Upstart. */
4733 execv("/lib/upstart/telinit", argv);
4735 log_error("Couldn't find an alternative telinit implementation to spawn.");
4739 } else if (strstr(program_invocation_short_name, "runlevel")) {
4740 arg_action = ACTION_RUNLEVEL;
4741 return runlevel_parse_argv(argc, argv);
4745 arg_action = ACTION_SYSTEMCTL;
4746 return systemctl_parse_argv(argc, argv);
4749 static int action_to_runlevel(void) {
4751 static const char table[_ACTION_MAX] = {
4752 [ACTION_HALT] = '0',
4753 [ACTION_POWEROFF] = '0',
4754 [ACTION_REBOOT] = '6',
4755 [ACTION_RUNLEVEL2] = '2',
4756 [ACTION_RUNLEVEL3] = '3',
4757 [ACTION_RUNLEVEL4] = '4',
4758 [ACTION_RUNLEVEL5] = '5',
4759 [ACTION_RESCUE] = '1'
4762 assert(arg_action < _ACTION_MAX);
4764 return table[arg_action];
4767 static int talk_upstart(void) {
4768 DBusMessage *m = NULL, *reply = NULL;
4770 int previous, rl, r;
4772 env1_buf[] = "RUNLEVEL=X",
4773 env2_buf[] = "PREVLEVEL=X";
4774 char *env1 = env1_buf, *env2 = env2_buf;
4775 const char *emit = "runlevel";
4776 dbus_bool_t b_false = FALSE;
4777 DBusMessageIter iter, sub;
4778 DBusConnection *bus;
4780 dbus_error_init(&error);
4782 if (!(rl = action_to_runlevel()))
4785 if (utmp_get_runlevel(&previous, NULL) < 0)
4788 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4789 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4794 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4799 if ((r = bus_check_peercred(bus)) < 0) {
4800 log_error("Failed to verify owner of bus.");
4804 if (!(m = dbus_message_new_method_call(
4805 "com.ubuntu.Upstart",
4806 "/com/ubuntu/Upstart",
4807 "com.ubuntu.Upstart0_6",
4810 log_error("Could not allocate message.");
4815 dbus_message_iter_init_append(m, &iter);
4817 env1_buf[sizeof(env1_buf)-2] = rl;
4818 env2_buf[sizeof(env2_buf)-2] = previous;
4820 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4821 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4822 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4823 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4824 !dbus_message_iter_close_container(&iter, &sub) ||
4825 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4826 log_error("Could not append arguments to message.");
4831 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4833 if (bus_error_is_no_service(&error)) {
4838 log_error("Failed to issue method call: %s", bus_error_message(&error));
4847 dbus_message_unref(m);
4850 dbus_message_unref(reply);
4853 dbus_connection_flush(bus);
4854 dbus_connection_close(bus);
4855 dbus_connection_unref(bus);
4858 dbus_error_free(&error);
4863 static int talk_initctl(void) {
4864 struct init_request request;
4868 if (!(rl = action_to_runlevel()))
4872 request.magic = INIT_MAGIC;
4873 request.sleeptime = 0;
4874 request.cmd = INIT_CMD_RUNLVL;
4875 request.runlevel = rl;
4877 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4879 if (errno == ENOENT)
4882 log_error("Failed to open "INIT_FIFO": %m");
4887 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
4888 close_nointr_nofail(fd);
4891 log_error("Failed to write to "INIT_FIFO": %m");
4892 return errno ? -errno : -EIO;
4898 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
4900 static const struct {
4908 int (* const dispatch)(DBusConnection *bus, char **args);
4910 { "list-units", LESS, 1, list_units },
4911 { "list-unit-files", EQUAL, 1, list_unit_files },
4912 { "list-jobs", EQUAL, 1, list_jobs },
4913 { "clear-jobs", EQUAL, 1, daemon_reload },
4914 { "load", MORE, 2, load_unit },
4915 { "cancel", MORE, 2, cancel_job },
4916 { "start", MORE, 2, start_unit },
4917 { "stop", MORE, 2, start_unit },
4918 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4919 { "reload", MORE, 2, start_unit },
4920 { "restart", MORE, 2, start_unit },
4921 { "try-restart", MORE, 2, start_unit },
4922 { "reload-or-restart", MORE, 2, start_unit },
4923 { "reload-or-try-restart", MORE, 2, start_unit },
4924 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
4925 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4926 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
4927 { "isolate", EQUAL, 2, start_unit },
4928 { "kill", MORE, 2, kill_unit },
4929 { "is-active", MORE, 2, check_unit },
4930 { "check", MORE, 2, check_unit },
4931 { "show", MORE, 1, show },
4932 { "status", MORE, 2, show },
4933 { "help", MORE, 2, show },
4934 { "dump", EQUAL, 1, dump },
4935 { "dot", EQUAL, 1, dot },
4936 { "snapshot", LESS, 2, snapshot },
4937 { "delete", MORE, 2, delete_snapshot },
4938 { "daemon-reload", EQUAL, 1, daemon_reload },
4939 { "daemon-reexec", EQUAL, 1, daemon_reload },
4940 { "show-environment", EQUAL, 1, show_enviroment },
4941 { "set-environment", MORE, 2, set_environment },
4942 { "unset-environment", MORE, 2, set_environment },
4943 { "halt", EQUAL, 1, start_special },
4944 { "poweroff", EQUAL, 1, start_special },
4945 { "reboot", EQUAL, 1, start_special },
4946 { "kexec", EQUAL, 1, start_special },
4947 { "suspend", EQUAL, 1, start_special },
4948 { "hibernate", EQUAL, 1, start_special },
4949 { "default", EQUAL, 1, start_special },
4950 { "rescue", EQUAL, 1, start_special },
4951 { "emergency", EQUAL, 1, start_special },
4952 { "exit", EQUAL, 1, start_special },
4953 { "reset-failed", MORE, 1, reset_failed },
4954 { "enable", MORE, 2, enable_unit },
4955 { "disable", MORE, 2, enable_unit },
4956 { "is-enabled", MORE, 2, unit_is_enabled },
4957 { "reenable", MORE, 2, enable_unit },
4958 { "preset", MORE, 2, enable_unit },
4959 { "mask", MORE, 2, enable_unit },
4960 { "unmask", MORE, 2, enable_unit },
4961 { "link", MORE, 2, enable_unit },
4962 { "switch-root", MORE, 2, switch_root },
4972 left = argc - optind;
4975 /* Special rule: no arguments means "list-units" */
4978 if (streq(argv[optind], "help") && !argv[optind+1]) {
4979 log_error("This command expects one or more "
4980 "unit names. Did you mean --help?");
4984 for (i = 0; i < ELEMENTSOF(verbs); i++)
4985 if (streq(argv[optind], verbs[i].verb))
4988 if (i >= ELEMENTSOF(verbs)) {
4989 log_error("Unknown operation '%s'.", argv[optind]);
4994 switch (verbs[i].argc_cmp) {
4997 if (left != verbs[i].argc) {
4998 log_error("Invalid number of arguments.");
5005 if (left < verbs[i].argc) {
5006 log_error("Too few arguments.");
5013 if (left > verbs[i].argc) {
5014 log_error("Too many arguments.");
5021 assert_not_reached("Unknown comparison operator.");
5024 /* Require a bus connection for all operations but
5026 if (!streq(verbs[i].verb, "enable") &&
5027 !streq(verbs[i].verb, "disable") &&
5028 !streq(verbs[i].verb, "is-enabled") &&
5029 !streq(verbs[i].verb, "list-unit-files") &&
5030 !streq(verbs[i].verb, "reenable") &&
5031 !streq(verbs[i].verb, "preset") &&
5032 !streq(verbs[i].verb, "mask") &&
5033 !streq(verbs[i].verb, "unmask") &&
5034 !streq(verbs[i].verb, "link")) {
5036 if (running_in_chroot() > 0) {
5037 log_info("Running in chroot, ignoring request.");
5041 if (((!streq(verbs[i].verb, "reboot") &&
5042 !streq(verbs[i].verb, "halt") &&
5043 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5044 log_error("Failed to get D-Bus connection: %s",
5045 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5051 if (!bus && !avoid_bus()) {
5052 log_error("Failed to get D-Bus connection: %s",
5053 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5058 return verbs[i].dispatch(bus, argv + optind);
5061 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5063 struct msghdr msghdr;
5064 struct iovec iovec[2];
5065 union sockaddr_union sockaddr;
5066 struct sd_shutdown_command c;
5068 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5075 c.dry_run = dry_run;
5079 sockaddr.sa.sa_family = AF_UNIX;
5080 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5083 msghdr.msg_name = &sockaddr;
5084 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5087 iovec[0].iov_base = (char*) &c;
5088 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5090 if (isempty(message))
5091 msghdr.msg_iovlen = 1;
5093 iovec[1].iov_base = (char*) message;
5094 iovec[1].iov_len = strlen(message);
5095 msghdr.msg_iovlen = 2;
5097 msghdr.msg_iov = iovec;
5099 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5100 close_nointr_nofail(fd);
5104 close_nointr_nofail(fd);
5108 static int reload_with_fallback(DBusConnection *bus) {
5111 /* First, try systemd via D-Bus. */
5112 if (daemon_reload(bus, NULL) >= 0)
5116 /* Nothing else worked, so let's try signals */
5117 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5119 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5120 log_error("kill() failed: %m");
5127 static int start_with_fallback(DBusConnection *bus) {
5130 /* First, try systemd via D-Bus. */
5131 if (start_unit(bus, NULL) >= 0)
5135 /* Hmm, talking to systemd via D-Bus didn't work. Then
5136 * let's try to talk to Upstart via D-Bus. */
5137 if (talk_upstart() > 0)
5140 /* Nothing else worked, so let's try
5142 if (talk_initctl() > 0)
5145 log_error("Failed to talk to init daemon.");
5149 warn_wall(arg_action);
5153 static _noreturn_ void halt_now(enum action a) {
5155 /* Make sure C-A-D is handled by the kernel from this
5157 reboot(RB_ENABLE_CAD);
5162 log_info("Halting.");
5163 reboot(RB_HALT_SYSTEM);
5166 case ACTION_POWEROFF:
5167 log_info("Powering off.");
5168 reboot(RB_POWER_OFF);
5172 log_info("Rebooting.");
5173 reboot(RB_AUTOBOOT);
5177 assert_not_reached("Unknown halt action.");
5180 assert_not_reached("Uh? This shouldn't happen.");
5183 static int halt_main(DBusConnection *bus) {
5186 if (geteuid() != 0) {
5187 /* Try logind if we are a normal user and no special
5188 * mode applies. Maybe PolicyKit allows us to shutdown
5191 if (arg_when <= 0 &&
5194 (arg_action == ACTION_POWEROFF ||
5195 arg_action == ACTION_REBOOT)) {
5196 r = reboot_with_logind(bus, arg_action);
5201 log_error("Must be root.");
5208 m = strv_join(arg_wall, " ");
5209 r = send_shutdownd(arg_when,
5210 arg_action == ACTION_HALT ? 'H' :
5211 arg_action == ACTION_POWEROFF ? 'P' :
5212 arg_action == ACTION_KEXEC ? 'K' :
5220 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5222 char date[FORMAT_TIMESTAMP_MAX];
5224 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5225 format_timestamp(date, sizeof(date), arg_when));
5230 if (!arg_dry && !arg_force)
5231 return start_with_fallback(bus);
5234 if (sd_booted() > 0)
5235 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5237 r = utmp_put_shutdown();
5239 log_warning("Failed to write utmp record: %s", strerror(-r));
5246 halt_now(arg_action);
5247 /* We should never reach this. */
5251 static int runlevel_main(void) {
5252 int r, runlevel, previous;
5254 r = utmp_get_runlevel(&runlevel, &previous);
5261 previous <= 0 ? 'N' : previous,
5262 runlevel <= 0 ? 'N' : runlevel);
5267 int main(int argc, char*argv[]) {
5268 int r, retval = EXIT_FAILURE;
5269 DBusConnection *bus = NULL;
5272 dbus_error_init(&error);
5274 log_parse_environment();
5277 r = parse_argv(argc, argv);
5281 retval = EXIT_SUCCESS;
5285 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5286 * let's shortcut this */
5287 if (arg_action == ACTION_RUNLEVEL) {
5288 r = runlevel_main();
5289 retval = r < 0 ? EXIT_FAILURE : r;
5293 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5294 log_info("Running in chroot, ignoring request.");
5300 if (arg_transport == TRANSPORT_NORMAL)
5301 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5302 else if (arg_transport == TRANSPORT_POLKIT) {
5303 bus_connect_system_polkit(&bus, &error);
5304 private_bus = false;
5305 } else if (arg_transport == TRANSPORT_SSH) {
5306 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5307 private_bus = false;
5309 assert_not_reached("Uh, invalid transport...");
5312 switch (arg_action) {
5314 case ACTION_SYSTEMCTL:
5315 r = systemctl_main(bus, argc, argv, &error);
5319 case ACTION_POWEROFF:
5325 case ACTION_RUNLEVEL2:
5326 case ACTION_RUNLEVEL3:
5327 case ACTION_RUNLEVEL4:
5328 case ACTION_RUNLEVEL5:
5330 case ACTION_EMERGENCY:
5331 case ACTION_DEFAULT:
5332 r = start_with_fallback(bus);
5337 r = reload_with_fallback(bus);
5340 case ACTION_CANCEL_SHUTDOWN: {
5344 m = strv_join(arg_wall, " ");
5346 retval = EXIT_FAILURE;
5350 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5352 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5357 case ACTION_INVALID:
5358 case ACTION_RUNLEVEL:
5360 assert_not_reached("Unknown action");
5363 retval = r < 0 ? EXIT_FAILURE : r;
5367 dbus_connection_flush(bus);
5368 dbus_connection_close(bus);
5369 dbus_connection_unref(bus);
5372 dbus_error_free(&error);
5376 strv_free(arg_property);
5379 ask_password_agent_close();
5380 polkit_agent_close();