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>
29 #include <sys/ioctl.h>
33 #include <sys/socket.h>
36 #include <sys/prctl.h>
37 #include <dbus/dbus.h>
39 #include <systemd/sd-daemon.h>
40 #include <systemd/sd-shutdown.h>
46 #include "utmp-wtmp.h"
49 #include "path-util.h"
51 #include "dbus-common.h"
52 #include "cgroup-show.h"
53 #include "cgroup-util.h"
55 #include "path-lookup.h"
56 #include "conf-parser.h"
57 #include "exit-status.h"
58 #include "bus-errors.h"
60 #include "unit-name.h"
62 #include "spawn-ask-password-agent.h"
63 #include "spawn-polkit-agent.h"
65 #include "logs-show.h"
66 #include "path-util.h"
67 #include "socket-util.h"
69 static const char *arg_type = NULL;
70 static const char *arg_load_state = NULL;
71 static char **arg_property = NULL;
72 static bool arg_all = false;
73 static const char *arg_job_mode = "replace";
74 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
75 static bool arg_no_block = false;
76 static bool arg_no_legend = false;
77 static bool arg_no_pager = false;
78 static bool arg_no_wtmp = false;
79 static bool arg_no_wall = false;
80 static bool arg_no_reload = false;
81 static bool arg_ignore_inhibitors = false;
82 static bool arg_dry = false;
83 static bool arg_quiet = false;
84 static bool arg_full = false;
85 static int arg_force = 0;
86 static bool arg_ask_password = true;
87 static bool arg_failed = false;
88 static bool arg_runtime = false;
89 static char **arg_wall = NULL;
90 static const char *arg_kill_who = NULL;
91 static int arg_signal = SIGTERM;
92 static const char *arg_root = NULL;
93 static usec_t arg_when = 0;
115 ACTION_CANCEL_SHUTDOWN,
117 } arg_action = ACTION_SYSTEMCTL;
123 static enum transport {
127 } arg_transport = TRANSPORT_NORMAL;
128 static const char *arg_host = NULL;
129 static unsigned arg_lines = 10;
130 static OutputMode arg_output = OUTPUT_SHORT;
132 static bool private_bus = false;
134 static int daemon_reload(DBusConnection *bus, char **args);
135 static void halt_now(enum action a);
137 static void pager_open_if_enabled(void) {
145 static void ask_password_agent_open_if_enabled(void) {
147 /* Open the password agent as a child process if necessary */
149 if (!arg_ask_password)
152 if (arg_scope != UNIT_FILE_SYSTEM)
155 ask_password_agent_open();
159 static void polkit_agent_open_if_enabled(void) {
161 /* Open the polkit agent as a child process if necessary */
163 if (!arg_ask_password)
166 if (arg_scope != UNIT_FILE_SYSTEM)
173 static const char *ansi_highlight(bool b) {
178 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
181 static const char *ansi_highlight_red(bool b) {
186 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
189 static const char *ansi_highlight_green(bool b) {
194 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
197 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
200 if (!dbus_error_is_set(error))
203 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
204 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
205 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
206 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
207 return EXIT_NOPERMISSION;
209 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
210 return EXIT_NOTINSTALLED;
212 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
213 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
214 return EXIT_NOTIMPLEMENTED;
216 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
217 return EXIT_NOTCONFIGURED;
225 static void warn_wall(enum action a) {
226 static const char *table[_ACTION_MAX] = {
227 [ACTION_HALT] = "The system is going down for system halt NOW!",
228 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
229 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
230 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
231 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
232 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
233 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
242 p = strv_join(arg_wall, " ");
244 log_error("Failed to join strings.");
260 utmp_wall(table[a], NULL);
263 static bool avoid_bus(void) {
265 if (running_in_chroot() > 0)
268 if (sd_booted() <= 0)
271 if (!isempty(arg_root))
274 if (arg_scope == UNIT_FILE_GLOBAL)
282 const char *description;
283 const char *load_state;
284 const char *active_state;
285 const char *sub_state;
286 const char *following;
287 const char *unit_path;
289 const char *job_type;
290 const char *job_path;
293 static int compare_unit_info(const void *a, const void *b) {
295 const struct unit_info *u = a, *v = b;
297 d1 = strrchr(u->id, '.');
298 d2 = strrchr(v->id, '.');
303 if ((r = strcasecmp(d1, d2)) != 0)
307 return strcasecmp(u->id, v->id);
310 static bool output_show_unit(const struct unit_info *u) {
314 return streq(u->active_state, "failed");
316 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
317 streq(dot+1, arg_type))) &&
318 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
319 (arg_all || !(streq(u->active_state, "inactive")
320 || u->following[0]) || u->job_id > 0);
323 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
324 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
325 const struct unit_info *u;
328 max_id_len = sizeof("UNIT")-1;
329 active_len = sizeof("ACTIVE")-1;
330 sub_len = sizeof("SUB")-1;
331 job_len = sizeof("JOB")-1;
334 for (u = unit_infos; u < unit_infos + c; u++) {
335 if (!output_show_unit(u))
338 max_id_len = MAX(max_id_len, strlen(u->id));
339 active_len = MAX(active_len, strlen(u->active_state));
340 sub_len = MAX(sub_len, strlen(u->sub_state));
341 if (u->job_id != 0) {
342 job_len = MAX(job_len, strlen(u->job_type));
349 id_len = MIN(max_id_len, 25);
350 basic_len = 5 + id_len + 5 + active_len + sub_len;
352 basic_len += job_len + 1;
353 if (basic_len < (unsigned) columns()) {
354 unsigned extra_len, incr;
355 extra_len = columns() - basic_len;
356 /* Either UNIT already got 25, or is fully satisfied.
357 * Grant up to 25 to DESC now. */
358 incr = MIN(extra_len, 25);
361 /* split the remaining space between UNIT and DESC,
362 * but do not give UNIT more than it needs. */
364 incr = MIN(extra_len / 2, max_id_len - id_len);
366 desc_len += extra_len - incr;
372 for (u = unit_infos; u < unit_infos + c; u++) {
374 const char *on_loaded, *off_loaded;
375 const char *on_active, *off_active;
377 if (!output_show_unit(u))
380 if (!n_shown && !arg_no_legend) {
381 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
382 active_len, "ACTIVE", sub_len, "SUB");
384 printf("%-*s ", job_len, "JOB");
385 if (!arg_full && arg_no_pager)
386 printf("%.*s\n", desc_len, "DESCRIPTION");
388 printf("%s\n", "DESCRIPTION");
393 if (streq(u->load_state, "error")) {
394 on_loaded = ansi_highlight_red(true);
395 off_loaded = ansi_highlight_red(false);
397 on_loaded = off_loaded = "";
399 if (streq(u->active_state, "failed")) {
400 on_active = ansi_highlight_red(true);
401 off_active = ansi_highlight_red(false);
403 on_active = off_active = "";
405 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
407 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s",
408 id_len, e ? e : u->id,
409 on_loaded, u->load_state, off_loaded,
410 on_active, active_len, u->active_state,
411 sub_len, u->sub_state, off_active,
412 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
413 if (!arg_full && arg_no_pager)
414 printf("%.*s\n", desc_len, u->description);
416 printf("%s\n", u->description);
421 if (!arg_no_legend) {
422 const char *on, *off;
425 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
426 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
427 "SUB = The low-level unit activation state, values depend on unit type.\n");
429 printf("JOB = Pending job for the unit.\n");
431 on = ansi_highlight(true);
432 off = ansi_highlight(false);
434 on = ansi_highlight_red(true);
435 off = ansi_highlight_red(false);
439 printf("%s%u loaded units listed.%s\n"
440 "To show all installed unit files use 'systemctl list-unit-files'.\n",
443 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
444 "To show all installed unit files use 'systemctl list-unit-files'.\n",
449 static int list_units(DBusConnection *bus, char **args) {
450 DBusMessage *reply = NULL;
452 DBusMessageIter iter, sub, sub2;
453 unsigned c = 0, n_units = 0;
454 struct unit_info *unit_infos = NULL;
456 pager_open_if_enabled();
458 r = bus_method_call_with_reply (
460 "org.freedesktop.systemd1",
461 "/org/freedesktop/systemd1",
462 "org.freedesktop.systemd1.Manager",
470 if (!dbus_message_iter_init(reply, &iter) ||
471 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
472 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
473 log_error("Failed to parse reply.");
478 dbus_message_iter_recurse(&iter, &sub);
480 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
483 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
484 log_error("Failed to parse reply.");
492 n_units = MAX(2*c, 16);
493 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
496 log_error("Failed to allocate unit array.");
506 dbus_message_iter_recurse(&sub, &sub2);
508 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
509 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
510 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
511 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
512 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
513 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
514 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
515 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
516 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
517 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
518 log_error("Failed to parse reply.");
523 dbus_message_iter_next(&sub);
528 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
529 output_units_list(unit_infos, c);
534 dbus_message_unref(reply);
541 static int compare_unit_file_list(const void *a, const void *b) {
543 const UnitFileList *u = a, *v = b;
545 d1 = strrchr(u->path, '.');
546 d2 = strrchr(v->path, '.');
551 r = strcasecmp(d1, d2);
556 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
559 static bool output_show_unit_file(const UnitFileList *u) {
562 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
565 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
566 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
567 const UnitFileList *u;
569 max_id_len = sizeof("UNIT FILE")-1;
570 state_cols = sizeof("STATE")-1;
571 for (u = units; u < units + c; u++) {
572 if (!output_show_unit_file(u))
575 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
576 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
581 id_cols = MIN(max_id_len, 25);
582 basic_cols = 1 + id_cols + state_cols;
583 if (basic_cols < (unsigned) columns())
584 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
586 id_cols = max_id_len;
589 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
591 for (u = units; u < units + c; u++) {
593 const char *on, *off;
596 if (!output_show_unit_file(u))
601 if (u->state == UNIT_FILE_MASKED ||
602 u->state == UNIT_FILE_MASKED_RUNTIME ||
603 u->state == UNIT_FILE_DISABLED ||
604 u->state == UNIT_FILE_INVALID) {
605 on = ansi_highlight_red(true);
606 off = ansi_highlight_red(false);
607 } else if (u->state == UNIT_FILE_ENABLED) {
608 on = ansi_highlight_green(true);
609 off = ansi_highlight_green(false);
613 id = path_get_file_name(u->path);
615 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
617 printf("%-*s %s%-*s%s\n",
619 on, state_cols, unit_file_state_to_string(u->state), off);
625 printf("\n%u unit files listed.\n", n_shown);
628 static int list_unit_files(DBusConnection *bus, char **args) {
629 DBusMessage *reply = NULL;
631 DBusMessageIter iter, sub, sub2;
632 unsigned c = 0, n_units = 0;
633 UnitFileList *units = NULL;
635 pager_open_if_enabled();
642 h = hashmap_new(string_hash_func, string_compare_func);
646 r = unit_file_get_list(arg_scope, arg_root, h);
648 unit_file_list_free(h);
649 log_error("Failed to get unit file list: %s", strerror(-r));
653 n_units = hashmap_size(h);
654 units = new(UnitFileList, n_units);
656 unit_file_list_free(h);
660 HASHMAP_FOREACH(u, h, i) {
661 memcpy(units + c++, u, sizeof(UnitFileList));
667 r = bus_method_call_with_reply (
669 "org.freedesktop.systemd1",
670 "/org/freedesktop/systemd1",
671 "org.freedesktop.systemd1.Manager",
679 if (!dbus_message_iter_init(reply, &iter) ||
680 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
681 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
682 log_error("Failed to parse reply.");
687 dbus_message_iter_recurse(&iter, &sub);
689 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
693 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
694 log_error("Failed to parse reply.");
702 n_units = MAX(2*c, 16);
703 w = realloc(units, sizeof(struct UnitFileList) * n_units);
706 log_error("Failed to allocate unit array.");
716 dbus_message_iter_recurse(&sub, &sub2);
718 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
719 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
720 log_error("Failed to parse reply.");
725 u->state = unit_file_state_from_string(state);
727 dbus_message_iter_next(&sub);
733 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
734 output_unit_file_list(units, c);
741 dbus_message_unref(reply);
748 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
749 static const char * const colors[] = {
750 "Requires", "[color=\"black\"]",
751 "RequiresOverridable", "[color=\"black\"]",
752 "Requisite", "[color=\"darkblue\"]",
753 "RequisiteOverridable", "[color=\"darkblue\"]",
754 "Wants", "[color=\"grey66\"]",
755 "Conflicts", "[color=\"red\"]",
756 "ConflictedBy", "[color=\"red\"]",
757 "After", "[color=\"green\"]"
760 const char *c = NULL;
767 for (i = 0; i < ELEMENTSOF(colors); i += 2)
768 if (streq(colors[i], prop)) {
776 if (arg_dot != DOT_ALL)
777 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
780 switch (dbus_message_iter_get_arg_type(iter)) {
782 case DBUS_TYPE_ARRAY:
784 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
787 dbus_message_iter_recurse(iter, &sub);
789 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
792 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
793 dbus_message_iter_get_basic(&sub, &s);
794 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
796 dbus_message_iter_next(&sub);
806 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
807 DBusMessage *reply = NULL;
808 const char *interface = "org.freedesktop.systemd1.Unit";
810 DBusMessageIter iter, sub, sub2, sub3;
814 r = bus_method_call_with_reply (
816 "org.freedesktop.systemd1",
818 "org.freedesktop.DBus.Properties",
822 DBUS_TYPE_STRING, &interface,
827 if (!dbus_message_iter_init(reply, &iter) ||
828 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
829 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
830 log_error("Failed to parse reply.");
835 dbus_message_iter_recurse(&iter, &sub);
837 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
840 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
841 log_error("Failed to parse reply.");
846 dbus_message_iter_recurse(&sub, &sub2);
848 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
849 log_error("Failed to parse reply.");
854 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
855 log_error("Failed to parse reply.");
860 dbus_message_iter_recurse(&sub2, &sub3);
862 if (dot_one_property(name, prop, &sub3)) {
863 log_error("Failed to parse reply.");
868 dbus_message_iter_next(&sub);
873 dbus_message_unref(reply);
878 static int dot(DBusConnection *bus, char **args) {
879 DBusMessage *reply = NULL;
881 DBusMessageIter iter, sub, sub2;
883 r = bus_method_call_with_reply (
885 "org.freedesktop.systemd1",
886 "/org/freedesktop/systemd1",
887 "org.freedesktop.systemd1.Manager",
895 if (!dbus_message_iter_init(reply, &iter) ||
896 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
897 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
898 log_error("Failed to parse reply.");
903 printf("digraph systemd {\n");
905 dbus_message_iter_recurse(&iter, &sub);
906 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
907 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
909 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
910 log_error("Failed to parse reply.");
915 dbus_message_iter_recurse(&sub, &sub2);
917 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
918 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
919 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
920 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
921 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
922 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
923 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
924 log_error("Failed to parse reply.");
929 if ((r = dot_one(bus, id, unit_path)) < 0)
932 /* printf("\t\"%s\";\n", id); */
933 dbus_message_iter_next(&sub);
938 log_info(" Color legend: black = Requires\n"
939 " dark blue = Requisite\n"
940 " dark grey = Wants\n"
945 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
946 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
952 dbus_message_unref(reply);
957 static int list_jobs(DBusConnection *bus, char **args) {
958 DBusMessage *reply = NULL;
960 DBusMessageIter iter, sub, sub2;
963 pager_open_if_enabled();
965 r = bus_method_call_with_reply (
967 "org.freedesktop.systemd1",
968 "/org/freedesktop/systemd1",
969 "org.freedesktop.systemd1.Manager",
977 if (!dbus_message_iter_init(reply, &iter) ||
978 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
979 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
980 log_error("Failed to parse reply.");
985 dbus_message_iter_recurse(&iter, &sub);
988 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
990 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
991 const char *name, *type, *state, *job_path, *unit_path;
995 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
996 log_error("Failed to parse reply.");
1001 dbus_message_iter_recurse(&sub, &sub2);
1003 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1004 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1005 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1006 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1007 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1008 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1009 log_error("Failed to parse reply.");
1014 e = arg_full ? NULL : ellipsize(name, 25, 33);
1015 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1020 dbus_message_iter_next(&sub);
1024 printf("\n%u jobs listed.\n", k);
1030 dbus_message_unref(reply);
1035 static int load_unit(DBusConnection *bus, char **args) {
1040 STRV_FOREACH(name, args+1) {
1041 _cleanup_free_ char *n = NULL;
1044 n = unit_name_mangle(*name);
1045 r = bus_method_call_with_reply (
1047 "org.freedesktop.systemd1",
1048 "/org/freedesktop/systemd1",
1049 "org.freedesktop.systemd1.Manager",
1053 DBUS_TYPE_STRING, n ? &n : name,
1062 static int cancel_job(DBusConnection *bus, char **args) {
1067 if (strv_length(args) <= 1)
1068 return daemon_reload(bus, args);
1070 STRV_FOREACH(name, args+1) {
1074 r = safe_atou32(*name, &id);
1076 log_error("Failed to parse job id: %s", strerror(-r));
1080 r = bus_method_call_with_reply(
1082 "org.freedesktop.systemd1",
1083 "/org/freedesktop/systemd1",
1084 "org.freedesktop.systemd1.Manager",
1088 DBUS_TYPE_UINT32, &id,
1097 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1098 DBusMessage *reply = NULL;
1099 dbus_bool_t b = FALSE;
1100 DBusMessageIter iter, sub;
1102 *interface = "org.freedesktop.systemd1.Unit",
1103 *property = "NeedDaemonReload",
1108 /* We ignore all errors here, since this is used to show a warning only */
1110 n = unit_name_mangle(unit);
1111 r = bus_method_call_with_reply (
1113 "org.freedesktop.systemd1",
1114 "/org/freedesktop/systemd1",
1115 "org.freedesktop.systemd1.Manager",
1119 DBUS_TYPE_STRING, n ? (const char**) &n : &unit,
1125 if (!dbus_message_get_args(reply, NULL,
1126 DBUS_TYPE_OBJECT_PATH, &path,
1130 dbus_message_unref(reply);
1131 r = bus_method_call_with_reply (
1133 "org.freedesktop.systemd1",
1135 "org.freedesktop.DBus.Properties",
1139 DBUS_TYPE_STRING, &interface,
1140 DBUS_TYPE_STRING, &property,
1145 if (!dbus_message_iter_init(reply, &iter) ||
1146 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1149 dbus_message_iter_recurse(&iter, &sub);
1151 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1154 dbus_message_iter_get_basic(&sub, &b);
1158 dbus_message_unref(reply);
1163 typedef struct WaitData {
1170 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1178 dbus_error_init(&error);
1180 log_debug("Got D-Bus request: %s.%s() on %s",
1181 dbus_message_get_interface(message),
1182 dbus_message_get_member(message),
1183 dbus_message_get_path(message));
1185 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1186 log_error("Warning! D-Bus connection terminated.");
1187 dbus_connection_close(connection);
1189 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1191 const char *path, *result, *unit;
1192 dbus_bool_t success = true;
1194 if (dbus_message_get_args(message, &error,
1195 DBUS_TYPE_UINT32, &id,
1196 DBUS_TYPE_OBJECT_PATH, &path,
1197 DBUS_TYPE_STRING, &unit,
1198 DBUS_TYPE_STRING, &result,
1199 DBUS_TYPE_INVALID)) {
1202 p = set_remove(d->set, (char*) path);
1205 if (!isempty(result))
1206 d->result = strdup(result);
1209 d->name = strdup(unit);
1214 dbus_error_free(&error);
1215 if (dbus_message_get_args(message, &error,
1216 DBUS_TYPE_UINT32, &id,
1217 DBUS_TYPE_OBJECT_PATH, &path,
1218 DBUS_TYPE_STRING, &result,
1219 DBUS_TYPE_INVALID)) {
1222 /* Compatibility with older systemd versions <
1223 * 183 during upgrades. This should be dropped
1225 p = set_remove(d->set, (char*) path);
1229 d->result = strdup(result);
1234 dbus_error_free(&error);
1235 if (dbus_message_get_args(message, &error,
1236 DBUS_TYPE_UINT32, &id,
1237 DBUS_TYPE_OBJECT_PATH, &path,
1238 DBUS_TYPE_BOOLEAN, &success,
1239 DBUS_TYPE_INVALID)) {
1242 /* Compatibility with older systemd versions <
1243 * 19 during upgrades. This should be dropped
1246 p = set_remove(d->set, (char*) path);
1250 d->result = strdup("failed");
1256 log_error("Failed to parse message: %s", bus_error_message(&error));
1260 dbus_error_free(&error);
1261 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1264 static int enable_wait_for_jobs(DBusConnection *bus) {
1272 dbus_error_init(&error);
1273 dbus_bus_add_match(bus,
1275 "sender='org.freedesktop.systemd1',"
1276 "interface='org.freedesktop.systemd1.Manager',"
1277 "member='JobRemoved',"
1278 "path='/org/freedesktop/systemd1'",
1281 if (dbus_error_is_set(&error)) {
1282 log_error("Failed to add match: %s", bus_error_message(&error));
1283 dbus_error_free(&error);
1287 /* This is slightly dirty, since we don't undo the match registrations. */
1291 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1301 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1304 while (!set_isempty(s)) {
1306 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1307 log_error("Disconnected from bus.");
1308 return -ECONNREFUSED;
1315 if (streq(d.result, "timeout"))
1316 log_error("Job for %s timed out.", strna(d.name));
1317 else if (streq(d.result, "canceled"))
1318 log_error("Job for %s canceled.", strna(d.name));
1319 else if (streq(d.result, "dependency"))
1320 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1321 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1322 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1325 if (streq_ptr(d.result, "timeout"))
1327 else if (streq_ptr(d.result, "canceled"))
1329 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1340 dbus_connection_remove_filter(bus, wait_filter, &d);
1344 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1345 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1346 DBusMessageIter iter, sub;
1348 *interface = "org.freedesktop.systemd1.Unit",
1349 *property = "ActiveState";
1350 const char *state, *path;
1351 _cleanup_free_ char *n = NULL;
1357 dbus_error_init(&error);
1359 n = unit_name_mangle(name);
1363 r = bus_method_call_with_reply (
1365 "org.freedesktop.systemd1",
1366 "/org/freedesktop/systemd1",
1367 "org.freedesktop.systemd1.Manager",
1371 DBUS_TYPE_STRING, &n,
1374 dbus_error_free(&error);
1381 if (!dbus_message_get_args(reply, NULL,
1382 DBUS_TYPE_OBJECT_PATH, &path,
1383 DBUS_TYPE_INVALID)) {
1384 log_error("Failed to parse reply.");
1388 dbus_message_unref(reply);
1391 r = bus_method_call_with_reply(
1393 "org.freedesktop.systemd1",
1395 "org.freedesktop.DBus.Properties",
1399 DBUS_TYPE_STRING, &interface,
1400 DBUS_TYPE_STRING, &property,
1408 if (!dbus_message_iter_init(reply, &iter) ||
1409 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1410 log_error("Failed to parse reply.");
1414 dbus_message_iter_recurse(&iter, &sub);
1416 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1417 log_error("Failed to parse reply.");
1421 dbus_message_iter_get_basic(&sub, &state);
1426 return strv_find(check_states, state) ? 1 : 0;
1429 static void check_triggering_units(
1430 DBusConnection *bus,
1431 const char *unit_name) {
1433 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1434 DBusMessageIter iter, sub;
1435 const char *interface = "org.freedesktop.systemd1.Unit",
1436 *triggered_by_property = "TriggeredBy";
1438 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1439 bool print_warning_label = true;
1442 n = unit_name_mangle(unit_name);
1448 unit_path = unit_dbus_path_from_name(n);
1454 r = bus_method_call_with_reply(
1456 "org.freedesktop.systemd1",
1458 "org.freedesktop.DBus.Properties",
1462 DBUS_TYPE_STRING, &interface,
1463 DBUS_TYPE_STRING, &triggered_by_property,
1468 if (!dbus_message_iter_init(reply, &iter) ||
1469 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1470 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) {
1479 const char * const check_states[] = {
1484 const char *service_trigger;
1486 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1487 log_error("Failed to parse reply.");
1491 dbus_message_iter_get_basic(&sub, &service_trigger);
1493 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1497 if (print_warning_label) {
1498 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1499 print_warning_label = false;
1502 log_warning(" %s", service_trigger);
1505 dbus_message_iter_next(&sub);
1509 static int start_unit_one(
1510 DBusConnection *bus,
1517 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1520 _cleanup_free_ char *n, *p = NULL;
1527 n = unit_name_mangle(name);
1531 r = bus_method_call_with_reply(
1533 "org.freedesktop.systemd1",
1534 "/org/freedesktop/systemd1",
1535 "org.freedesktop.systemd1.Manager",
1539 DBUS_TYPE_STRING, &n,
1540 DBUS_TYPE_STRING, &mode,
1543 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1544 /* There's always a fallback possible for
1545 * legacy actions. */
1548 log_error("Failed to issue method call: %s", bus_error_message(error));
1553 if (!dbus_message_get_args(reply, error,
1554 DBUS_TYPE_OBJECT_PATH, &path,
1555 DBUS_TYPE_INVALID)) {
1556 log_error("Failed to parse reply: %s", bus_error_message(error));
1560 if (need_daemon_reload(bus, n))
1561 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1562 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1571 log_error("Failed to add path to set.");
1581 static enum action verb_to_action(const char *verb) {
1582 if (streq(verb, "halt"))
1584 else if (streq(verb, "poweroff"))
1585 return ACTION_POWEROFF;
1586 else if (streq(verb, "reboot"))
1587 return ACTION_REBOOT;
1588 else if (streq(verb, "kexec"))
1589 return ACTION_KEXEC;
1590 else if (streq(verb, "rescue"))
1591 return ACTION_RESCUE;
1592 else if (streq(verb, "emergency"))
1593 return ACTION_EMERGENCY;
1594 else if (streq(verb, "default"))
1595 return ACTION_DEFAULT;
1596 else if (streq(verb, "exit"))
1598 else if (streq(verb, "suspend"))
1599 return ACTION_SUSPEND;
1600 else if (streq(verb, "hibernate"))
1601 return ACTION_HIBERNATE;
1602 else if (streq(verb, "hybrid-sleep"))
1603 return ACTION_HYBRID_SLEEP;
1605 return ACTION_INVALID;
1608 static int start_unit(DBusConnection *bus, char **args) {
1610 static const char * const table[_ACTION_MAX] = {
1611 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1612 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1613 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1614 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1615 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1616 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1617 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1618 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1619 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1620 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1621 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1622 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1623 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1624 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
1625 [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
1629 const char *method, *mode, *one_name;
1634 dbus_error_init(&error);
1638 ask_password_agent_open_if_enabled();
1640 if (arg_action == ACTION_SYSTEMCTL) {
1642 streq(args[0], "stop") ||
1643 streq(args[0], "condstop") ? "StopUnit" :
1644 streq(args[0], "reload") ? "ReloadUnit" :
1645 streq(args[0], "restart") ? "RestartUnit" :
1647 streq(args[0], "try-restart") ||
1648 streq(args[0], "condrestart") ? "TryRestartUnit" :
1650 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1652 streq(args[0], "reload-or-try-restart") ||
1653 streq(args[0], "condreload") ||
1655 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1659 (streq(args[0], "isolate") ||
1660 streq(args[0], "rescue") ||
1661 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1663 one_name = table[verb_to_action(args[0])];
1666 assert(arg_action < ELEMENTSOF(table));
1667 assert(table[arg_action]);
1669 method = "StartUnit";
1671 mode = (arg_action == ACTION_EMERGENCY ||
1672 arg_action == ACTION_RESCUE ||
1673 arg_action == ACTION_RUNLEVEL2 ||
1674 arg_action == ACTION_RUNLEVEL3 ||
1675 arg_action == ACTION_RUNLEVEL4 ||
1676 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1678 one_name = table[arg_action];
1681 if (!arg_no_block) {
1682 ret = enable_wait_for_jobs(bus);
1684 log_error("Could not watch jobs: %s", strerror(-ret));
1688 s = set_new(string_hash_func, string_compare_func);
1696 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1698 ret = translate_bus_error_to_exit_status(ret, &error);
1700 STRV_FOREACH(name, args+1) {
1701 r = start_unit_one(bus, method, *name, mode, &error, s);
1703 ret = translate_bus_error_to_exit_status(r, &error);
1704 dbus_error_free(&error);
1709 if (!arg_no_block) {
1710 r = wait_for_jobs(bus, s);
1716 /* When stopping units, warn if they can still be triggered by
1717 * another active unit (socket, path, timer) */
1718 if (!arg_quiet && streq(method, "StopUnit")) {
1720 check_triggering_units(bus, one_name);
1722 STRV_FOREACH(name, args+1)
1723 check_triggering_units(bus, *name);
1729 dbus_error_free(&error);
1734 /* Ask systemd-logind, which might grant access to unprivileged users
1735 * through PolicyKit */
1736 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1739 dbus_bool_t interactive = true;
1741 polkit_agent_open_if_enabled();
1749 case ACTION_POWEROFF:
1750 method = "PowerOff";
1753 case ACTION_SUSPEND:
1757 case ACTION_HIBERNATE:
1758 method = "Hibernate";
1761 case ACTION_HYBRID_SLEEP:
1762 method = "HybridSleep";
1769 return bus_method_call_with_reply (
1771 "org.freedesktop.login1",
1772 "/org/freedesktop/login1",
1773 "org.freedesktop.login1.Manager",
1777 DBUS_TYPE_BOOLEAN, &interactive,
1784 static int check_inhibitors(DBusConnection *bus, enum action a) {
1786 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1787 DBusMessageIter iter, sub, sub2;
1791 if (arg_ignore_inhibitors)
1797 r = bus_method_call_with_reply(
1799 "org.freedesktop.login1",
1800 "/org/freedesktop/login1",
1801 "org.freedesktop.login1.Manager",
1807 /* If logind is not around, then there are no inhibitors... */
1810 if (!dbus_message_iter_init(reply, &iter) ||
1811 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1812 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1813 log_error("Failed to parse reply.");
1817 dbus_message_iter_recurse(&iter, &sub);
1818 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1819 const char *what, *who, *why, *mode;
1821 _cleanup_strv_free_ char **sv = NULL;
1822 _cleanup_free_ char *comm = NULL;
1824 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1825 log_error("Failed to parse reply.");
1829 dbus_message_iter_recurse(&sub, &sub2);
1831 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
1832 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
1833 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
1834 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
1835 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
1836 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
1837 log_error("Failed to parse reply.");
1841 if (!streq(mode, "block"))
1844 sv = strv_split(what, ":");
1848 if (!strv_contains(sv,
1850 a == ACTION_POWEROFF ||
1851 a == ACTION_REBOOT ||
1852 a == ACTION_KEXEC ? "shutdown" : "sleep"))
1855 get_process_comm(pid, &comm);
1856 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", UID %lu), reason is \"%s\".", who, (unsigned long) pid, strna(comm), (unsigned long) uid, why);
1860 dbus_message_iter_next(&sub);
1863 dbus_message_iter_recurse(&iter, &sub);
1868 log_error("Please try again after closing inhibitors or ignore them with 'systemctl %s -i'.",
1869 a == ACTION_HALT ? "halt" :
1870 a == ACTION_POWEROFF ? "poweroff" :
1871 a == ACTION_REBOOT ? "reboot" :
1872 a == ACTION_KEXEC ? "kexec" :
1873 a == ACTION_SUSPEND ? "suspend" :
1874 a == ACTION_HIBERNATE ? "hibernate" : "hybrid-sleep");
1882 static int start_special(DBusConnection *bus, char **args) {
1888 a = verb_to_action(args[0]);
1890 if (arg_force >= 2 && geteuid() != 0) {
1891 log_error("Must be root.");
1895 if (arg_force >= 2 &&
1896 (a == ACTION_HALT ||
1897 a == ACTION_POWEROFF ||
1898 a == ACTION_REBOOT))
1901 if (arg_force >= 1 &&
1902 (a == ACTION_HALT ||
1903 a == ACTION_POWEROFF ||
1904 a == ACTION_REBOOT ||
1905 a == ACTION_KEXEC ||
1907 return daemon_reload(bus, args);
1909 if (arg_force <= 0) {
1910 r = check_inhibitors(bus, a);
1915 /* first try logind, to allow authentication with polkit */
1916 if (geteuid() != 0 &&
1917 (a == ACTION_POWEROFF ||
1918 a == ACTION_REBOOT ||
1919 a == ACTION_SUSPEND ||
1920 a == ACTION_HIBERNATE ||
1921 a == ACTION_HYBRID_SLEEP)) {
1922 r = reboot_with_logind(bus, a);
1927 r = start_unit(bus, args);
1934 static int check_unit_active(DBusConnection *bus, char **args) {
1935 const char * const check_states[] = {
1942 int r = 3; /* According to LSB: "program is not running" */
1947 STRV_FOREACH(name, args+1) {
1950 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1960 static int check_unit_failed(DBusConnection *bus, char **args) {
1961 const char * const check_states[] = {
1972 STRV_FOREACH(name, args+1) {
1975 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1985 static int kill_unit(DBusConnection *bus, char **args) {
1993 arg_kill_who = "all";
1995 STRV_FOREACH(name, args+1) {
1996 _cleanup_free_ char *n = NULL;
1998 n = unit_name_mangle(*name);
2000 r = bus_method_call_with_reply(
2002 "org.freedesktop.systemd1",
2003 "/org/freedesktop/systemd1",
2004 "org.freedesktop.systemd1.Manager",
2008 DBUS_TYPE_STRING, n ? &n : name,
2009 DBUS_TYPE_STRING, &arg_kill_who,
2010 DBUS_TYPE_INT32, &arg_signal,
2018 typedef struct ExecStatusInfo {
2026 usec_t start_timestamp;
2027 usec_t exit_timestamp;
2032 LIST_FIELDS(struct ExecStatusInfo, exec);
2035 static void exec_status_info_free(ExecStatusInfo *i) {
2044 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2045 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2046 DBusMessageIter sub2, sub3;
2050 int32_t code, status;
2056 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2059 dbus_message_iter_recurse(sub, &sub2);
2061 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2064 if (!(i->path = strdup(path)))
2067 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2068 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2072 dbus_message_iter_recurse(&sub2, &sub3);
2073 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2074 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2075 dbus_message_iter_next(&sub3);
2080 if (!(i->argv = new0(char*, n+1)))
2084 dbus_message_iter_recurse(&sub2, &sub3);
2085 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2088 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2089 dbus_message_iter_get_basic(&sub3, &s);
2090 dbus_message_iter_next(&sub3);
2092 if (!(i->argv[n++] = strdup(s)))
2096 if (!dbus_message_iter_next(&sub2) ||
2097 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2098 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2099 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2100 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2101 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2102 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2103 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2104 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2108 i->start_timestamp = (usec_t) start_timestamp;
2109 i->exit_timestamp = (usec_t) exit_timestamp;
2110 i->pid = (pid_t) pid;
2117 typedef struct UnitStatusInfo {
2119 const char *load_state;
2120 const char *active_state;
2121 const char *sub_state;
2122 const char *unit_file_state;
2124 const char *description;
2125 const char *following;
2127 char **documentation;
2129 const char *fragment_path;
2130 const char *source_path;
2131 const char *default_control_group;
2133 const char *load_error;
2136 usec_t inactive_exit_timestamp;
2137 usec_t inactive_exit_timestamp_monotonic;
2138 usec_t active_enter_timestamp;
2139 usec_t active_exit_timestamp;
2140 usec_t inactive_enter_timestamp;
2142 bool need_daemon_reload;
2147 const char *status_text;
2150 usec_t start_timestamp;
2151 usec_t exit_timestamp;
2153 int exit_code, exit_status;
2155 usec_t condition_timestamp;
2156 bool condition_result;
2159 unsigned n_accepted;
2160 unsigned n_connections;
2164 const char *sysfs_path;
2166 /* Mount, Automount */
2172 LIST_HEAD(ExecStatusInfo, exec);
2175 static void print_status_info(UnitStatusInfo *i) {
2177 const char *on, *off, *ss;
2179 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2180 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2185 /* This shows pretty information about a unit. See
2186 * print_property() for a low-level property printer */
2188 printf("%s", strna(i->id));
2190 if (i->description && !streq_ptr(i->id, i->description))
2191 printf(" - %s", i->description);
2196 printf("\t Follow: unit currently follows state of %s\n", i->following);
2198 if (streq_ptr(i->load_state, "error")) {
2199 on = ansi_highlight_red(true);
2200 off = ansi_highlight_red(false);
2204 path = i->source_path ? i->source_path : i->fragment_path;
2207 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2208 else if (path && i->unit_file_state)
2209 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2211 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2213 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2215 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2217 if (streq_ptr(i->active_state, "failed")) {
2218 on = ansi_highlight_red(true);
2219 off = ansi_highlight_red(false);
2220 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2221 on = ansi_highlight_green(true);
2222 off = ansi_highlight_green(false);
2227 printf("\t Active: %s%s (%s)%s",
2229 strna(i->active_state),
2233 printf("\t Active: %s%s%s",
2235 strna(i->active_state),
2238 if (!isempty(i->result) && !streq(i->result, "success"))
2239 printf(" (Result: %s)", i->result);
2241 timestamp = (streq_ptr(i->active_state, "active") ||
2242 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2243 (streq_ptr(i->active_state, "inactive") ||
2244 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2245 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2246 i->active_exit_timestamp;
2248 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2249 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2252 printf(" since %s; %s\n", s2, s1);
2254 printf(" since %s\n", s2);
2258 if (!i->condition_result && i->condition_timestamp > 0) {
2259 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2260 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2263 printf("\t start condition failed at %s; %s\n", s2, s1);
2265 printf("\t start condition failed at %s\n", s2);
2269 printf("\t Device: %s\n", i->sysfs_path);
2271 printf("\t Where: %s\n", i->where);
2273 printf("\t What: %s\n", i->what);
2275 if (!strv_isempty(i->documentation)) {
2279 STRV_FOREACH(t, i->documentation) {
2281 printf("\t Docs: %s\n", *t);
2284 printf("\t %s\n", *t);
2289 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2291 LIST_FOREACH(exec, p, i->exec) {
2295 /* Only show exited processes here */
2299 t = strv_join(p->argv, " ");
2300 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2303 good = is_clean_exit_lsb(p->code, p->status, NULL);
2305 on = ansi_highlight_red(true);
2306 off = ansi_highlight_red(false);
2310 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2312 if (p->code == CLD_EXITED) {
2315 printf("status=%i", p->status);
2317 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2322 printf("signal=%s", signal_to_string(p->status));
2324 printf(")%s\n", off);
2326 if (i->main_pid == p->pid &&
2327 i->start_timestamp == p->start_timestamp &&
2328 i->exit_timestamp == p->start_timestamp)
2329 /* Let's not show this twice */
2332 if (p->pid == i->control_pid)
2336 if (i->main_pid > 0 || i->control_pid > 0) {
2339 if (i->main_pid > 0) {
2340 printf("Main PID: %u", (unsigned) i->main_pid);
2344 get_process_comm(i->main_pid, &t);
2349 } else if (i->exit_code > 0) {
2350 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2352 if (i->exit_code == CLD_EXITED) {
2355 printf("status=%i", i->exit_status);
2357 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2362 printf("signal=%s", signal_to_string(i->exit_status));
2367 if (i->main_pid > 0 && i->control_pid > 0)
2370 if (i->control_pid > 0) {
2373 printf(" Control: %u", (unsigned) i->control_pid);
2375 get_process_comm(i->control_pid, &t);
2386 printf("\t Status: \"%s\"\n", i->status_text);
2388 if (i->default_control_group &&
2389 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2392 printf("\t CGroup: %s\n", i->default_control_group);
2394 if (arg_transport != TRANSPORT_SSH) {
2404 if (i->main_pid > 0)
2405 extra[k++] = i->main_pid;
2407 if (i->control_pid > 0)
2408 extra[k++] = i->control_pid;
2410 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2414 if (i->id && arg_transport != TRANSPORT_SSH) {
2416 arg_all * OUTPUT_SHOW_ALL |
2417 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2418 on_tty() * OUTPUT_COLOR |
2419 !arg_quiet * OUTPUT_WARN_CUTOFF;
2422 show_journal_by_unit(stdout,
2426 i->inactive_exit_timestamp_monotonic,
2431 if (i->need_daemon_reload)
2432 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2433 ansi_highlight_red(true),
2434 ansi_highlight_red(false),
2435 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2438 static void show_unit_help(UnitStatusInfo *i) {
2443 if (!i->documentation) {
2444 log_info("Documentation for %s not known.", i->id);
2448 STRV_FOREACH(p, i->documentation) {
2450 if (startswith(*p, "man:")) {
2453 char *page = NULL, *section = NULL;
2454 const char *args[4] = { "man", NULL, NULL, NULL };
2459 if ((*p)[k-1] == ')')
2460 e = strrchr(*p, '(');
2463 page = strndup((*p) + 4, e - *p - 4);
2469 section = strndup(e + 1, *p + k - e - 2);
2483 log_error("Failed to fork: %m");
2491 execvp(args[0], (char**) args);
2492 log_error("Failed to execute man: %m");
2493 _exit(EXIT_FAILURE);
2499 wait_for_terminate(pid, NULL);
2501 log_info("Can't show: %s", *p);
2505 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2511 switch (dbus_message_iter_get_arg_type(iter)) {
2513 case DBUS_TYPE_STRING: {
2516 dbus_message_iter_get_basic(iter, &s);
2519 if (streq(name, "Id"))
2521 else if (streq(name, "LoadState"))
2523 else if (streq(name, "ActiveState"))
2524 i->active_state = s;
2525 else if (streq(name, "SubState"))
2527 else if (streq(name, "Description"))
2529 else if (streq(name, "FragmentPath"))
2530 i->fragment_path = s;
2531 else if (streq(name, "SourcePath"))
2533 else if (streq(name, "DefaultControlGroup"))
2534 i->default_control_group = s;
2535 else if (streq(name, "StatusText"))
2537 else if (streq(name, "SysFSPath"))
2539 else if (streq(name, "Where"))
2541 else if (streq(name, "What"))
2543 else if (streq(name, "Following"))
2545 else if (streq(name, "UnitFileState"))
2546 i->unit_file_state = s;
2547 else if (streq(name, "Result"))
2554 case DBUS_TYPE_BOOLEAN: {
2557 dbus_message_iter_get_basic(iter, &b);
2559 if (streq(name, "Accept"))
2561 else if (streq(name, "NeedDaemonReload"))
2562 i->need_daemon_reload = b;
2563 else if (streq(name, "ConditionResult"))
2564 i->condition_result = b;
2569 case DBUS_TYPE_UINT32: {
2572 dbus_message_iter_get_basic(iter, &u);
2574 if (streq(name, "MainPID")) {
2576 i->main_pid = (pid_t) u;
2579 } else if (streq(name, "ControlPID"))
2580 i->control_pid = (pid_t) u;
2581 else if (streq(name, "ExecMainPID")) {
2583 i->main_pid = (pid_t) u;
2584 } else if (streq(name, "NAccepted"))
2586 else if (streq(name, "NConnections"))
2587 i->n_connections = u;
2592 case DBUS_TYPE_INT32: {
2595 dbus_message_iter_get_basic(iter, &j);
2597 if (streq(name, "ExecMainCode"))
2598 i->exit_code = (int) j;
2599 else if (streq(name, "ExecMainStatus"))
2600 i->exit_status = (int) j;
2605 case DBUS_TYPE_UINT64: {
2608 dbus_message_iter_get_basic(iter, &u);
2610 if (streq(name, "ExecMainStartTimestamp"))
2611 i->start_timestamp = (usec_t) u;
2612 else if (streq(name, "ExecMainExitTimestamp"))
2613 i->exit_timestamp = (usec_t) u;
2614 else if (streq(name, "ActiveEnterTimestamp"))
2615 i->active_enter_timestamp = (usec_t) u;
2616 else if (streq(name, "InactiveEnterTimestamp"))
2617 i->inactive_enter_timestamp = (usec_t) u;
2618 else if (streq(name, "InactiveExitTimestamp"))
2619 i->inactive_exit_timestamp = (usec_t) u;
2620 else if (streq(name, "InactiveExitTimestampMonotonic"))
2621 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2622 else if (streq(name, "ActiveExitTimestamp"))
2623 i->active_exit_timestamp = (usec_t) u;
2624 else if (streq(name, "ConditionTimestamp"))
2625 i->condition_timestamp = (usec_t) u;
2630 case DBUS_TYPE_ARRAY: {
2632 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2633 startswith(name, "Exec")) {
2634 DBusMessageIter sub;
2636 dbus_message_iter_recurse(iter, &sub);
2637 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2638 ExecStatusInfo *info;
2641 if (!(info = new0(ExecStatusInfo, 1)))
2644 if (!(info->name = strdup(name))) {
2649 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2654 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2656 dbus_message_iter_next(&sub);
2658 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2659 streq(name, "Documentation")) {
2661 DBusMessageIter sub;
2663 dbus_message_iter_recurse(iter, &sub);
2664 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2668 dbus_message_iter_get_basic(&sub, &s);
2670 l = strv_append(i->documentation, s);
2674 strv_free(i->documentation);
2675 i->documentation = l;
2677 dbus_message_iter_next(&sub);
2684 case DBUS_TYPE_STRUCT: {
2686 if (streq(name, "LoadError")) {
2687 DBusMessageIter sub;
2688 const char *n, *message;
2691 dbus_message_iter_recurse(iter, &sub);
2693 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2697 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2701 if (!isempty(message))
2702 i->load_error = message;
2712 static int print_property(const char *name, DBusMessageIter *iter) {
2716 /* This is a low-level property printer, see
2717 * print_status_info() for the nicer output */
2719 if (arg_property && !strv_find(arg_property, name))
2722 switch (dbus_message_iter_get_arg_type(iter)) {
2724 case DBUS_TYPE_STRUCT: {
2725 DBusMessageIter sub;
2726 dbus_message_iter_recurse(iter, &sub);
2728 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2731 dbus_message_iter_get_basic(&sub, &u);
2734 printf("%s=%u\n", name, (unsigned) u);
2736 printf("%s=\n", name);
2739 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2742 dbus_message_iter_get_basic(&sub, &s);
2744 if (arg_all || s[0])
2745 printf("%s=%s\n", name, s);
2748 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2749 const char *a = NULL, *b = NULL;
2751 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2752 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2754 if (arg_all || !isempty(a) || !isempty(b))
2755 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2763 case DBUS_TYPE_ARRAY:
2765 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2766 DBusMessageIter sub, sub2;
2768 dbus_message_iter_recurse(iter, &sub);
2769 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2773 dbus_message_iter_recurse(&sub, &sub2);
2775 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2776 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2777 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2779 dbus_message_iter_next(&sub);
2784 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2785 DBusMessageIter sub, sub2;
2787 dbus_message_iter_recurse(iter, &sub);
2788 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2789 const char *type, *path;
2791 dbus_message_iter_recurse(&sub, &sub2);
2793 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2794 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2795 printf("%s=%s\n", type, path);
2797 dbus_message_iter_next(&sub);
2802 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2803 DBusMessageIter sub, sub2;
2805 dbus_message_iter_recurse(iter, &sub);
2806 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2808 uint64_t value, next_elapse;
2810 dbus_message_iter_recurse(&sub, &sub2);
2812 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2813 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2814 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2815 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2817 printf("%s={ value=%s ; next_elapse=%s }\n",
2819 format_timespan(timespan1, sizeof(timespan1), value),
2820 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2823 dbus_message_iter_next(&sub);
2828 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2829 DBusMessageIter sub, sub2;
2831 dbus_message_iter_recurse(iter, &sub);
2832 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2833 const char *controller, *attr, *value;
2835 dbus_message_iter_recurse(&sub, &sub2);
2837 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2838 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2839 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2841 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2847 dbus_message_iter_next(&sub);
2852 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2853 DBusMessageIter sub;
2855 dbus_message_iter_recurse(iter, &sub);
2856 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2857 ExecStatusInfo info;
2860 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2861 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2864 t = strv_join(info.argv, " ");
2866 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2870 yes_no(info.ignore),
2871 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2872 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2873 (unsigned) info. pid,
2874 sigchld_code_to_string(info.code),
2876 info.code == CLD_EXITED ? "" : "/",
2877 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2883 strv_free(info.argv);
2885 dbus_message_iter_next(&sub);
2894 if (generic_print_property(name, iter, arg_all) > 0)
2898 printf("%s=[unprintable]\n", name);
2903 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2904 DBusMessage *reply = NULL;
2905 const char *interface = "";
2907 DBusMessageIter iter, sub, sub2, sub3;
2908 UnitStatusInfo info;
2916 r = bus_method_call_with_reply (
2918 "org.freedesktop.systemd1",
2920 "org.freedesktop.DBus.Properties",
2924 DBUS_TYPE_STRING, &interface,
2929 if (!dbus_message_iter_init(reply, &iter) ||
2930 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2931 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2932 log_error("Failed to parse reply.");
2937 dbus_message_iter_recurse(&iter, &sub);
2944 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2947 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2948 log_error("Failed to parse reply.");
2953 dbus_message_iter_recurse(&sub, &sub2);
2955 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2956 log_error("Failed to parse reply.");
2961 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2962 log_error("Failed to parse reply.");
2967 dbus_message_iter_recurse(&sub2, &sub3);
2969 if (show_properties)
2970 r = print_property(name, &sub3);
2972 r = status_property(name, &sub3, &info);
2975 log_error("Failed to parse reply.");
2980 dbus_message_iter_next(&sub);
2985 if (!show_properties) {
2986 if (streq(verb, "help"))
2987 show_unit_help(&info);
2989 print_status_info(&info);
2992 strv_free(info.documentation);
2994 if (!streq_ptr(info.active_state, "active") &&
2995 !streq_ptr(info.active_state, "reloading") &&
2996 streq(verb, "status"))
2997 /* According to LSB: "program not running" */
3000 while ((p = info.exec)) {
3001 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3002 exec_status_info_free(p);
3007 dbus_message_unref(reply);
3012 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3013 DBusMessage *reply = NULL;
3014 const char *path = NULL;
3018 dbus_error_init(&error);
3020 r = bus_method_call_with_reply (
3022 "org.freedesktop.systemd1",
3023 "/org/freedesktop/systemd1",
3024 "org.freedesktop.systemd1.Manager",
3028 DBUS_TYPE_UINT32, &pid,
3033 if (!dbus_message_get_args(reply, &error,
3034 DBUS_TYPE_OBJECT_PATH, &path,
3035 DBUS_TYPE_INVALID)) {
3036 log_error("Failed to parse reply: %s", bus_error_message(&error));
3041 r = show_one(verb, bus, path, false, new_line);
3045 dbus_message_unref(reply);
3047 dbus_error_free(&error);
3052 static int show(DBusConnection *bus, char **args) {
3054 bool show_properties, new_line = false;
3060 show_properties = streq(args[0], "show");
3062 if (show_properties)
3063 pager_open_if_enabled();
3065 if (show_properties && strv_length(args) <= 1) {
3066 /* If not argument is specified inspect the manager
3069 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3072 STRV_FOREACH(name, args+1) {
3075 if (safe_atou32(*name, &id) < 0) {
3077 /* Interpret as unit name */
3079 n = unit_name_mangle(*name);
3080 p = unit_dbus_path_from_name(n ? n : *name);
3085 r = show_one(args[0], bus, p, show_properties, &new_line);
3091 } else if (show_properties) {
3093 /* Interpret as job id */
3096 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3099 r = show_one(args[0], bus, p, show_properties, &new_line);
3107 /* Interpret as PID */
3109 r = show_one_by_pid(args[0], bus, id, &new_line);
3118 static int dump(DBusConnection *bus, char **args) {
3119 DBusMessage *reply = NULL;
3124 dbus_error_init(&error);
3126 pager_open_if_enabled();
3128 r = bus_method_call_with_reply (
3130 "org.freedesktop.systemd1",
3131 "/org/freedesktop/systemd1",
3132 "org.freedesktop.systemd1.Manager",
3140 if (!dbus_message_get_args(reply, &error,
3141 DBUS_TYPE_STRING, &text,
3142 DBUS_TYPE_INVALID)) {
3143 log_error("Failed to parse reply: %s", bus_error_message(&error));
3148 fputs(text, stdout);
3152 dbus_message_unref(reply);
3154 dbus_error_free(&error);
3159 static int snapshot(DBusConnection *bus, char **args) {
3160 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3163 dbus_bool_t cleanup = FALSE;
3164 DBusMessageIter iter, sub;
3166 *name = "", *path, *id,
3167 *interface = "org.freedesktop.systemd1.Unit",
3169 _cleanup_free_ char *n = NULL;
3171 dbus_error_init(&error);
3173 if (strv_length(args) > 1) {
3175 n = unit_name_mangle(name);
3178 r = bus_method_call_with_reply (
3180 "org.freedesktop.systemd1",
3181 "/org/freedesktop/systemd1",
3182 "org.freedesktop.systemd1.Manager",
3186 DBUS_TYPE_STRING, n ? (const char**) &n : &name,
3187 DBUS_TYPE_BOOLEAN, &cleanup,
3192 if (!dbus_message_get_args(reply, &error,
3193 DBUS_TYPE_OBJECT_PATH, &path,
3194 DBUS_TYPE_INVALID)) {
3195 log_error("Failed to parse reply: %s", bus_error_message(&error));
3200 dbus_message_unref(reply);
3203 r = bus_method_call_with_reply (
3205 "org.freedesktop.systemd1",
3207 "org.freedesktop.DBus.Properties",
3211 DBUS_TYPE_STRING, &interface,
3212 DBUS_TYPE_STRING, &property,
3217 if (!dbus_message_iter_init(reply, &iter) ||
3218 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3219 log_error("Failed to parse reply.");
3224 dbus_message_iter_recurse(&iter, &sub);
3226 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3227 log_error("Failed to parse reply.");
3232 dbus_message_iter_get_basic(&sub, &id);
3238 dbus_error_free(&error);
3243 static int delete_snapshot(DBusConnection *bus, char **args) {
3248 STRV_FOREACH(name, args+1) {
3249 _cleanup_free_ char *n = NULL;
3252 n = unit_name_mangle(*name);
3253 r = bus_method_call_with_reply(
3255 "org.freedesktop.systemd1",
3256 "/org/freedesktop/systemd1",
3257 "org.freedesktop.systemd1.Manager",
3261 DBUS_TYPE_STRING, n ? &n : name,
3270 static int daemon_reload(DBusConnection *bus, char **args) {
3275 if (arg_action == ACTION_RELOAD)
3277 else if (arg_action == ACTION_REEXEC)
3278 method = "Reexecute";
3280 assert(arg_action == ACTION_SYSTEMCTL);
3283 streq(args[0], "clear-jobs") ||
3284 streq(args[0], "cancel") ? "ClearJobs" :
3285 streq(args[0], "daemon-reexec") ? "Reexecute" :
3286 streq(args[0], "reset-failed") ? "ResetFailed" :
3287 streq(args[0], "halt") ? "Halt" :
3288 streq(args[0], "poweroff") ? "PowerOff" :
3289 streq(args[0], "reboot") ? "Reboot" :
3290 streq(args[0], "kexec") ? "KExec" :
3291 streq(args[0], "exit") ? "Exit" :
3292 /* "daemon-reload" */ "Reload";
3295 r = bus_method_call_with_reply (
3297 "org.freedesktop.systemd1",
3298 "/org/freedesktop/systemd1",
3299 "org.freedesktop.systemd1.Manager",
3305 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3306 /* There's always a fallback possible for
3307 * legacy actions. */
3309 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3310 /* On reexecution, we expect a disconnect, not
3314 log_error("Failed to issue method call: %s", bus_error_message(&error));
3315 dbus_error_free(&error);
3320 static int reset_failed(DBusConnection *bus, char **args) {
3324 if (strv_length(args) <= 1)
3325 return daemon_reload(bus, args);
3327 STRV_FOREACH(name, args+1) {
3328 n = unit_name_mangle(*name);
3329 r = bus_method_call_with_reply (
3331 "org.freedesktop.systemd1",
3332 "/org/freedesktop/systemd1",
3333 "org.freedesktop.systemd1.Manager",
3337 DBUS_TYPE_STRING, n ? &n : name,
3348 static int show_enviroment(DBusConnection *bus, char **args) {
3349 DBusMessage *reply = NULL;
3350 DBusMessageIter iter, sub, sub2;
3353 *interface = "org.freedesktop.systemd1.Manager",
3354 *property = "Environment";
3356 pager_open_if_enabled();
3358 r = bus_method_call_with_reply (
3360 "org.freedesktop.systemd1",
3361 "/org/freedesktop/systemd1",
3362 "org.freedesktop.DBus.Properties",
3366 DBUS_TYPE_STRING, &interface,
3367 DBUS_TYPE_STRING, &property,
3372 if (!dbus_message_iter_init(reply, &iter) ||
3373 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3374 log_error("Failed to parse reply.");
3379 dbus_message_iter_recurse(&iter, &sub);
3381 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3382 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3383 log_error("Failed to parse reply.");
3388 dbus_message_iter_recurse(&sub, &sub2);
3390 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3393 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3394 log_error("Failed to parse reply.");
3399 dbus_message_iter_get_basic(&sub2, &text);
3400 printf("%s\n", text);
3402 dbus_message_iter_next(&sub2);
3409 dbus_message_unref(reply);
3414 static int switch_root(DBusConnection *bus, char **args) {
3417 _cleanup_free_ char *init = NULL;
3419 l = strv_length(args);
3420 if (l < 2 || l > 3) {
3421 log_error("Wrong number of arguments.");
3428 init = strdup(args[2]);
3430 parse_env_file("/proc/cmdline", WHITESPACE,
3442 log_debug("switching root - root: %s; init: %s", root, init);
3444 return bus_method_call_with_reply (
3446 "org.freedesktop.systemd1",
3447 "/org/freedesktop/systemd1",
3448 "org.freedesktop.systemd1.Manager",
3452 DBUS_TYPE_STRING, &root,
3453 DBUS_TYPE_STRING, &init,
3457 static int set_environment(DBusConnection *bus, char **args) {
3458 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3461 DBusMessageIter iter;
3467 dbus_error_init(&error);
3469 method = streq(args[0], "set-environment")
3471 : "UnsetEnvironment";
3473 m = dbus_message_new_method_call(
3474 "org.freedesktop.systemd1",
3475 "/org/freedesktop/systemd1",
3476 "org.freedesktop.systemd1.Manager",
3481 dbus_message_iter_init_append(m, &iter);
3483 r = bus_append_strv_iter(&iter, args + 1);
3487 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3489 log_error("Failed to issue method call: %s", bus_error_message(&error));
3497 dbus_error_free(&error);
3501 static int enable_sysv_units(char **args) {
3504 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3505 const char *verb = args[0];
3506 unsigned f = 1, t = 1;
3509 if (arg_scope != UNIT_FILE_SYSTEM)
3512 if (!streq(verb, "enable") &&
3513 !streq(verb, "disable") &&
3514 !streq(verb, "is-enabled"))
3517 /* Processes all SysV units, and reshuffles the array so that
3518 * afterwards only the native units remain */
3521 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3526 for (f = 1; args[f]; f++) {
3529 bool found_native = false, found_sysv;
3531 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3532 char **k, *l, *q = NULL;
3539 if (!endswith(name, ".service"))
3542 if (path_is_absolute(name))
3545 STRV_FOREACH(k, paths.unit_path) {
3548 if (!isempty(arg_root))
3549 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3551 asprintf(&p, "%s/%s", *k, name);
3558 found_native = access(p, F_OK) >= 0;
3569 if (!isempty(arg_root))
3570 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3572 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3578 p[strlen(p) - sizeof(".service") + 1] = 0;
3579 found_sysv = access(p, F_OK) >= 0;
3586 /* Mark this entry, so that we don't try enabling it as native unit */
3587 args[f] = (char*) "";
3589 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3591 if (!isempty(arg_root))
3592 argv[c++] = q = strappend("--root=", arg_root);
3594 argv[c++] = path_get_file_name(p);
3596 streq(verb, "enable") ? "on" :
3597 streq(verb, "disable") ? "off" : "--level=5";
3600 l = strv_join((char**)argv, " ");
3608 log_info("Executing %s", l);
3613 log_error("Failed to fork: %m");
3618 } else if (pid == 0) {
3621 execv(argv[0], (char**) argv);
3622 _exit(EXIT_FAILURE);
3628 j = wait_for_terminate(pid, &status);
3630 log_error("Failed to wait for child: %s", strerror(-r));
3635 if (status.si_code == CLD_EXITED) {
3636 if (streq(verb, "is-enabled")) {
3637 if (status.si_status == 0) {
3646 } else if (status.si_status != 0) {
3657 lookup_paths_free(&paths);
3659 /* Drop all SysV units */
3660 for (f = 1, t = 1; args[f]; f++) {
3662 if (isempty(args[f]))
3665 args[t++] = args[f];
3674 static int mangle_names(char **original_names, char ***mangled_names) {
3675 char **i, **l, **name;
3677 l = new(char*, strv_length(original_names) + 1);
3682 STRV_FOREACH(name, original_names) {
3684 /* When enabling units qualified path names are OK,
3685 * too, hence allow them explicitly. */
3690 *i = unit_name_mangle(*name);
3706 static int enable_unit(DBusConnection *bus, char **args) {
3707 const char *verb = args[0];
3708 UnitFileChange *changes = NULL;
3709 unsigned n_changes = 0, i;
3710 int carries_install_info = -1;
3711 DBusMessage *m = NULL, *reply = NULL;
3714 char **mangled_names = NULL;
3716 r = enable_sysv_units(args);
3723 dbus_error_init(&error);
3725 if (!bus || avoid_bus()) {
3726 if (streq(verb, "enable")) {
3727 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3728 carries_install_info = r;
3729 } else if (streq(verb, "disable"))
3730 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3731 else if (streq(verb, "reenable")) {
3732 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3733 carries_install_info = r;
3734 } else if (streq(verb, "link"))
3735 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3736 else if (streq(verb, "preset")) {
3737 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3738 carries_install_info = r;
3739 } else if (streq(verb, "mask"))
3740 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3741 else if (streq(verb, "unmask"))
3742 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3744 assert_not_reached("Unknown verb");
3747 log_error("Operation failed: %s", strerror(-r));
3752 for (i = 0; i < n_changes; i++) {
3753 if (changes[i].type == UNIT_FILE_SYMLINK)
3754 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3756 log_info("rm '%s'", changes[i].path);
3763 bool send_force = true, expect_carries_install_info = false;
3765 DBusMessageIter iter, sub, sub2;
3767 if (streq(verb, "enable")) {
3768 method = "EnableUnitFiles";
3769 expect_carries_install_info = true;
3770 } else if (streq(verb, "disable")) {
3771 method = "DisableUnitFiles";
3773 } else if (streq(verb, "reenable")) {
3774 method = "ReenableUnitFiles";
3775 expect_carries_install_info = true;
3776 } else if (streq(verb, "link"))
3777 method = "LinkUnitFiles";
3778 else if (streq(verb, "preset")) {
3779 method = "PresetUnitFiles";
3780 expect_carries_install_info = true;
3781 } else if (streq(verb, "mask"))
3782 method = "MaskUnitFiles";
3783 else if (streq(verb, "unmask")) {
3784 method = "UnmaskUnitFiles";
3787 assert_not_reached("Unknown verb");
3789 m = dbus_message_new_method_call(
3790 "org.freedesktop.systemd1",
3791 "/org/freedesktop/systemd1",
3792 "org.freedesktop.systemd1.Manager",
3799 dbus_message_iter_init_append(m, &iter);
3801 r = mangle_names(args+1, &mangled_names);
3805 r = bus_append_strv_iter(&iter, mangled_names);
3807 log_error("Failed to append unit files.");
3812 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3813 log_error("Failed to append runtime boolean.");
3821 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3822 log_error("Failed to append force boolean.");
3828 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3830 log_error("Failed to issue method call: %s", bus_error_message(&error));
3835 if (!dbus_message_iter_init(reply, &iter)) {
3836 log_error("Failed to initialize iterator.");
3840 if (expect_carries_install_info) {
3841 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3843 log_error("Failed to parse reply.");
3847 carries_install_info = b;
3850 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3851 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3852 log_error("Failed to parse reply.");
3857 dbus_message_iter_recurse(&iter, &sub);
3858 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3859 const char *type, *path, *source;
3861 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3862 log_error("Failed to parse reply.");
3867 dbus_message_iter_recurse(&sub, &sub2);
3869 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3870 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3871 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3872 log_error("Failed to parse reply.");
3878 if (streq(type, "symlink"))
3879 log_info("ln -s '%s' '%s'", source, path);
3881 log_info("rm '%s'", path);
3884 dbus_message_iter_next(&sub);
3887 /* Try to reload if enabeld */
3889 r = daemon_reload(bus, args);
3892 if (carries_install_info == 0)
3894 "The unit files have no [Install] section. They are not meant to be enabled\n"
3895 "using systemctl.\n"
3896 "Possible reasons for having this kind of units are:\n"
3897 "1) A unit may be statically enabled by being symlinked from another unit's\n"
3898 " .wants/ or .requires/ directory.\n"
3899 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
3900 " a requirement dependency on it.\n"
3901 "3) A unit may be started when needed via activation (socket, path, timer,\n"
3902 " D-Bus, udev, scripted systemctl call, ...).\n");
3906 dbus_message_unref(m);
3909 dbus_message_unref(reply);
3911 unit_file_changes_free(changes, n_changes);
3913 dbus_error_free(&error);
3915 strv_free(mangled_names);
3920 static int unit_is_enabled(DBusConnection *bus, char **args) {
3923 DBusMessage *reply = NULL;
3927 dbus_error_init(&error);
3929 r = enable_sysv_units(args);
3935 if (!bus || avoid_bus()) {
3937 STRV_FOREACH(name, args+1) {
3938 UnitFileState state;
3940 state = unit_file_get_state(arg_scope, arg_root, *name);
3946 if (state == UNIT_FILE_ENABLED ||
3947 state == UNIT_FILE_ENABLED_RUNTIME ||
3948 state == UNIT_FILE_STATIC)
3952 puts(unit_file_state_to_string(state));
3956 STRV_FOREACH(name, args+1) {
3959 r = bus_method_call_with_reply (
3961 "org.freedesktop.systemd1",
3962 "/org/freedesktop/systemd1",
3963 "org.freedesktop.systemd1.Manager",
3967 DBUS_TYPE_STRING, name,
3972 if (!dbus_message_get_args(reply, &error,
3973 DBUS_TYPE_STRING, &s,
3974 DBUS_TYPE_INVALID)) {
3975 log_error("Failed to parse reply: %s", bus_error_message(&error));
3980 dbus_message_unref(reply);
3983 if (streq(s, "enabled") ||
3984 streq(s, "enabled-runtime") ||
3993 r = enabled ? 0 : 1;
3997 dbus_message_unref(reply);
3999 dbus_error_free(&error);
4003 static int systemctl_help(void) {
4005 pager_open_if_enabled();
4007 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4008 "Query or send control commands to the systemd manager.\n\n"
4009 " -h --help Show this help\n"
4010 " --version Show package version\n"
4011 " -t --type=TYPE List only units of a particular type\n"
4012 " -p --property=NAME Show only properties by this name\n"
4013 " -a --all Show all units/properties, including dead/empty ones\n"
4014 " --failed Show only failed units\n"
4015 " --full Don't ellipsize unit names on output\n"
4016 " --fail When queueing a new job, fail if conflicting jobs are\n"
4018 " --ignore-dependencies\n"
4019 " When queueing a new job, ignore all its dependencies\n"
4020 " -i --ignore-inhibitors\n"
4021 " When shutting down or sleeping, ignore inhibitors\n"
4022 " --kill-who=WHO Who to send signal to\n"
4023 " -s --signal=SIGNAL Which signal to send\n"
4024 " -H --host=[USER@]HOST\n"
4025 " Show information for remote host\n"
4026 " -P --privileged Acquire privileges before execution\n"
4027 " -q --quiet Suppress output\n"
4028 " --no-block Do not wait until operation finished\n"
4029 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4030 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4032 " --no-legend Do not print a legend (column headers and hints)\n"
4033 " --no-pager Do not pipe output into a pager\n"
4034 " --no-ask-password\n"
4035 " Do not ask for system passwords\n"
4036 " --order When generating graph for dot, show only order\n"
4037 " --require When generating graph for dot, show only requirement\n"
4038 " --system Connect to system manager\n"
4039 " --user Connect to user service manager\n"
4040 " --global Enable/disable unit files globally\n"
4041 " -f --force When enabling unit files, override existing symlinks\n"
4042 " When shutting down, execute action immediately\n"
4043 " --root=PATH Enable unit files in the specified root directory\n"
4044 " --runtime Enable unit files only temporarily until next reboot\n"
4045 " -n --lines=INTEGER Journal entries to show\n"
4046 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4047 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4049 " list-units List loaded units\n"
4050 " start [NAME...] Start (activate) one or more units\n"
4051 " stop [NAME...] Stop (deactivate) one or more units\n"
4052 " reload [NAME...] Reload one or more units\n"
4053 " restart [NAME...] Start or restart one or more units\n"
4054 " try-restart [NAME...] Restart one or more units if active\n"
4055 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4056 " otherwise start or restart\n"
4057 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4058 " otherwise restart if active\n"
4059 " isolate [NAME] Start one unit and stop all others\n"
4060 " kill [NAME...] Send signal to processes of a unit\n"
4061 " is-active [NAME...] Check whether units are active\n"
4062 " is-failed [NAME...] Check whether units are failed\n"
4063 " status [NAME...|PID...] Show runtime status of one or more units\n"
4064 " show [NAME...|JOB...] Show properties of one or more\n"
4065 " units/jobs or the manager\n"
4066 " help [NAME...|PID...] Show manual for one or more units\n"
4067 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4069 " load [NAME...] Load one or more units\n\n"
4070 "Unit File Commands:\n"
4071 " list-unit-files List installed unit files\n"
4072 " enable [NAME...] Enable one or more unit files\n"
4073 " disable [NAME...] Disable one or more unit files\n"
4074 " reenable [NAME...] Reenable one or more unit files\n"
4075 " preset [NAME...] Enable/disable one or more unit files\n"
4076 " based on preset configuration\n"
4077 " mask [NAME...] Mask one or more units\n"
4078 " unmask [NAME...] Unmask one or more units\n"
4079 " link [PATH...] Link one or more units files into\n"
4080 " the search path\n"
4081 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4083 " list-jobs List jobs\n"
4084 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4085 "Status Commands:\n"
4086 " dump Dump server status\n"
4087 " dot Dump dependency graph for dot(1)\n\n"
4088 "Snapshot Commands:\n"
4089 " snapshot [NAME] Create a snapshot\n"
4090 " delete [NAME...] Remove one or more snapshots\n\n"
4091 "Environment Commands:\n"
4092 " show-environment Dump environment\n"
4093 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4094 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4095 "Manager Lifecycle Commands:\n"
4096 " daemon-reload Reload systemd manager configuration\n"
4097 " daemon-reexec Reexecute systemd manager\n\n"
4098 "System Commands:\n"
4099 " default Enter system default mode\n"
4100 " rescue Enter system rescue mode\n"
4101 " emergency Enter system emergency mode\n"
4102 " halt Shut down and halt the system\n"
4103 " poweroff Shut down and power-off the system\n"
4104 " reboot Shut down and reboot the system\n"
4105 " kexec Shut down and reboot the system with kexec\n"
4106 " exit Request user instance exit\n"
4107 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4108 " suspend Suspend the system\n"
4109 " hibernate Hibernate the system\n"
4110 " hybrid-sleep Hibernate and suspend the system\n",
4111 program_invocation_short_name);
4116 static int halt_help(void) {
4118 printf("%s [OPTIONS...]\n\n"
4119 "%s the system.\n\n"
4120 " --help Show this help\n"
4121 " --halt Halt the machine\n"
4122 " -p --poweroff Switch off the machine\n"
4123 " --reboot Reboot the machine\n"
4124 " -f --force Force immediate halt/power-off/reboot\n"
4125 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4126 " -d --no-wtmp Don't write wtmp record\n"
4127 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4128 program_invocation_short_name,
4129 arg_action == ACTION_REBOOT ? "Reboot" :
4130 arg_action == ACTION_POWEROFF ? "Power off" :
4136 static int shutdown_help(void) {
4138 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4139 "Shut down the system.\n\n"
4140 " --help Show this help\n"
4141 " -H --halt Halt the machine\n"
4142 " -P --poweroff Power-off the machine\n"
4143 " -r --reboot Reboot the machine\n"
4144 " -h Equivalent to --poweroff, overridden by --halt\n"
4145 " -k Don't halt/power-off/reboot, just send warnings\n"
4146 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4147 " -c Cancel a pending shutdown\n",
4148 program_invocation_short_name);
4153 static int telinit_help(void) {
4155 printf("%s [OPTIONS...] {COMMAND}\n\n"
4156 "Send control commands to the init daemon.\n\n"
4157 " --help Show this help\n"
4158 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4160 " 0 Power-off the machine\n"
4161 " 6 Reboot the machine\n"
4162 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4163 " 1, s, S Enter rescue mode\n"
4164 " q, Q Reload init daemon configuration\n"
4165 " u, U Reexecute init daemon\n",
4166 program_invocation_short_name);
4171 static int runlevel_help(void) {
4173 printf("%s [OPTIONS...]\n\n"
4174 "Prints the previous and current runlevel of the init system.\n\n"
4175 " --help Show this help\n",
4176 program_invocation_short_name);
4181 static int help_types(void) {
4184 puts("Available unit types:");
4185 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4186 if (unit_type_table[i])
4187 puts(unit_type_table[i]);
4189 puts("\nAvailable unit load states: ");
4190 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4191 if (unit_type_table[i])
4192 puts(unit_load_state_table[i]);
4197 static int systemctl_parse_argv(int argc, char *argv[]) {
4201 ARG_IGNORE_DEPENDENCIES,
4216 ARG_NO_ASK_PASSWORD,
4222 static const struct option options[] = {
4223 { "help", no_argument, NULL, 'h' },
4224 { "version", no_argument, NULL, ARG_VERSION },
4225 { "type", required_argument, NULL, 't' },
4226 { "property", required_argument, NULL, 'p' },
4227 { "all", no_argument, NULL, 'a' },
4228 { "failed", no_argument, NULL, ARG_FAILED },
4229 { "full", no_argument, NULL, ARG_FULL },
4230 { "fail", no_argument, NULL, ARG_FAIL },
4231 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4232 { "ignore-inhibitors", no_argument, NULL, 'i' },
4233 { "user", no_argument, NULL, ARG_USER },
4234 { "system", no_argument, NULL, ARG_SYSTEM },
4235 { "global", no_argument, NULL, ARG_GLOBAL },
4236 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4237 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4238 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4239 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4240 { "quiet", no_argument, NULL, 'q' },
4241 { "order", no_argument, NULL, ARG_ORDER },
4242 { "require", no_argument, NULL, ARG_REQUIRE },
4243 { "root", required_argument, NULL, ARG_ROOT },
4244 { "force", no_argument, NULL, ARG_FORCE },
4245 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4246 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4247 { "signal", required_argument, NULL, 's' },
4248 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4249 { "host", required_argument, NULL, 'H' },
4250 { "privileged",no_argument, NULL, 'P' },
4251 { "runtime", no_argument, NULL, ARG_RUNTIME },
4252 { "lines", required_argument, NULL, 'n' },
4253 { "output", required_argument, NULL, 'o' },
4254 { NULL, 0, NULL, 0 }
4262 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4271 puts(PACKAGE_STRING);
4272 puts(SYSTEMD_FEATURES);
4276 if (streq(optarg, "help")) {
4281 if (unit_type_from_string(optarg) >= 0) {
4285 if (unit_load_state_from_string(optarg) >= 0) {
4286 arg_load_state = optarg;
4289 log_error("Unkown unit type or load state '%s'.",
4291 log_info("Use -t help to see a list of allowed values.");
4296 if (!(l = strv_append(arg_property, optarg)))
4299 strv_free(arg_property);
4302 /* If the user asked for a particular
4303 * property, show it to him, even if it is
4314 arg_job_mode = "fail";
4317 case ARG_IGNORE_DEPENDENCIES:
4318 arg_job_mode = "ignore-dependencies";
4322 arg_scope = UNIT_FILE_USER;
4326 arg_scope = UNIT_FILE_SYSTEM;
4330 arg_scope = UNIT_FILE_GLOBAL;
4334 arg_no_block = true;
4338 arg_no_legend = true;
4342 arg_no_pager = true;
4350 arg_dot = DOT_ORDER;
4354 arg_dot = DOT_REQUIRE;
4382 arg_no_reload = true;
4386 arg_kill_who = optarg;
4390 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4391 log_error("Failed to parse signal string %s.", optarg);
4396 case ARG_NO_ASK_PASSWORD:
4397 arg_ask_password = false;
4401 arg_transport = TRANSPORT_POLKIT;
4405 arg_transport = TRANSPORT_SSH;
4414 if (safe_atou(optarg, &arg_lines) < 0) {
4415 log_error("Failed to parse lines '%s'", optarg);
4421 arg_output = output_mode_from_string(optarg);
4422 if (arg_output < 0) {
4423 log_error("Unknown output '%s'.", optarg);
4429 arg_ignore_inhibitors = true;
4436 log_error("Unknown option code '%c'.", c);
4441 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4442 log_error("Cannot access user instance remotely.");
4449 static int halt_parse_argv(int argc, char *argv[]) {
4458 static const struct option options[] = {
4459 { "help", no_argument, NULL, ARG_HELP },
4460 { "halt", no_argument, NULL, ARG_HALT },
4461 { "poweroff", no_argument, NULL, 'p' },
4462 { "reboot", no_argument, NULL, ARG_REBOOT },
4463 { "force", no_argument, NULL, 'f' },
4464 { "wtmp-only", no_argument, NULL, 'w' },
4465 { "no-wtmp", no_argument, NULL, 'd' },
4466 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4467 { NULL, 0, NULL, 0 }
4475 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4476 if (runlevel == '0' || runlevel == '6')
4479 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4487 arg_action = ACTION_HALT;
4491 if (arg_action != ACTION_REBOOT)
4492 arg_action = ACTION_POWEROFF;
4496 arg_action = ACTION_REBOOT;
4518 /* Compatibility nops */
4525 log_error("Unknown option code '%c'.", c);
4530 if (optind < argc) {
4531 log_error("Too many arguments.");
4538 static int parse_time_spec(const char *t, usec_t *_u) {
4542 if (streq(t, "now"))
4544 else if (!strchr(t, ':')) {
4547 if (safe_atou64(t, &u) < 0)
4550 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4559 hour = strtol(t, &e, 10);
4560 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4563 minute = strtol(e+1, &e, 10);
4564 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4567 n = now(CLOCK_REALTIME);
4568 s = (time_t) (n / USEC_PER_SEC);
4571 assert_se(localtime_r(&s, &tm));
4573 tm.tm_hour = (int) hour;
4574 tm.tm_min = (int) minute;
4577 assert_se(s = mktime(&tm));
4579 *_u = (usec_t) s * USEC_PER_SEC;
4582 *_u += USEC_PER_DAY;
4588 static int shutdown_parse_argv(int argc, char *argv[]) {
4595 static const struct option options[] = {
4596 { "help", no_argument, NULL, ARG_HELP },
4597 { "halt", no_argument, NULL, 'H' },
4598 { "poweroff", no_argument, NULL, 'P' },
4599 { "reboot", no_argument, NULL, 'r' },
4600 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4601 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4602 { NULL, 0, NULL, 0 }
4610 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4618 arg_action = ACTION_HALT;
4622 arg_action = ACTION_POWEROFF;
4627 arg_action = ACTION_KEXEC;
4629 arg_action = ACTION_REBOOT;
4633 arg_action = ACTION_KEXEC;
4637 if (arg_action != ACTION_HALT)
4638 arg_action = ACTION_POWEROFF;
4651 /* Compatibility nops */
4655 arg_action = ACTION_CANCEL_SHUTDOWN;
4662 log_error("Unknown option code '%c'.", c);
4667 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4668 r = parse_time_spec(argv[optind], &arg_when);
4670 log_error("Failed to parse time specification: %s", argv[optind]);
4674 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4676 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4677 /* No time argument for shutdown cancel */
4678 arg_wall = argv + optind;
4679 else if (argc > optind + 1)
4680 /* We skip the time argument */
4681 arg_wall = argv + optind + 1;
4688 static int telinit_parse_argv(int argc, char *argv[]) {
4695 static const struct option options[] = {
4696 { "help", no_argument, NULL, ARG_HELP },
4697 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4698 { NULL, 0, NULL, 0 }
4701 static const struct {
4705 { '0', ACTION_POWEROFF },
4706 { '6', ACTION_REBOOT },
4707 { '1', ACTION_RESCUE },
4708 { '2', ACTION_RUNLEVEL2 },
4709 { '3', ACTION_RUNLEVEL3 },
4710 { '4', ACTION_RUNLEVEL4 },
4711 { '5', ACTION_RUNLEVEL5 },
4712 { 's', ACTION_RESCUE },
4713 { 'S', ACTION_RESCUE },
4714 { 'q', ACTION_RELOAD },
4715 { 'Q', ACTION_RELOAD },
4716 { 'u', ACTION_REEXEC },
4717 { 'U', ACTION_REEXEC }
4726 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4741 log_error("Unknown option code '%c'.", c);
4746 if (optind >= argc) {
4751 if (optind + 1 < argc) {
4752 log_error("Too many arguments.");
4756 if (strlen(argv[optind]) != 1) {
4757 log_error("Expected single character argument.");
4761 for (i = 0; i < ELEMENTSOF(table); i++)
4762 if (table[i].from == argv[optind][0])
4765 if (i >= ELEMENTSOF(table)) {
4766 log_error("Unknown command '%s'.", argv[optind]);
4770 arg_action = table[i].to;
4777 static int runlevel_parse_argv(int argc, char *argv[]) {
4783 static const struct option options[] = {
4784 { "help", no_argument, NULL, ARG_HELP },
4785 { NULL, 0, NULL, 0 }
4793 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4804 log_error("Unknown option code '%c'.", c);
4809 if (optind < argc) {
4810 log_error("Too many arguments.");
4817 static int parse_argv(int argc, char *argv[]) {
4821 if (program_invocation_short_name) {
4823 if (strstr(program_invocation_short_name, "halt")) {
4824 arg_action = ACTION_HALT;
4825 return halt_parse_argv(argc, argv);
4826 } else if (strstr(program_invocation_short_name, "poweroff")) {
4827 arg_action = ACTION_POWEROFF;
4828 return halt_parse_argv(argc, argv);
4829 } else if (strstr(program_invocation_short_name, "reboot")) {
4831 arg_action = ACTION_KEXEC;
4833 arg_action = ACTION_REBOOT;
4834 return halt_parse_argv(argc, argv);
4835 } else if (strstr(program_invocation_short_name, "shutdown")) {
4836 arg_action = ACTION_POWEROFF;
4837 return shutdown_parse_argv(argc, argv);
4838 } else if (strstr(program_invocation_short_name, "init")) {
4840 if (sd_booted() > 0) {
4841 arg_action = ACTION_INVALID;
4842 return telinit_parse_argv(argc, argv);
4844 /* Hmm, so some other init system is
4845 * running, we need to forward this
4846 * request to it. For now we simply
4847 * guess that it is Upstart. */
4849 execv("/lib/upstart/telinit", argv);
4851 log_error("Couldn't find an alternative telinit implementation to spawn.");
4855 } else if (strstr(program_invocation_short_name, "runlevel")) {
4856 arg_action = ACTION_RUNLEVEL;
4857 return runlevel_parse_argv(argc, argv);
4861 arg_action = ACTION_SYSTEMCTL;
4862 return systemctl_parse_argv(argc, argv);
4865 static int action_to_runlevel(void) {
4867 static const char table[_ACTION_MAX] = {
4868 [ACTION_HALT] = '0',
4869 [ACTION_POWEROFF] = '0',
4870 [ACTION_REBOOT] = '6',
4871 [ACTION_RUNLEVEL2] = '2',
4872 [ACTION_RUNLEVEL3] = '3',
4873 [ACTION_RUNLEVEL4] = '4',
4874 [ACTION_RUNLEVEL5] = '5',
4875 [ACTION_RESCUE] = '1'
4878 assert(arg_action < _ACTION_MAX);
4880 return table[arg_action];
4883 static int talk_upstart(void) {
4884 DBusMessage *m = NULL, *reply = NULL;
4886 int previous, rl, r;
4888 env1_buf[] = "RUNLEVEL=X",
4889 env2_buf[] = "PREVLEVEL=X";
4890 char *env1 = env1_buf, *env2 = env2_buf;
4891 const char *emit = "runlevel";
4892 dbus_bool_t b_false = FALSE;
4893 DBusMessageIter iter, sub;
4894 DBusConnection *bus;
4896 dbus_error_init(&error);
4898 if (!(rl = action_to_runlevel()))
4901 if (utmp_get_runlevel(&previous, NULL) < 0)
4904 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4905 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4910 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4915 if ((r = bus_check_peercred(bus)) < 0) {
4916 log_error("Failed to verify owner of bus.");
4920 if (!(m = dbus_message_new_method_call(
4921 "com.ubuntu.Upstart",
4922 "/com/ubuntu/Upstart",
4923 "com.ubuntu.Upstart0_6",
4926 log_error("Could not allocate message.");
4931 dbus_message_iter_init_append(m, &iter);
4933 env1_buf[sizeof(env1_buf)-2] = rl;
4934 env2_buf[sizeof(env2_buf)-2] = previous;
4936 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4937 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4938 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4939 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4940 !dbus_message_iter_close_container(&iter, &sub) ||
4941 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4942 log_error("Could not append arguments to message.");
4947 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4949 if (bus_error_is_no_service(&error)) {
4954 log_error("Failed to issue method call: %s", bus_error_message(&error));
4963 dbus_message_unref(m);
4966 dbus_message_unref(reply);
4969 dbus_connection_flush(bus);
4970 dbus_connection_close(bus);
4971 dbus_connection_unref(bus);
4974 dbus_error_free(&error);
4979 static int talk_initctl(void) {
4980 struct init_request request;
4984 if (!(rl = action_to_runlevel()))
4988 request.magic = INIT_MAGIC;
4989 request.sleeptime = 0;
4990 request.cmd = INIT_CMD_RUNLVL;
4991 request.runlevel = rl;
4993 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4995 if (errno == ENOENT)
4998 log_error("Failed to open "INIT_FIFO": %m");
5003 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5004 close_nointr_nofail(fd);
5007 log_error("Failed to write to "INIT_FIFO": %m");
5008 return errno ? -errno : -EIO;
5014 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5016 static const struct {
5024 int (* const dispatch)(DBusConnection *bus, char **args);
5026 { "list-units", LESS, 1, list_units },
5027 { "list-unit-files", EQUAL, 1, list_unit_files },
5028 { "list-jobs", EQUAL, 1, list_jobs },
5029 { "clear-jobs", EQUAL, 1, daemon_reload },
5030 { "load", MORE, 2, load_unit },
5031 { "cancel", MORE, 2, cancel_job },
5032 { "start", MORE, 2, start_unit },
5033 { "stop", MORE, 2, start_unit },
5034 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5035 { "reload", MORE, 2, start_unit },
5036 { "restart", MORE, 2, start_unit },
5037 { "try-restart", MORE, 2, start_unit },
5038 { "reload-or-restart", MORE, 2, start_unit },
5039 { "reload-or-try-restart", MORE, 2, start_unit },
5040 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5041 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5042 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5043 { "isolate", EQUAL, 2, start_unit },
5044 { "kill", MORE, 2, kill_unit },
5045 { "is-active", MORE, 2, check_unit_active },
5046 { "check", MORE, 2, check_unit_active },
5047 { "is-failed", MORE, 2, check_unit_failed },
5048 { "show", MORE, 1, show },
5049 { "status", MORE, 2, show },
5050 { "help", MORE, 2, show },
5051 { "dump", EQUAL, 1, dump },
5052 { "dot", EQUAL, 1, dot },
5053 { "snapshot", LESS, 2, snapshot },
5054 { "delete", MORE, 2, delete_snapshot },
5055 { "daemon-reload", EQUAL, 1, daemon_reload },
5056 { "daemon-reexec", EQUAL, 1, daemon_reload },
5057 { "show-environment", EQUAL, 1, show_enviroment },
5058 { "set-environment", MORE, 2, set_environment },
5059 { "unset-environment", MORE, 2, set_environment },
5060 { "halt", EQUAL, 1, start_special },
5061 { "poweroff", EQUAL, 1, start_special },
5062 { "reboot", EQUAL, 1, start_special },
5063 { "kexec", EQUAL, 1, start_special },
5064 { "suspend", EQUAL, 1, start_special },
5065 { "hibernate", EQUAL, 1, start_special },
5066 { "hybrid-sleep", EQUAL, 1, start_special },
5067 { "default", EQUAL, 1, start_special },
5068 { "rescue", EQUAL, 1, start_special },
5069 { "emergency", EQUAL, 1, start_special },
5070 { "exit", EQUAL, 1, start_special },
5071 { "reset-failed", MORE, 1, reset_failed },
5072 { "enable", MORE, 2, enable_unit },
5073 { "disable", MORE, 2, enable_unit },
5074 { "is-enabled", MORE, 2, unit_is_enabled },
5075 { "reenable", MORE, 2, enable_unit },
5076 { "preset", MORE, 2, enable_unit },
5077 { "mask", MORE, 2, enable_unit },
5078 { "unmask", MORE, 2, enable_unit },
5079 { "link", MORE, 2, enable_unit },
5080 { "switch-root", MORE, 2, switch_root },
5090 left = argc - optind;
5093 /* Special rule: no arguments means "list-units" */
5096 if (streq(argv[optind], "help") && !argv[optind+1]) {
5097 log_error("This command expects one or more "
5098 "unit names. Did you mean --help?");
5102 for (i = 0; i < ELEMENTSOF(verbs); i++)
5103 if (streq(argv[optind], verbs[i].verb))
5106 if (i >= ELEMENTSOF(verbs)) {
5107 log_error("Unknown operation '%s'.", argv[optind]);
5112 switch (verbs[i].argc_cmp) {
5115 if (left != verbs[i].argc) {
5116 log_error("Invalid number of arguments.");
5123 if (left < verbs[i].argc) {
5124 log_error("Too few arguments.");
5131 if (left > verbs[i].argc) {
5132 log_error("Too many arguments.");
5139 assert_not_reached("Unknown comparison operator.");
5142 /* Require a bus connection for all operations but
5144 if (!streq(verbs[i].verb, "enable") &&
5145 !streq(verbs[i].verb, "disable") &&
5146 !streq(verbs[i].verb, "is-enabled") &&
5147 !streq(verbs[i].verb, "list-unit-files") &&
5148 !streq(verbs[i].verb, "reenable") &&
5149 !streq(verbs[i].verb, "preset") &&
5150 !streq(verbs[i].verb, "mask") &&
5151 !streq(verbs[i].verb, "unmask") &&
5152 !streq(verbs[i].verb, "link")) {
5154 if (running_in_chroot() > 0) {
5155 log_info("Running in chroot, ignoring request.");
5159 if (((!streq(verbs[i].verb, "reboot") &&
5160 !streq(verbs[i].verb, "halt") &&
5161 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5162 log_error("Failed to get D-Bus connection: %s",
5163 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5169 if (!bus && !avoid_bus()) {
5170 log_error("Failed to get D-Bus connection: %s",
5171 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5176 return verbs[i].dispatch(bus, argv + optind);
5179 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5181 struct msghdr msghdr;
5182 struct iovec iovec[2];
5183 union sockaddr_union sockaddr;
5184 struct sd_shutdown_command c;
5186 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5193 c.dry_run = dry_run;
5197 sockaddr.sa.sa_family = AF_UNIX;
5198 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5201 msghdr.msg_name = &sockaddr;
5202 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5205 iovec[0].iov_base = (char*) &c;
5206 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5208 if (isempty(message))
5209 msghdr.msg_iovlen = 1;
5211 iovec[1].iov_base = (char*) message;
5212 iovec[1].iov_len = strlen(message);
5213 msghdr.msg_iovlen = 2;
5215 msghdr.msg_iov = iovec;
5217 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5218 close_nointr_nofail(fd);
5222 close_nointr_nofail(fd);
5226 static int reload_with_fallback(DBusConnection *bus) {
5229 /* First, try systemd via D-Bus. */
5230 if (daemon_reload(bus, NULL) >= 0)
5234 /* Nothing else worked, so let's try signals */
5235 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5237 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5238 log_error("kill() failed: %m");
5245 static int start_with_fallback(DBusConnection *bus) {
5248 /* First, try systemd via D-Bus. */
5249 if (start_unit(bus, NULL) >= 0)
5253 /* Hmm, talking to systemd via D-Bus didn't work. Then
5254 * let's try to talk to Upstart via D-Bus. */
5255 if (talk_upstart() > 0)
5258 /* Nothing else worked, so let's try
5260 if (talk_initctl() > 0)
5263 log_error("Failed to talk to init daemon.");
5267 warn_wall(arg_action);
5271 static _noreturn_ void halt_now(enum action a) {
5273 /* Make sure C-A-D is handled by the kernel from this
5275 reboot(RB_ENABLE_CAD);
5280 log_info("Halting.");
5281 reboot(RB_HALT_SYSTEM);
5284 case ACTION_POWEROFF:
5285 log_info("Powering off.");
5286 reboot(RB_POWER_OFF);
5290 log_info("Rebooting.");
5291 reboot(RB_AUTOBOOT);
5295 assert_not_reached("Unknown halt action.");
5298 assert_not_reached("Uh? This shouldn't happen.");
5301 static int halt_main(DBusConnection *bus) {
5304 if (arg_when <= 0 && arg_force <= 0) {
5305 r = check_inhibitors(bus, arg_action);
5310 if (geteuid() != 0) {
5311 /* Try logind if we are a normal user and no special
5312 * mode applies. Maybe PolicyKit allows us to shutdown
5315 if (arg_when <= 0 &&
5318 (arg_action == ACTION_POWEROFF ||
5319 arg_action == ACTION_REBOOT)) {
5320 r = reboot_with_logind(bus, arg_action);
5325 log_error("Must be root.");
5332 m = strv_join(arg_wall, " ");
5333 r = send_shutdownd(arg_when,
5334 arg_action == ACTION_HALT ? 'H' :
5335 arg_action == ACTION_POWEROFF ? 'P' :
5336 arg_action == ACTION_KEXEC ? 'K' :
5344 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5346 char date[FORMAT_TIMESTAMP_MAX];
5348 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5349 format_timestamp(date, sizeof(date), arg_when));
5354 if (!arg_dry && !arg_force)
5355 return start_with_fallback(bus);
5358 if (sd_booted() > 0)
5359 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5361 r = utmp_put_shutdown();
5363 log_warning("Failed to write utmp record: %s", strerror(-r));
5370 halt_now(arg_action);
5371 /* We should never reach this. */
5375 static int runlevel_main(void) {
5376 int r, runlevel, previous;
5378 r = utmp_get_runlevel(&runlevel, &previous);
5385 previous <= 0 ? 'N' : previous,
5386 runlevel <= 0 ? 'N' : runlevel);
5391 int main(int argc, char*argv[]) {
5392 int r, retval = EXIT_FAILURE;
5393 DBusConnection *bus = NULL;
5396 dbus_error_init(&error);
5398 setlocale(LC_ALL, "");
5399 log_parse_environment();
5402 r = parse_argv(argc, argv);
5406 retval = EXIT_SUCCESS;
5410 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5411 * let's shortcut this */
5412 if (arg_action == ACTION_RUNLEVEL) {
5413 r = runlevel_main();
5414 retval = r < 0 ? EXIT_FAILURE : r;
5418 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5419 log_info("Running in chroot, ignoring request.");
5425 if (arg_transport == TRANSPORT_NORMAL)
5426 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5427 else if (arg_transport == TRANSPORT_POLKIT) {
5428 bus_connect_system_polkit(&bus, &error);
5429 private_bus = false;
5430 } else if (arg_transport == TRANSPORT_SSH) {
5431 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5432 private_bus = false;
5434 assert_not_reached("Uh, invalid transport...");
5437 switch (arg_action) {
5439 case ACTION_SYSTEMCTL:
5440 r = systemctl_main(bus, argc, argv, &error);
5444 case ACTION_POWEROFF:
5450 case ACTION_RUNLEVEL2:
5451 case ACTION_RUNLEVEL3:
5452 case ACTION_RUNLEVEL4:
5453 case ACTION_RUNLEVEL5:
5455 case ACTION_EMERGENCY:
5456 case ACTION_DEFAULT:
5457 r = start_with_fallback(bus);
5462 r = reload_with_fallback(bus);
5465 case ACTION_CANCEL_SHUTDOWN: {
5469 m = strv_join(arg_wall, " ");
5471 retval = EXIT_FAILURE;
5475 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5477 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5482 case ACTION_INVALID:
5483 case ACTION_RUNLEVEL:
5485 assert_not_reached("Unknown action");
5488 retval = r < 0 ? EXIT_FAILURE : r;
5492 dbus_connection_flush(bus);
5493 dbus_connection_close(bus);
5494 dbus_connection_unref(bus);
5497 dbus_error_free(&error);
5501 strv_free(arg_property);
5504 ask_password_agent_close();
5505 polkit_agent_close();