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"
67 static const char *arg_type = NULL;
68 static const char *arg_load_state = NULL;
69 static char **arg_property = NULL;
70 static bool arg_all = false;
71 static const char *arg_job_mode = "replace";
72 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
73 static bool arg_no_block = false;
74 static bool arg_no_legend = false;
75 static bool arg_no_pager = false;
76 static bool arg_no_wtmp = false;
77 static bool arg_no_sync = false;
78 static bool arg_no_wall = false;
79 static bool arg_no_reload = false;
80 static bool arg_dry = false;
81 static bool arg_quiet = false;
82 static bool arg_full = false;
83 static int arg_force = 0;
84 static bool arg_ask_password = true;
85 static bool arg_failed = false;
86 static bool arg_runtime = false;
87 static char **arg_wall = NULL;
88 static const char *arg_kill_who = NULL;
89 static int arg_signal = SIGTERM;
90 static const char *arg_root = NULL;
91 static usec_t arg_when = 0;
112 ACTION_CANCEL_SHUTDOWN,
114 } arg_action = ACTION_SYSTEMCTL;
120 static enum transport {
124 } arg_transport = TRANSPORT_NORMAL;
125 static const char *arg_host = NULL;
126 static bool arg_follow = false;
127 static unsigned arg_lines = 10;
128 static OutputMode arg_output = OUTPUT_SHORT;
130 static bool private_bus = false;
132 static int daemon_reload(DBusConnection *bus, char **args);
133 static void halt_now(enum action a);
135 static bool on_tty(void) {
138 /* Note that this is invoked relatively early, before we start
139 * the pager. That means the value we return reflects whether
140 * we originally were started on a tty, not if we currently
141 * are. But this is intended, since we want colour and so on
142 * when run in our own pager. */
144 if (_unlikely_(t < 0))
145 t = isatty(STDOUT_FILENO) > 0;
150 static void pager_open_if_enabled(void) {
152 /* Cache result before we open the pager */
161 static void ask_password_agent_open_if_enabled(void) {
163 /* Open the password agent as a child process if necessary */
165 if (!arg_ask_password)
168 if (arg_scope != UNIT_FILE_SYSTEM)
171 ask_password_agent_open();
175 static void polkit_agent_open_if_enabled(void) {
177 /* Open the polkit agent as a child process if necessary */
179 if (!arg_ask_password)
182 if (arg_scope != UNIT_FILE_SYSTEM)
189 static const char *ansi_highlight_red(bool b) {
194 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
197 static const char *ansi_highlight_green(bool b) {
202 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
205 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
208 if (!dbus_error_is_set(error))
211 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
212 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
213 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
214 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
215 return EXIT_NOPERMISSION;
217 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
218 return EXIT_NOTINSTALLED;
220 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
221 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
222 return EXIT_NOTIMPLEMENTED;
224 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
225 return EXIT_NOTCONFIGURED;
233 static void warn_wall(enum action a) {
234 static const char *table[_ACTION_MAX] = {
235 [ACTION_HALT] = "The system is going down for system halt NOW!",
236 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
237 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
238 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
239 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
240 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
241 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
250 p = strv_join(arg_wall, " ");
252 log_error("Failed to join strings.");
268 utmp_wall(table[a], NULL);
271 static bool avoid_bus(void) {
273 if (running_in_chroot() > 0)
276 if (sd_booted() <= 0)
279 if (!isempty(arg_root))
282 if (arg_scope == UNIT_FILE_GLOBAL)
290 const char *description;
291 const char *load_state;
292 const char *active_state;
293 const char *sub_state;
294 const char *following;
295 const char *unit_path;
297 const char *job_type;
298 const char *job_path;
301 static int compare_unit_info(const void *a, const void *b) {
303 const struct unit_info *u = a, *v = b;
305 d1 = strrchr(u->id, '.');
306 d2 = strrchr(v->id, '.');
311 if ((r = strcasecmp(d1, d2)) != 0)
315 return strcasecmp(u->id, v->id);
318 static bool output_show_unit(const struct unit_info *u) {
322 return streq(u->active_state, "failed");
324 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
325 streq(dot+1, arg_type))) &&
326 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
327 (arg_all || !(streq(u->active_state, "inactive")
328 || u->following[0]) || u->job_id > 0);
331 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
332 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
333 const struct unit_info *u;
335 max_id_len = sizeof("UNIT")-1;
336 active_len = sizeof("ACTIVE")-1;
337 sub_len = sizeof("SUB")-1;
338 job_len = sizeof("JOB")-1;
341 for (u = unit_infos; u < unit_infos + c; u++) {
342 if (!output_show_unit(u))
345 max_id_len = MAX(max_id_len, strlen(u->id));
346 active_len = MAX(active_len, strlen(u->active_state));
347 sub_len = MAX(sub_len, strlen(u->sub_state));
349 job_len = MAX(job_len, strlen(u->job_type));
354 id_len = MIN(max_id_len, 25);
355 basic_len = 5 + id_len + 6 + active_len + sub_len + job_len;
356 if (basic_len < (unsigned) columns()) {
357 unsigned extra_len, incr;
358 extra_len = columns() - basic_len;
359 /* Either UNIT already got 25, or is fully satisfied.
360 * Grant up to 25 to DESC now. */
361 incr = MIN(extra_len, 25);
364 /* split the remaining space between UNIT and DESC,
365 * but do not give UNIT more than it needs. */
367 incr = MIN(extra_len / 2, max_id_len - id_len);
369 desc_len += extra_len - incr;
375 if (!arg_no_legend) {
376 printf("%-*s %-6s %-*s %-*s %-*s ", id_len, "UNIT", "LOAD",
377 active_len, "ACTIVE", sub_len, "SUB", job_len, "JOB");
378 if (!arg_full && arg_no_pager)
379 printf("%.*s\n", desc_len, "DESCRIPTION");
381 printf("%s\n", "DESCRIPTION");
384 for (u = unit_infos; u < unit_infos + c; u++) {
386 const char *on_loaded, *off_loaded;
387 const char *on_active, *off_active;
389 if (!output_show_unit(u))
394 if (streq(u->load_state, "error")) {
395 on_loaded = ansi_highlight_red(true);
396 off_loaded = ansi_highlight_red(false);
398 on_loaded = off_loaded = "";
400 if (streq(u->active_state, "failed")) {
401 on_active = ansi_highlight_red(true);
402 off_active = ansi_highlight_red(false);
404 on_active = off_active = "";
406 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
408 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s ",
409 id_len, e ? e : u->id,
410 on_loaded, u->load_state, off_loaded,
411 on_active, active_len, u->active_state,
412 sub_len, u->sub_state, off_active,
413 job_len, u->job_id ? u->job_type : "");
414 if (!arg_full && arg_no_pager)
415 printf("%.*s\n", desc_len, u->description);
417 printf("%s\n", u->description);
422 if (!arg_no_legend) {
423 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
424 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
425 "SUB = The low-level unit activation state, values depend on unit type.\n"
426 "JOB = Pending job for the unit.\n");
429 printf("\n%u units listed.\n", n_shown);
431 printf("\n%u units listed. Pass --all to see inactive units, too.\n", n_shown);
435 static int list_units(DBusConnection *bus, char **args) {
436 DBusMessage *reply = NULL;
438 DBusMessageIter iter, sub, sub2;
439 unsigned c = 0, n_units = 0;
440 struct unit_info *unit_infos = NULL;
442 pager_open_if_enabled();
444 r = bus_method_call_with_reply (
446 "org.freedesktop.systemd1",
447 "/org/freedesktop/systemd1",
448 "org.freedesktop.systemd1.Manager",
456 if (!dbus_message_iter_init(reply, &iter) ||
457 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
458 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
459 log_error("Failed to parse reply.");
464 dbus_message_iter_recurse(&iter, &sub);
466 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
469 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
470 log_error("Failed to parse reply.");
478 n_units = MAX(2*c, 16);
479 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
482 log_error("Failed to allocate unit array.");
492 dbus_message_iter_recurse(&sub, &sub2);
494 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
495 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
496 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
497 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
498 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
499 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
500 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
501 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
502 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
503 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
504 log_error("Failed to parse reply.");
509 dbus_message_iter_next(&sub);
514 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
515 output_units_list(unit_infos, c);
520 dbus_message_unref(reply);
527 static int compare_unit_file_list(const void *a, const void *b) {
529 const UnitFileList *u = a, *v = b;
531 d1 = strrchr(u->path, '.');
532 d2 = strrchr(v->path, '.');
537 r = strcasecmp(d1, d2);
542 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
545 static bool output_show_unit_file(const UnitFileList *u) {
548 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
551 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
552 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
553 const UnitFileList *u;
555 max_id_len = sizeof("UNIT FILE")-1;
556 state_cols = sizeof("STATE")-1;
557 for (u = units; u < units + c; u++) {
558 if (!output_show_unit_file(u))
561 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
562 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
567 id_cols = MIN(max_id_len, 25);
568 basic_cols = 1 + id_cols + state_cols;
569 if (basic_cols < (unsigned) columns())
570 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
572 id_cols = max_id_len;
575 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
577 for (u = units; u < units + c; u++) {
579 const char *on, *off;
582 if (!output_show_unit_file(u))
587 if (u->state == UNIT_FILE_MASKED ||
588 u->state == UNIT_FILE_MASKED_RUNTIME ||
589 u->state == UNIT_FILE_DISABLED) {
590 on = ansi_highlight_red(true);
591 off = ansi_highlight_red(false);
592 } else if (u->state == UNIT_FILE_ENABLED) {
593 on = ansi_highlight_green(true);
594 off = ansi_highlight_green(false);
598 id = path_get_file_name(u->path);
600 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
602 printf("%-*s %s%-*s%s\n",
604 on, state_cols, unit_file_state_to_string(u->state), off);
610 printf("\n%u unit files listed.\n", n_shown);
613 static int list_unit_files(DBusConnection *bus, char **args) {
614 DBusMessage *reply = NULL;
616 DBusMessageIter iter, sub, sub2;
617 unsigned c = 0, n_units = 0;
618 UnitFileList *units = NULL;
620 pager_open_if_enabled();
627 h = hashmap_new(string_hash_func, string_compare_func);
631 r = unit_file_get_list(arg_scope, arg_root, h);
633 unit_file_list_free(h);
634 log_error("Failed to get unit file list: %s", strerror(-r));
638 n_units = hashmap_size(h);
639 units = new(UnitFileList, n_units);
641 unit_file_list_free(h);
645 HASHMAP_FOREACH(u, h, i) {
646 memcpy(units + c++, u, sizeof(UnitFileList));
652 r = bus_method_call_with_reply (
654 "org.freedesktop.systemd1",
655 "/org/freedesktop/systemd1",
656 "org.freedesktop.systemd1.Manager",
664 if (!dbus_message_iter_init(reply, &iter) ||
665 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
666 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
667 log_error("Failed to parse reply.");
672 dbus_message_iter_recurse(&iter, &sub);
674 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
678 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
679 log_error("Failed to parse reply.");
687 n_units = MAX(2*c, 16);
688 w = realloc(units, sizeof(struct UnitFileList) * n_units);
691 log_error("Failed to allocate unit array.");
701 dbus_message_iter_recurse(&sub, &sub2);
703 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
704 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
705 log_error("Failed to parse reply.");
710 u->state = unit_file_state_from_string(state);
712 dbus_message_iter_next(&sub);
718 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
719 output_unit_file_list(units, c);
726 dbus_message_unref(reply);
733 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
734 static const char * const colors[] = {
735 "Requires", "[color=\"black\"]",
736 "RequiresOverridable", "[color=\"black\"]",
737 "Requisite", "[color=\"darkblue\"]",
738 "RequisiteOverridable", "[color=\"darkblue\"]",
739 "Wants", "[color=\"grey66\"]",
740 "Conflicts", "[color=\"red\"]",
741 "ConflictedBy", "[color=\"red\"]",
742 "After", "[color=\"green\"]"
745 const char *c = NULL;
752 for (i = 0; i < ELEMENTSOF(colors); i += 2)
753 if (streq(colors[i], prop)) {
761 if (arg_dot != DOT_ALL)
762 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
765 switch (dbus_message_iter_get_arg_type(iter)) {
767 case DBUS_TYPE_ARRAY:
769 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
772 dbus_message_iter_recurse(iter, &sub);
774 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
777 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
778 dbus_message_iter_get_basic(&sub, &s);
779 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
781 dbus_message_iter_next(&sub);
791 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
792 DBusMessage *reply = NULL;
793 const char *interface = "org.freedesktop.systemd1.Unit";
795 DBusMessageIter iter, sub, sub2, sub3;
799 r = bus_method_call_with_reply (
801 "org.freedesktop.systemd1",
803 "org.freedesktop.DBus.Properties",
807 DBUS_TYPE_STRING, &interface,
812 if (!dbus_message_iter_init(reply, &iter) ||
813 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
814 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
815 log_error("Failed to parse reply.");
820 dbus_message_iter_recurse(&iter, &sub);
822 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
825 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
826 log_error("Failed to parse reply.");
831 dbus_message_iter_recurse(&sub, &sub2);
833 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
834 log_error("Failed to parse reply.");
839 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
840 log_error("Failed to parse reply.");
845 dbus_message_iter_recurse(&sub2, &sub3);
847 if (dot_one_property(name, prop, &sub3)) {
848 log_error("Failed to parse reply.");
853 dbus_message_iter_next(&sub);
858 dbus_message_unref(reply);
863 static int dot(DBusConnection *bus, char **args) {
864 DBusMessage *reply = NULL;
866 DBusMessageIter iter, sub, sub2;
868 r = bus_method_call_with_reply (
870 "org.freedesktop.systemd1",
871 "/org/freedesktop/systemd1",
872 "org.freedesktop.systemd1.Manager",
880 if (!dbus_message_iter_init(reply, &iter) ||
881 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
882 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
883 log_error("Failed to parse reply.");
888 printf("digraph systemd {\n");
890 dbus_message_iter_recurse(&iter, &sub);
891 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
892 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
894 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
895 log_error("Failed to parse reply.");
900 dbus_message_iter_recurse(&sub, &sub2);
902 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
903 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
904 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
905 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
906 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
907 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
908 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
909 log_error("Failed to parse reply.");
914 if ((r = dot_one(bus, id, unit_path)) < 0)
917 /* printf("\t\"%s\";\n", id); */
918 dbus_message_iter_next(&sub);
923 log_info(" Color legend: black = Requires\n"
924 " dark blue = Requisite\n"
925 " dark grey = Wants\n"
930 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
931 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
937 dbus_message_unref(reply);
942 static int list_jobs(DBusConnection *bus, char **args) {
943 DBusMessage *reply = NULL;
945 DBusMessageIter iter, sub, sub2;
948 pager_open_if_enabled();
950 r = bus_method_call_with_reply (
952 "org.freedesktop.systemd1",
953 "/org/freedesktop/systemd1",
954 "org.freedesktop.systemd1.Manager",
962 if (!dbus_message_iter_init(reply, &iter) ||
963 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
964 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
965 log_error("Failed to parse reply.");
970 dbus_message_iter_recurse(&iter, &sub);
973 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
975 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
976 const char *name, *type, *state, *job_path, *unit_path;
980 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
981 log_error("Failed to parse reply.");
986 dbus_message_iter_recurse(&sub, &sub2);
988 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
989 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
990 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
991 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
992 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
993 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
994 log_error("Failed to parse reply.");
999 e = arg_full ? NULL : ellipsize(name, 25, 33);
1000 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1005 dbus_message_iter_next(&sub);
1009 printf("\n%u jobs listed.\n", k);
1015 dbus_message_unref(reply);
1020 static int load_unit(DBusConnection *bus, char **args) {
1026 STRV_FOREACH(name, args+1) {
1027 n = unit_name_mangle(*name);
1028 r = bus_method_call_with_reply (
1030 "org.freedesktop.systemd1",
1031 "/org/freedesktop/systemd1",
1032 "org.freedesktop.systemd1.Manager",
1036 DBUS_TYPE_STRING, n ? &n : name,
1047 static int cancel_job(DBusConnection *bus, char **args) {
1048 DBusMessage *reply = NULL;
1054 if (strv_length(args) <= 1)
1055 return daemon_reload(bus, args);
1057 STRV_FOREACH(name, args+1) {
1061 r = safe_atou(*name, &id);
1063 log_error("Failed to parse job id: %s", strerror(-r));
1066 assert_cc(sizeof(uint32_t) == sizeof(id));
1068 r = bus_method_call_with_reply (
1070 "org.freedesktop.systemd1",
1071 "/org/freedesktop/systemd1",
1072 "org.freedesktop.systemd1.Manager",
1076 DBUS_TYPE_UINT32, &id,
1081 if (!dbus_message_get_args(reply, NULL,
1082 DBUS_TYPE_OBJECT_PATH, &path,
1083 DBUS_TYPE_INVALID)) {
1084 log_error("Failed to parse reply");
1085 dbus_message_unref(reply);
1089 dbus_message_unref(reply);
1091 r = bus_method_call_with_reply (
1093 "org.freedesktop.systemd1",
1095 "org.freedesktop.systemd1.Job",
1108 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1109 DBusMessage *reply = NULL;
1110 dbus_bool_t b = FALSE;
1111 DBusMessageIter iter, sub;
1113 *interface = "org.freedesktop.systemd1.Unit",
1114 *property = "NeedDaemonReload",
1119 /* We ignore all errors here, since this is used to show a warning only */
1121 n = unit_name_mangle(unit);
1122 r = bus_method_call_with_reply (
1124 "org.freedesktop.systemd1",
1125 "/org/freedesktop/systemd1",
1126 "org.freedesktop.systemd1.Manager",
1130 DBUS_TYPE_STRING, n ? (const char**) &n : &unit,
1136 if (!dbus_message_get_args(reply, NULL,
1137 DBUS_TYPE_OBJECT_PATH, &path,
1141 dbus_message_unref(reply);
1142 r = bus_method_call_with_reply (
1144 "org.freedesktop.systemd1",
1146 "org.freedesktop.DBus.Properties",
1150 DBUS_TYPE_STRING, &interface,
1151 DBUS_TYPE_STRING, &property,
1156 if (!dbus_message_iter_init(reply, &iter) ||
1157 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1160 dbus_message_iter_recurse(&iter, &sub);
1162 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1165 dbus_message_iter_get_basic(&sub, &b);
1169 dbus_message_unref(reply);
1174 typedef struct WaitData {
1179 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1187 dbus_error_init(&error);
1189 log_debug("Got D-Bus request: %s.%s() on %s",
1190 dbus_message_get_interface(message),
1191 dbus_message_get_member(message),
1192 dbus_message_get_path(message));
1194 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1195 log_error("Warning! D-Bus connection terminated.");
1196 dbus_connection_close(connection);
1198 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1200 const char *path, *result, *unit;
1201 dbus_bool_t success = true;
1203 if (dbus_message_get_args(message, &error,
1204 DBUS_TYPE_UINT32, &id,
1205 DBUS_TYPE_OBJECT_PATH, &path,
1206 DBUS_TYPE_STRING, &unit,
1207 DBUS_TYPE_STRING, &result,
1208 DBUS_TYPE_INVALID)) {
1211 p = set_remove(d->set, (char*) path);
1215 d->result = strdup(result);
1220 dbus_error_free(&error);
1221 if (dbus_message_get_args(message, &error,
1222 DBUS_TYPE_UINT32, &id,
1223 DBUS_TYPE_OBJECT_PATH, &path,
1224 DBUS_TYPE_STRING, &result,
1225 DBUS_TYPE_INVALID)) {
1228 /* Compatibility with older systemd versions <
1229 * 183 during upgrades. This should be dropped
1231 p = set_remove(d->set, (char*) path);
1235 d->result = strdup(result);
1240 dbus_error_free(&error);
1241 if (dbus_message_get_args(message, &error,
1242 DBUS_TYPE_UINT32, &id,
1243 DBUS_TYPE_OBJECT_PATH, &path,
1244 DBUS_TYPE_BOOLEAN, &success,
1245 DBUS_TYPE_INVALID)) {
1248 /* Compatibility with older systemd versions <
1249 * 19 during upgrades. This should be dropped
1252 p = set_remove(d->set, (char*) path);
1256 d->result = strdup("failed");
1262 log_error("Failed to parse message: %s", bus_error_message(&error));
1266 dbus_error_free(&error);
1267 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1270 static int enable_wait_for_jobs(DBusConnection *bus) {
1278 dbus_error_init(&error);
1279 dbus_bus_add_match(bus,
1281 "sender='org.freedesktop.systemd1',"
1282 "interface='org.freedesktop.systemd1.Manager',"
1283 "member='JobRemoved',"
1284 "path='/org/freedesktop/systemd1'",
1287 if (dbus_error_is_set(&error)) {
1288 log_error("Failed to add match: %s", bus_error_message(&error));
1289 dbus_error_free(&error);
1293 /* This is slightly dirty, since we don't undo the match registrations. */
1297 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1307 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL)) {
1308 log_error("Failed to add filter.");
1313 while (!set_isempty(s) &&
1314 dbus_connection_read_write_dispatch(bus, -1))
1317 if (!arg_quiet && d.result) {
1318 if (streq(d.result, "timeout"))
1319 log_error("Job timed out.");
1320 else if (streq(d.result, "canceled"))
1321 log_error("Job canceled.");
1322 else if (streq(d.result, "dependency"))
1323 log_error("A dependency job failed. See system journal for details.");
1324 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1325 log_error("Job failed. See system journal and 'systemctl status' for details.");
1328 if (streq_ptr(d.result, "timeout"))
1330 else if (streq_ptr(d.result, "canceled"))
1332 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1340 /* This is slightly dirty, since we don't undo the filter registration. */
1345 static int check_one_unit(DBusConnection *bus, char *name, bool quiet) {
1346 DBusMessage *reply = NULL;
1347 DBusMessageIter iter, sub;
1349 *interface = "org.freedesktop.systemd1.Unit",
1350 *property = "ActiveState";
1351 const char *path = NULL;
1358 n = unit_name_mangle(name);
1359 r = bus_method_call_with_reply (
1361 "org.freedesktop.systemd1",
1362 "/org/freedesktop/systemd1",
1363 "org.freedesktop.systemd1.Manager",
1367 DBUS_TYPE_STRING, n ? &n : &name,
1371 if ((r != -ENOMEM) && (!quiet))
1376 if (!dbus_message_get_args(reply, NULL,
1377 DBUS_TYPE_OBJECT_PATH, &path,
1378 DBUS_TYPE_INVALID)) {
1379 log_error("Failed to parse reply.");
1384 dbus_message_unref(reply);
1385 r = bus_method_call_with_reply (
1387 "org.freedesktop.systemd1",
1389 "org.freedesktop.DBus.Properties",
1393 DBUS_TYPE_STRING, &interface,
1394 DBUS_TYPE_STRING, &property,
1399 if (!dbus_message_iter_init(reply, &iter) ||
1400 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1401 log_error("Failed to parse reply.");
1406 dbus_message_iter_recurse(&iter, &sub);
1408 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1409 log_error("Failed to parse reply.");
1414 dbus_message_iter_get_basic(&sub, &state);
1419 if (streq(state, "active") || streq(state, "reloading"))
1422 r = 3; /* According to LSB: "program is not running" */
1426 dbus_message_unref(reply);
1431 static void check_triggering_units(
1432 DBusConnection *bus,
1433 const char *unit_name) {
1435 DBusMessage *reply = NULL;
1436 DBusMessageIter iter, sub;
1437 char *service_trigger = NULL;
1438 const char *interface = "org.freedesktop.systemd1.Unit",
1439 *triggered_by_property = "TriggeredBy";
1441 char *unit_path = NULL, *n = NULL;
1442 bool print_warning_label = true;
1445 n = unit_name_mangle(unit_name);
1446 unit_path = unit_dbus_path_from_name(n ? n : unit_name);
1449 log_error("Could not allocate dbus path.");
1453 r = bus_method_call_with_reply (
1455 "org.freedesktop.systemd1",
1457 "org.freedesktop.DBus.Properties",
1461 DBUS_TYPE_STRING, &interface,
1462 DBUS_TYPE_STRING, &triggered_by_property,
1467 if (!dbus_message_iter_init(reply, &iter) ||
1468 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1469 log_error("Failed to parse reply.");
1474 dbus_message_iter_recurse(&iter, &sub);
1475 dbus_message_iter_recurse(&sub, &iter);
1478 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1480 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1481 log_error("Failed to parse reply.");
1485 dbus_message_iter_get_basic(&sub, &service_trigger);
1487 r = check_one_unit(bus, service_trigger, true);
1491 if (print_warning_label) {
1492 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1493 print_warning_label = false;
1495 log_warning(" %s", service_trigger);
1498 dbus_message_iter_next(&sub);
1502 dbus_message_unref(reply);
1507 static int start_unit_one(
1508 DBusConnection *bus,
1515 DBusMessage *reply = NULL;
1524 assert(arg_no_block || s);
1526 n = unit_name_mangle(name);
1527 r = bus_method_call_with_reply (
1529 "org.freedesktop.systemd1",
1530 "/org/freedesktop/systemd1",
1531 "org.freedesktop.systemd1.Manager",
1535 DBUS_TYPE_STRING, n ? (const char **) &n : &name,
1536 DBUS_TYPE_STRING, &mode,
1540 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL ) {
1541 /* There's always a fallback possible for
1542 * legacy actions. */
1548 if (!dbus_message_get_args(reply, error,
1549 DBUS_TYPE_OBJECT_PATH, &path,
1550 DBUS_TYPE_INVALID)) {
1551 log_error("Failed to parse reply: %s", bus_error_message(error));
1556 if (need_daemon_reload(bus, name))
1557 log_warning("Warning: Unit file of created job changed on disk, 'systemctl %s daemon-reload' recommended.",
1558 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1560 if (!arg_no_block) {
1563 if (!(p = strdup(path))) {
1564 log_error("Failed to duplicate path.");
1569 if ((r = set_put(s, p)) < 0) {
1571 log_error("Failed to add path to set.");
1576 /* When stopping a unit warn if it can still be triggered by
1577 * another active unit (socket, path, timer) */
1578 if (!arg_quiet && streq(method, "StopUnit"))
1579 check_triggering_units(bus, name);
1585 dbus_message_unref(reply);
1590 static enum action verb_to_action(const char *verb) {
1591 if (streq(verb, "halt"))
1593 else if (streq(verb, "poweroff"))
1594 return ACTION_POWEROFF;
1595 else if (streq(verb, "reboot"))
1596 return ACTION_REBOOT;
1597 else if (streq(verb, "kexec"))
1598 return ACTION_KEXEC;
1599 else if (streq(verb, "rescue"))
1600 return ACTION_RESCUE;
1601 else if (streq(verb, "emergency"))
1602 return ACTION_EMERGENCY;
1603 else if (streq(verb, "default"))
1604 return ACTION_DEFAULT;
1605 else if (streq(verb, "exit"))
1607 else if (streq(verb, "suspend"))
1608 return ACTION_SUSPEND;
1609 else if (streq(verb, "hibernate"))
1610 return ACTION_HIBERNATE;
1612 return ACTION_INVALID;
1615 static int start_unit(DBusConnection *bus, char **args) {
1617 static const char * const table[_ACTION_MAX] = {
1618 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1619 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1620 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1621 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1622 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1623 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1624 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1625 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1626 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1627 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1628 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1629 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1630 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1631 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET
1635 const char *method, *mode, *one_name;
1640 dbus_error_init(&error);
1644 ask_password_agent_open_if_enabled();
1646 if (arg_action == ACTION_SYSTEMCTL) {
1648 streq(args[0], "stop") ||
1649 streq(args[0], "condstop") ? "StopUnit" :
1650 streq(args[0], "reload") ? "ReloadUnit" :
1651 streq(args[0], "restart") ? "RestartUnit" :
1653 streq(args[0], "try-restart") ||
1654 streq(args[0], "condrestart") ? "TryRestartUnit" :
1656 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1658 streq(args[0], "reload-or-try-restart") ||
1659 streq(args[0], "condreload") ||
1661 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1665 (streq(args[0], "isolate") ||
1666 streq(args[0], "rescue") ||
1667 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1669 one_name = table[verb_to_action(args[0])];
1672 assert(arg_action < ELEMENTSOF(table));
1673 assert(table[arg_action]);
1675 method = "StartUnit";
1677 mode = (arg_action == ACTION_EMERGENCY ||
1678 arg_action == ACTION_RESCUE ||
1679 arg_action == ACTION_RUNLEVEL2 ||
1680 arg_action == ACTION_RUNLEVEL3 ||
1681 arg_action == ACTION_RUNLEVEL4 ||
1682 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1684 one_name = table[arg_action];
1687 if (!arg_no_block) {
1688 if ((ret = enable_wait_for_jobs(bus)) < 0) {
1689 log_error("Could not watch jobs: %s", strerror(-ret));
1693 if (!(s = set_new(string_hash_func, string_compare_func))) {
1694 log_error("Failed to allocate set.");
1701 if ((ret = start_unit_one(bus, method, one_name, mode, &error, s)) <= 0)
1704 STRV_FOREACH(name, args+1)
1705 if ((r = start_unit_one(bus, method, *name, mode, &error, s)) != 0) {
1706 ret = translate_bus_error_to_exit_status(r, &error);
1707 dbus_error_free(&error);
1712 if ((r = wait_for_jobs(bus, s)) < 0) {
1721 dbus_error_free(&error);
1726 /* Ask systemd-logind, which might grant access to unprivileged users
1727 * through PolicyKit */
1728 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1731 dbus_bool_t interactive = true;
1733 polkit_agent_open_if_enabled();
1741 case ACTION_POWEROFF:
1742 method = "PowerOff";
1745 case ACTION_SUSPEND:
1749 case ACTION_HIBERNATE:
1750 method = "Hibernate";
1757 return bus_method_call_with_reply (
1759 "org.freedesktop.login1",
1760 "/org/freedesktop/login1",
1761 "org.freedesktop.login1.Manager",
1765 DBUS_TYPE_BOOLEAN, &interactive,
1772 static int start_special(DBusConnection *bus, char **args) {
1778 a = verb_to_action(args[0]);
1780 if (arg_force >= 2 && geteuid() != 0) {
1781 log_error("Must be root.");
1785 if (arg_force >= 2 &&
1786 (a == ACTION_HALT ||
1787 a == ACTION_POWEROFF ||
1788 a == ACTION_REBOOT))
1791 if (arg_force >= 1 &&
1792 (a == ACTION_HALT ||
1793 a == ACTION_POWEROFF ||
1794 a == ACTION_REBOOT ||
1795 a == ACTION_KEXEC ||
1797 return daemon_reload(bus, args);
1799 /* first try logind, to allow authentication with polkit */
1800 if (geteuid() != 0 &&
1801 (a == ACTION_POWEROFF ||
1802 a == ACTION_REBOOT ||
1803 a == ACTION_SUSPEND ||
1804 a == ACTION_HIBERNATE)) {
1805 r = reboot_with_logind(bus, a);
1810 r = start_unit(bus, args);
1817 static int check_unit(DBusConnection *bus, char **args) {
1819 int r = 3; /* According to LSB: "program is not running" */
1824 STRV_FOREACH(name, args+1) {
1825 int state = check_one_unit(bus, *name, arg_quiet);
1835 static int kill_unit(DBusConnection *bus, char **args) {
1842 arg_kill_who = "all";
1844 STRV_FOREACH(name, args+1) {
1845 n = unit_name_mangle(*name);
1846 r = bus_method_call_with_reply (
1848 "org.freedesktop.systemd1",
1849 "/org/freedesktop/systemd1",
1850 "org.freedesktop.systemd1.Manager",
1854 DBUS_TYPE_STRING, n ? &n : name,
1855 DBUS_TYPE_STRING, &arg_kill_who,
1856 DBUS_TYPE_INT32, &arg_signal,
1865 typedef struct ExecStatusInfo {
1873 usec_t start_timestamp;
1874 usec_t exit_timestamp;
1879 LIST_FIELDS(struct ExecStatusInfo, exec);
1882 static void exec_status_info_free(ExecStatusInfo *i) {
1891 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
1892 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
1893 DBusMessageIter sub2, sub3;
1897 int32_t code, status;
1903 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
1906 dbus_message_iter_recurse(sub, &sub2);
1908 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
1911 if (!(i->path = strdup(path)))
1914 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
1915 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
1919 dbus_message_iter_recurse(&sub2, &sub3);
1920 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1921 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1922 dbus_message_iter_next(&sub3);
1927 if (!(i->argv = new0(char*, n+1)))
1931 dbus_message_iter_recurse(&sub2, &sub3);
1932 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
1935 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
1936 dbus_message_iter_get_basic(&sub3, &s);
1937 dbus_message_iter_next(&sub3);
1939 if (!(i->argv[n++] = strdup(s)))
1943 if (!dbus_message_iter_next(&sub2) ||
1944 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
1945 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
1946 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
1947 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
1948 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
1949 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
1950 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
1951 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
1955 i->start_timestamp = (usec_t) start_timestamp;
1956 i->exit_timestamp = (usec_t) exit_timestamp;
1957 i->pid = (pid_t) pid;
1964 typedef struct UnitStatusInfo {
1966 const char *load_state;
1967 const char *active_state;
1968 const char *sub_state;
1969 const char *unit_file_state;
1971 const char *description;
1972 const char *following;
1974 char **documentation;
1976 const char *fragment_path;
1977 const char *source_path;
1978 const char *default_control_group;
1980 const char *load_error;
1983 usec_t inactive_exit_timestamp;
1984 usec_t inactive_exit_timestamp_monotonic;
1985 usec_t active_enter_timestamp;
1986 usec_t active_exit_timestamp;
1987 usec_t inactive_enter_timestamp;
1989 bool need_daemon_reload;
1994 const char *status_text;
1997 usec_t start_timestamp;
1998 usec_t exit_timestamp;
2000 int exit_code, exit_status;
2002 usec_t condition_timestamp;
2003 bool condition_result;
2006 unsigned n_accepted;
2007 unsigned n_connections;
2011 const char *sysfs_path;
2013 /* Mount, Automount */
2019 LIST_HEAD(ExecStatusInfo, exec);
2022 static void print_status_info(UnitStatusInfo *i) {
2024 const char *on, *off, *ss;
2026 char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
2027 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2032 /* This shows pretty information about a unit. See
2033 * print_property() for a low-level property printer */
2035 printf("%s", strna(i->id));
2037 if (i->description && !streq_ptr(i->id, i->description))
2038 printf(" - %s", i->description);
2043 printf("\t Follow: unit currently follows state of %s\n", i->following);
2045 if (streq_ptr(i->load_state, "error")) {
2046 on = ansi_highlight_red(true);
2047 off = ansi_highlight_red(false);
2051 path = i->source_path ? i->source_path : i->fragment_path;
2054 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2055 else if (path && i->unit_file_state)
2056 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2058 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2060 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2062 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2064 if (streq_ptr(i->active_state, "failed")) {
2065 on = ansi_highlight_red(true);
2066 off = ansi_highlight_red(false);
2067 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2068 on = ansi_highlight_green(true);
2069 off = ansi_highlight_green(false);
2074 printf("\t Active: %s%s (%s)%s",
2076 strna(i->active_state),
2080 printf("\t Active: %s%s%s",
2082 strna(i->active_state),
2085 if (!isempty(i->result) && !streq(i->result, "success"))
2086 printf(" (Result: %s)", i->result);
2088 timestamp = (streq_ptr(i->active_state, "active") ||
2089 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2090 (streq_ptr(i->active_state, "inactive") ||
2091 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2092 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2093 i->active_exit_timestamp;
2095 s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
2096 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2099 printf(" since %s; %s\n", s2, s1);
2101 printf(" since %s\n", s2);
2105 if (!i->condition_result && i->condition_timestamp > 0) {
2106 s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
2107 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2110 printf("\t start condition failed at %s; %s\n", s2, s1);
2112 printf("\t start condition failed at %s\n", s2);
2116 printf("\t Device: %s\n", i->sysfs_path);
2118 printf("\t Where: %s\n", i->where);
2120 printf("\t What: %s\n", i->what);
2122 if (!strv_isempty(i->documentation)) {
2126 STRV_FOREACH(t, i->documentation) {
2128 printf("\t Docs: %s\n", *t);
2131 printf("\t %s\n", *t);
2136 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2138 LIST_FOREACH(exec, p, i->exec) {
2142 /* Only show exited processes here */
2146 t = strv_join(p->argv, " ");
2147 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2150 good = is_clean_exit_lsb(p->code, p->status);
2152 on = ansi_highlight_red(true);
2153 off = ansi_highlight_red(false);
2157 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2159 if (p->code == CLD_EXITED) {
2162 printf("status=%i", p->status);
2164 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2169 printf("signal=%s", signal_to_string(p->status));
2171 printf(")%s\n", off);
2173 if (i->main_pid == p->pid &&
2174 i->start_timestamp == p->start_timestamp &&
2175 i->exit_timestamp == p->start_timestamp)
2176 /* Let's not show this twice */
2179 if (p->pid == i->control_pid)
2183 if (i->main_pid > 0 || i->control_pid > 0) {
2186 if (i->main_pid > 0) {
2187 printf("Main PID: %u", (unsigned) i->main_pid);
2191 get_process_comm(i->main_pid, &t);
2196 } else if (i->exit_code > 0) {
2197 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2199 if (i->exit_code == CLD_EXITED) {
2202 printf("status=%i", i->exit_status);
2204 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2209 printf("signal=%s", signal_to_string(i->exit_status));
2214 if (i->main_pid > 0 && i->control_pid > 0)
2217 if (i->control_pid > 0) {
2220 printf(" Control: %u", (unsigned) i->control_pid);
2222 get_process_comm(i->control_pid, &t);
2233 printf("\t Status: \"%s\"\n", i->status_text);
2235 if (i->default_control_group) {
2238 printf("\t CGroup: %s\n", i->default_control_group);
2240 if (arg_transport != TRANSPORT_SSH) {
2250 if (i->main_pid > 0)
2251 extra[k++] = i->main_pid;
2253 if (i->control_pid > 0)
2254 extra[k++] = i->control_pid;
2256 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2260 if (i->id && arg_transport != TRANSPORT_SSH) {
2262 arg_lines * OUTPUT_SHOW_ALL |
2263 arg_follow * OUTPUT_FOLLOW |
2264 !arg_quiet * OUTPUT_WARN_CUTOFF |
2265 on_tty() * OUTPUT_COLOR;
2268 show_journal_by_unit(i->id, arg_output, 0,
2269 i->inactive_exit_timestamp_monotonic,
2273 if (i->need_daemon_reload)
2274 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2275 ansi_highlight_red(true),
2276 ansi_highlight_red(false),
2277 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2280 static void show_unit_help(UnitStatusInfo *i) {
2285 if (!i->documentation) {
2286 log_info("Documentation for %s not known.", i->id);
2290 STRV_FOREACH(p, i->documentation) {
2292 if (startswith(*p, "man:")) {
2295 char *page = NULL, *section = NULL;
2296 const char *args[4] = { "man", NULL, NULL, NULL };
2301 if ((*p)[k-1] == ')')
2302 e = strrchr(*p, '(');
2305 page = strndup((*p) + 4, e - *p - 4);
2311 section = strndup(e + 1, *p + k - e - 2);
2325 log_error("Failed to fork: %m");
2333 execvp(args[0], (char**) args);
2334 log_error("Failed to execute man: %m");
2335 _exit(EXIT_FAILURE);
2341 wait_for_terminate(pid, NULL);
2343 log_info("Can't show: %s", *p);
2347 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2353 switch (dbus_message_iter_get_arg_type(iter)) {
2355 case DBUS_TYPE_STRING: {
2358 dbus_message_iter_get_basic(iter, &s);
2361 if (streq(name, "Id"))
2363 else if (streq(name, "LoadState"))
2365 else if (streq(name, "ActiveState"))
2366 i->active_state = s;
2367 else if (streq(name, "SubState"))
2369 else if (streq(name, "Description"))
2371 else if (streq(name, "FragmentPath"))
2372 i->fragment_path = s;
2373 else if (streq(name, "SourcePath"))
2375 else if (streq(name, "DefaultControlGroup"))
2376 i->default_control_group = s;
2377 else if (streq(name, "StatusText"))
2379 else if (streq(name, "SysFSPath"))
2381 else if (streq(name, "Where"))
2383 else if (streq(name, "What"))
2385 else if (streq(name, "Following"))
2387 else if (streq(name, "UnitFileState"))
2388 i->unit_file_state = s;
2389 else if (streq(name, "Result"))
2396 case DBUS_TYPE_BOOLEAN: {
2399 dbus_message_iter_get_basic(iter, &b);
2401 if (streq(name, "Accept"))
2403 else if (streq(name, "NeedDaemonReload"))
2404 i->need_daemon_reload = b;
2405 else if (streq(name, "ConditionResult"))
2406 i->condition_result = b;
2411 case DBUS_TYPE_UINT32: {
2414 dbus_message_iter_get_basic(iter, &u);
2416 if (streq(name, "MainPID")) {
2418 i->main_pid = (pid_t) u;
2421 } else if (streq(name, "ControlPID"))
2422 i->control_pid = (pid_t) u;
2423 else if (streq(name, "ExecMainPID")) {
2425 i->main_pid = (pid_t) u;
2426 } else if (streq(name, "NAccepted"))
2428 else if (streq(name, "NConnections"))
2429 i->n_connections = u;
2434 case DBUS_TYPE_INT32: {
2437 dbus_message_iter_get_basic(iter, &j);
2439 if (streq(name, "ExecMainCode"))
2440 i->exit_code = (int) j;
2441 else if (streq(name, "ExecMainStatus"))
2442 i->exit_status = (int) j;
2447 case DBUS_TYPE_UINT64: {
2450 dbus_message_iter_get_basic(iter, &u);
2452 if (streq(name, "ExecMainStartTimestamp"))
2453 i->start_timestamp = (usec_t) u;
2454 else if (streq(name, "ExecMainExitTimestamp"))
2455 i->exit_timestamp = (usec_t) u;
2456 else if (streq(name, "ActiveEnterTimestamp"))
2457 i->active_enter_timestamp = (usec_t) u;
2458 else if (streq(name, "InactiveEnterTimestamp"))
2459 i->inactive_enter_timestamp = (usec_t) u;
2460 else if (streq(name, "InactiveExitTimestamp"))
2461 i->inactive_exit_timestamp = (usec_t) u;
2462 else if (streq(name, "InactiveExitTimestampMonotonic"))
2463 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2464 else if (streq(name, "ActiveExitTimestamp"))
2465 i->active_exit_timestamp = (usec_t) u;
2466 else if (streq(name, "ConditionTimestamp"))
2467 i->condition_timestamp = (usec_t) u;
2472 case DBUS_TYPE_ARRAY: {
2474 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2475 startswith(name, "Exec")) {
2476 DBusMessageIter sub;
2478 dbus_message_iter_recurse(iter, &sub);
2479 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2480 ExecStatusInfo *info;
2483 if (!(info = new0(ExecStatusInfo, 1)))
2486 if (!(info->name = strdup(name))) {
2491 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2496 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2498 dbus_message_iter_next(&sub);
2500 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2501 streq(name, "Documentation")) {
2503 DBusMessageIter sub;
2505 dbus_message_iter_recurse(iter, &sub);
2506 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2510 dbus_message_iter_get_basic(&sub, &s);
2512 l = strv_append(i->documentation, s);
2516 strv_free(i->documentation);
2517 i->documentation = l;
2519 dbus_message_iter_next(&sub);
2526 case DBUS_TYPE_STRUCT: {
2528 if (streq(name, "LoadError")) {
2529 DBusMessageIter sub;
2530 const char *n, *message;
2533 dbus_message_iter_recurse(iter, &sub);
2535 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2539 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2543 if (!isempty(message))
2544 i->load_error = message;
2554 static int print_property(const char *name, DBusMessageIter *iter) {
2558 /* This is a low-level property printer, see
2559 * print_status_info() for the nicer output */
2561 if (arg_property && !strv_find(arg_property, name))
2564 switch (dbus_message_iter_get_arg_type(iter)) {
2566 case DBUS_TYPE_STRUCT: {
2567 DBusMessageIter sub;
2568 dbus_message_iter_recurse(iter, &sub);
2570 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2573 dbus_message_iter_get_basic(&sub, &u);
2576 printf("%s=%u\n", name, (unsigned) u);
2578 printf("%s=\n", name);
2581 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2584 dbus_message_iter_get_basic(&sub, &s);
2586 if (arg_all || s[0])
2587 printf("%s=%s\n", name, s);
2590 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2591 const char *a = NULL, *b = NULL;
2593 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2594 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2596 if (arg_all || !isempty(a) || !isempty(b))
2597 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2605 case DBUS_TYPE_ARRAY:
2607 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2608 DBusMessageIter sub, sub2;
2610 dbus_message_iter_recurse(iter, &sub);
2611 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2615 dbus_message_iter_recurse(&sub, &sub2);
2617 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2618 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2619 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2621 dbus_message_iter_next(&sub);
2626 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2627 DBusMessageIter sub, sub2;
2629 dbus_message_iter_recurse(iter, &sub);
2630 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2631 const char *type, *path;
2633 dbus_message_iter_recurse(&sub, &sub2);
2635 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2636 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2637 printf("%s=%s\n", type, path);
2639 dbus_message_iter_next(&sub);
2644 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2645 DBusMessageIter sub, sub2;
2647 dbus_message_iter_recurse(iter, &sub);
2648 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2650 uint64_t value, next_elapse;
2652 dbus_message_iter_recurse(&sub, &sub2);
2654 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2655 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2656 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2657 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2659 printf("%s={ value=%s ; next_elapse=%s }\n",
2661 format_timespan(timespan1, sizeof(timespan1), value),
2662 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2665 dbus_message_iter_next(&sub);
2670 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2671 DBusMessageIter sub, sub2;
2673 dbus_message_iter_recurse(iter, &sub);
2674 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2675 const char *controller, *attr, *value;
2677 dbus_message_iter_recurse(&sub, &sub2);
2679 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2680 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2681 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2683 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2689 dbus_message_iter_next(&sub);
2694 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2695 DBusMessageIter sub;
2697 dbus_message_iter_recurse(iter, &sub);
2698 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2699 ExecStatusInfo info;
2702 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2703 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2706 t = strv_join(info.argv, " ");
2708 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2712 yes_no(info.ignore),
2713 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2714 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2715 (unsigned) info. pid,
2716 sigchld_code_to_string(info.code),
2718 info.code == CLD_EXITED ? "" : "/",
2719 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2725 strv_free(info.argv);
2727 dbus_message_iter_next(&sub);
2736 if (generic_print_property(name, iter, arg_all) > 0)
2740 printf("%s=[unprintable]\n", name);
2745 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2746 DBusMessage *reply = NULL;
2747 const char *interface = "";
2749 DBusMessageIter iter, sub, sub2, sub3;
2750 UnitStatusInfo info;
2758 r = bus_method_call_with_reply (
2760 "org.freedesktop.systemd1",
2762 "org.freedesktop.DBus.Properties",
2766 DBUS_TYPE_STRING, &interface,
2771 if (!dbus_message_iter_init(reply, &iter) ||
2772 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2773 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2774 log_error("Failed to parse reply.");
2779 dbus_message_iter_recurse(&iter, &sub);
2786 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2789 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2790 log_error("Failed to parse reply.");
2795 dbus_message_iter_recurse(&sub, &sub2);
2797 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2798 log_error("Failed to parse reply.");
2803 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2804 log_error("Failed to parse reply.");
2809 dbus_message_iter_recurse(&sub2, &sub3);
2811 if (show_properties)
2812 r = print_property(name, &sub3);
2814 r = status_property(name, &sub3, &info);
2817 log_error("Failed to parse reply.");
2822 dbus_message_iter_next(&sub);
2827 if (!show_properties) {
2828 if (streq(verb, "help"))
2829 show_unit_help(&info);
2831 print_status_info(&info);
2834 strv_free(info.documentation);
2836 if (!streq_ptr(info.active_state, "active") &&
2837 !streq_ptr(info.active_state, "reloading") &&
2838 streq(verb, "status"))
2839 /* According to LSB: "program not running" */
2842 while ((p = info.exec)) {
2843 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2844 exec_status_info_free(p);
2849 dbus_message_unref(reply);
2854 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
2855 DBusMessage *reply = NULL;
2856 const char *path = NULL;
2860 dbus_error_init(&error);
2862 r = bus_method_call_with_reply (
2864 "org.freedesktop.systemd1",
2865 "/org/freedesktop/systemd1",
2866 "org.freedesktop.systemd1.Manager",
2870 DBUS_TYPE_UINT32, &pid,
2875 if (!dbus_message_get_args(reply, &error,
2876 DBUS_TYPE_OBJECT_PATH, &path,
2877 DBUS_TYPE_INVALID)) {
2878 log_error("Failed to parse reply: %s", bus_error_message(&error));
2883 r = show_one(verb, bus, path, false, new_line);
2887 dbus_message_unref(reply);
2889 dbus_error_free(&error);
2894 static int show(DBusConnection *bus, char **args) {
2896 bool show_properties, new_line = false;
2902 show_properties = streq(args[0], "show");
2904 if (show_properties)
2905 pager_open_if_enabled();
2907 if (show_properties && strv_length(args) <= 1) {
2908 /* If not argument is specified inspect the manager
2911 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
2914 STRV_FOREACH(name, args+1) {
2917 if (safe_atou32(*name, &id) < 0) {
2919 /* Interpret as unit name */
2921 n = unit_name_mangle(*name);
2922 p = unit_dbus_path_from_name(n ? n : *name);
2927 r = show_one(args[0], bus, p, show_properties, &new_line);
2933 } else if (show_properties) {
2935 /* Interpret as job id */
2938 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
2941 r = show_one(args[0], bus, p, show_properties, &new_line);
2949 /* Interpret as PID */
2951 r = show_one_by_pid(args[0], bus, id, &new_line);
2960 static int dump(DBusConnection *bus, char **args) {
2961 DBusMessage *reply = NULL;
2966 dbus_error_init(&error);
2968 pager_open_if_enabled();
2970 r = bus_method_call_with_reply (
2972 "org.freedesktop.systemd1",
2973 "/org/freedesktop/systemd1",
2974 "org.freedesktop.systemd1.Manager",
2982 if (!dbus_message_get_args(reply, &error,
2983 DBUS_TYPE_STRING, &text,
2984 DBUS_TYPE_INVALID)) {
2985 log_error("Failed to parse reply: %s", bus_error_message(&error));
2990 fputs(text, stdout);
2994 dbus_message_unref(reply);
2996 dbus_error_free(&error);
3001 static int snapshot(DBusConnection *bus, char **args) {
3002 DBusMessage *reply = NULL;
3005 dbus_bool_t cleanup = FALSE;
3006 DBusMessageIter iter, sub;
3008 *name = "", *path, *id,
3009 *interface = "org.freedesktop.systemd1.Unit",
3013 dbus_error_init(&error);
3015 if (strv_length(args) > 1)
3018 n = unit_name_mangle(name);
3019 r = bus_method_call_with_reply (
3021 "org.freedesktop.systemd1",
3022 "/org/freedesktop/systemd1",
3023 "org.freedesktop.systemd1.Manager",
3027 DBUS_TYPE_STRING, n ? (const char**) &n : &name,
3028 DBUS_TYPE_BOOLEAN, &cleanup,
3034 if (!dbus_message_get_args(reply, &error,
3035 DBUS_TYPE_OBJECT_PATH, &path,
3036 DBUS_TYPE_INVALID)) {
3037 log_error("Failed to parse reply: %s", bus_error_message(&error));
3042 dbus_message_unref(reply);
3043 r = bus_method_call_with_reply (
3045 "org.freedesktop.systemd1",
3047 "org.freedesktop.DBus.Properties",
3051 DBUS_TYPE_STRING, &interface,
3052 DBUS_TYPE_STRING, &property,
3057 if (!dbus_message_iter_init(reply, &iter) ||
3058 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3059 log_error("Failed to parse reply.");
3064 dbus_message_iter_recurse(&iter, &sub);
3066 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3067 log_error("Failed to parse reply.");
3072 dbus_message_iter_get_basic(&sub, &id);
3079 dbus_message_unref(reply);
3081 dbus_error_free(&error);
3086 static int delete_snapshot(DBusConnection *bus, char **args) {
3087 DBusMessage *reply = NULL;
3094 dbus_error_init(&error);
3096 STRV_FOREACH(name, args+1) {
3097 const char *path = NULL;
3100 n = unit_name_mangle(*name);
3101 r = bus_method_call_with_reply (
3103 "org.freedesktop.systemd1",
3104 "/org/freedesktop/systemd1",
3105 "org.freedesktop.systemd1.Manager",
3109 DBUS_TYPE_STRING, n ? &n : name,
3115 if (!dbus_message_get_args(reply, &error,
3116 DBUS_TYPE_OBJECT_PATH, &path,
3117 DBUS_TYPE_INVALID)) {
3118 log_error("Failed to parse reply: %s", bus_error_message(&error));
3120 dbus_message_unref(reply);
3121 dbus_error_free(&error);
3124 dbus_message_unref(reply);
3126 r = bus_method_call_with_reply (
3128 "org.freedesktop.systemd1",
3130 "org.freedesktop.systemd1.Snapshot",
3143 static int daemon_reload(DBusConnection *bus, char **args) {
3147 if (arg_action == ACTION_RELOAD)
3149 else if (arg_action == ACTION_REEXEC)
3150 method = "Reexecute";
3152 assert(arg_action == ACTION_SYSTEMCTL);
3155 streq(args[0], "clear-jobs") ||
3156 streq(args[0], "cancel") ? "ClearJobs" :
3157 streq(args[0], "daemon-reexec") ? "Reexecute" :
3158 streq(args[0], "reset-failed") ? "ResetFailed" :
3159 streq(args[0], "halt") ? "Halt" :
3160 streq(args[0], "poweroff") ? "PowerOff" :
3161 streq(args[0], "reboot") ? "Reboot" :
3162 streq(args[0], "kexec") ? "KExec" :
3163 streq(args[0], "exit") ? "Exit" :
3164 /* "daemon-reload" */ "Reload";
3167 r = bus_method_call_with_reply (
3169 "org.freedesktop.systemd1",
3170 "/org/freedesktop/systemd1",
3171 "org.freedesktop.systemd1.Manager",
3177 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3178 /* There's always a fallback possible for
3179 * legacy actions. */
3181 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3182 /* On reexecution, we expect a disconnect, not
3189 static int reset_failed(DBusConnection *bus, char **args) {
3193 if (strv_length(args) <= 1)
3194 return daemon_reload(bus, args);
3196 STRV_FOREACH(name, args+1) {
3197 n = unit_name_mangle(*name);
3198 r = bus_method_call_with_reply (
3200 "org.freedesktop.systemd1",
3201 "/org/freedesktop/systemd1",
3202 "org.freedesktop.systemd1.Manager",
3206 DBUS_TYPE_STRING, n ? &n : name,
3217 static int show_enviroment(DBusConnection *bus, char **args) {
3218 DBusMessage *reply = NULL;
3219 DBusMessageIter iter, sub, sub2;
3222 *interface = "org.freedesktop.systemd1.Manager",
3223 *property = "Environment";
3225 pager_open_if_enabled();
3227 r = bus_method_call_with_reply (
3229 "org.freedesktop.systemd1",
3230 "/org/freedesktop/systemd1",
3231 "org.freedesktop.DBus.Properties",
3235 DBUS_TYPE_STRING, &interface,
3236 DBUS_TYPE_STRING, &property,
3241 if (!dbus_message_iter_init(reply, &iter) ||
3242 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3243 log_error("Failed to parse reply.");
3248 dbus_message_iter_recurse(&iter, &sub);
3250 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3251 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3252 log_error("Failed to parse reply.");
3257 dbus_message_iter_recurse(&sub, &sub2);
3259 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3262 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3263 log_error("Failed to parse reply.");
3268 dbus_message_iter_get_basic(&sub2, &text);
3269 printf("%s\n", text);
3271 dbus_message_iter_next(&sub2);
3278 dbus_message_unref(reply);
3283 static int switch_root(DBusConnection *bus, char **args) {
3285 const char *root, *init;
3287 l = strv_length(args);
3288 if (l < 2 || l > 3) {
3289 log_error("Wrong number of arguments.");
3294 init = l >= 3 ? args[2] : "";
3296 return bus_method_call_with_reply (
3298 "org.freedesktop.systemd1",
3299 "/org/freedesktop/systemd1",
3300 "org.freedesktop.systemd1.Manager",
3304 DBUS_TYPE_STRING, &root,
3305 DBUS_TYPE_STRING, &init,
3309 static int set_environment(DBusConnection *bus, char **args) {
3310 DBusMessage *m = NULL, *reply = NULL;
3314 DBusMessageIter iter, sub;
3317 dbus_error_init(&error);
3319 method = streq(args[0], "set-environment")
3321 : "UnsetEnvironment";
3323 if (!(m = dbus_message_new_method_call(
3324 "org.freedesktop.systemd1",
3325 "/org/freedesktop/systemd1",
3326 "org.freedesktop.systemd1.Manager",
3329 log_error("Could not allocate message.");
3333 dbus_message_iter_init_append(m, &iter);
3335 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub)) {
3336 log_error("Could not append arguments to message.");
3341 STRV_FOREACH(name, args+1)
3342 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, name)) {
3343 log_error("Could not append arguments to message.");
3348 if (!dbus_message_iter_close_container(&iter, &sub)) {
3349 log_error("Could not append arguments to message.");
3354 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
3355 log_error("Failed to issue method call: %s", bus_error_message(&error));
3364 dbus_message_unref(m);
3367 dbus_message_unref(reply);
3369 dbus_error_free(&error);
3374 static int enable_sysv_units(char **args) {
3377 #if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
3378 const char *verb = args[0];
3379 unsigned f = 1, t = 1;
3382 if (arg_scope != UNIT_FILE_SYSTEM)
3385 if (!streq(verb, "enable") &&
3386 !streq(verb, "disable") &&
3387 !streq(verb, "is-enabled"))
3390 /* Processes all SysV units, and reshuffles the array so that
3391 * afterwards only the native units remain */
3394 r = lookup_paths_init(&paths, MANAGER_SYSTEM, false, NULL, NULL, NULL);
3399 for (f = 1; args[f]; f++) {
3402 bool found_native = false, found_sysv;
3404 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3405 char **k, *l, *q = NULL;
3412 if (!endswith(name, ".service"))
3415 if (path_is_absolute(name))
3418 STRV_FOREACH(k, paths.unit_path) {
3421 if (!isempty(arg_root))
3422 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3424 asprintf(&p, "%s/%s", *k, name);
3431 found_native = access(p, F_OK) >= 0;
3442 if (!isempty(arg_root))
3443 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3445 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3451 p[strlen(p) - sizeof(".service") + 1] = 0;
3452 found_sysv = access(p, F_OK) >= 0;
3459 /* Mark this entry, so that we don't try enabling it as native unit */
3460 args[f] = (char*) "";
3462 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3464 if (!isempty(arg_root))
3465 argv[c++] = q = strappend("--root=", arg_root);
3467 argv[c++] = path_get_file_name(p);
3469 streq(verb, "enable") ? "on" :
3470 streq(verb, "disable") ? "off" : "--level=5";
3473 l = strv_join((char**)argv, " ");
3481 log_info("Executing %s", l);
3486 log_error("Failed to fork: %m");
3491 } else if (pid == 0) {
3494 execv(argv[0], (char**) argv);
3495 _exit(EXIT_FAILURE);
3501 j = wait_for_terminate(pid, &status);
3503 log_error("Failed to wait for child: %s", strerror(-r));
3508 if (status.si_code == CLD_EXITED) {
3509 if (streq(verb, "is-enabled")) {
3510 if (status.si_status == 0) {
3519 } else if (status.si_status != 0) {
3530 lookup_paths_free(&paths);
3532 /* Drop all SysV units */
3533 for (f = 1, t = 1; args[f]; f++) {
3535 if (isempty(args[f]))
3538 args[t++] = args[f];
3547 static int enable_unit(DBusConnection *bus, char **args) {
3548 const char *verb = args[0];
3549 UnitFileChange *changes = NULL;
3550 unsigned n_changes = 0, i;
3551 int carries_install_info = -1;
3552 DBusMessage *m = NULL, *reply = NULL;
3556 r = enable_sysv_units(args);
3563 dbus_error_init(&error);
3565 if (!bus || avoid_bus()) {
3566 if (streq(verb, "enable")) {
3567 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3568 carries_install_info = r;
3569 } else if (streq(verb, "disable"))
3570 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3571 else if (streq(verb, "reenable")) {
3572 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3573 carries_install_info = r;
3574 } else if (streq(verb, "link"))
3575 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3576 else if (streq(verb, "preset")) {
3577 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3578 carries_install_info = r;
3579 } else if (streq(verb, "mask"))
3580 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3581 else if (streq(verb, "unmask"))
3582 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3584 assert_not_reached("Unknown verb");
3587 log_error("Operation failed: %s", strerror(-r));
3592 for (i = 0; i < n_changes; i++) {
3593 if (changes[i].type == UNIT_FILE_SYMLINK)
3594 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3596 log_info("rm '%s'", changes[i].path);
3602 bool send_force = true, expect_carries_install_info = false;
3604 DBusMessageIter iter, sub, sub2;
3606 if (streq(verb, "enable")) {
3607 method = "EnableUnitFiles";
3608 expect_carries_install_info = true;
3609 } else if (streq(verb, "disable")) {
3610 method = "DisableUnitFiles";
3612 } else if (streq(verb, "reenable")) {
3613 method = "ReenableUnitFiles";
3614 expect_carries_install_info = true;
3615 } else if (streq(verb, "link"))
3616 method = "LinkUnitFiles";
3617 else if (streq(verb, "preset")) {
3618 method = "PresetUnitFiles";
3619 expect_carries_install_info = true;
3620 } else if (streq(verb, "mask"))
3621 method = "MaskUnitFiles";
3622 else if (streq(verb, "unmask")) {
3623 method = "UnmaskUnitFiles";
3626 assert_not_reached("Unknown verb");
3628 m = dbus_message_new_method_call(
3629 "org.freedesktop.systemd1",
3630 "/org/freedesktop/systemd1",
3631 "org.freedesktop.systemd1.Manager",
3638 dbus_message_iter_init_append(m, &iter);
3640 r = bus_append_strv_iter(&iter, args+1);
3642 log_error("Failed to append unit files.");
3647 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3648 log_error("Failed to append runtime boolean.");
3656 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3657 log_error("Failed to append force boolean.");
3663 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3665 log_error("Failed to issue method call: %s", bus_error_message(&error));
3670 if (!dbus_message_iter_init(reply, &iter)) {
3671 log_error("Failed to initialize iterator.");
3675 if (expect_carries_install_info) {
3676 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3678 log_error("Failed to parse reply.");
3682 carries_install_info = b;
3685 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3686 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3687 log_error("Failed to parse reply.");
3692 dbus_message_iter_recurse(&iter, &sub);
3693 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3694 const char *type, *path, *source;
3696 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3697 log_error("Failed to parse reply.");
3702 dbus_message_iter_recurse(&sub, &sub2);
3704 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3705 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3706 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3707 log_error("Failed to parse reply.");
3713 if (streq(type, "symlink"))
3714 log_info("ln -s '%s' '%s'", source, path);
3716 log_info("rm '%s'", path);
3719 dbus_message_iter_next(&sub);
3722 /* Try to reload if enabeld */
3724 r = daemon_reload(bus, args);
3727 if (carries_install_info == 0)
3728 log_warning("The unit files have no [Install] section. They are not meant to be enabled using systemctl.");
3732 dbus_message_unref(m);
3735 dbus_message_unref(reply);
3737 unit_file_changes_free(changes, n_changes);
3739 dbus_error_free(&error);
3743 static int unit_is_enabled(DBusConnection *bus, char **args) {
3746 DBusMessage *reply = NULL;
3750 dbus_error_init(&error);
3752 r = enable_sysv_units(args);
3758 if (!bus || avoid_bus()) {
3760 STRV_FOREACH(name, args+1) {
3761 UnitFileState state;
3763 state = unit_file_get_state(arg_scope, arg_root, *name);
3769 if (state == UNIT_FILE_ENABLED ||
3770 state == UNIT_FILE_ENABLED_RUNTIME ||
3771 state == UNIT_FILE_STATIC)
3775 puts(unit_file_state_to_string(state));
3779 STRV_FOREACH(name, args+1) {
3782 r = bus_method_call_with_reply (
3784 "org.freedesktop.systemd1",
3785 "/org/freedesktop/systemd1",
3786 "org.freedesktop.systemd1.Manager",
3790 DBUS_TYPE_STRING, name,
3795 if (!dbus_message_get_args(reply, &error,
3796 DBUS_TYPE_STRING, &s,
3797 DBUS_TYPE_INVALID)) {
3798 log_error("Failed to parse reply: %s", bus_error_message(&error));
3803 dbus_message_unref(reply);
3806 if (streq(s, "enabled") ||
3807 streq(s, "enabled-runtime") ||
3816 r = enabled ? 0 : 1;
3820 dbus_message_unref(reply);
3822 dbus_error_free(&error);
3826 static int systemctl_help(void) {
3828 pager_open_if_enabled();
3830 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
3831 "Query or send control commands to the systemd manager.\n\n"
3832 " -h --help Show this help\n"
3833 " --version Show package version\n"
3834 " -t --type=TYPE List only units of a particular type\n"
3835 " -p --property=NAME Show only properties by this name\n"
3836 " -a --all Show all units/properties, including dead/empty ones\n"
3837 " --failed Show only failed units\n"
3838 " --full Don't ellipsize unit names on output\n"
3839 " --fail When queueing a new job, fail if conflicting jobs are\n"
3841 " --ignore-dependencies\n"
3842 " When queueing a new job, ignore all its dependencies\n"
3843 " --kill-who=WHO Who to send signal to\n"
3844 " -s --signal=SIGNAL Which signal to send\n"
3845 " -H --host=[USER@]HOST\n"
3846 " Show information for remote host\n"
3847 " -P --privileged Acquire privileges before execution\n"
3848 " -q --quiet Suppress output\n"
3849 " --no-block Do not wait until operation finished\n"
3850 " --no-wall Don't send wall message before halt/power-off/reboot\n"
3851 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
3853 " --no-legend Do not print a legend (column headers and hints)\n"
3854 " --no-pager Do not pipe output into a pager\n"
3855 " --no-ask-password\n"
3856 " Do not ask for system passwords\n"
3857 " --order When generating graph for dot, show only order\n"
3858 " --require When generating graph for dot, show only requirement\n"
3859 " --system Connect to system manager\n"
3860 " --user Connect to user service manager\n"
3861 " --global Enable/disable unit files globally\n"
3862 " -f --force When enabling unit files, override existing symlinks\n"
3863 " When shutting down, execute action immediately\n"
3864 " --root=PATH Enable unit files in the specified root directory\n"
3865 " --runtime Enable unit files only temporarily until next reboot\n"
3866 " -n --lines=INTEGER Journal entries to show\n"
3867 " --follow Follow journal\n"
3868 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
3869 " verbose, export, json, cat)\n\n"
3871 " list-units List loaded units\n"
3872 " start [NAME...] Start (activate) one or more units\n"
3873 " stop [NAME...] Stop (deactivate) one or more units\n"
3874 " reload [NAME...] Reload one or more units\n"
3875 " restart [NAME...] Start or restart one or more units\n"
3876 " try-restart [NAME...] Restart one or more units if active\n"
3877 " reload-or-restart [NAME...] Reload one or more units is possible,\n"
3878 " otherwise start or restart\n"
3879 " reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
3880 " otherwise restart if active\n"
3881 " isolate [NAME] Start one unit and stop all others\n"
3882 " kill [NAME...] Send signal to processes of a unit\n"
3883 " is-active [NAME...] Check whether units are active\n"
3884 " status [NAME...|PID...] Show runtime status of one or more units\n"
3885 " show [NAME...|JOB...] Show properties of one or more\n"
3886 " units/jobs or the manager\n"
3887 " help [NAME...|PID...] Show manual for one or more units\n"
3888 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
3890 " load [NAME...] Load one or more units\n\n"
3891 "Unit File Commands:\n"
3892 " list-unit-files List installed unit files\n"
3893 " enable [NAME...] Enable one or more unit files\n"
3894 " disable [NAME...] Disable one or more unit files\n"
3895 " reenable [NAME...] Reenable one or more unit files\n"
3896 " preset [NAME...] Enable/disable one or more unit files\n"
3897 " based on preset configuration\n"
3898 " mask [NAME...] Mask one or more units\n"
3899 " unmask [NAME...] Unmask one or more units\n"
3900 " link [PATH...] Link one or more units files into\n"
3901 " the search path\n"
3902 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
3904 " list-jobs List jobs\n"
3905 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
3906 "Status Commands:\n"
3907 " dump Dump server status\n"
3908 " dot Dump dependency graph for dot(1)\n\n"
3909 "Snapshot Commands:\n"
3910 " snapshot [NAME] Create a snapshot\n"
3911 " delete [NAME...] Remove one or more snapshots\n\n"
3912 "Environment Commands:\n"
3913 " show-environment Dump environment\n"
3914 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
3915 " unset-environment [NAME...] Unset one or more environment variables\n\n"
3916 "Manager Lifecycle Commands:\n"
3917 " daemon-reload Reload systemd manager configuration\n"
3918 " daemon-reexec Reexecute systemd manager\n\n"
3919 "System Commands:\n"
3920 " default Enter system default mode\n"
3921 " rescue Enter system rescue mode\n"
3922 " emergency Enter system emergency mode\n"
3923 " halt Shut down and halt the system\n"
3924 " poweroff Shut down and power-off the system\n"
3925 " reboot Shut down and reboot the system\n"
3926 " kexec Shut down and reboot the system with kexec\n"
3927 " exit Request user instance exit\n"
3928 " switch-root [ROOT] [INIT] Change to a different root file system\n"
3929 " suspend Suspend the system\n"
3930 " hibernate Hibernate the system\n",
3931 program_invocation_short_name);
3936 static int halt_help(void) {
3938 printf("%s [OPTIONS...]\n\n"
3939 "%s the system.\n\n"
3940 " --help Show this help\n"
3941 " --halt Halt the machine\n"
3942 " -p --poweroff Switch off the machine\n"
3943 " --reboot Reboot the machine\n"
3944 " -f --force Force immediate halt/power-off/reboot\n"
3945 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
3946 " -d --no-wtmp Don't write wtmp record\n"
3947 " -n --no-sync Don't sync before halt/power-off/reboot\n"
3948 " --no-wall Don't send wall message before halt/power-off/reboot\n",
3949 program_invocation_short_name,
3950 arg_action == ACTION_REBOOT ? "Reboot" :
3951 arg_action == ACTION_POWEROFF ? "Power off" :
3957 static int shutdown_help(void) {
3959 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
3960 "Shut down the system.\n\n"
3961 " --help Show this help\n"
3962 " -H --halt Halt the machine\n"
3963 " -P --poweroff Power-off the machine\n"
3964 " -r --reboot Reboot the machine\n"
3965 " -h Equivalent to --poweroff, overridden by --halt\n"
3966 " -k Don't halt/power-off/reboot, just send warnings\n"
3967 " --no-wall Don't send wall message before halt/power-off/reboot\n"
3968 " -c Cancel a pending shutdown\n",
3969 program_invocation_short_name);
3974 static int telinit_help(void) {
3976 printf("%s [OPTIONS...] {COMMAND}\n\n"
3977 "Send control commands to the init daemon.\n\n"
3978 " --help Show this help\n"
3979 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
3981 " 0 Power-off the machine\n"
3982 " 6 Reboot the machine\n"
3983 " 2, 3, 4, 5 Start runlevelX.target unit\n"
3984 " 1, s, S Enter rescue mode\n"
3985 " q, Q Reload init daemon configuration\n"
3986 " u, U Reexecute init daemon\n",
3987 program_invocation_short_name);
3992 static int runlevel_help(void) {
3994 printf("%s [OPTIONS...]\n\n"
3995 "Prints the previous and current runlevel of the init system.\n\n"
3996 " --help Show this help\n",
3997 program_invocation_short_name);
4002 static int systemctl_parse_argv(int argc, char *argv[]) {
4006 ARG_IGNORE_DEPENDENCIES,
4021 ARG_NO_ASK_PASSWORD,
4028 static const struct option options[] = {
4029 { "help", no_argument, NULL, 'h' },
4030 { "version", no_argument, NULL, ARG_VERSION },
4031 { "type", required_argument, NULL, 't' },
4032 { "property", required_argument, NULL, 'p' },
4033 { "all", no_argument, NULL, 'a' },
4034 { "failed", no_argument, NULL, ARG_FAILED },
4035 { "full", no_argument, NULL, ARG_FULL },
4036 { "fail", no_argument, NULL, ARG_FAIL },
4037 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4038 { "user", no_argument, NULL, ARG_USER },
4039 { "system", no_argument, NULL, ARG_SYSTEM },
4040 { "global", no_argument, NULL, ARG_GLOBAL },
4041 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4042 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4043 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4044 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4045 { "quiet", no_argument, NULL, 'q' },
4046 { "order", no_argument, NULL, ARG_ORDER },
4047 { "require", no_argument, NULL, ARG_REQUIRE },
4048 { "root", required_argument, NULL, ARG_ROOT },
4049 { "force", no_argument, NULL, ARG_FORCE },
4050 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4051 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4052 { "signal", required_argument, NULL, 's' },
4053 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4054 { "host", required_argument, NULL, 'H' },
4055 { "privileged",no_argument, NULL, 'P' },
4056 { "runtime", no_argument, NULL, ARG_RUNTIME },
4057 { "lines", required_argument, NULL, 'n' },
4058 { "follow", no_argument, NULL, ARG_FOLLOW },
4059 { "output", required_argument, NULL, 'o' },
4060 { NULL, 0, NULL, 0 }
4068 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
4077 puts(PACKAGE_STRING);
4079 puts(SYSTEMD_FEATURES);
4083 if (unit_type_from_string(optarg) >= 0) {
4087 if (unit_load_state_from_string(optarg) >= 0) {
4088 arg_load_state = optarg;
4091 log_error("Unkown unit type or load state '%s'.",
4097 if (!(l = strv_append(arg_property, optarg)))
4100 strv_free(arg_property);
4103 /* If the user asked for a particular
4104 * property, show it to him, even if it is
4115 arg_job_mode = "fail";
4118 case ARG_IGNORE_DEPENDENCIES:
4119 arg_job_mode = "ignore-dependencies";
4123 arg_scope = UNIT_FILE_USER;
4127 arg_scope = UNIT_FILE_SYSTEM;
4131 arg_scope = UNIT_FILE_GLOBAL;
4135 arg_no_block = true;
4139 arg_no_legend = true;
4143 arg_no_pager = true;
4151 arg_dot = DOT_ORDER;
4155 arg_dot = DOT_REQUIRE;
4183 /* -f is short for both --follow and --force! */
4189 arg_no_reload = true;
4193 arg_kill_who = optarg;
4197 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4198 log_error("Failed to parse signal string %s.", optarg);
4203 case ARG_NO_ASK_PASSWORD:
4204 arg_ask_password = false;
4208 arg_transport = TRANSPORT_POLKIT;
4212 arg_transport = TRANSPORT_SSH;
4221 if (safe_atou(optarg, &arg_lines) < 0) {
4222 log_error("Failed to parse lines '%s'", optarg);
4228 arg_output = output_mode_from_string(optarg);
4229 if (arg_output < 0) {
4230 log_error("Unknown output '%s'.", optarg);
4239 log_error("Unknown option code '%c'.", c);
4244 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4245 log_error("Cannot access user instance remotely.");
4252 static int halt_parse_argv(int argc, char *argv[]) {
4261 static const struct option options[] = {
4262 { "help", no_argument, NULL, ARG_HELP },
4263 { "halt", no_argument, NULL, ARG_HALT },
4264 { "poweroff", no_argument, NULL, 'p' },
4265 { "reboot", no_argument, NULL, ARG_REBOOT },
4266 { "force", no_argument, NULL, 'f' },
4267 { "wtmp-only", no_argument, NULL, 'w' },
4268 { "no-wtmp", no_argument, NULL, 'd' },
4269 { "no-sync", no_argument, NULL, 'n' },
4270 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4271 { NULL, 0, NULL, 0 }
4279 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4280 if (runlevel == '0' || runlevel == '6')
4283 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4291 arg_action = ACTION_HALT;
4295 if (arg_action != ACTION_REBOOT)
4296 arg_action = ACTION_POWEROFF;
4300 arg_action = ACTION_REBOOT;
4325 /* Compatibility nops */
4332 log_error("Unknown option code '%c'.", c);
4337 if (optind < argc) {
4338 log_error("Too many arguments.");
4345 static int parse_time_spec(const char *t, usec_t *_u) {
4349 if (streq(t, "now"))
4351 else if (!strchr(t, ':')) {
4354 if (safe_atou64(t, &u) < 0)
4357 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4366 hour = strtol(t, &e, 10);
4367 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4370 minute = strtol(e+1, &e, 10);
4371 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4374 n = now(CLOCK_REALTIME);
4375 s = (time_t) (n / USEC_PER_SEC);
4378 assert_se(localtime_r(&s, &tm));
4380 tm.tm_hour = (int) hour;
4381 tm.tm_min = (int) minute;
4384 assert_se(s = mktime(&tm));
4386 *_u = (usec_t) s * USEC_PER_SEC;
4389 *_u += USEC_PER_DAY;
4395 static int shutdown_parse_argv(int argc, char *argv[]) {
4402 static const struct option options[] = {
4403 { "help", no_argument, NULL, ARG_HELP },
4404 { "halt", no_argument, NULL, 'H' },
4405 { "poweroff", no_argument, NULL, 'P' },
4406 { "reboot", no_argument, NULL, 'r' },
4407 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4408 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4409 { NULL, 0, NULL, 0 }
4417 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4425 arg_action = ACTION_HALT;
4429 arg_action = ACTION_POWEROFF;
4434 arg_action = ACTION_KEXEC;
4436 arg_action = ACTION_REBOOT;
4440 arg_action = ACTION_KEXEC;
4444 if (arg_action != ACTION_HALT)
4445 arg_action = ACTION_POWEROFF;
4458 /* Compatibility nops */
4462 arg_action = ACTION_CANCEL_SHUTDOWN;
4469 log_error("Unknown option code '%c'.", c);
4474 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4475 r = parse_time_spec(argv[optind], &arg_when);
4477 log_error("Failed to parse time specification: %s", argv[optind]);
4481 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4483 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4484 /* No time argument for shutdown cancel */
4485 arg_wall = argv + optind;
4486 else if (argc > optind + 1)
4487 /* We skip the time argument */
4488 arg_wall = argv + optind + 1;
4495 static int telinit_parse_argv(int argc, char *argv[]) {
4502 static const struct option options[] = {
4503 { "help", no_argument, NULL, ARG_HELP },
4504 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4505 { NULL, 0, NULL, 0 }
4508 static const struct {
4512 { '0', ACTION_POWEROFF },
4513 { '6', ACTION_REBOOT },
4514 { '1', ACTION_RESCUE },
4515 { '2', ACTION_RUNLEVEL2 },
4516 { '3', ACTION_RUNLEVEL3 },
4517 { '4', ACTION_RUNLEVEL4 },
4518 { '5', ACTION_RUNLEVEL5 },
4519 { 's', ACTION_RESCUE },
4520 { 'S', ACTION_RESCUE },
4521 { 'q', ACTION_RELOAD },
4522 { 'Q', ACTION_RELOAD },
4523 { 'u', ACTION_REEXEC },
4524 { 'U', ACTION_REEXEC }
4533 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4548 log_error("Unknown option code '%c'.", c);
4553 if (optind >= argc) {
4558 if (optind + 1 < argc) {
4559 log_error("Too many arguments.");
4563 if (strlen(argv[optind]) != 1) {
4564 log_error("Expected single character argument.");
4568 for (i = 0; i < ELEMENTSOF(table); i++)
4569 if (table[i].from == argv[optind][0])
4572 if (i >= ELEMENTSOF(table)) {
4573 log_error("Unknown command '%s'.", argv[optind]);
4577 arg_action = table[i].to;
4584 static int runlevel_parse_argv(int argc, char *argv[]) {
4590 static const struct option options[] = {
4591 { "help", no_argument, NULL, ARG_HELP },
4592 { NULL, 0, NULL, 0 }
4600 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4611 log_error("Unknown option code '%c'.", c);
4616 if (optind < argc) {
4617 log_error("Too many arguments.");
4624 static int parse_argv(int argc, char *argv[]) {
4628 if (program_invocation_short_name) {
4630 if (strstr(program_invocation_short_name, "halt")) {
4631 arg_action = ACTION_HALT;
4632 return halt_parse_argv(argc, argv);
4633 } else if (strstr(program_invocation_short_name, "poweroff")) {
4634 arg_action = ACTION_POWEROFF;
4635 return halt_parse_argv(argc, argv);
4636 } else if (strstr(program_invocation_short_name, "reboot")) {
4638 arg_action = ACTION_KEXEC;
4640 arg_action = ACTION_REBOOT;
4641 return halt_parse_argv(argc, argv);
4642 } else if (strstr(program_invocation_short_name, "shutdown")) {
4643 arg_action = ACTION_POWEROFF;
4644 return shutdown_parse_argv(argc, argv);
4645 } else if (strstr(program_invocation_short_name, "init")) {
4647 if (sd_booted() > 0) {
4648 arg_action = ACTION_INVALID;
4649 return telinit_parse_argv(argc, argv);
4651 /* Hmm, so some other init system is
4652 * running, we need to forward this
4653 * request to it. For now we simply
4654 * guess that it is Upstart. */
4656 execv("/lib/upstart/telinit", argv);
4658 log_error("Couldn't find an alternative telinit implementation to spawn.");
4662 } else if (strstr(program_invocation_short_name, "runlevel")) {
4663 arg_action = ACTION_RUNLEVEL;
4664 return runlevel_parse_argv(argc, argv);
4668 arg_action = ACTION_SYSTEMCTL;
4669 return systemctl_parse_argv(argc, argv);
4672 static int action_to_runlevel(void) {
4674 static const char table[_ACTION_MAX] = {
4675 [ACTION_HALT] = '0',
4676 [ACTION_POWEROFF] = '0',
4677 [ACTION_REBOOT] = '6',
4678 [ACTION_RUNLEVEL2] = '2',
4679 [ACTION_RUNLEVEL3] = '3',
4680 [ACTION_RUNLEVEL4] = '4',
4681 [ACTION_RUNLEVEL5] = '5',
4682 [ACTION_RESCUE] = '1'
4685 assert(arg_action < _ACTION_MAX);
4687 return table[arg_action];
4690 static int talk_upstart(void) {
4691 DBusMessage *m = NULL, *reply = NULL;
4693 int previous, rl, r;
4695 env1_buf[] = "RUNLEVEL=X",
4696 env2_buf[] = "PREVLEVEL=X";
4697 char *env1 = env1_buf, *env2 = env2_buf;
4698 const char *emit = "runlevel";
4699 dbus_bool_t b_false = FALSE;
4700 DBusMessageIter iter, sub;
4701 DBusConnection *bus;
4703 dbus_error_init(&error);
4705 if (!(rl = action_to_runlevel()))
4708 if (utmp_get_runlevel(&previous, NULL) < 0)
4711 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4712 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4717 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4722 if ((r = bus_check_peercred(bus)) < 0) {
4723 log_error("Failed to verify owner of bus.");
4727 if (!(m = dbus_message_new_method_call(
4728 "com.ubuntu.Upstart",
4729 "/com/ubuntu/Upstart",
4730 "com.ubuntu.Upstart0_6",
4733 log_error("Could not allocate message.");
4738 dbus_message_iter_init_append(m, &iter);
4740 env1_buf[sizeof(env1_buf)-2] = rl;
4741 env2_buf[sizeof(env2_buf)-2] = previous;
4743 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4744 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4745 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4746 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4747 !dbus_message_iter_close_container(&iter, &sub) ||
4748 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4749 log_error("Could not append arguments to message.");
4754 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4756 if (bus_error_is_no_service(&error)) {
4761 log_error("Failed to issue method call: %s", bus_error_message(&error));
4770 dbus_message_unref(m);
4773 dbus_message_unref(reply);
4776 dbus_connection_flush(bus);
4777 dbus_connection_close(bus);
4778 dbus_connection_unref(bus);
4781 dbus_error_free(&error);
4786 static int talk_initctl(void) {
4787 struct init_request request;
4791 if (!(rl = action_to_runlevel()))
4795 request.magic = INIT_MAGIC;
4796 request.sleeptime = 0;
4797 request.cmd = INIT_CMD_RUNLVL;
4798 request.runlevel = rl;
4800 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4802 if (errno == ENOENT)
4805 log_error("Failed to open "INIT_FIFO": %m");
4810 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
4811 close_nointr_nofail(fd);
4814 log_error("Failed to write to "INIT_FIFO": %m");
4815 return errno ? -errno : -EIO;
4821 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
4823 static const struct {
4831 int (* const dispatch)(DBusConnection *bus, char **args);
4833 { "list-units", LESS, 1, list_units },
4834 { "list-unit-files", EQUAL, 1, list_unit_files },
4835 { "list-jobs", EQUAL, 1, list_jobs },
4836 { "clear-jobs", EQUAL, 1, daemon_reload },
4837 { "load", MORE, 2, load_unit },
4838 { "cancel", MORE, 2, cancel_job },
4839 { "start", MORE, 2, start_unit },
4840 { "stop", MORE, 2, start_unit },
4841 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4842 { "reload", MORE, 2, start_unit },
4843 { "restart", MORE, 2, start_unit },
4844 { "try-restart", MORE, 2, start_unit },
4845 { "reload-or-restart", MORE, 2, start_unit },
4846 { "reload-or-try-restart", MORE, 2, start_unit },
4847 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
4848 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
4849 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
4850 { "isolate", EQUAL, 2, start_unit },
4851 { "kill", MORE, 2, kill_unit },
4852 { "is-active", MORE, 2, check_unit },
4853 { "check", MORE, 2, check_unit },
4854 { "show", MORE, 1, show },
4855 { "status", MORE, 2, show },
4856 { "help", MORE, 2, show },
4857 { "dump", EQUAL, 1, dump },
4858 { "dot", EQUAL, 1, dot },
4859 { "snapshot", LESS, 2, snapshot },
4860 { "delete", MORE, 2, delete_snapshot },
4861 { "daemon-reload", EQUAL, 1, daemon_reload },
4862 { "daemon-reexec", EQUAL, 1, daemon_reload },
4863 { "show-environment", EQUAL, 1, show_enviroment },
4864 { "set-environment", MORE, 2, set_environment },
4865 { "unset-environment", MORE, 2, set_environment },
4866 { "halt", EQUAL, 1, start_special },
4867 { "poweroff", EQUAL, 1, start_special },
4868 { "reboot", EQUAL, 1, start_special },
4869 { "kexec", EQUAL, 1, start_special },
4870 { "suspend", EQUAL, 1, start_special },
4871 { "hibernate", EQUAL, 1, start_special },
4872 { "default", EQUAL, 1, start_special },
4873 { "rescue", EQUAL, 1, start_special },
4874 { "emergency", EQUAL, 1, start_special },
4875 { "exit", EQUAL, 1, start_special },
4876 { "reset-failed", MORE, 1, reset_failed },
4877 { "enable", MORE, 2, enable_unit },
4878 { "disable", MORE, 2, enable_unit },
4879 { "is-enabled", MORE, 2, unit_is_enabled },
4880 { "reenable", MORE, 2, enable_unit },
4881 { "preset", MORE, 2, enable_unit },
4882 { "mask", MORE, 2, enable_unit },
4883 { "unmask", MORE, 2, enable_unit },
4884 { "link", MORE, 2, enable_unit },
4885 { "switch-root", MORE, 2, switch_root },
4895 left = argc - optind;
4898 /* Special rule: no arguments means "list-units" */
4901 if (streq(argv[optind], "help") && !argv[optind+1]) {
4902 log_error("This command expects one or more "
4903 "unit names. Did you mean --help?");
4907 for (i = 0; i < ELEMENTSOF(verbs); i++)
4908 if (streq(argv[optind], verbs[i].verb))
4911 if (i >= ELEMENTSOF(verbs)) {
4912 log_error("Unknown operation '%s'.", argv[optind]);
4917 switch (verbs[i].argc_cmp) {
4920 if (left != verbs[i].argc) {
4921 log_error("Invalid number of arguments.");
4928 if (left < verbs[i].argc) {
4929 log_error("Too few arguments.");
4936 if (left > verbs[i].argc) {
4937 log_error("Too many arguments.");
4944 assert_not_reached("Unknown comparison operator.");
4947 /* Require a bus connection for all operations but
4949 if (!streq(verbs[i].verb, "enable") &&
4950 !streq(verbs[i].verb, "disable") &&
4951 !streq(verbs[i].verb, "is-enabled") &&
4952 !streq(verbs[i].verb, "list-unit-files") &&
4953 !streq(verbs[i].verb, "reenable") &&
4954 !streq(verbs[i].verb, "preset") &&
4955 !streq(verbs[i].verb, "mask") &&
4956 !streq(verbs[i].verb, "unmask") &&
4957 !streq(verbs[i].verb, "link")) {
4959 if (running_in_chroot() > 0) {
4960 log_info("Running in chroot, ignoring request.");
4964 if (((!streq(verbs[i].verb, "reboot") &&
4965 !streq(verbs[i].verb, "halt") &&
4966 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
4967 log_error("Failed to get D-Bus connection: %s",
4968 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
4974 if (!bus && !avoid_bus()) {
4975 log_error("Failed to get D-Bus connection: %s",
4976 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
4981 return verbs[i].dispatch(bus, argv + optind);
4984 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
4986 struct msghdr msghdr;
4987 struct iovec iovec[2];
4988 union sockaddr_union sockaddr;
4989 struct sd_shutdown_command c;
4991 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
4998 c.dry_run = dry_run;
5002 sockaddr.sa.sa_family = AF_UNIX;
5003 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5006 msghdr.msg_name = &sockaddr;
5007 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5010 iovec[0].iov_base = (char*) &c;
5011 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5013 if (isempty(message))
5014 msghdr.msg_iovlen = 1;
5016 iovec[1].iov_base = (char*) message;
5017 iovec[1].iov_len = strlen(message);
5018 msghdr.msg_iovlen = 2;
5020 msghdr.msg_iov = iovec;
5022 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5023 close_nointr_nofail(fd);
5027 close_nointr_nofail(fd);
5031 static int reload_with_fallback(DBusConnection *bus) {
5034 /* First, try systemd via D-Bus. */
5035 if (daemon_reload(bus, NULL) >= 0)
5039 /* Nothing else worked, so let's try signals */
5040 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5042 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5043 log_error("kill() failed: %m");
5050 static int start_with_fallback(DBusConnection *bus) {
5053 /* First, try systemd via D-Bus. */
5054 if (start_unit(bus, NULL) >= 0)
5058 /* Hmm, talking to systemd via D-Bus didn't work. Then
5059 * let's try to talk to Upstart via D-Bus. */
5060 if (talk_upstart() > 0)
5063 /* Nothing else worked, so let's try
5065 if (talk_initctl() > 0)
5068 log_error("Failed to talk to init daemon.");
5072 warn_wall(arg_action);
5076 static _noreturn_ void halt_now(enum action a) {
5078 /* Make sure C-A-D is handled by the kernel from this
5080 reboot(RB_ENABLE_CAD);
5085 log_info("Halting.");
5086 reboot(RB_HALT_SYSTEM);
5089 case ACTION_POWEROFF:
5090 log_info("Powering off.");
5091 reboot(RB_POWER_OFF);
5095 log_info("Rebooting.");
5096 reboot(RB_AUTOBOOT);
5100 assert_not_reached("Unknown halt action.");
5103 assert_not_reached("Uh? This shouldn't happen.");
5106 static int halt_main(DBusConnection *bus) {
5109 if (geteuid() != 0) {
5110 /* Try logind if we are a normal user and no special
5111 * mode applies. Maybe PolicyKit allows us to shutdown
5114 if (arg_when <= 0 &&
5117 (arg_action == ACTION_POWEROFF ||
5118 arg_action == ACTION_REBOOT)) {
5119 r = reboot_with_logind(bus, arg_action);
5124 log_error("Must be root.");
5131 m = strv_join(arg_wall, " ");
5132 r = send_shutdownd(arg_when,
5133 arg_action == ACTION_HALT ? 'H' :
5134 arg_action == ACTION_POWEROFF ? 'P' :
5135 arg_action == ACTION_KEXEC ? 'K' :
5143 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5145 char date[FORMAT_TIMESTAMP_MAX];
5147 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5148 format_timestamp(date, sizeof(date), arg_when));
5153 if (!arg_dry && !arg_force)
5154 return start_with_fallback(bus);
5157 if (sd_booted() > 0)
5158 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5160 r = utmp_put_shutdown();
5162 log_warning("Failed to write utmp record: %s", strerror(-r));
5172 halt_now(arg_action);
5173 /* We should never reach this. */
5177 static int runlevel_main(void) {
5178 int r, runlevel, previous;
5180 r = utmp_get_runlevel(&runlevel, &previous);
5187 previous <= 0 ? 'N' : previous,
5188 runlevel <= 0 ? 'N' : runlevel);
5193 int main(int argc, char*argv[]) {
5194 int r, retval = EXIT_FAILURE;
5195 DBusConnection *bus = NULL;
5198 dbus_error_init(&error);
5200 log_parse_environment();
5203 r = parse_argv(argc, argv);
5207 retval = EXIT_SUCCESS;
5211 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5212 * let's shortcut this */
5213 if (arg_action == ACTION_RUNLEVEL) {
5214 r = runlevel_main();
5215 retval = r < 0 ? EXIT_FAILURE : r;
5219 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5220 log_info("Running in chroot, ignoring request.");
5226 if (arg_transport == TRANSPORT_NORMAL)
5227 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5228 else if (arg_transport == TRANSPORT_POLKIT) {
5229 bus_connect_system_polkit(&bus, &error);
5230 private_bus = false;
5231 } else if (arg_transport == TRANSPORT_SSH) {
5232 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5233 private_bus = false;
5235 assert_not_reached("Uh, invalid transport...");
5238 switch (arg_action) {
5240 case ACTION_SYSTEMCTL:
5241 r = systemctl_main(bus, argc, argv, &error);
5245 case ACTION_POWEROFF:
5251 case ACTION_RUNLEVEL2:
5252 case ACTION_RUNLEVEL3:
5253 case ACTION_RUNLEVEL4:
5254 case ACTION_RUNLEVEL5:
5256 case ACTION_EMERGENCY:
5257 case ACTION_DEFAULT:
5258 r = start_with_fallback(bus);
5263 r = reload_with_fallback(bus);
5266 case ACTION_CANCEL_SHUTDOWN: {
5270 m = strv_join(arg_wall, " ");
5272 retval = EXIT_FAILURE;
5276 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5278 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5283 case ACTION_INVALID:
5284 case ACTION_RUNLEVEL:
5286 assert_not_reached("Unknown action");
5289 retval = r < 0 ? EXIT_FAILURE : r;
5293 dbus_connection_flush(bus);
5294 dbus_connection_close(bus);
5295 dbus_connection_unref(bus);
5298 dbus_error_free(&error);
5302 strv_free(arg_property);
5305 ask_password_agent_close();
5306 polkit_agent_close();