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 arg_follow * OUTPUT_FOLLOW |
2297 !arg_quiet * OUTPUT_WARN_CUTOFF |
2298 on_tty() * OUTPUT_COLOR;
2301 show_journal_by_unit(stdout,
2305 i->inactive_exit_timestamp_monotonic,
2310 if (i->need_daemon_reload)
2311 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2312 ansi_highlight_red(true),
2313 ansi_highlight_red(false),
2314 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2317 static void show_unit_help(UnitStatusInfo *i) {
2322 if (!i->documentation) {
2323 log_info("Documentation for %s not known.", i->id);
2327 STRV_FOREACH(p, i->documentation) {
2329 if (startswith(*p, "man:")) {
2332 char *page = NULL, *section = NULL;
2333 const char *args[4] = { "man", NULL, NULL, NULL };
2338 if ((*p)[k-1] == ')')
2339 e = strrchr(*p, '(');
2342 page = strndup((*p) + 4, e - *p - 4);
2348 section = strndup(e + 1, *p + k - e - 2);
2362 log_error("Failed to fork: %m");
2370 execvp(args[0], (char**) args);
2371 log_error("Failed to execute man: %m");
2372 _exit(EXIT_FAILURE);
2378 wait_for_terminate(pid, NULL);
2380 log_info("Can't show: %s", *p);
2384 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2390 switch (dbus_message_iter_get_arg_type(iter)) {
2392 case DBUS_TYPE_STRING: {
2395 dbus_message_iter_get_basic(iter, &s);
2398 if (streq(name, "Id"))
2400 else if (streq(name, "LoadState"))
2402 else if (streq(name, "ActiveState"))
2403 i->active_state = s;
2404 else if (streq(name, "SubState"))
2406 else if (streq(name, "Description"))
2408 else if (streq(name, "FragmentPath"))
2409 i->fragment_path = s;
2410 else if (streq(name, "SourcePath"))
2412 else if (streq(name, "DefaultControlGroup"))
2413 i->default_control_group = s;
2414 else if (streq(name, "StatusText"))
2416 else if (streq(name, "SysFSPath"))
2418 else if (streq(name, "Where"))
2420 else if (streq(name, "What"))
2422 else if (streq(name, "Following"))
2424 else if (streq(name, "UnitFileState"))
2425 i->unit_file_state = s;
2426 else if (streq(name, "Result"))
2433 case DBUS_TYPE_BOOLEAN: {
2436 dbus_message_iter_get_basic(iter, &b);
2438 if (streq(name, "Accept"))
2440 else if (streq(name, "NeedDaemonReload"))
2441 i->need_daemon_reload = b;
2442 else if (streq(name, "ConditionResult"))
2443 i->condition_result = b;
2448 case DBUS_TYPE_UINT32: {
2451 dbus_message_iter_get_basic(iter, &u);
2453 if (streq(name, "MainPID")) {
2455 i->main_pid = (pid_t) u;
2458 } else if (streq(name, "ControlPID"))
2459 i->control_pid = (pid_t) u;
2460 else if (streq(name, "ExecMainPID")) {
2462 i->main_pid = (pid_t) u;
2463 } else if (streq(name, "NAccepted"))
2465 else if (streq(name, "NConnections"))
2466 i->n_connections = u;
2471 case DBUS_TYPE_INT32: {
2474 dbus_message_iter_get_basic(iter, &j);
2476 if (streq(name, "ExecMainCode"))
2477 i->exit_code = (int) j;
2478 else if (streq(name, "ExecMainStatus"))
2479 i->exit_status = (int) j;
2484 case DBUS_TYPE_UINT64: {
2487 dbus_message_iter_get_basic(iter, &u);
2489 if (streq(name, "ExecMainStartTimestamp"))
2490 i->start_timestamp = (usec_t) u;
2491 else if (streq(name, "ExecMainExitTimestamp"))
2492 i->exit_timestamp = (usec_t) u;
2493 else if (streq(name, "ActiveEnterTimestamp"))
2494 i->active_enter_timestamp = (usec_t) u;
2495 else if (streq(name, "InactiveEnterTimestamp"))
2496 i->inactive_enter_timestamp = (usec_t) u;
2497 else if (streq(name, "InactiveExitTimestamp"))
2498 i->inactive_exit_timestamp = (usec_t) u;
2499 else if (streq(name, "InactiveExitTimestampMonotonic"))
2500 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2501 else if (streq(name, "ActiveExitTimestamp"))
2502 i->active_exit_timestamp = (usec_t) u;
2503 else if (streq(name, "ConditionTimestamp"))
2504 i->condition_timestamp = (usec_t) u;
2509 case DBUS_TYPE_ARRAY: {
2511 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2512 startswith(name, "Exec")) {
2513 DBusMessageIter sub;
2515 dbus_message_iter_recurse(iter, &sub);
2516 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2517 ExecStatusInfo *info;
2520 if (!(info = new0(ExecStatusInfo, 1)))
2523 if (!(info->name = strdup(name))) {
2528 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2533 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2535 dbus_message_iter_next(&sub);
2537 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2538 streq(name, "Documentation")) {
2540 DBusMessageIter sub;
2542 dbus_message_iter_recurse(iter, &sub);
2543 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2547 dbus_message_iter_get_basic(&sub, &s);
2549 l = strv_append(i->documentation, s);
2553 strv_free(i->documentation);
2554 i->documentation = l;
2556 dbus_message_iter_next(&sub);
2563 case DBUS_TYPE_STRUCT: {
2565 if (streq(name, "LoadError")) {
2566 DBusMessageIter sub;
2567 const char *n, *message;
2570 dbus_message_iter_recurse(iter, &sub);
2572 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2576 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2580 if (!isempty(message))
2581 i->load_error = message;
2591 static int print_property(const char *name, DBusMessageIter *iter) {
2595 /* This is a low-level property printer, see
2596 * print_status_info() for the nicer output */
2598 if (arg_property && !strv_find(arg_property, name))
2601 switch (dbus_message_iter_get_arg_type(iter)) {
2603 case DBUS_TYPE_STRUCT: {
2604 DBusMessageIter sub;
2605 dbus_message_iter_recurse(iter, &sub);
2607 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2610 dbus_message_iter_get_basic(&sub, &u);
2613 printf("%s=%u\n", name, (unsigned) u);
2615 printf("%s=\n", name);
2618 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2621 dbus_message_iter_get_basic(&sub, &s);
2623 if (arg_all || s[0])
2624 printf("%s=%s\n", name, s);
2627 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2628 const char *a = NULL, *b = NULL;
2630 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2631 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2633 if (arg_all || !isempty(a) || !isempty(b))
2634 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2642 case DBUS_TYPE_ARRAY:
2644 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2645 DBusMessageIter sub, sub2;
2647 dbus_message_iter_recurse(iter, &sub);
2648 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2652 dbus_message_iter_recurse(&sub, &sub2);
2654 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2655 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2656 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2658 dbus_message_iter_next(&sub);
2663 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2664 DBusMessageIter sub, sub2;
2666 dbus_message_iter_recurse(iter, &sub);
2667 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2668 const char *type, *path;
2670 dbus_message_iter_recurse(&sub, &sub2);
2672 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2673 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2674 printf("%s=%s\n", type, path);
2676 dbus_message_iter_next(&sub);
2681 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2682 DBusMessageIter sub, sub2;
2684 dbus_message_iter_recurse(iter, &sub);
2685 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2687 uint64_t value, next_elapse;
2689 dbus_message_iter_recurse(&sub, &sub2);
2691 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2692 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2693 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2694 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2696 printf("%s={ value=%s ; next_elapse=%s }\n",
2698 format_timespan(timespan1, sizeof(timespan1), value),
2699 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2702 dbus_message_iter_next(&sub);
2707 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2708 DBusMessageIter sub, sub2;
2710 dbus_message_iter_recurse(iter, &sub);
2711 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2712 const char *controller, *attr, *value;
2714 dbus_message_iter_recurse(&sub, &sub2);
2716 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2717 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2718 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2720 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2726 dbus_message_iter_next(&sub);
2731 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2732 DBusMessageIter sub;
2734 dbus_message_iter_recurse(iter, &sub);
2735 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2736 ExecStatusInfo info;
2739 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2740 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2743 t = strv_join(info.argv, " ");
2745 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2749 yes_no(info.ignore),
2750 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2751 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2752 (unsigned) info. pid,
2753 sigchld_code_to_string(info.code),
2755 info.code == CLD_EXITED ? "" : "/",
2756 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2762 strv_free(info.argv);
2764 dbus_message_iter_next(&sub);
2773 if (generic_print_property(name, iter, arg_all) > 0)
2777 printf("%s=[unprintable]\n", name);
2782 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2783 DBusMessage *reply = NULL;
2784 const char *interface = "";
2786 DBusMessageIter iter, sub, sub2, sub3;
2787 UnitStatusInfo info;
2795 r = bus_method_call_with_reply (
2797 "org.freedesktop.systemd1",
2799 "org.freedesktop.DBus.Properties",
2803 DBUS_TYPE_STRING, &interface,
2808 if (!dbus_message_iter_init(reply, &iter) ||
2809 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2810 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2811 log_error("Failed to parse reply.");
2816 dbus_message_iter_recurse(&iter, &sub);
2823 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2826 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2827 log_error("Failed to parse reply.");
2832 dbus_message_iter_recurse(&sub, &sub2);
2834 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2835 log_error("Failed to parse reply.");
2840 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2841 log_error("Failed to parse reply.");
2846 dbus_message_iter_recurse(&sub2, &sub3);
2848 if (show_properties)
2849 r = print_property(name, &sub3);
2851 r = status_property(name, &sub3, &info);
2854 log_error("Failed to parse reply.");
2859 dbus_message_iter_next(&sub);
2864 if (!show_properties) {
2865 if (streq(verb, "help"))
2866 show_unit_help(&info);
2868 print_status_info(&info);
2871 strv_free(info.documentation);
2873 if (!streq_ptr(info.active_state, "active") &&
2874 !streq_ptr(info.active_state, "reloading") &&
2875 streq(verb, "status"))
2876 /* According to LSB: "program not running" */
2879 while ((p = info.exec)) {
2880 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2881 exec_status_info_free(p);
2886 dbus_message_unref(reply);
2891 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
2892 DBusMessage *reply = NULL;
2893 const char *path = NULL;
2897 dbus_error_init(&error);
2899 r = bus_method_call_with_reply (
2901 "org.freedesktop.systemd1",
2902 "/org/freedesktop/systemd1",
2903 "org.freedesktop.systemd1.Manager",
2907 DBUS_TYPE_UINT32, &pid,
2912 if (!dbus_message_get_args(reply, &error,
2913 DBUS_TYPE_OBJECT_PATH, &path,
2914 DBUS_TYPE_INVALID)) {
2915 log_error("Failed to parse reply: %s", bus_error_message(&error));
2920 r = show_one(verb, bus, path, false, new_line);
2924 dbus_message_unref(reply);
2926 dbus_error_free(&error);
2931 static int show(DBusConnection *bus, char **args) {
2933 bool show_properties, new_line = false;
2939 show_properties = streq(args[0], "show");
2941 if (show_properties)
2942 pager_open_if_enabled();
2944 if (show_properties && strv_length(args) <= 1) {
2945 /* If not argument is specified inspect the manager
2948 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2951 STRV_FOREACH(name, args+1) {
2954 if (safe_atou32(*name, &id) < 0) {
2956 /* Interpret as unit name */
2958 n = unit_name_mangle(*name);
2959 p = unit_dbus_path_from_name(n ? n : *name);
2964 r = show_one(args[0], bus, p, show_properties, &new_line);
2970 } else if (show_properties) {
2972 /* Interpret as job id */
2975 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
2978 r = show_one(args[0], bus, p, show_properties, &new_line);
2986 /* Interpret as PID */
2988 r = show_one_by_pid(args[0], bus, id, &new_line);
2997 static int dump(DBusConnection *bus, char **args) {
2998 DBusMessage *reply = NULL;
3003 dbus_error_init(&error);
3005 pager_open_if_enabled();
3007 r = bus_method_call_with_reply (
3009 "org.freedesktop.systemd1",
3010 "/org/freedesktop/systemd1",
3011 "org.freedesktop.systemd1.Manager",
3019 if (!dbus_message_get_args(reply, &error,
3020 DBUS_TYPE_STRING, &text,
3021 DBUS_TYPE_INVALID)) {
3022 log_error("Failed to parse reply: %s", bus_error_message(&error));
3027 fputs(text, stdout);
3031 dbus_message_unref(reply);
3033 dbus_error_free(&error);
3038 static int snapshot(DBusConnection *bus, char **args) {
3039 DBusMessage *reply = NULL;
3042 dbus_bool_t cleanup = FALSE;
3043 DBusMessageIter iter, sub;
3045 *name = "", *path, *id,
3046 *interface = "org.freedesktop.systemd1.Unit",
3050 dbus_error_init(&error);
3052 if (strv_length(args) > 1)
3055 n = unit_name_mangle(name);
3056 r = bus_method_call_with_reply (
3058 "org.freedesktop.systemd1",
3059 "/org/freedesktop/systemd1",
3060 "org.freedesktop.systemd1.Manager",
3064 DBUS_TYPE_STRING, n ? (const char**) &n : &name,
3065 DBUS_TYPE_BOOLEAN, &cleanup,
3071 if (!dbus_message_get_args(reply, &error,
3072 DBUS_TYPE_OBJECT_PATH, &path,
3073 DBUS_TYPE_INVALID)) {
3074 log_error("Failed to parse reply: %s", bus_error_message(&error));
3079 dbus_message_unref(reply);
3080 r = bus_method_call_with_reply (
3082 "org.freedesktop.systemd1",
3084 "org.freedesktop.DBus.Properties",
3088 DBUS_TYPE_STRING, &interface,
3089 DBUS_TYPE_STRING, &property,
3094 if (!dbus_message_iter_init(reply, &iter) ||
3095 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3096 log_error("Failed to parse reply.");
3101 dbus_message_iter_recurse(&iter, &sub);
3103 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3104 log_error("Failed to parse reply.");
3109 dbus_message_iter_get_basic(&sub, &id);
3116 dbus_message_unref(reply);
3118 dbus_error_free(&error);
3123 static int delete_snapshot(DBusConnection *bus, char **args) {
3124 DBusMessage *reply = NULL;
3131 dbus_error_init(&error);
3133 STRV_FOREACH(name, args+1) {
3134 const char *path = NULL;
3137 n = unit_name_mangle(*name);
3138 r = bus_method_call_with_reply (
3140 "org.freedesktop.systemd1",
3141 "/org/freedesktop/systemd1",
3142 "org.freedesktop.systemd1.Manager",
3146 DBUS_TYPE_STRING, n ? &n : name,
3152 if (!dbus_message_get_args(reply, &error,
3153 DBUS_TYPE_OBJECT_PATH, &path,
3154 DBUS_TYPE_INVALID)) {
3155 log_error("Failed to parse reply: %s", bus_error_message(&error));
3157 dbus_message_unref(reply);
3158 dbus_error_free(&error);
3161 dbus_message_unref(reply);
3163 r = bus_method_call_with_reply (
3165 "org.freedesktop.systemd1",
3167 "org.freedesktop.systemd1.Snapshot",
3180 static int daemon_reload(DBusConnection *bus, char **args) {
3185 if (arg_action == ACTION_RELOAD)
3187 else if (arg_action == ACTION_REEXEC)
3188 method = "Reexecute";
3190 assert(arg_action == ACTION_SYSTEMCTL);
3193 streq(args[0], "clear-jobs") ||
3194 streq(args[0], "cancel") ? "ClearJobs" :
3195 streq(args[0], "daemon-reexec") ? "Reexecute" :
3196 streq(args[0], "reset-failed") ? "ResetFailed" :
3197 streq(args[0], "halt") ? "Halt" :
3198 streq(args[0], "poweroff") ? "PowerOff" :
3199 streq(args[0], "reboot") ? "Reboot" :
3200 streq(args[0], "kexec") ? "KExec" :
3201 streq(args[0], "exit") ? "Exit" :
3202 /* "daemon-reload" */ "Reload";
3205 r = bus_method_call_with_reply (
3207 "org.freedesktop.systemd1",
3208 "/org/freedesktop/systemd1",
3209 "org.freedesktop.systemd1.Manager",
3215 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3216 /* There's always a fallback possible for
3217 * legacy actions. */
3219 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3220 /* On reexecution, we expect a disconnect, not
3224 log_error("Failed to issue method call: %s", bus_error_message(&error));
3225 dbus_error_free(&error);
3230 static int reset_failed(DBusConnection *bus, char **args) {
3234 if (strv_length(args) <= 1)
3235 return daemon_reload(bus, args);
3237 STRV_FOREACH(name, args+1) {
3238 n = unit_name_mangle(*name);
3239 r = bus_method_call_with_reply (
3241 "org.freedesktop.systemd1",
3242 "/org/freedesktop/systemd1",
3243 "org.freedesktop.systemd1.Manager",
3247 DBUS_TYPE_STRING, n ? &n : name,
3258 static int show_enviroment(DBusConnection *bus, char **args) {
3259 DBusMessage *reply = NULL;
3260 DBusMessageIter iter, sub, sub2;
3263 *interface = "org.freedesktop.systemd1.Manager",
3264 *property = "Environment";
3266 pager_open_if_enabled();
3268 r = bus_method_call_with_reply (
3270 "org.freedesktop.systemd1",
3271 "/org/freedesktop/systemd1",
3272 "org.freedesktop.DBus.Properties",
3276 DBUS_TYPE_STRING, &interface,
3277 DBUS_TYPE_STRING, &property,
3282 if (!dbus_message_iter_init(reply, &iter) ||
3283 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3284 log_error("Failed to parse reply.");
3289 dbus_message_iter_recurse(&iter, &sub);
3291 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3292 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3293 log_error("Failed to parse reply.");
3298 dbus_message_iter_recurse(&sub, &sub2);
3300 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3303 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3304 log_error("Failed to parse reply.");
3309 dbus_message_iter_get_basic(&sub2, &text);
3310 printf("%s\n", text);
3312 dbus_message_iter_next(&sub2);
3319 dbus_message_unref(reply);
3324 static int switch_root(DBusConnection *bus, char **args) {
3326 const char *root, *init;
3328 l = strv_length(args);
3329 if (l < 2 || l > 3) {
3330 log_error("Wrong number of arguments.");
3335 init = l >= 3 ? args[2] : "";
3337 return bus_method_call_with_reply (
3339 "org.freedesktop.systemd1",
3340 "/org/freedesktop/systemd1",
3341 "org.freedesktop.systemd1.Manager",
3345 DBUS_TYPE_STRING, &root,
3346 DBUS_TYPE_STRING, &init,
3350 static int set_environment(DBusConnection *bus, char **args) {
3351 DBusMessage *m = NULL, *reply = NULL;
3355 DBusMessageIter iter, sub;
3358 dbus_error_init(&error);
3360 method = streq(args[0], "set-environment")
3362 : "UnsetEnvironment";
3364 if (!(m = dbus_message_new_method_call(
3365 "org.freedesktop.systemd1",
3366 "/org/freedesktop/systemd1",
3367 "org.freedesktop.systemd1.Manager",
3370 log_error("Could not allocate message.");
3374 dbus_message_iter_init_append(m, &iter);
3376 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
3377 log_error("Could not append arguments to message.");
3382 STRV_FOREACH(name, args+1)
3383 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, name)) {
3384 log_error("Could not append arguments to message.");
3389 if (!dbus_message_iter_close_container(&iter, &sub)) {
3390 log_error("Could not append arguments to message.");
3395 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3396 log_error("Failed to issue method call: %s", bus_error_message(&error));
3405 dbus_message_unref(m);
3408 dbus_message_unref(reply);
3410 dbus_error_free(&error);
3415 static int enable_sysv_units(char **args) {
3418 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3419 const char *verb = args[0];
3420 unsigned f = 1, t = 1;
3423 if (arg_scope != UNIT_FILE_SYSTEM)
3426 if (!streq(verb, "enable") &&
3427 !streq(verb, "disable") &&
3428 !streq(verb, "is-enabled"))
3431 /* Processes all SysV units, and reshuffles the array so that
3432 * afterwards only the native units remain */
3435 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3440 for (f = 1; args[f]; f++) {
3443 bool found_native = false, found_sysv;
3445 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3446 char **k, *l, *q = NULL;
3453 if (!endswith(name, ".service"))
3456 if (path_is_absolute(name))
3459 STRV_FOREACH(k, paths.unit_path) {
3462 if (!isempty(arg_root))
3463 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3465 asprintf(&p, "%s/%s", *k, name);
3472 found_native = access(p, F_OK) >= 0;
3483 if (!isempty(arg_root))
3484 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3486 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3492 p[strlen(p) - sizeof(".service") + 1] = 0;
3493 found_sysv = access(p, F_OK) >= 0;
3500 /* Mark this entry, so that we don't try enabling it as native unit */
3501 args[f] = (char*) "";
3503 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3505 if (!isempty(arg_root))
3506 argv[c++] = q = strappend("--root=", arg_root);
3508 argv[c++] = path_get_file_name(p);
3510 streq(verb, "enable") ? "on" :
3511 streq(verb, "disable") ? "off" : "--level=5";
3514 l = strv_join((char**)argv, " ");
3522 log_info("Executing %s", l);
3527 log_error("Failed to fork: %m");
3532 } else if (pid == 0) {
3535 execv(argv[0], (char**) argv);
3536 _exit(EXIT_FAILURE);
3542 j = wait_for_terminate(pid, &status);
3544 log_error("Failed to wait for child: %s", strerror(-r));
3549 if (status.si_code == CLD_EXITED) {
3550 if (streq(verb, "is-enabled")) {
3551 if (status.si_status == 0) {
3560 } else if (status.si_status != 0) {
3571 lookup_paths_free(&paths);
3573 /* Drop all SysV units */
3574 for (f = 1, t = 1; args[f]; f++) {
3576 if (isempty(args[f]))
3579 args[t++] = args[f];
3588 static int mangle_names(char **original_names, char ***mangled_names) {
3589 char **i, **l, **name;
3591 l = new(char*, strv_length(original_names) + 1);
3596 STRV_FOREACH(name, original_names) {
3598 /* When enabling units qualified path names are OK,
3599 * too, hence allow them explicitly. */
3604 *i = unit_name_mangle(*name);
3620 static int enable_unit(DBusConnection *bus, char **args) {
3621 const char *verb = args[0];
3622 UnitFileChange *changes = NULL;
3623 unsigned n_changes = 0, i;
3624 int carries_install_info = -1;
3625 DBusMessage *m = NULL, *reply = NULL;
3628 char **mangled_names = NULL;
3630 r = enable_sysv_units(args);
3637 dbus_error_init(&error);
3639 if (!bus || avoid_bus()) {
3640 if (streq(verb, "enable")) {
3641 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3642 carries_install_info = r;
3643 } else if (streq(verb, "disable"))
3644 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3645 else if (streq(verb, "reenable")) {
3646 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3647 carries_install_info = r;
3648 } else if (streq(verb, "link"))
3649 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3650 else if (streq(verb, "preset")) {
3651 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3652 carries_install_info = r;
3653 } else if (streq(verb, "mask"))
3654 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3655 else if (streq(verb, "unmask"))
3656 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3658 assert_not_reached("Unknown verb");
3661 log_error("Operation failed: %s", strerror(-r));
3666 for (i = 0; i < n_changes; i++) {
3667 if (changes[i].type == UNIT_FILE_SYMLINK)
3668 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3670 log_info("rm '%s'", changes[i].path);
3676 bool send_force = true, expect_carries_install_info = false;
3678 DBusMessageIter iter, sub, sub2;
3680 if (streq(verb, "enable")) {
3681 method = "EnableUnitFiles";
3682 expect_carries_install_info = true;
3683 } else if (streq(verb, "disable")) {
3684 method = "DisableUnitFiles";
3686 } else if (streq(verb, "reenable")) {
3687 method = "ReenableUnitFiles";
3688 expect_carries_install_info = true;
3689 } else if (streq(verb, "link"))
3690 method = "LinkUnitFiles";
3691 else if (streq(verb, "preset")) {
3692 method = "PresetUnitFiles";
3693 expect_carries_install_info = true;
3694 } else if (streq(verb, "mask"))
3695 method = "MaskUnitFiles";
3696 else if (streq(verb, "unmask")) {
3697 method = "UnmaskUnitFiles";
3700 assert_not_reached("Unknown verb");
3702 m = dbus_message_new_method_call(
3703 "org.freedesktop.systemd1",
3704 "/org/freedesktop/systemd1",
3705 "org.freedesktop.systemd1.Manager",
3712 dbus_message_iter_init_append(m, &iter);
3714 r = mangle_names(args+1, &mangled_names);
3718 r = bus_append_strv_iter(&iter, mangled_names);
3720 log_error("Failed to append unit files.");
3725 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3726 log_error("Failed to append runtime boolean.");
3734 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3735 log_error("Failed to append force boolean.");
3741 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3743 log_error("Failed to issue method call: %s", bus_error_message(&error));
3748 if (!dbus_message_iter_init(reply, &iter)) {
3749 log_error("Failed to initialize iterator.");
3753 if (expect_carries_install_info) {
3754 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3756 log_error("Failed to parse reply.");
3760 carries_install_info = b;
3763 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3764 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3765 log_error("Failed to parse reply.");
3770 dbus_message_iter_recurse(&iter, &sub);
3771 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3772 const char *type, *path, *source;
3774 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3775 log_error("Failed to parse reply.");
3780 dbus_message_iter_recurse(&sub, &sub2);
3782 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3783 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3784 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3785 log_error("Failed to parse reply.");
3791 if (streq(type, "symlink"))
3792 log_info("ln -s '%s' '%s'", source, path);
3794 log_info("rm '%s'", path);
3797 dbus_message_iter_next(&sub);
3800 /* Try to reload if enabeld */
3802 r = daemon_reload(bus, args);
3805 if (carries_install_info == 0)
3806 log_warning("The unit files have no [Install] section. They are not meant to be enabled using systemctl.");
3810 dbus_message_unref(m);
3813 dbus_message_unref(reply);
3815 unit_file_changes_free(changes, n_changes);
3817 dbus_error_free(&error);
3819 strv_free(mangled_names);
3824 static int unit_is_enabled(DBusConnection *bus, char **args) {
3827 DBusMessage *reply = NULL;
3831 dbus_error_init(&error);
3833 r = enable_sysv_units(args);
3839 if (!bus || avoid_bus()) {
3841 STRV_FOREACH(name, args+1) {
3842 UnitFileState state;
3844 state = unit_file_get_state(arg_scope, arg_root, *name);
3850 if (state == UNIT_FILE_ENABLED ||
3851 state == UNIT_FILE_ENABLED_RUNTIME ||
3852 state == UNIT_FILE_STATIC)
3856 puts(unit_file_state_to_string(state));
3860 STRV_FOREACH(name, args+1) {
3863 r = bus_method_call_with_reply (
3865 "org.freedesktop.systemd1",
3866 "/org/freedesktop/systemd1",
3867 "org.freedesktop.systemd1.Manager",
3871 DBUS_TYPE_STRING, name,
3876 if (!dbus_message_get_args(reply, &error,
3877 DBUS_TYPE_STRING, &s,
3878 DBUS_TYPE_INVALID)) {
3879 log_error("Failed to parse reply: %s", bus_error_message(&error));
3884 dbus_message_unref(reply);
3887 if (streq(s, "enabled") ||
3888 streq(s, "enabled-runtime") ||
3897 r = enabled ? 0 : 1;
3901 dbus_message_unref(reply);
3903 dbus_error_free(&error);
3907 static int systemctl_help(void) {
3909 pager_open_if_enabled();
3911 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
3912 "Query or send control commands to the systemd manager.\n\n"
3913 " -h --help Show this help\n"
3914 " --version Show package version\n"
3915 " -t --type=TYPE List only units of a particular type\n"
3916 " -p --property=NAME Show only properties by this name\n"
3917 " -a --all Show all units/properties, including dead/empty ones\n"
3918 " --failed Show only failed units\n"
3919 " --full Don't ellipsize unit names on output\n"
3920 " --fail When queueing a new job, fail if conflicting jobs are\n"
3922 " --ignore-dependencies\n"
3923 " When queueing a new job, ignore all its dependencies\n"
3924 " --kill-who=WHO Who to send signal to\n"
3925 " -s --signal=SIGNAL Which signal to send\n"
3926 " -H --host=[USER@]HOST\n"
3927 " Show information for remote host\n"
3928 " -P --privileged Acquire privileges before execution\n"
3929 " -q --quiet Suppress output\n"
3930 " --no-block Do not wait until operation finished\n"
3931 " --no-wall Don't send wall message before halt/power-off/reboot\n"
3932 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
3934 " --no-legend Do not print a legend (column headers and hints)\n"
3935 " --no-pager Do not pipe output into a pager\n"
3936 " --no-ask-password\n"
3937 " Do not ask for system passwords\n"
3938 " --order When generating graph for dot, show only order\n"
3939 " --require When generating graph for dot, show only requirement\n"
3940 " --system Connect to system manager\n"
3941 " --user Connect to user service manager\n"
3942 " --global Enable/disable unit files globally\n"
3943 " -f --force When enabling unit files, override existing symlinks\n"
3944 " When shutting down, execute action immediately\n"
3945 " --root=PATH Enable unit files in the specified root directory\n"
3946 " --runtime Enable unit files only temporarily until next reboot\n"
3947 " -n --lines=INTEGER Journal entries to show\n"
3948 " --follow Follow journal\n"
3949 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
3950 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
3952 " list-units List loaded units\n"
3953 " start [NAME...] Start (activate) one or more units\n"
3954 " stop [NAME...] Stop (deactivate) one or more units\n"
3955 " reload [NAME...] Reload one or more units\n"
3956 " restart [NAME...] Start or restart one or more units\n"
3957 " try-restart [NAME...] Restart one or more units if active\n"
3958 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
3959 " otherwise start or restart\n"
3960 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
3961 " otherwise restart if active\n"
3962 " isolate [NAME] Start one unit and stop all others\n"
3963 " kill [NAME...] Send signal to processes of a unit\n"
3964 " is-active [NAME...] Check whether units are active\n"
3965 " status [NAME...|PID...] Show runtime status of one or more units\n"
3966 " show [NAME...|JOB...] Show properties of one or more\n"
3967 " units/jobs or the manager\n"
3968 " help [NAME...|PID...] Show manual for one or more units\n"
3969 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
3971 " load [NAME...] Load one or more units\n\n"
3972 "Unit File Commands:\n"
3973 " list-unit-files List installed unit files\n"
3974 " enable [NAME...] Enable one or more unit files\n"
3975 " disable [NAME...] Disable one or more unit files\n"
3976 " reenable [NAME...] Reenable one or more unit files\n"
3977 " preset [NAME...] Enable/disable one or more unit files\n"
3978 " based on preset configuration\n"
3979 " mask [NAME...] Mask one or more units\n"
3980 " unmask [NAME...] Unmask one or more units\n"
3981 " link [PATH...] Link one or more units files into\n"
3982 " the search path\n"
3983 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
3985 " list-jobs List jobs\n"
3986 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
3987 "Status Commands:\n"
3988 " dump Dump server status\n"
3989 " dot Dump dependency graph for dot(1)\n\n"
3990 "Snapshot Commands:\n"
3991 " snapshot [NAME] Create a snapshot\n"
3992 " delete [NAME...] Remove one or more snapshots\n\n"
3993 "Environment Commands:\n"
3994 " show-environment Dump environment\n"
3995 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
3996 " unset-environment [NAME...] Unset one or more environment variables\n\n"
3997 "Manager Lifecycle Commands:\n"
3998 " daemon-reload Reload systemd manager configuration\n"
3999 " daemon-reexec Reexecute systemd manager\n\n"
4000 "System Commands:\n"
4001 " default Enter system default mode\n"
4002 " rescue Enter system rescue mode\n"
4003 " emergency Enter system emergency mode\n"
4004 " halt Shut down and halt the system\n"
4005 " poweroff Shut down and power-off the system\n"
4006 " reboot Shut down and reboot the system\n"
4007 " kexec Shut down and reboot the system with kexec\n"
4008 " exit Request user instance exit\n"
4009 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4010 " suspend Suspend the system\n"
4011 " hibernate Hibernate the system\n",
4012 program_invocation_short_name);
4017 static int halt_help(void) {
4019 printf("%s [OPTIONS...]\n\n"
4020 "%s the system.\n\n"
4021 " --help Show this help\n"
4022 " --halt Halt the machine\n"
4023 " -p --poweroff Switch off the machine\n"
4024 " --reboot Reboot the machine\n"
4025 " -f --force Force immediate halt/power-off/reboot\n"
4026 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4027 " -d --no-wtmp Don't write wtmp record\n"
4028 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4029 program_invocation_short_name,
4030 arg_action == ACTION_REBOOT ? "Reboot" :
4031 arg_action == ACTION_POWEROFF ? "Power off" :
4037 static int shutdown_help(void) {
4039 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4040 "Shut down the system.\n\n"
4041 " --help Show this help\n"
4042 " -H --halt Halt the machine\n"
4043 " -P --poweroff Power-off the machine\n"
4044 " -r --reboot Reboot the machine\n"
4045 " -h Equivalent to --poweroff, overridden by --halt\n"
4046 " -k Don't halt/power-off/reboot, just send warnings\n"
4047 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4048 " -c Cancel a pending shutdown\n",
4049 program_invocation_short_name);
4054 static int telinit_help(void) {
4056 printf("%s [OPTIONS...] {COMMAND}\n\n"
4057 "Send control commands to the init daemon.\n\n"
4058 " --help Show this help\n"
4059 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4061 " 0 Power-off the machine\n"
4062 " 6 Reboot the machine\n"
4063 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4064 " 1, s, S Enter rescue mode\n"
4065 " q, Q Reload init daemon configuration\n"
4066 " u, U Reexecute init daemon\n",
4067 program_invocation_short_name);
4072 static int runlevel_help(void) {
4074 printf("%s [OPTIONS...]\n\n"
4075 "Prints the previous and current runlevel of the init system.\n\n"
4076 " --help Show this help\n",
4077 program_invocation_short_name);
4082 static int systemctl_parse_argv(int argc, char *argv[]) {
4086 ARG_IGNORE_DEPENDENCIES,
4101 ARG_NO_ASK_PASSWORD,
4108 static const struct option options[] = {
4109 { "help", no_argument, NULL, 'h' },
4110 { "version", no_argument, NULL, ARG_VERSION },
4111 { "type", required_argument, NULL, 't' },
4112 { "property", required_argument, NULL, 'p' },
4113 { "all", no_argument, NULL, 'a' },
4114 { "failed", no_argument, NULL, ARG_FAILED },
4115 { "full", no_argument, NULL, ARG_FULL },
4116 { "fail", no_argument, NULL, ARG_FAIL },
4117 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4118 { "user", no_argument, NULL, ARG_USER },
4119 { "system", no_argument, NULL, ARG_SYSTEM },
4120 { "global", no_argument, NULL, ARG_GLOBAL },
4121 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4122 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4123 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4124 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4125 { "quiet", no_argument, NULL, 'q' },
4126 { "order", no_argument, NULL, ARG_ORDER },
4127 { "require", no_argument, NULL, ARG_REQUIRE },
4128 { "root", required_argument, NULL, ARG_ROOT },
4129 { "force", no_argument, NULL, ARG_FORCE },
4130 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4131 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4132 { "signal", required_argument, NULL, 's' },
4133 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4134 { "host", required_argument, NULL, 'H' },
4135 { "privileged",no_argument, NULL, 'P' },
4136 { "runtime", no_argument, NULL, ARG_RUNTIME },
4137 { "lines", required_argument, NULL, 'n' },
4138 { "follow", no_argument, NULL, ARG_FOLLOW },
4139 { "output", required_argument, NULL, 'o' },
4140 { NULL, 0, NULL, 0 }
4148 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4157 puts(PACKAGE_STRING);
4159 puts(SYSTEMD_FEATURES);
4163 if (unit_type_from_string(optarg) >= 0) {
4167 if (unit_load_state_from_string(optarg) >= 0) {
4168 arg_load_state = optarg;
4171 log_error("Unkown unit type or load state '%s'.",
4177 if (!(l = strv_append(arg_property, optarg)))
4180 strv_free(arg_property);
4183 /* If the user asked for a particular
4184 * property, show it to him, even if it is
4195 arg_job_mode = "fail";
4198 case ARG_IGNORE_DEPENDENCIES:
4199 arg_job_mode = "ignore-dependencies";
4203 arg_scope = UNIT_FILE_USER;
4207 arg_scope = UNIT_FILE_SYSTEM;
4211 arg_scope = UNIT_FILE_GLOBAL;
4215 arg_no_block = true;
4219 arg_no_legend = true;
4223 arg_no_pager = true;
4231 arg_dot = DOT_ORDER;
4235 arg_dot = DOT_REQUIRE;
4263 /* -f is short for both --follow and --force! */
4269 arg_no_reload = true;
4273 arg_kill_who = optarg;
4277 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4278 log_error("Failed to parse signal string %s.", optarg);
4283 case ARG_NO_ASK_PASSWORD:
4284 arg_ask_password = false;
4288 arg_transport = TRANSPORT_POLKIT;
4292 arg_transport = TRANSPORT_SSH;
4301 if (safe_atou(optarg, &arg_lines) < 0) {
4302 log_error("Failed to parse lines '%s'", optarg);
4308 arg_output = output_mode_from_string(optarg);
4309 if (arg_output < 0) {
4310 log_error("Unknown output '%s'.", optarg);
4319 log_error("Unknown option code '%c'.", c);
4324 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4325 log_error("Cannot access user instance remotely.");
4332 static int halt_parse_argv(int argc, char *argv[]) {
4341 static const struct option options[] = {
4342 { "help", no_argument, NULL, ARG_HELP },
4343 { "halt", no_argument, NULL, ARG_HALT },
4344 { "poweroff", no_argument, NULL, 'p' },
4345 { "reboot", no_argument, NULL, ARG_REBOOT },
4346 { "force", no_argument, NULL, 'f' },
4347 { "wtmp-only", no_argument, NULL, 'w' },
4348 { "no-wtmp", no_argument, NULL, 'd' },
4349 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4350 { NULL, 0, NULL, 0 }
4358 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4359 if (runlevel == '0' || runlevel == '6')
4362 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4370 arg_action = ACTION_HALT;
4374 if (arg_action != ACTION_REBOOT)
4375 arg_action = ACTION_POWEROFF;
4379 arg_action = ACTION_REBOOT;
4401 /* Compatibility nops */
4408 log_error("Unknown option code '%c'.", c);
4413 if (optind < argc) {
4414 log_error("Too many arguments.");
4421 static int parse_time_spec(const char *t, usec_t *_u) {
4425 if (streq(t, "now"))
4427 else if (!strchr(t, ':')) {
4430 if (safe_atou64(t, &u) < 0)
4433 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4442 hour = strtol(t, &e, 10);
4443 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4446 minute = strtol(e+1, &e, 10);
4447 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4450 n = now(CLOCK_REALTIME);
4451 s = (time_t) (n / USEC_PER_SEC);
4454 assert_se(localtime_r(&s, &tm));
4456 tm.tm_hour = (int) hour;
4457 tm.tm_min = (int) minute;
4460 assert_se(s = mktime(&tm));
4462 *_u = (usec_t) s * USEC_PER_SEC;
4465 *_u += USEC_PER_DAY;
4471 static int shutdown_parse_argv(int argc, char *argv[]) {
4478 static const struct option options[] = {
4479 { "help", no_argument, NULL, ARG_HELP },
4480 { "halt", no_argument, NULL, 'H' },
4481 { "poweroff", no_argument, NULL, 'P' },
4482 { "reboot", no_argument, NULL, 'r' },
4483 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4484 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4485 { NULL, 0, NULL, 0 }
4493 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4501 arg_action = ACTION_HALT;
4505 arg_action = ACTION_POWEROFF;
4510 arg_action = ACTION_KEXEC;
4512 arg_action = ACTION_REBOOT;
4516 arg_action = ACTION_KEXEC;
4520 if (arg_action != ACTION_HALT)
4521 arg_action = ACTION_POWEROFF;
4534 /* Compatibility nops */
4538 arg_action = ACTION_CANCEL_SHUTDOWN;
4545 log_error("Unknown option code '%c'.", c);
4550 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4551 r = parse_time_spec(argv[optind], &arg_when);
4553 log_error("Failed to parse time specification: %s", argv[optind]);
4557 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4559 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4560 /* No time argument for shutdown cancel */
4561 arg_wall = argv + optind;
4562 else if (argc > optind + 1)
4563 /* We skip the time argument */
4564 arg_wall = argv + optind + 1;
4571 static int telinit_parse_argv(int argc, char *argv[]) {
4578 static const struct option options[] = {
4579 { "help", no_argument, NULL, ARG_HELP },
4580 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4581 { NULL, 0, NULL, 0 }
4584 static const struct {
4588 { '0', ACTION_POWEROFF },
4589 { '6', ACTION_REBOOT },
4590 { '1', ACTION_RESCUE },
4591 { '2', ACTION_RUNLEVEL2 },
4592 { '3', ACTION_RUNLEVEL3 },
4593 { '4', ACTION_RUNLEVEL4 },
4594 { '5', ACTION_RUNLEVEL5 },
4595 { 's', ACTION_RESCUE },
4596 { 'S', ACTION_RESCUE },
4597 { 'q', ACTION_RELOAD },
4598 { 'Q', ACTION_RELOAD },
4599 { 'u', ACTION_REEXEC },
4600 { 'U', ACTION_REEXEC }
4609 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4624 log_error("Unknown option code '%c'.", c);
4629 if (optind >= argc) {
4634 if (optind + 1 < argc) {
4635 log_error("Too many arguments.");
4639 if (strlen(argv[optind]) != 1) {
4640 log_error("Expected single character argument.");
4644 for (i = 0; i < ELEMENTSOF(table); i++)
4645 if (table[i].from == argv[optind][0])
4648 if (i >= ELEMENTSOF(table)) {
4649 log_error("Unknown command '%s'.", argv[optind]);
4653 arg_action = table[i].to;
4660 static int runlevel_parse_argv(int argc, char *argv[]) {
4666 static const struct option options[] = {
4667 { "help", no_argument, NULL, ARG_HELP },
4668 { NULL, 0, NULL, 0 }
4676 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4687 log_error("Unknown option code '%c'.", c);
4692 if (optind < argc) {
4693 log_error("Too many arguments.");
4700 static int parse_argv(int argc, char *argv[]) {
4704 if (program_invocation_short_name) {
4706 if (strstr(program_invocation_short_name, "halt")) {
4707 arg_action = ACTION_HALT;
4708 return halt_parse_argv(argc, argv);
4709 } else if (strstr(program_invocation_short_name, "poweroff")) {
4710 arg_action = ACTION_POWEROFF;
4711 return halt_parse_argv(argc, argv);
4712 } else if (strstr(program_invocation_short_name, "reboot")) {
4714 arg_action = ACTION_KEXEC;
4716 arg_action = ACTION_REBOOT;
4717 return halt_parse_argv(argc, argv);
4718 } else if (strstr(program_invocation_short_name, "shutdown")) {
4719 arg_action = ACTION_POWEROFF;
4720 return shutdown_parse_argv(argc, argv);
4721 } else if (strstr(program_invocation_short_name, "init")) {
4723 if (sd_booted() > 0) {
4724 arg_action = ACTION_INVALID;
4725 return telinit_parse_argv(argc, argv);
4727 /* Hmm, so some other init system is
4728 * running, we need to forward this
4729 * request to it. For now we simply
4730 * guess that it is Upstart. */
4732 execv("/lib/upstart/telinit", argv);
4734 log_error("Couldn't find an alternative telinit implementation to spawn.");
4738 } else if (strstr(program_invocation_short_name, "runlevel")) {
4739 arg_action = ACTION_RUNLEVEL;
4740 return runlevel_parse_argv(argc, argv);
4744 arg_action = ACTION_SYSTEMCTL;
4745 return systemctl_parse_argv(argc, argv);
4748 static int action_to_runlevel(void) {
4750 static const char table[_ACTION_MAX] = {
4751 [ACTION_HALT] = '0',
4752 [ACTION_POWEROFF] = '0',
4753 [ACTION_REBOOT] = '6',
4754 [ACTION_RUNLEVEL2] = '2',
4755 [ACTION_RUNLEVEL3] = '3',
4756 [ACTION_RUNLEVEL4] = '4',
4757 [ACTION_RUNLEVEL5] = '5',
4758 [ACTION_RESCUE] = '1'
4761 assert(arg_action < _ACTION_MAX);
4763 return table[arg_action];
4766 static int talk_upstart(void) {
4767 DBusMessage *m = NULL, *reply = NULL;
4769 int previous, rl, r;
4771 env1_buf[] = "RUNLEVEL=X",
4772 env2_buf[] = "PREVLEVEL=X";
4773 char *env1 = env1_buf, *env2 = env2_buf;
4774 const char *emit = "runlevel";
4775 dbus_bool_t b_false = FALSE;
4776 DBusMessageIter iter, sub;
4777 DBusConnection *bus;
4779 dbus_error_init(&error);
4781 if (!(rl = action_to_runlevel()))
4784 if (utmp_get_runlevel(&previous, NULL) < 0)
4787 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4788 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4793 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4798 if ((r = bus_check_peercred(bus)) < 0) {
4799 log_error("Failed to verify owner of bus.");
4803 if (!(m = dbus_message_new_method_call(
4804 "com.ubuntu.Upstart",
4805 "/com/ubuntu/Upstart",
4806 "com.ubuntu.Upstart0_6",
4809 log_error("Could not allocate message.");
4814 dbus_message_iter_init_append(m, &iter);
4816 env1_buf[sizeof(env1_buf)-2] = rl;
4817 env2_buf[sizeof(env2_buf)-2] = previous;
4819 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4820 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4821 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4822 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4823 !dbus_message_iter_close_container(&iter, &sub) ||
4824 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4825 log_error("Could not append arguments to message.");
4830 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4832 if (bus_error_is_no_service(&error)) {
4837 log_error("Failed to issue method call: %s", bus_error_message(&error));
4846 dbus_message_unref(m);
4849 dbus_message_unref(reply);
4852 dbus_connection_flush(bus);
4853 dbus_connection_close(bus);
4854 dbus_connection_unref(bus);
4857 dbus_error_free(&error);
4862 static int talk_initctl(void) {
4863 struct init_request request;
4867 if (!(rl = action_to_runlevel()))
4871 request.magic = INIT_MAGIC;
4872 request.sleeptime = 0;
4873 request.cmd = INIT_CMD_RUNLVL;
4874 request.runlevel = rl;
4876 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4878 if (errno == ENOENT)
4881 log_error("Failed to open "INIT_FIFO": %m");
4886 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
4887 close_nointr_nofail(fd);
4890 log_error("Failed to write to "INIT_FIFO": %m");
4891 return errno ? -errno : -EIO;
4897 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
4899 static const struct {
4907 int (* const dispatch)(DBusConnection *bus, char **args);
4909 { "list-units", LESS, 1, list_units },
4910 { "list-unit-files", EQUAL, 1, list_unit_files },
4911 { "list-jobs", EQUAL, 1, list_jobs },
4912 { "clear-jobs", EQUAL, 1, daemon_reload },
4913 { "load", MORE, 2, load_unit },
4914 { "cancel", MORE, 2, cancel_job },
4915 { "start", MORE, 2, start_unit },
4916 { "stop", MORE, 2, start_unit },
4917 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4918 { "reload", MORE, 2, start_unit },
4919 { "restart", MORE, 2, start_unit },
4920 { "try-restart", MORE, 2, start_unit },
4921 { "reload-or-restart", MORE, 2, start_unit },
4922 { "reload-or-try-restart", MORE, 2, start_unit },
4923 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
4924 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4925 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
4926 { "isolate", EQUAL, 2, start_unit },
4927 { "kill", MORE, 2, kill_unit },
4928 { "is-active", MORE, 2, check_unit },
4929 { "check", MORE, 2, check_unit },
4930 { "show", MORE, 1, show },
4931 { "status", MORE, 2, show },
4932 { "help", MORE, 2, show },
4933 { "dump", EQUAL, 1, dump },
4934 { "dot", EQUAL, 1, dot },
4935 { "snapshot", LESS, 2, snapshot },
4936 { "delete", MORE, 2, delete_snapshot },
4937 { "daemon-reload", EQUAL, 1, daemon_reload },
4938 { "daemon-reexec", EQUAL, 1, daemon_reload },
4939 { "show-environment", EQUAL, 1, show_enviroment },
4940 { "set-environment", MORE, 2, set_environment },
4941 { "unset-environment", MORE, 2, set_environment },
4942 { "halt", EQUAL, 1, start_special },
4943 { "poweroff", EQUAL, 1, start_special },
4944 { "reboot", EQUAL, 1, start_special },
4945 { "kexec", EQUAL, 1, start_special },
4946 { "suspend", EQUAL, 1, start_special },
4947 { "hibernate", EQUAL, 1, start_special },
4948 { "default", EQUAL, 1, start_special },
4949 { "rescue", EQUAL, 1, start_special },
4950 { "emergency", EQUAL, 1, start_special },
4951 { "exit", EQUAL, 1, start_special },
4952 { "reset-failed", MORE, 1, reset_failed },
4953 { "enable", MORE, 2, enable_unit },
4954 { "disable", MORE, 2, enable_unit },
4955 { "is-enabled", MORE, 2, unit_is_enabled },
4956 { "reenable", MORE, 2, enable_unit },
4957 { "preset", MORE, 2, enable_unit },
4958 { "mask", MORE, 2, enable_unit },
4959 { "unmask", MORE, 2, enable_unit },
4960 { "link", MORE, 2, enable_unit },
4961 { "switch-root", MORE, 2, switch_root },
4971 left = argc - optind;
4974 /* Special rule: no arguments means "list-units" */
4977 if (streq(argv[optind], "help") && !argv[optind+1]) {
4978 log_error("This command expects one or more "
4979 "unit names. Did you mean --help?");
4983 for (i = 0; i < ELEMENTSOF(verbs); i++)
4984 if (streq(argv[optind], verbs[i].verb))
4987 if (i >= ELEMENTSOF(verbs)) {
4988 log_error("Unknown operation '%s'.", argv[optind]);
4993 switch (verbs[i].argc_cmp) {
4996 if (left != verbs[i].argc) {
4997 log_error("Invalid number of arguments.");
5004 if (left < verbs[i].argc) {
5005 log_error("Too few arguments.");
5012 if (left > verbs[i].argc) {
5013 log_error("Too many arguments.");
5020 assert_not_reached("Unknown comparison operator.");
5023 /* Require a bus connection for all operations but
5025 if (!streq(verbs[i].verb, "enable") &&
5026 !streq(verbs[i].verb, "disable") &&
5027 !streq(verbs[i].verb, "is-enabled") &&
5028 !streq(verbs[i].verb, "list-unit-files") &&
5029 !streq(verbs[i].verb, "reenable") &&
5030 !streq(verbs[i].verb, "preset") &&
5031 !streq(verbs[i].verb, "mask") &&
5032 !streq(verbs[i].verb, "unmask") &&
5033 !streq(verbs[i].verb, "link")) {
5035 if (running_in_chroot() > 0) {
5036 log_info("Running in chroot, ignoring request.");
5040 if (((!streq(verbs[i].verb, "reboot") &&
5041 !streq(verbs[i].verb, "halt") &&
5042 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5043 log_error("Failed to get D-Bus connection: %s",
5044 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5050 if (!bus && !avoid_bus()) {
5051 log_error("Failed to get D-Bus connection: %s",
5052 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5057 return verbs[i].dispatch(bus, argv + optind);
5060 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5062 struct msghdr msghdr;
5063 struct iovec iovec[2];
5064 union sockaddr_union sockaddr;
5065 struct sd_shutdown_command c;
5067 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5074 c.dry_run = dry_run;
5078 sockaddr.sa.sa_family = AF_UNIX;
5079 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5082 msghdr.msg_name = &sockaddr;
5083 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5086 iovec[0].iov_base = (char*) &c;
5087 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5089 if (isempty(message))
5090 msghdr.msg_iovlen = 1;
5092 iovec[1].iov_base = (char*) message;
5093 iovec[1].iov_len = strlen(message);
5094 msghdr.msg_iovlen = 2;
5096 msghdr.msg_iov = iovec;
5098 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5099 close_nointr_nofail(fd);
5103 close_nointr_nofail(fd);
5107 static int reload_with_fallback(DBusConnection *bus) {
5110 /* First, try systemd via D-Bus. */
5111 if (daemon_reload(bus, NULL) >= 0)
5115 /* Nothing else worked, so let's try signals */
5116 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5118 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5119 log_error("kill() failed: %m");
5126 static int start_with_fallback(DBusConnection *bus) {
5129 /* First, try systemd via D-Bus. */
5130 if (start_unit(bus, NULL) >= 0)
5134 /* Hmm, talking to systemd via D-Bus didn't work. Then
5135 * let's try to talk to Upstart via D-Bus. */
5136 if (talk_upstart() > 0)
5139 /* Nothing else worked, so let's try
5141 if (talk_initctl() > 0)
5144 log_error("Failed to talk to init daemon.");
5148 warn_wall(arg_action);
5152 static _noreturn_ void halt_now(enum action a) {
5154 /* Make sure C-A-D is handled by the kernel from this
5156 reboot(RB_ENABLE_CAD);
5161 log_info("Halting.");
5162 reboot(RB_HALT_SYSTEM);
5165 case ACTION_POWEROFF:
5166 log_info("Powering off.");
5167 reboot(RB_POWER_OFF);
5171 log_info("Rebooting.");
5172 reboot(RB_AUTOBOOT);
5176 assert_not_reached("Unknown halt action.");
5179 assert_not_reached("Uh? This shouldn't happen.");
5182 static int halt_main(DBusConnection *bus) {
5185 if (geteuid() != 0) {
5186 /* Try logind if we are a normal user and no special
5187 * mode applies. Maybe PolicyKit allows us to shutdown
5190 if (arg_when <= 0 &&
5193 (arg_action == ACTION_POWEROFF ||
5194 arg_action == ACTION_REBOOT)) {
5195 r = reboot_with_logind(bus, arg_action);
5200 log_error("Must be root.");
5207 m = strv_join(arg_wall, " ");
5208 r = send_shutdownd(arg_when,
5209 arg_action == ACTION_HALT ? 'H' :
5210 arg_action == ACTION_POWEROFF ? 'P' :
5211 arg_action == ACTION_KEXEC ? 'K' :
5219 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5221 char date[FORMAT_TIMESTAMP_MAX];
5223 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5224 format_timestamp(date, sizeof(date), arg_when));
5229 if (!arg_dry && !arg_force)
5230 return start_with_fallback(bus);
5233 if (sd_booted() > 0)
5234 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5236 r = utmp_put_shutdown();
5238 log_warning("Failed to write utmp record: %s", strerror(-r));
5245 halt_now(arg_action);
5246 /* We should never reach this. */
5250 static int runlevel_main(void) {
5251 int r, runlevel, previous;
5253 r = utmp_get_runlevel(&runlevel, &previous);
5260 previous <= 0 ? 'N' : previous,
5261 runlevel <= 0 ? 'N' : runlevel);
5266 int main(int argc, char*argv[]) {
5267 int r, retval = EXIT_FAILURE;
5268 DBusConnection *bus = NULL;
5271 dbus_error_init(&error);
5273 log_parse_environment();
5276 r = parse_argv(argc, argv);
5280 retval = EXIT_SUCCESS;
5284 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5285 * let's shortcut this */
5286 if (arg_action == ACTION_RUNLEVEL) {
5287 r = runlevel_main();
5288 retval = r < 0 ? EXIT_FAILURE : r;
5292 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5293 log_info("Running in chroot, ignoring request.");
5299 if (arg_transport == TRANSPORT_NORMAL)
5300 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5301 else if (arg_transport == TRANSPORT_POLKIT) {
5302 bus_connect_system_polkit(&bus, &error);
5303 private_bus = false;
5304 } else if (arg_transport == TRANSPORT_SSH) {
5305 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5306 private_bus = false;
5308 assert_not_reached("Uh, invalid transport...");
5311 switch (arg_action) {
5313 case ACTION_SYSTEMCTL:
5314 r = systemctl_main(bus, argc, argv, &error);
5318 case ACTION_POWEROFF:
5324 case ACTION_RUNLEVEL2:
5325 case ACTION_RUNLEVEL3:
5326 case ACTION_RUNLEVEL4:
5327 case ACTION_RUNLEVEL5:
5329 case ACTION_EMERGENCY:
5330 case ACTION_DEFAULT:
5331 r = start_with_fallback(bus);
5336 r = reload_with_fallback(bus);
5339 case ACTION_CANCEL_SHUTDOWN: {
5343 m = strv_join(arg_wall, " ");
5345 retval = EXIT_FAILURE;
5349 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5351 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5356 case ACTION_INVALID:
5357 case ACTION_RUNLEVEL:
5359 assert_not_reached("Unknown action");
5362 retval = r < 0 ? EXIT_FAILURE : r;
5366 dbus_connection_flush(bus);
5367 dbus_connection_close(bus);
5368 dbus_connection_unref(bus);
5371 dbus_error_free(&error);
5375 strv_free(arg_property);
5378 ask_password_agent_close();
5379 polkit_agent_close();