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;
1744 polkit_agent_open_if_enabled();
1752 case ACTION_POWEROFF:
1753 method = "PowerOff";
1756 case ACTION_SUSPEND:
1760 case ACTION_HIBERNATE:
1761 method = "Hibernate";
1764 case ACTION_HYBRID_SLEEP:
1765 method = "HybridSleep";
1772 return bus_method_call_with_reply (
1774 "org.freedesktop.login1",
1775 "/org/freedesktop/login1",
1776 "org.freedesktop.login1.Manager",
1780 DBUS_TYPE_BOOLEAN, &interactive,
1787 static int check_inhibitors(DBusConnection *bus, enum action a) {
1789 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1790 DBusMessageIter iter, sub, sub2;
1794 if (arg_ignore_inhibitors)
1800 r = bus_method_call_with_reply(
1802 "org.freedesktop.login1",
1803 "/org/freedesktop/login1",
1804 "org.freedesktop.login1.Manager",
1810 /* If logind is not around, then there are no inhibitors... */
1813 if (!dbus_message_iter_init(reply, &iter) ||
1814 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1815 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1816 log_error("Failed to parse reply.");
1820 dbus_message_iter_recurse(&iter, &sub);
1821 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1822 const char *what, *who, *why, *mode;
1824 _cleanup_strv_free_ char **sv = NULL;
1825 _cleanup_free_ char *comm = NULL;
1827 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1828 log_error("Failed to parse reply.");
1832 dbus_message_iter_recurse(&sub, &sub2);
1834 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
1835 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
1836 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
1837 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
1838 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
1839 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
1840 log_error("Failed to parse reply.");
1844 if (!streq(mode, "block"))
1847 sv = strv_split(what, ":");
1851 if (!strv_contains(sv,
1853 a == ACTION_POWEROFF ||
1854 a == ACTION_REBOOT ||
1855 a == ACTION_KEXEC ? "shutdown" : "sleep"))
1858 get_process_comm(pid, &comm);
1859 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", UID %lu), reason is \"%s\".", who, (unsigned long) pid, strna(comm), (unsigned long) uid, why);
1863 dbus_message_iter_next(&sub);
1866 dbus_message_iter_recurse(&iter, &sub);
1871 log_error("Please try again after closing inhibitors or ignore them with 'systemctl %s -i'.",
1872 a == ACTION_HALT ? "halt" :
1873 a == ACTION_POWEROFF ? "poweroff" :
1874 a == ACTION_REBOOT ? "reboot" :
1875 a == ACTION_KEXEC ? "kexec" :
1876 a == ACTION_SUSPEND ? "suspend" :
1877 a == ACTION_HIBERNATE ? "hibernate" : "hybrid-sleep");
1885 static int start_special(DBusConnection *bus, char **args) {
1891 a = verb_to_action(args[0]);
1893 if (arg_force >= 2 && geteuid() != 0) {
1894 log_error("Must be root.");
1898 if (arg_force >= 2 &&
1899 (a == ACTION_HALT ||
1900 a == ACTION_POWEROFF ||
1901 a == ACTION_REBOOT))
1904 if (arg_force >= 1 &&
1905 (a == ACTION_HALT ||
1906 a == ACTION_POWEROFF ||
1907 a == ACTION_REBOOT ||
1908 a == ACTION_KEXEC ||
1910 return daemon_reload(bus, args);
1912 if (arg_force <= 0) {
1913 r = check_inhibitors(bus, a);
1918 /* first try logind, to allow authentication with polkit */
1919 if (geteuid() != 0 &&
1920 (a == ACTION_POWEROFF ||
1921 a == ACTION_REBOOT ||
1922 a == ACTION_SUSPEND ||
1923 a == ACTION_HIBERNATE ||
1924 a == ACTION_HYBRID_SLEEP)) {
1925 r = reboot_with_logind(bus, a);
1930 r = start_unit(bus, args);
1937 static int check_unit_active(DBusConnection *bus, char **args) {
1938 const char * const check_states[] = {
1945 int r = 3; /* According to LSB: "program is not running" */
1950 STRV_FOREACH(name, args+1) {
1953 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1963 static int check_unit_failed(DBusConnection *bus, char **args) {
1964 const char * const check_states[] = {
1975 STRV_FOREACH(name, args+1) {
1978 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1988 static int kill_unit(DBusConnection *bus, char **args) {
1996 arg_kill_who = "all";
1998 STRV_FOREACH(name, args+1) {
1999 _cleanup_free_ char *n = NULL;
2001 n = unit_name_mangle(*name);
2003 r = bus_method_call_with_reply(
2005 "org.freedesktop.systemd1",
2006 "/org/freedesktop/systemd1",
2007 "org.freedesktop.systemd1.Manager",
2011 DBUS_TYPE_STRING, n ? &n : name,
2012 DBUS_TYPE_STRING, &arg_kill_who,
2013 DBUS_TYPE_INT32, &arg_signal,
2021 typedef struct ExecStatusInfo {
2029 usec_t start_timestamp;
2030 usec_t exit_timestamp;
2035 LIST_FIELDS(struct ExecStatusInfo, exec);
2038 static void exec_status_info_free(ExecStatusInfo *i) {
2047 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2048 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2049 DBusMessageIter sub2, sub3;
2053 int32_t code, status;
2059 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2062 dbus_message_iter_recurse(sub, &sub2);
2064 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2067 if (!(i->path = strdup(path)))
2070 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2071 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2075 dbus_message_iter_recurse(&sub2, &sub3);
2076 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2077 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2078 dbus_message_iter_next(&sub3);
2083 if (!(i->argv = new0(char*, n+1)))
2087 dbus_message_iter_recurse(&sub2, &sub3);
2088 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2091 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2092 dbus_message_iter_get_basic(&sub3, &s);
2093 dbus_message_iter_next(&sub3);
2095 if (!(i->argv[n++] = strdup(s)))
2099 if (!dbus_message_iter_next(&sub2) ||
2100 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2101 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2102 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2103 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2104 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2105 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2106 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2107 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2111 i->start_timestamp = (usec_t) start_timestamp;
2112 i->exit_timestamp = (usec_t) exit_timestamp;
2113 i->pid = (pid_t) pid;
2120 typedef struct UnitStatusInfo {
2122 const char *load_state;
2123 const char *active_state;
2124 const char *sub_state;
2125 const char *unit_file_state;
2127 const char *description;
2128 const char *following;
2130 char **documentation;
2132 const char *fragment_path;
2133 const char *source_path;
2134 const char *default_control_group;
2136 const char *load_error;
2139 usec_t inactive_exit_timestamp;
2140 usec_t inactive_exit_timestamp_monotonic;
2141 usec_t active_enter_timestamp;
2142 usec_t active_exit_timestamp;
2143 usec_t inactive_enter_timestamp;
2145 bool need_daemon_reload;
2150 const char *status_text;
2153 usec_t start_timestamp;
2154 usec_t exit_timestamp;
2156 int exit_code, exit_status;
2158 usec_t condition_timestamp;
2159 bool condition_result;
2162 unsigned n_accepted;
2163 unsigned n_connections;
2167 const char *sysfs_path;
2169 /* Mount, Automount */
2175 LIST_HEAD(ExecStatusInfo, exec);
2178 static void print_status_info(UnitStatusInfo *i) {
2180 const char *on, *off, *ss;
2182 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2183 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2188 /* This shows pretty information about a unit. See
2189 * print_property() for a low-level property printer */
2191 printf("%s", strna(i->id));
2193 if (i->description && !streq_ptr(i->id, i->description))
2194 printf(" - %s", i->description);
2199 printf("\t Follow: unit currently follows state of %s\n", i->following);
2201 if (streq_ptr(i->load_state, "error")) {
2202 on = ansi_highlight_red(true);
2203 off = ansi_highlight_red(false);
2207 path = i->source_path ? i->source_path : i->fragment_path;
2210 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2211 else if (path && i->unit_file_state)
2212 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2214 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2216 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2218 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2220 if (streq_ptr(i->active_state, "failed")) {
2221 on = ansi_highlight_red(true);
2222 off = ansi_highlight_red(false);
2223 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2224 on = ansi_highlight_green(true);
2225 off = ansi_highlight_green(false);
2230 printf("\t Active: %s%s (%s)%s",
2232 strna(i->active_state),
2236 printf("\t Active: %s%s%s",
2238 strna(i->active_state),
2241 if (!isempty(i->result) && !streq(i->result, "success"))
2242 printf(" (Result: %s)", i->result);
2244 timestamp = (streq_ptr(i->active_state, "active") ||
2245 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2246 (streq_ptr(i->active_state, "inactive") ||
2247 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2248 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2249 i->active_exit_timestamp;
2251 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2252 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2255 printf(" since %s; %s\n", s2, s1);
2257 printf(" since %s\n", s2);
2261 if (!i->condition_result && i->condition_timestamp > 0) {
2262 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2263 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2266 printf("\t start condition failed at %s; %s\n", s2, s1);
2268 printf("\t start condition failed at %s\n", s2);
2272 printf("\t Device: %s\n", i->sysfs_path);
2274 printf("\t Where: %s\n", i->where);
2276 printf("\t What: %s\n", i->what);
2278 if (!strv_isempty(i->documentation)) {
2282 STRV_FOREACH(t, i->documentation) {
2284 printf("\t Docs: %s\n", *t);
2287 printf("\t %s\n", *t);
2292 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2294 LIST_FOREACH(exec, p, i->exec) {
2298 /* Only show exited processes here */
2302 t = strv_join(p->argv, " ");
2303 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2306 good = is_clean_exit_lsb(p->code, p->status, NULL);
2308 on = ansi_highlight_red(true);
2309 off = ansi_highlight_red(false);
2313 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2315 if (p->code == CLD_EXITED) {
2318 printf("status=%i", p->status);
2320 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2325 printf("signal=%s", signal_to_string(p->status));
2327 printf(")%s\n", off);
2329 if (i->main_pid == p->pid &&
2330 i->start_timestamp == p->start_timestamp &&
2331 i->exit_timestamp == p->start_timestamp)
2332 /* Let's not show this twice */
2335 if (p->pid == i->control_pid)
2339 if (i->main_pid > 0 || i->control_pid > 0) {
2342 if (i->main_pid > 0) {
2343 printf("Main PID: %u", (unsigned) i->main_pid);
2347 get_process_comm(i->main_pid, &t);
2352 } else if (i->exit_code > 0) {
2353 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2355 if (i->exit_code == CLD_EXITED) {
2358 printf("status=%i", i->exit_status);
2360 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2365 printf("signal=%s", signal_to_string(i->exit_status));
2370 if (i->main_pid > 0 && i->control_pid > 0)
2373 if (i->control_pid > 0) {
2376 printf(" Control: %u", (unsigned) i->control_pid);
2378 get_process_comm(i->control_pid, &t);
2389 printf("\t Status: \"%s\"\n", i->status_text);
2391 if (i->default_control_group &&
2392 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2395 printf("\t CGroup: %s\n", i->default_control_group);
2397 if (arg_transport != TRANSPORT_SSH) {
2407 if (i->main_pid > 0)
2408 extra[k++] = i->main_pid;
2410 if (i->control_pid > 0)
2411 extra[k++] = i->control_pid;
2413 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2417 if (i->id && arg_transport != TRANSPORT_SSH) {
2419 arg_all * OUTPUT_SHOW_ALL |
2420 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2421 on_tty() * OUTPUT_COLOR |
2422 !arg_quiet * OUTPUT_WARN_CUTOFF;
2425 show_journal_by_unit(stdout,
2429 i->inactive_exit_timestamp_monotonic,
2434 if (i->need_daemon_reload)
2435 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2436 ansi_highlight_red(true),
2437 ansi_highlight_red(false),
2438 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2441 static void show_unit_help(UnitStatusInfo *i) {
2446 if (!i->documentation) {
2447 log_info("Documentation for %s not known.", i->id);
2451 STRV_FOREACH(p, i->documentation) {
2453 if (startswith(*p, "man:")) {
2456 char *page = NULL, *section = NULL;
2457 const char *args[4] = { "man", NULL, NULL, NULL };
2462 if ((*p)[k-1] == ')')
2463 e = strrchr(*p, '(');
2466 page = strndup((*p) + 4, e - *p - 4);
2472 section = strndup(e + 1, *p + k - e - 2);
2486 log_error("Failed to fork: %m");
2494 execvp(args[0], (char**) args);
2495 log_error("Failed to execute man: %m");
2496 _exit(EXIT_FAILURE);
2502 wait_for_terminate(pid, NULL);
2504 log_info("Can't show: %s", *p);
2508 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2514 switch (dbus_message_iter_get_arg_type(iter)) {
2516 case DBUS_TYPE_STRING: {
2519 dbus_message_iter_get_basic(iter, &s);
2522 if (streq(name, "Id"))
2524 else if (streq(name, "LoadState"))
2526 else if (streq(name, "ActiveState"))
2527 i->active_state = s;
2528 else if (streq(name, "SubState"))
2530 else if (streq(name, "Description"))
2532 else if (streq(name, "FragmentPath"))
2533 i->fragment_path = s;
2534 else if (streq(name, "SourcePath"))
2536 else if (streq(name, "DefaultControlGroup"))
2537 i->default_control_group = s;
2538 else if (streq(name, "StatusText"))
2540 else if (streq(name, "SysFSPath"))
2542 else if (streq(name, "Where"))
2544 else if (streq(name, "What"))
2546 else if (streq(name, "Following"))
2548 else if (streq(name, "UnitFileState"))
2549 i->unit_file_state = s;
2550 else if (streq(name, "Result"))
2557 case DBUS_TYPE_BOOLEAN: {
2560 dbus_message_iter_get_basic(iter, &b);
2562 if (streq(name, "Accept"))
2564 else if (streq(name, "NeedDaemonReload"))
2565 i->need_daemon_reload = b;
2566 else if (streq(name, "ConditionResult"))
2567 i->condition_result = b;
2572 case DBUS_TYPE_UINT32: {
2575 dbus_message_iter_get_basic(iter, &u);
2577 if (streq(name, "MainPID")) {
2579 i->main_pid = (pid_t) u;
2582 } else if (streq(name, "ControlPID"))
2583 i->control_pid = (pid_t) u;
2584 else if (streq(name, "ExecMainPID")) {
2586 i->main_pid = (pid_t) u;
2587 } else if (streq(name, "NAccepted"))
2589 else if (streq(name, "NConnections"))
2590 i->n_connections = u;
2595 case DBUS_TYPE_INT32: {
2598 dbus_message_iter_get_basic(iter, &j);
2600 if (streq(name, "ExecMainCode"))
2601 i->exit_code = (int) j;
2602 else if (streq(name, "ExecMainStatus"))
2603 i->exit_status = (int) j;
2608 case DBUS_TYPE_UINT64: {
2611 dbus_message_iter_get_basic(iter, &u);
2613 if (streq(name, "ExecMainStartTimestamp"))
2614 i->start_timestamp = (usec_t) u;
2615 else if (streq(name, "ExecMainExitTimestamp"))
2616 i->exit_timestamp = (usec_t) u;
2617 else if (streq(name, "ActiveEnterTimestamp"))
2618 i->active_enter_timestamp = (usec_t) u;
2619 else if (streq(name, "InactiveEnterTimestamp"))
2620 i->inactive_enter_timestamp = (usec_t) u;
2621 else if (streq(name, "InactiveExitTimestamp"))
2622 i->inactive_exit_timestamp = (usec_t) u;
2623 else if (streq(name, "InactiveExitTimestampMonotonic"))
2624 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2625 else if (streq(name, "ActiveExitTimestamp"))
2626 i->active_exit_timestamp = (usec_t) u;
2627 else if (streq(name, "ConditionTimestamp"))
2628 i->condition_timestamp = (usec_t) u;
2633 case DBUS_TYPE_ARRAY: {
2635 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2636 startswith(name, "Exec")) {
2637 DBusMessageIter sub;
2639 dbus_message_iter_recurse(iter, &sub);
2640 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2641 ExecStatusInfo *info;
2644 if (!(info = new0(ExecStatusInfo, 1)))
2647 if (!(info->name = strdup(name))) {
2652 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2657 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2659 dbus_message_iter_next(&sub);
2661 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2662 streq(name, "Documentation")) {
2664 DBusMessageIter sub;
2666 dbus_message_iter_recurse(iter, &sub);
2667 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2671 dbus_message_iter_get_basic(&sub, &s);
2673 l = strv_append(i->documentation, s);
2677 strv_free(i->documentation);
2678 i->documentation = l;
2680 dbus_message_iter_next(&sub);
2687 case DBUS_TYPE_STRUCT: {
2689 if (streq(name, "LoadError")) {
2690 DBusMessageIter sub;
2691 const char *n, *message;
2694 dbus_message_iter_recurse(iter, &sub);
2696 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2700 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2704 if (!isempty(message))
2705 i->load_error = message;
2715 static int print_property(const char *name, DBusMessageIter *iter) {
2719 /* This is a low-level property printer, see
2720 * print_status_info() for the nicer output */
2722 if (arg_property && !strv_find(arg_property, name))
2725 switch (dbus_message_iter_get_arg_type(iter)) {
2727 case DBUS_TYPE_STRUCT: {
2728 DBusMessageIter sub;
2729 dbus_message_iter_recurse(iter, &sub);
2731 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2734 dbus_message_iter_get_basic(&sub, &u);
2737 printf("%s=%u\n", name, (unsigned) u);
2739 printf("%s=\n", name);
2742 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2745 dbus_message_iter_get_basic(&sub, &s);
2747 if (arg_all || s[0])
2748 printf("%s=%s\n", name, s);
2751 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2752 const char *a = NULL, *b = NULL;
2754 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2755 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2757 if (arg_all || !isempty(a) || !isempty(b))
2758 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2766 case DBUS_TYPE_ARRAY:
2768 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2769 DBusMessageIter sub, sub2;
2771 dbus_message_iter_recurse(iter, &sub);
2772 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2776 dbus_message_iter_recurse(&sub, &sub2);
2778 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2779 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2780 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2782 dbus_message_iter_next(&sub);
2787 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2788 DBusMessageIter sub, sub2;
2790 dbus_message_iter_recurse(iter, &sub);
2791 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2792 const char *type, *path;
2794 dbus_message_iter_recurse(&sub, &sub2);
2796 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2797 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2798 printf("%s=%s\n", type, path);
2800 dbus_message_iter_next(&sub);
2805 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2806 DBusMessageIter sub, sub2;
2808 dbus_message_iter_recurse(iter, &sub);
2809 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2811 uint64_t value, next_elapse;
2813 dbus_message_iter_recurse(&sub, &sub2);
2815 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2816 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2817 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2818 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2820 printf("%s={ value=%s ; next_elapse=%s }\n",
2822 format_timespan(timespan1, sizeof(timespan1), value),
2823 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2826 dbus_message_iter_next(&sub);
2831 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2832 DBusMessageIter sub, sub2;
2834 dbus_message_iter_recurse(iter, &sub);
2835 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2836 const char *controller, *attr, *value;
2838 dbus_message_iter_recurse(&sub, &sub2);
2840 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2841 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2842 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2844 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2850 dbus_message_iter_next(&sub);
2855 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2856 DBusMessageIter sub;
2858 dbus_message_iter_recurse(iter, &sub);
2859 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2860 ExecStatusInfo info;
2863 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2864 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2867 t = strv_join(info.argv, " ");
2869 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2873 yes_no(info.ignore),
2874 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2875 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2876 (unsigned) info. pid,
2877 sigchld_code_to_string(info.code),
2879 info.code == CLD_EXITED ? "" : "/",
2880 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2886 strv_free(info.argv);
2888 dbus_message_iter_next(&sub);
2897 if (generic_print_property(name, iter, arg_all) > 0)
2901 printf("%s=[unprintable]\n", name);
2906 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2907 DBusMessage *reply = NULL;
2908 const char *interface = "";
2910 DBusMessageIter iter, sub, sub2, sub3;
2911 UnitStatusInfo info;
2919 r = bus_method_call_with_reply (
2921 "org.freedesktop.systemd1",
2923 "org.freedesktop.DBus.Properties",
2927 DBUS_TYPE_STRING, &interface,
2932 if (!dbus_message_iter_init(reply, &iter) ||
2933 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2934 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2935 log_error("Failed to parse reply.");
2940 dbus_message_iter_recurse(&iter, &sub);
2947 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2950 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2951 log_error("Failed to parse reply.");
2956 dbus_message_iter_recurse(&sub, &sub2);
2958 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2959 log_error("Failed to parse reply.");
2964 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2965 log_error("Failed to parse reply.");
2970 dbus_message_iter_recurse(&sub2, &sub3);
2972 if (show_properties)
2973 r = print_property(name, &sub3);
2975 r = status_property(name, &sub3, &info);
2978 log_error("Failed to parse reply.");
2983 dbus_message_iter_next(&sub);
2988 if (!show_properties) {
2989 if (streq(verb, "help"))
2990 show_unit_help(&info);
2992 print_status_info(&info);
2995 strv_free(info.documentation);
2997 if (!streq_ptr(info.active_state, "active") &&
2998 !streq_ptr(info.active_state, "reloading") &&
2999 streq(verb, "status"))
3000 /* According to LSB: "program not running" */
3003 while ((p = info.exec)) {
3004 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3005 exec_status_info_free(p);
3010 dbus_message_unref(reply);
3015 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3016 DBusMessage *reply = NULL;
3017 const char *path = NULL;
3021 dbus_error_init(&error);
3023 r = bus_method_call_with_reply (
3025 "org.freedesktop.systemd1",
3026 "/org/freedesktop/systemd1",
3027 "org.freedesktop.systemd1.Manager",
3031 DBUS_TYPE_UINT32, &pid,
3036 if (!dbus_message_get_args(reply, &error,
3037 DBUS_TYPE_OBJECT_PATH, &path,
3038 DBUS_TYPE_INVALID)) {
3039 log_error("Failed to parse reply: %s", bus_error_message(&error));
3044 r = show_one(verb, bus, path, false, new_line);
3048 dbus_message_unref(reply);
3050 dbus_error_free(&error);
3055 static int show(DBusConnection *bus, char **args) {
3057 bool show_properties, new_line = false;
3063 show_properties = streq(args[0], "show");
3065 if (show_properties)
3066 pager_open_if_enabled();
3068 if (show_properties && strv_length(args) <= 1) {
3069 /* If not argument is specified inspect the manager
3072 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3075 STRV_FOREACH(name, args+1) {
3078 if (safe_atou32(*name, &id) < 0) {
3080 /* Interpret as unit name */
3082 n = unit_name_mangle(*name);
3083 p = unit_dbus_path_from_name(n ? n : *name);
3088 r = show_one(args[0], bus, p, show_properties, &new_line);
3094 } else if (show_properties) {
3096 /* Interpret as job id */
3099 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3102 r = show_one(args[0], bus, p, show_properties, &new_line);
3110 /* Interpret as PID */
3112 r = show_one_by_pid(args[0], bus, id, &new_line);
3121 static int dump(DBusConnection *bus, char **args) {
3122 DBusMessage *reply = NULL;
3127 dbus_error_init(&error);
3129 pager_open_if_enabled();
3131 r = bus_method_call_with_reply (
3133 "org.freedesktop.systemd1",
3134 "/org/freedesktop/systemd1",
3135 "org.freedesktop.systemd1.Manager",
3143 if (!dbus_message_get_args(reply, &error,
3144 DBUS_TYPE_STRING, &text,
3145 DBUS_TYPE_INVALID)) {
3146 log_error("Failed to parse reply: %s", bus_error_message(&error));
3151 fputs(text, stdout);
3155 dbus_message_unref(reply);
3157 dbus_error_free(&error);
3162 static int snapshot(DBusConnection *bus, char **args) {
3163 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3166 dbus_bool_t cleanup = FALSE;
3167 DBusMessageIter iter, sub;
3169 *name = "", *path, *id,
3170 *interface = "org.freedesktop.systemd1.Unit",
3172 _cleanup_free_ char *n = NULL;
3174 dbus_error_init(&error);
3176 if (strv_length(args) > 1) {
3178 n = unit_name_mangle(name);
3181 r = bus_method_call_with_reply (
3183 "org.freedesktop.systemd1",
3184 "/org/freedesktop/systemd1",
3185 "org.freedesktop.systemd1.Manager",
3189 DBUS_TYPE_STRING, n ? (const char**) &n : &name,
3190 DBUS_TYPE_BOOLEAN, &cleanup,
3195 if (!dbus_message_get_args(reply, &error,
3196 DBUS_TYPE_OBJECT_PATH, &path,
3197 DBUS_TYPE_INVALID)) {
3198 log_error("Failed to parse reply: %s", bus_error_message(&error));
3203 dbus_message_unref(reply);
3206 r = bus_method_call_with_reply (
3208 "org.freedesktop.systemd1",
3210 "org.freedesktop.DBus.Properties",
3214 DBUS_TYPE_STRING, &interface,
3215 DBUS_TYPE_STRING, &property,
3220 if (!dbus_message_iter_init(reply, &iter) ||
3221 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3222 log_error("Failed to parse reply.");
3227 dbus_message_iter_recurse(&iter, &sub);
3229 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3230 log_error("Failed to parse reply.");
3235 dbus_message_iter_get_basic(&sub, &id);
3241 dbus_error_free(&error);
3246 static int delete_snapshot(DBusConnection *bus, char **args) {
3251 STRV_FOREACH(name, args+1) {
3252 _cleanup_free_ char *n = NULL;
3255 n = unit_name_mangle(*name);
3256 r = bus_method_call_with_reply(
3258 "org.freedesktop.systemd1",
3259 "/org/freedesktop/systemd1",
3260 "org.freedesktop.systemd1.Manager",
3264 DBUS_TYPE_STRING, n ? &n : name,
3273 static int daemon_reload(DBusConnection *bus, char **args) {
3278 if (arg_action == ACTION_RELOAD)
3280 else if (arg_action == ACTION_REEXEC)
3281 method = "Reexecute";
3283 assert(arg_action == ACTION_SYSTEMCTL);
3286 streq(args[0], "clear-jobs") ||
3287 streq(args[0], "cancel") ? "ClearJobs" :
3288 streq(args[0], "daemon-reexec") ? "Reexecute" :
3289 streq(args[0], "reset-failed") ? "ResetFailed" :
3290 streq(args[0], "halt") ? "Halt" :
3291 streq(args[0], "poweroff") ? "PowerOff" :
3292 streq(args[0], "reboot") ? "Reboot" :
3293 streq(args[0], "kexec") ? "KExec" :
3294 streq(args[0], "exit") ? "Exit" :
3295 /* "daemon-reload" */ "Reload";
3298 r = bus_method_call_with_reply (
3300 "org.freedesktop.systemd1",
3301 "/org/freedesktop/systemd1",
3302 "org.freedesktop.systemd1.Manager",
3308 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3309 /* There's always a fallback possible for
3310 * legacy actions. */
3312 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3313 /* On reexecution, we expect a disconnect, not
3317 log_error("Failed to issue method call: %s", bus_error_message(&error));
3318 dbus_error_free(&error);
3323 static int reset_failed(DBusConnection *bus, char **args) {
3327 if (strv_length(args) <= 1)
3328 return daemon_reload(bus, args);
3330 STRV_FOREACH(name, args+1) {
3331 n = unit_name_mangle(*name);
3332 r = bus_method_call_with_reply (
3334 "org.freedesktop.systemd1",
3335 "/org/freedesktop/systemd1",
3336 "org.freedesktop.systemd1.Manager",
3340 DBUS_TYPE_STRING, n ? &n : name,
3351 static int show_enviroment(DBusConnection *bus, char **args) {
3352 DBusMessage *reply = NULL;
3353 DBusMessageIter iter, sub, sub2;
3356 *interface = "org.freedesktop.systemd1.Manager",
3357 *property = "Environment";
3359 pager_open_if_enabled();
3361 r = bus_method_call_with_reply (
3363 "org.freedesktop.systemd1",
3364 "/org/freedesktop/systemd1",
3365 "org.freedesktop.DBus.Properties",
3369 DBUS_TYPE_STRING, &interface,
3370 DBUS_TYPE_STRING, &property,
3375 if (!dbus_message_iter_init(reply, &iter) ||
3376 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3377 log_error("Failed to parse reply.");
3382 dbus_message_iter_recurse(&iter, &sub);
3384 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3385 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3386 log_error("Failed to parse reply.");
3391 dbus_message_iter_recurse(&sub, &sub2);
3393 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3396 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3397 log_error("Failed to parse reply.");
3402 dbus_message_iter_get_basic(&sub2, &text);
3403 printf("%s\n", text);
3405 dbus_message_iter_next(&sub2);
3412 dbus_message_unref(reply);
3417 static int switch_root(DBusConnection *bus, char **args) {
3420 _cleanup_free_ char *init = NULL;
3422 l = strv_length(args);
3423 if (l < 2 || l > 3) {
3424 log_error("Wrong number of arguments.");
3431 init = strdup(args[2]);
3433 parse_env_file("/proc/cmdline", WHITESPACE,
3445 log_debug("switching root - root: %s; init: %s", root, init);
3447 return bus_method_call_with_reply (
3449 "org.freedesktop.systemd1",
3450 "/org/freedesktop/systemd1",
3451 "org.freedesktop.systemd1.Manager",
3455 DBUS_TYPE_STRING, &root,
3456 DBUS_TYPE_STRING, &init,
3460 static int set_environment(DBusConnection *bus, char **args) {
3461 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3464 DBusMessageIter iter;
3470 dbus_error_init(&error);
3472 method = streq(args[0], "set-environment")
3474 : "UnsetEnvironment";
3476 m = dbus_message_new_method_call(
3477 "org.freedesktop.systemd1",
3478 "/org/freedesktop/systemd1",
3479 "org.freedesktop.systemd1.Manager",
3484 dbus_message_iter_init_append(m, &iter);
3486 r = bus_append_strv_iter(&iter, args + 1);
3490 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3492 log_error("Failed to issue method call: %s", bus_error_message(&error));
3500 dbus_error_free(&error);
3504 static int enable_sysv_units(char **args) {
3507 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3508 const char *verb = args[0];
3509 unsigned f = 1, t = 1;
3512 if (arg_scope != UNIT_FILE_SYSTEM)
3515 if (!streq(verb, "enable") &&
3516 !streq(verb, "disable") &&
3517 !streq(verb, "is-enabled"))
3520 /* Processes all SysV units, and reshuffles the array so that
3521 * afterwards only the native units remain */
3524 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3529 for (f = 1; args[f]; f++) {
3532 bool found_native = false, found_sysv;
3534 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3535 char **k, *l, *q = NULL;
3542 if (!endswith(name, ".service"))
3545 if (path_is_absolute(name))
3548 STRV_FOREACH(k, paths.unit_path) {
3551 if (!isempty(arg_root))
3552 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3554 asprintf(&p, "%s/%s", *k, name);
3561 found_native = access(p, F_OK) >= 0;
3572 if (!isempty(arg_root))
3573 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3575 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3581 p[strlen(p) - sizeof(".service") + 1] = 0;
3582 found_sysv = access(p, F_OK) >= 0;
3589 /* Mark this entry, so that we don't try enabling it as native unit */
3590 args[f] = (char*) "";
3592 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3594 if (!isempty(arg_root))
3595 argv[c++] = q = strappend("--root=", arg_root);
3597 argv[c++] = path_get_file_name(p);
3599 streq(verb, "enable") ? "on" :
3600 streq(verb, "disable") ? "off" : "--level=5";
3603 l = strv_join((char**)argv, " ");
3611 log_info("Executing %s", l);
3616 log_error("Failed to fork: %m");
3621 } else if (pid == 0) {
3624 execv(argv[0], (char**) argv);
3625 _exit(EXIT_FAILURE);
3631 j = wait_for_terminate(pid, &status);
3633 log_error("Failed to wait for child: %s", strerror(-r));
3638 if (status.si_code == CLD_EXITED) {
3639 if (streq(verb, "is-enabled")) {
3640 if (status.si_status == 0) {
3649 } else if (status.si_status != 0) {
3660 lookup_paths_free(&paths);
3662 /* Drop all SysV units */
3663 for (f = 1, t = 1; args[f]; f++) {
3665 if (isempty(args[f]))
3668 args[t++] = args[f];
3677 static int mangle_names(char **original_names, char ***mangled_names) {
3678 char **i, **l, **name;
3680 l = new(char*, strv_length(original_names) + 1);
3685 STRV_FOREACH(name, original_names) {
3687 /* When enabling units qualified path names are OK,
3688 * too, hence allow them explicitly. */
3693 *i = unit_name_mangle(*name);
3709 static int enable_unit(DBusConnection *bus, char **args) {
3710 const char *verb = args[0];
3711 UnitFileChange *changes = NULL;
3712 unsigned n_changes = 0, i;
3713 int carries_install_info = -1;
3714 DBusMessage *m = NULL, *reply = NULL;
3717 char **mangled_names = NULL;
3719 r = enable_sysv_units(args);
3726 dbus_error_init(&error);
3728 if (!bus || avoid_bus()) {
3729 if (streq(verb, "enable")) {
3730 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3731 carries_install_info = r;
3732 } else if (streq(verb, "disable"))
3733 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3734 else if (streq(verb, "reenable")) {
3735 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3736 carries_install_info = r;
3737 } else if (streq(verb, "link"))
3738 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3739 else if (streq(verb, "preset")) {
3740 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3741 carries_install_info = r;
3742 } else if (streq(verb, "mask"))
3743 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3744 else if (streq(verb, "unmask"))
3745 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3747 assert_not_reached("Unknown verb");
3750 log_error("Operation failed: %s", strerror(-r));
3755 for (i = 0; i < n_changes; i++) {
3756 if (changes[i].type == UNIT_FILE_SYMLINK)
3757 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3759 log_info("rm '%s'", changes[i].path);
3766 bool send_force = true, expect_carries_install_info = false;
3768 DBusMessageIter iter, sub, sub2;
3770 if (streq(verb, "enable")) {
3771 method = "EnableUnitFiles";
3772 expect_carries_install_info = true;
3773 } else if (streq(verb, "disable")) {
3774 method = "DisableUnitFiles";
3776 } else if (streq(verb, "reenable")) {
3777 method = "ReenableUnitFiles";
3778 expect_carries_install_info = true;
3779 } else if (streq(verb, "link"))
3780 method = "LinkUnitFiles";
3781 else if (streq(verb, "preset")) {
3782 method = "PresetUnitFiles";
3783 expect_carries_install_info = true;
3784 } else if (streq(verb, "mask"))
3785 method = "MaskUnitFiles";
3786 else if (streq(verb, "unmask")) {
3787 method = "UnmaskUnitFiles";
3790 assert_not_reached("Unknown verb");
3792 m = dbus_message_new_method_call(
3793 "org.freedesktop.systemd1",
3794 "/org/freedesktop/systemd1",
3795 "org.freedesktop.systemd1.Manager",
3802 dbus_message_iter_init_append(m, &iter);
3804 r = mangle_names(args+1, &mangled_names);
3808 r = bus_append_strv_iter(&iter, mangled_names);
3810 log_error("Failed to append unit files.");
3815 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3816 log_error("Failed to append runtime boolean.");
3824 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3825 log_error("Failed to append force boolean.");
3831 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3833 log_error("Failed to issue method call: %s", bus_error_message(&error));
3838 if (!dbus_message_iter_init(reply, &iter)) {
3839 log_error("Failed to initialize iterator.");
3843 if (expect_carries_install_info) {
3844 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3846 log_error("Failed to parse reply.");
3850 carries_install_info = b;
3853 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3854 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3855 log_error("Failed to parse reply.");
3860 dbus_message_iter_recurse(&iter, &sub);
3861 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3862 const char *type, *path, *source;
3864 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3865 log_error("Failed to parse reply.");
3870 dbus_message_iter_recurse(&sub, &sub2);
3872 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3873 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3874 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3875 log_error("Failed to parse reply.");
3881 if (streq(type, "symlink"))
3882 log_info("ln -s '%s' '%s'", source, path);
3884 log_info("rm '%s'", path);
3887 dbus_message_iter_next(&sub);
3890 /* Try to reload if enabeld */
3892 r = daemon_reload(bus, args);
3895 if (carries_install_info == 0)
3897 "The unit files have no [Install] section. They are not meant to be enabled\n"
3898 "using systemctl.\n"
3899 "Possible reasons for having this kind of units are:\n"
3900 "1) A unit may be statically enabled by being symlinked from another unit's\n"
3901 " .wants/ or .requires/ directory.\n"
3902 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
3903 " a requirement dependency on it.\n"
3904 "3) A unit may be started when needed via activation (socket, path, timer,\n"
3905 " D-Bus, udev, scripted systemctl call, ...).\n");
3909 dbus_message_unref(m);
3912 dbus_message_unref(reply);
3914 unit_file_changes_free(changes, n_changes);
3916 dbus_error_free(&error);
3918 strv_free(mangled_names);
3923 static int unit_is_enabled(DBusConnection *bus, char **args) {
3926 DBusMessage *reply = NULL;
3930 dbus_error_init(&error);
3932 r = enable_sysv_units(args);
3938 if (!bus || avoid_bus()) {
3940 STRV_FOREACH(name, args+1) {
3941 UnitFileState state;
3943 state = unit_file_get_state(arg_scope, arg_root, *name);
3949 if (state == UNIT_FILE_ENABLED ||
3950 state == UNIT_FILE_ENABLED_RUNTIME ||
3951 state == UNIT_FILE_STATIC)
3955 puts(unit_file_state_to_string(state));
3959 STRV_FOREACH(name, args+1) {
3962 r = bus_method_call_with_reply (
3964 "org.freedesktop.systemd1",
3965 "/org/freedesktop/systemd1",
3966 "org.freedesktop.systemd1.Manager",
3970 DBUS_TYPE_STRING, name,
3975 if (!dbus_message_get_args(reply, &error,
3976 DBUS_TYPE_STRING, &s,
3977 DBUS_TYPE_INVALID)) {
3978 log_error("Failed to parse reply: %s", bus_error_message(&error));
3983 dbus_message_unref(reply);
3986 if (streq(s, "enabled") ||
3987 streq(s, "enabled-runtime") ||
3996 r = enabled ? 0 : 1;
4000 dbus_message_unref(reply);
4002 dbus_error_free(&error);
4006 static int systemctl_help(void) {
4008 pager_open_if_enabled();
4010 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4011 "Query or send control commands to the systemd manager.\n\n"
4012 " -h --help Show this help\n"
4013 " --version Show package version\n"
4014 " -t --type=TYPE List only units of a particular type\n"
4015 " -p --property=NAME Show only properties by this name\n"
4016 " -a --all Show all units/properties, including dead/empty ones\n"
4017 " --failed Show only failed units\n"
4018 " --full Don't ellipsize unit names on output\n"
4019 " --fail When queueing a new job, fail if conflicting jobs are\n"
4021 " --ignore-dependencies\n"
4022 " When queueing a new job, ignore all its dependencies\n"
4023 " -i --ignore-inhibitors\n"
4024 " When shutting down or sleeping, ignore inhibitors\n"
4025 " --kill-who=WHO Who to send signal to\n"
4026 " -s --signal=SIGNAL Which signal to send\n"
4027 " -H --host=[USER@]HOST\n"
4028 " Show information for remote host\n"
4029 " -P --privileged Acquire privileges before execution\n"
4030 " -q --quiet Suppress output\n"
4031 " --no-block Do not wait until operation finished\n"
4032 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4033 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4035 " --no-legend Do not print a legend (column headers and hints)\n"
4036 " --no-pager Do not pipe output into a pager\n"
4037 " --no-ask-password\n"
4038 " Do not ask for system passwords\n"
4039 " --order When generating graph for dot, show only order\n"
4040 " --require When generating graph for dot, show only requirement\n"
4041 " --system Connect to system manager\n"
4042 " --user Connect to user service manager\n"
4043 " --global Enable/disable unit files globally\n"
4044 " -f --force When enabling unit files, override existing symlinks\n"
4045 " When shutting down, execute action immediately\n"
4046 " --root=PATH Enable unit files in the specified root directory\n"
4047 " --runtime Enable unit files only temporarily until next reboot\n"
4048 " -n --lines=INTEGER Journal entries to show\n"
4049 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4050 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4052 " list-units List loaded units\n"
4053 " start [NAME...] Start (activate) one or more units\n"
4054 " stop [NAME...] Stop (deactivate) one or more units\n"
4055 " reload [NAME...] Reload one or more units\n"
4056 " restart [NAME...] Start or restart one or more units\n"
4057 " try-restart [NAME...] Restart one or more units if active\n"
4058 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4059 " otherwise start or restart\n"
4060 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4061 " otherwise restart if active\n"
4062 " isolate [NAME] Start one unit and stop all others\n"
4063 " kill [NAME...] Send signal to processes of a unit\n"
4064 " is-active [NAME...] Check whether units are active\n"
4065 " is-failed [NAME...] Check whether units are failed\n"
4066 " status [NAME...|PID...] Show runtime status of one or more units\n"
4067 " show [NAME...|JOB...] Show properties of one or more\n"
4068 " units/jobs or the manager\n"
4069 " help [NAME...|PID...] Show manual for one or more units\n"
4070 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4072 " load [NAME...] Load one or more units\n\n"
4073 "Unit File Commands:\n"
4074 " list-unit-files List installed unit files\n"
4075 " enable [NAME...] Enable one or more unit files\n"
4076 " disable [NAME...] Disable one or more unit files\n"
4077 " reenable [NAME...] Reenable one or more unit files\n"
4078 " preset [NAME...] Enable/disable one or more unit files\n"
4079 " based on preset configuration\n"
4080 " mask [NAME...] Mask one or more units\n"
4081 " unmask [NAME...] Unmask one or more units\n"
4082 " link [PATH...] Link one or more units files into\n"
4083 " the search path\n"
4084 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4086 " list-jobs List jobs\n"
4087 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4088 "Status Commands:\n"
4089 " dump Dump server status\n"
4090 " dot Dump dependency graph for dot(1)\n\n"
4091 "Snapshot Commands:\n"
4092 " snapshot [NAME] Create a snapshot\n"
4093 " delete [NAME...] Remove one or more snapshots\n\n"
4094 "Environment Commands:\n"
4095 " show-environment Dump environment\n"
4096 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4097 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4098 "Manager Lifecycle Commands:\n"
4099 " daemon-reload Reload systemd manager configuration\n"
4100 " daemon-reexec Reexecute systemd manager\n\n"
4101 "System Commands:\n"
4102 " default Enter system default mode\n"
4103 " rescue Enter system rescue mode\n"
4104 " emergency Enter system emergency mode\n"
4105 " halt Shut down and halt the system\n"
4106 " poweroff Shut down and power-off the system\n"
4107 " reboot Shut down and reboot the system\n"
4108 " kexec Shut down and reboot the system with kexec\n"
4109 " exit Request user instance exit\n"
4110 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4111 " suspend Suspend the system\n"
4112 " hibernate Hibernate the system\n"
4113 " hybrid-sleep Hibernate and suspend the system\n",
4114 program_invocation_short_name);
4119 static int halt_help(void) {
4121 printf("%s [OPTIONS...]\n\n"
4122 "%s the system.\n\n"
4123 " --help Show this help\n"
4124 " --halt Halt the machine\n"
4125 " -p --poweroff Switch off the machine\n"
4126 " --reboot Reboot the machine\n"
4127 " -f --force Force immediate halt/power-off/reboot\n"
4128 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4129 " -d --no-wtmp Don't write wtmp record\n"
4130 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4131 program_invocation_short_name,
4132 arg_action == ACTION_REBOOT ? "Reboot" :
4133 arg_action == ACTION_POWEROFF ? "Power off" :
4139 static int shutdown_help(void) {
4141 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4142 "Shut down the system.\n\n"
4143 " --help Show this help\n"
4144 " -H --halt Halt the machine\n"
4145 " -P --poweroff Power-off the machine\n"
4146 " -r --reboot Reboot the machine\n"
4147 " -h Equivalent to --poweroff, overridden by --halt\n"
4148 " -k Don't halt/power-off/reboot, just send warnings\n"
4149 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4150 " -c Cancel a pending shutdown\n",
4151 program_invocation_short_name);
4156 static int telinit_help(void) {
4158 printf("%s [OPTIONS...] {COMMAND}\n\n"
4159 "Send control commands to the init daemon.\n\n"
4160 " --help Show this help\n"
4161 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4163 " 0 Power-off the machine\n"
4164 " 6 Reboot the machine\n"
4165 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4166 " 1, s, S Enter rescue mode\n"
4167 " q, Q Reload init daemon configuration\n"
4168 " u, U Reexecute init daemon\n",
4169 program_invocation_short_name);
4174 static int runlevel_help(void) {
4176 printf("%s [OPTIONS...]\n\n"
4177 "Prints the previous and current runlevel of the init system.\n\n"
4178 " --help Show this help\n",
4179 program_invocation_short_name);
4184 static int help_types(void) {
4187 puts("Available unit types:");
4188 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4189 if (unit_type_table[i])
4190 puts(unit_type_table[i]);
4192 puts("\nAvailable unit load states: ");
4193 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4194 if (unit_type_table[i])
4195 puts(unit_load_state_table[i]);
4200 static int systemctl_parse_argv(int argc, char *argv[]) {
4204 ARG_IGNORE_DEPENDENCIES,
4219 ARG_NO_ASK_PASSWORD,
4225 static const struct option options[] = {
4226 { "help", no_argument, NULL, 'h' },
4227 { "version", no_argument, NULL, ARG_VERSION },
4228 { "type", required_argument, NULL, 't' },
4229 { "property", required_argument, NULL, 'p' },
4230 { "all", no_argument, NULL, 'a' },
4231 { "failed", no_argument, NULL, ARG_FAILED },
4232 { "full", no_argument, NULL, ARG_FULL },
4233 { "fail", no_argument, NULL, ARG_FAIL },
4234 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4235 { "ignore-inhibitors", no_argument, NULL, 'i' },
4236 { "user", no_argument, NULL, ARG_USER },
4237 { "system", no_argument, NULL, ARG_SYSTEM },
4238 { "global", no_argument, NULL, ARG_GLOBAL },
4239 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4240 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4241 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4242 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4243 { "quiet", no_argument, NULL, 'q' },
4244 { "order", no_argument, NULL, ARG_ORDER },
4245 { "require", no_argument, NULL, ARG_REQUIRE },
4246 { "root", required_argument, NULL, ARG_ROOT },
4247 { "force", no_argument, NULL, ARG_FORCE },
4248 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4249 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4250 { "signal", required_argument, NULL, 's' },
4251 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4252 { "host", required_argument, NULL, 'H' },
4253 { "privileged",no_argument, NULL, 'P' },
4254 { "runtime", no_argument, NULL, ARG_RUNTIME },
4255 { "lines", required_argument, NULL, 'n' },
4256 { "output", required_argument, NULL, 'o' },
4257 { NULL, 0, NULL, 0 }
4265 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4274 puts(PACKAGE_STRING);
4275 puts(SYSTEMD_FEATURES);
4279 if (streq(optarg, "help")) {
4284 if (unit_type_from_string(optarg) >= 0) {
4288 if (unit_load_state_from_string(optarg) >= 0) {
4289 arg_load_state = optarg;
4292 log_error("Unkown unit type or load state '%s'.",
4294 log_info("Use -t help to see a list of allowed values.");
4299 if (!(l = strv_append(arg_property, optarg)))
4302 strv_free(arg_property);
4305 /* If the user asked for a particular
4306 * property, show it to him, even if it is
4317 arg_job_mode = "fail";
4320 case ARG_IGNORE_DEPENDENCIES:
4321 arg_job_mode = "ignore-dependencies";
4325 arg_scope = UNIT_FILE_USER;
4329 arg_scope = UNIT_FILE_SYSTEM;
4333 arg_scope = UNIT_FILE_GLOBAL;
4337 arg_no_block = true;
4341 arg_no_legend = true;
4345 arg_no_pager = true;
4353 arg_dot = DOT_ORDER;
4357 arg_dot = DOT_REQUIRE;
4385 arg_no_reload = true;
4389 arg_kill_who = optarg;
4393 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4394 log_error("Failed to parse signal string %s.", optarg);
4399 case ARG_NO_ASK_PASSWORD:
4400 arg_ask_password = false;
4404 arg_transport = TRANSPORT_POLKIT;
4408 arg_transport = TRANSPORT_SSH;
4417 if (safe_atou(optarg, &arg_lines) < 0) {
4418 log_error("Failed to parse lines '%s'", optarg);
4424 arg_output = output_mode_from_string(optarg);
4425 if (arg_output < 0) {
4426 log_error("Unknown output '%s'.", optarg);
4432 arg_ignore_inhibitors = true;
4439 log_error("Unknown option code '%c'.", c);
4444 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4445 log_error("Cannot access user instance remotely.");
4452 static int halt_parse_argv(int argc, char *argv[]) {
4461 static const struct option options[] = {
4462 { "help", no_argument, NULL, ARG_HELP },
4463 { "halt", no_argument, NULL, ARG_HALT },
4464 { "poweroff", no_argument, NULL, 'p' },
4465 { "reboot", no_argument, NULL, ARG_REBOOT },
4466 { "force", no_argument, NULL, 'f' },
4467 { "wtmp-only", no_argument, NULL, 'w' },
4468 { "no-wtmp", no_argument, NULL, 'd' },
4469 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4470 { NULL, 0, NULL, 0 }
4478 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4479 if (runlevel == '0' || runlevel == '6')
4482 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4490 arg_action = ACTION_HALT;
4494 if (arg_action != ACTION_REBOOT)
4495 arg_action = ACTION_POWEROFF;
4499 arg_action = ACTION_REBOOT;
4521 /* Compatibility nops */
4528 log_error("Unknown option code '%c'.", c);
4533 if (optind < argc) {
4534 log_error("Too many arguments.");
4541 static int parse_time_spec(const char *t, usec_t *_u) {
4545 if (streq(t, "now"))
4547 else if (!strchr(t, ':')) {
4550 if (safe_atou64(t, &u) < 0)
4553 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4562 hour = strtol(t, &e, 10);
4563 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4566 minute = strtol(e+1, &e, 10);
4567 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4570 n = now(CLOCK_REALTIME);
4571 s = (time_t) (n / USEC_PER_SEC);
4574 assert_se(localtime_r(&s, &tm));
4576 tm.tm_hour = (int) hour;
4577 tm.tm_min = (int) minute;
4580 assert_se(s = mktime(&tm));
4582 *_u = (usec_t) s * USEC_PER_SEC;
4585 *_u += USEC_PER_DAY;
4591 static int shutdown_parse_argv(int argc, char *argv[]) {
4598 static const struct option options[] = {
4599 { "help", no_argument, NULL, ARG_HELP },
4600 { "halt", no_argument, NULL, 'H' },
4601 { "poweroff", no_argument, NULL, 'P' },
4602 { "reboot", no_argument, NULL, 'r' },
4603 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4604 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4605 { NULL, 0, NULL, 0 }
4613 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4621 arg_action = ACTION_HALT;
4625 arg_action = ACTION_POWEROFF;
4630 arg_action = ACTION_KEXEC;
4632 arg_action = ACTION_REBOOT;
4636 arg_action = ACTION_KEXEC;
4640 if (arg_action != ACTION_HALT)
4641 arg_action = ACTION_POWEROFF;
4654 /* Compatibility nops */
4658 arg_action = ACTION_CANCEL_SHUTDOWN;
4665 log_error("Unknown option code '%c'.", c);
4670 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4671 r = parse_time_spec(argv[optind], &arg_when);
4673 log_error("Failed to parse time specification: %s", argv[optind]);
4677 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4679 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4680 /* No time argument for shutdown cancel */
4681 arg_wall = argv + optind;
4682 else if (argc > optind + 1)
4683 /* We skip the time argument */
4684 arg_wall = argv + optind + 1;
4691 static int telinit_parse_argv(int argc, char *argv[]) {
4698 static const struct option options[] = {
4699 { "help", no_argument, NULL, ARG_HELP },
4700 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4701 { NULL, 0, NULL, 0 }
4704 static const struct {
4708 { '0', ACTION_POWEROFF },
4709 { '6', ACTION_REBOOT },
4710 { '1', ACTION_RESCUE },
4711 { '2', ACTION_RUNLEVEL2 },
4712 { '3', ACTION_RUNLEVEL3 },
4713 { '4', ACTION_RUNLEVEL4 },
4714 { '5', ACTION_RUNLEVEL5 },
4715 { 's', ACTION_RESCUE },
4716 { 'S', ACTION_RESCUE },
4717 { 'q', ACTION_RELOAD },
4718 { 'Q', ACTION_RELOAD },
4719 { 'u', ACTION_REEXEC },
4720 { 'U', ACTION_REEXEC }
4729 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4744 log_error("Unknown option code '%c'.", c);
4749 if (optind >= argc) {
4754 if (optind + 1 < argc) {
4755 log_error("Too many arguments.");
4759 if (strlen(argv[optind]) != 1) {
4760 log_error("Expected single character argument.");
4764 for (i = 0; i < ELEMENTSOF(table); i++)
4765 if (table[i].from == argv[optind][0])
4768 if (i >= ELEMENTSOF(table)) {
4769 log_error("Unknown command '%s'.", argv[optind]);
4773 arg_action = table[i].to;
4780 static int runlevel_parse_argv(int argc, char *argv[]) {
4786 static const struct option options[] = {
4787 { "help", no_argument, NULL, ARG_HELP },
4788 { NULL, 0, NULL, 0 }
4796 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4807 log_error("Unknown option code '%c'.", c);
4812 if (optind < argc) {
4813 log_error("Too many arguments.");
4820 static int parse_argv(int argc, char *argv[]) {
4824 if (program_invocation_short_name) {
4826 if (strstr(program_invocation_short_name, "halt")) {
4827 arg_action = ACTION_HALT;
4828 return halt_parse_argv(argc, argv);
4829 } else if (strstr(program_invocation_short_name, "poweroff")) {
4830 arg_action = ACTION_POWEROFF;
4831 return halt_parse_argv(argc, argv);
4832 } else if (strstr(program_invocation_short_name, "reboot")) {
4834 arg_action = ACTION_KEXEC;
4836 arg_action = ACTION_REBOOT;
4837 return halt_parse_argv(argc, argv);
4838 } else if (strstr(program_invocation_short_name, "shutdown")) {
4839 arg_action = ACTION_POWEROFF;
4840 return shutdown_parse_argv(argc, argv);
4841 } else if (strstr(program_invocation_short_name, "init")) {
4843 if (sd_booted() > 0) {
4844 arg_action = ACTION_INVALID;
4845 return telinit_parse_argv(argc, argv);
4847 /* Hmm, so some other init system is
4848 * running, we need to forward this
4849 * request to it. For now we simply
4850 * guess that it is Upstart. */
4852 execv("/lib/upstart/telinit", argv);
4854 log_error("Couldn't find an alternative telinit implementation to spawn.");
4858 } else if (strstr(program_invocation_short_name, "runlevel")) {
4859 arg_action = ACTION_RUNLEVEL;
4860 return runlevel_parse_argv(argc, argv);
4864 arg_action = ACTION_SYSTEMCTL;
4865 return systemctl_parse_argv(argc, argv);
4868 static int action_to_runlevel(void) {
4870 static const char table[_ACTION_MAX] = {
4871 [ACTION_HALT] = '0',
4872 [ACTION_POWEROFF] = '0',
4873 [ACTION_REBOOT] = '6',
4874 [ACTION_RUNLEVEL2] = '2',
4875 [ACTION_RUNLEVEL3] = '3',
4876 [ACTION_RUNLEVEL4] = '4',
4877 [ACTION_RUNLEVEL5] = '5',
4878 [ACTION_RESCUE] = '1'
4881 assert(arg_action < _ACTION_MAX);
4883 return table[arg_action];
4886 static int talk_upstart(void) {
4887 DBusMessage *m = NULL, *reply = NULL;
4889 int previous, rl, r;
4891 env1_buf[] = "RUNLEVEL=X",
4892 env2_buf[] = "PREVLEVEL=X";
4893 char *env1 = env1_buf, *env2 = env2_buf;
4894 const char *emit = "runlevel";
4895 dbus_bool_t b_false = FALSE;
4896 DBusMessageIter iter, sub;
4897 DBusConnection *bus;
4899 dbus_error_init(&error);
4901 if (!(rl = action_to_runlevel()))
4904 if (utmp_get_runlevel(&previous, NULL) < 0)
4907 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4908 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4913 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4918 if ((r = bus_check_peercred(bus)) < 0) {
4919 log_error("Failed to verify owner of bus.");
4923 if (!(m = dbus_message_new_method_call(
4924 "com.ubuntu.Upstart",
4925 "/com/ubuntu/Upstart",
4926 "com.ubuntu.Upstart0_6",
4929 log_error("Could not allocate message.");
4934 dbus_message_iter_init_append(m, &iter);
4936 env1_buf[sizeof(env1_buf)-2] = rl;
4937 env2_buf[sizeof(env2_buf)-2] = previous;
4939 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4940 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4941 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4942 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4943 !dbus_message_iter_close_container(&iter, &sub) ||
4944 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4945 log_error("Could not append arguments to message.");
4950 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4952 if (bus_error_is_no_service(&error)) {
4957 log_error("Failed to issue method call: %s", bus_error_message(&error));
4966 dbus_message_unref(m);
4969 dbus_message_unref(reply);
4972 dbus_connection_flush(bus);
4973 dbus_connection_close(bus);
4974 dbus_connection_unref(bus);
4977 dbus_error_free(&error);
4982 static int talk_initctl(void) {
4983 struct init_request request;
4987 if (!(rl = action_to_runlevel()))
4991 request.magic = INIT_MAGIC;
4992 request.sleeptime = 0;
4993 request.cmd = INIT_CMD_RUNLVL;
4994 request.runlevel = rl;
4996 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4998 if (errno == ENOENT)
5001 log_error("Failed to open "INIT_FIFO": %m");
5006 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5007 close_nointr_nofail(fd);
5010 log_error("Failed to write to "INIT_FIFO": %m");
5011 return errno ? -errno : -EIO;
5017 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5019 static const struct {
5027 int (* const dispatch)(DBusConnection *bus, char **args);
5029 { "list-units", LESS, 1, list_units },
5030 { "list-unit-files", EQUAL, 1, list_unit_files },
5031 { "list-jobs", EQUAL, 1, list_jobs },
5032 { "clear-jobs", EQUAL, 1, daemon_reload },
5033 { "load", MORE, 2, load_unit },
5034 { "cancel", MORE, 2, cancel_job },
5035 { "start", MORE, 2, start_unit },
5036 { "stop", MORE, 2, start_unit },
5037 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5038 { "reload", MORE, 2, start_unit },
5039 { "restart", MORE, 2, start_unit },
5040 { "try-restart", MORE, 2, start_unit },
5041 { "reload-or-restart", MORE, 2, start_unit },
5042 { "reload-or-try-restart", MORE, 2, start_unit },
5043 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5044 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5045 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5046 { "isolate", EQUAL, 2, start_unit },
5047 { "kill", MORE, 2, kill_unit },
5048 { "is-active", MORE, 2, check_unit_active },
5049 { "check", MORE, 2, check_unit_active },
5050 { "is-failed", MORE, 2, check_unit_failed },
5051 { "show", MORE, 1, show },
5052 { "status", MORE, 2, show },
5053 { "help", MORE, 2, show },
5054 { "dump", EQUAL, 1, dump },
5055 { "dot", EQUAL, 1, dot },
5056 { "snapshot", LESS, 2, snapshot },
5057 { "delete", MORE, 2, delete_snapshot },
5058 { "daemon-reload", EQUAL, 1, daemon_reload },
5059 { "daemon-reexec", EQUAL, 1, daemon_reload },
5060 { "show-environment", EQUAL, 1, show_enviroment },
5061 { "set-environment", MORE, 2, set_environment },
5062 { "unset-environment", MORE, 2, set_environment },
5063 { "halt", EQUAL, 1, start_special },
5064 { "poweroff", EQUAL, 1, start_special },
5065 { "reboot", EQUAL, 1, start_special },
5066 { "kexec", EQUAL, 1, start_special },
5067 { "suspend", EQUAL, 1, start_special },
5068 { "hibernate", EQUAL, 1, start_special },
5069 { "hybrid-sleep", EQUAL, 1, start_special },
5070 { "default", EQUAL, 1, start_special },
5071 { "rescue", EQUAL, 1, start_special },
5072 { "emergency", EQUAL, 1, start_special },
5073 { "exit", EQUAL, 1, start_special },
5074 { "reset-failed", MORE, 1, reset_failed },
5075 { "enable", MORE, 2, enable_unit },
5076 { "disable", MORE, 2, enable_unit },
5077 { "is-enabled", MORE, 2, unit_is_enabled },
5078 { "reenable", MORE, 2, enable_unit },
5079 { "preset", MORE, 2, enable_unit },
5080 { "mask", MORE, 2, enable_unit },
5081 { "unmask", MORE, 2, enable_unit },
5082 { "link", MORE, 2, enable_unit },
5083 { "switch-root", MORE, 2, switch_root },
5093 left = argc - optind;
5096 /* Special rule: no arguments means "list-units" */
5099 if (streq(argv[optind], "help") && !argv[optind+1]) {
5100 log_error("This command expects one or more "
5101 "unit names. Did you mean --help?");
5105 for (i = 0; i < ELEMENTSOF(verbs); i++)
5106 if (streq(argv[optind], verbs[i].verb))
5109 if (i >= ELEMENTSOF(verbs)) {
5110 log_error("Unknown operation '%s'.", argv[optind]);
5115 switch (verbs[i].argc_cmp) {
5118 if (left != verbs[i].argc) {
5119 log_error("Invalid number of arguments.");
5126 if (left < verbs[i].argc) {
5127 log_error("Too few arguments.");
5134 if (left > verbs[i].argc) {
5135 log_error("Too many arguments.");
5142 assert_not_reached("Unknown comparison operator.");
5145 /* Require a bus connection for all operations but
5147 if (!streq(verbs[i].verb, "enable") &&
5148 !streq(verbs[i].verb, "disable") &&
5149 !streq(verbs[i].verb, "is-enabled") &&
5150 !streq(verbs[i].verb, "list-unit-files") &&
5151 !streq(verbs[i].verb, "reenable") &&
5152 !streq(verbs[i].verb, "preset") &&
5153 !streq(verbs[i].verb, "mask") &&
5154 !streq(verbs[i].verb, "unmask") &&
5155 !streq(verbs[i].verb, "link")) {
5157 if (running_in_chroot() > 0) {
5158 log_info("Running in chroot, ignoring request.");
5162 if (((!streq(verbs[i].verb, "reboot") &&
5163 !streq(verbs[i].verb, "halt") &&
5164 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5165 log_error("Failed to get D-Bus connection: %s",
5166 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5172 if (!bus && !avoid_bus()) {
5173 log_error("Failed to get D-Bus connection: %s",
5174 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5179 return verbs[i].dispatch(bus, argv + optind);
5182 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5184 struct msghdr msghdr;
5185 struct iovec iovec[2];
5186 union sockaddr_union sockaddr;
5187 struct sd_shutdown_command c;
5189 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5196 c.dry_run = dry_run;
5200 sockaddr.sa.sa_family = AF_UNIX;
5201 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5204 msghdr.msg_name = &sockaddr;
5205 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5208 iovec[0].iov_base = (char*) &c;
5209 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5211 if (isempty(message))
5212 msghdr.msg_iovlen = 1;
5214 iovec[1].iov_base = (char*) message;
5215 iovec[1].iov_len = strlen(message);
5216 msghdr.msg_iovlen = 2;
5218 msghdr.msg_iov = iovec;
5220 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5221 close_nointr_nofail(fd);
5225 close_nointr_nofail(fd);
5229 static int reload_with_fallback(DBusConnection *bus) {
5232 /* First, try systemd via D-Bus. */
5233 if (daemon_reload(bus, NULL) >= 0)
5237 /* Nothing else worked, so let's try signals */
5238 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5240 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5241 log_error("kill() failed: %m");
5248 static int start_with_fallback(DBusConnection *bus) {
5251 /* First, try systemd via D-Bus. */
5252 if (start_unit(bus, NULL) >= 0)
5256 /* Hmm, talking to systemd via D-Bus didn't work. Then
5257 * let's try to talk to Upstart via D-Bus. */
5258 if (talk_upstart() > 0)
5261 /* Nothing else worked, so let's try
5263 if (talk_initctl() > 0)
5266 log_error("Failed to talk to init daemon.");
5270 warn_wall(arg_action);
5274 static _noreturn_ void halt_now(enum action a) {
5276 /* Make sure C-A-D is handled by the kernel from this
5278 reboot(RB_ENABLE_CAD);
5283 log_info("Halting.");
5284 reboot(RB_HALT_SYSTEM);
5287 case ACTION_POWEROFF:
5288 log_info("Powering off.");
5289 reboot(RB_POWER_OFF);
5293 log_info("Rebooting.");
5294 reboot(RB_AUTOBOOT);
5298 assert_not_reached("Unknown halt action.");
5301 assert_not_reached("Uh? This shouldn't happen.");
5304 static int halt_main(DBusConnection *bus) {
5307 if (arg_when <= 0 && arg_force <= 0) {
5308 r = check_inhibitors(bus, arg_action);
5313 if (geteuid() != 0) {
5314 /* Try logind if we are a normal user and no special
5315 * mode applies. Maybe PolicyKit allows us to shutdown
5318 if (arg_when <= 0 &&
5321 (arg_action == ACTION_POWEROFF ||
5322 arg_action == ACTION_REBOOT)) {
5323 r = reboot_with_logind(bus, arg_action);
5328 log_error("Must be root.");
5335 m = strv_join(arg_wall, " ");
5336 r = send_shutdownd(arg_when,
5337 arg_action == ACTION_HALT ? 'H' :
5338 arg_action == ACTION_POWEROFF ? 'P' :
5339 arg_action == ACTION_KEXEC ? 'K' :
5347 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5349 char date[FORMAT_TIMESTAMP_MAX];
5351 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5352 format_timestamp(date, sizeof(date), arg_when));
5357 if (!arg_dry && !arg_force)
5358 return start_with_fallback(bus);
5361 if (sd_booted() > 0)
5362 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5364 r = utmp_put_shutdown();
5366 log_warning("Failed to write utmp record: %s", strerror(-r));
5373 halt_now(arg_action);
5374 /* We should never reach this. */
5378 static int runlevel_main(void) {
5379 int r, runlevel, previous;
5381 r = utmp_get_runlevel(&runlevel, &previous);
5388 previous <= 0 ? 'N' : previous,
5389 runlevel <= 0 ? 'N' : runlevel);
5394 int main(int argc, char*argv[]) {
5395 int r, retval = EXIT_FAILURE;
5396 DBusConnection *bus = NULL;
5399 dbus_error_init(&error);
5401 setlocale(LC_ALL, "");
5402 log_parse_environment();
5405 r = parse_argv(argc, argv);
5409 retval = EXIT_SUCCESS;
5413 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5414 * let's shortcut this */
5415 if (arg_action == ACTION_RUNLEVEL) {
5416 r = runlevel_main();
5417 retval = r < 0 ? EXIT_FAILURE : r;
5421 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5422 log_info("Running in chroot, ignoring request.");
5428 if (arg_transport == TRANSPORT_NORMAL)
5429 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5430 else if (arg_transport == TRANSPORT_POLKIT) {
5431 bus_connect_system_polkit(&bus, &error);
5432 private_bus = false;
5433 } else if (arg_transport == TRANSPORT_SSH) {
5434 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5435 private_bus = false;
5437 assert_not_reached("Uh, invalid transport...");
5440 switch (arg_action) {
5442 case ACTION_SYSTEMCTL:
5443 r = systemctl_main(bus, argc, argv, &error);
5447 case ACTION_POWEROFF:
5453 case ACTION_RUNLEVEL2:
5454 case ACTION_RUNLEVEL3:
5455 case ACTION_RUNLEVEL4:
5456 case ACTION_RUNLEVEL5:
5458 case ACTION_EMERGENCY:
5459 case ACTION_DEFAULT:
5460 r = start_with_fallback(bus);
5465 r = reload_with_fallback(bus);
5468 case ACTION_CANCEL_SHUTDOWN: {
5472 m = strv_join(arg_wall, " ");
5474 retval = EXIT_FAILURE;
5478 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5480 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5485 case ACTION_INVALID:
5486 case ACTION_RUNLEVEL:
5488 assert_not_reached("Unknown action");
5491 retval = r < 0 ? EXIT_FAILURE : r;
5495 dbus_connection_flush(bus);
5496 dbus_connection_close(bus);
5497 dbus_connection_unref(bus);
5500 dbus_error_free(&error);
5504 strv_free(arg_property);
5507 ask_password_agent_close();
5508 polkit_agent_close();