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, char *name, char **check_states, bool quiet) {
1345 DBusMessage *reply = NULL;
1346 DBusMessageIter iter, sub;
1348 *interface = "org.freedesktop.systemd1.Unit",
1349 *property = "ActiveState";
1350 const char *path = NULL;
1357 n = unit_name_mangle(name);
1358 r = bus_method_call_with_reply (
1360 "org.freedesktop.systemd1",
1361 "/org/freedesktop/systemd1",
1362 "org.freedesktop.systemd1.Manager",
1366 DBUS_TYPE_STRING, n ? &n : &name,
1370 if ((r != -ENOMEM) && (!quiet))
1375 if (!dbus_message_get_args(reply, NULL,
1376 DBUS_TYPE_OBJECT_PATH, &path,
1377 DBUS_TYPE_INVALID)) {
1378 log_error("Failed to parse reply.");
1383 dbus_message_unref(reply);
1384 r = bus_method_call_with_reply (
1386 "org.freedesktop.systemd1",
1388 "org.freedesktop.DBus.Properties",
1392 DBUS_TYPE_STRING, &interface,
1393 DBUS_TYPE_STRING, &property,
1398 if (!dbus_message_iter_init(reply, &iter) ||
1399 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1400 log_error("Failed to parse reply.");
1405 dbus_message_iter_recurse(&iter, &sub);
1407 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1408 log_error("Failed to parse reply.");
1413 dbus_message_iter_get_basic(&sub, &state);
1418 if (strv_find(check_states, state))
1421 r = 3; /* According to LSB: "program is not running" */
1425 dbus_message_unref(reply);
1430 static void check_triggering_units(
1431 DBusConnection *bus,
1432 const char *unit_name) {
1434 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1435 DBusMessageIter iter, sub;
1436 char *service_trigger = NULL;
1437 const char *interface = "org.freedesktop.systemd1.Unit",
1438 *triggered_by_property = "TriggeredBy";
1440 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1441 bool print_warning_label = true;
1444 n = unit_name_mangle(unit_name);
1450 unit_path = unit_dbus_path_from_name(n);
1456 r = bus_method_call_with_reply (
1458 "org.freedesktop.systemd1",
1460 "org.freedesktop.DBus.Properties",
1464 DBUS_TYPE_STRING, &interface,
1465 DBUS_TYPE_STRING, &triggered_by_property,
1470 if (!dbus_message_iter_init(reply, &iter) ||
1471 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1472 log_error("Failed to parse reply.");
1476 dbus_message_iter_recurse(&iter, &sub);
1477 dbus_message_iter_recurse(&sub, &iter);
1480 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1481 char **check_states = NULL;
1483 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1484 log_error("Failed to parse reply.");
1488 dbus_message_iter_get_basic(&sub, &service_trigger);
1490 check_states = strv_new("active", "reloading", NULL);
1491 r = check_one_unit(bus, service_trigger, check_states, true);
1492 strv_free(check_states);
1496 if (print_warning_label) {
1497 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1498 print_warning_label = false;
1500 log_warning(" %s", service_trigger);
1503 dbus_message_iter_next(&sub);
1507 static int start_unit_one(
1508 DBusConnection *bus,
1515 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1518 _cleanup_free_ char *n, *p = NULL;
1525 n = unit_name_mangle(name);
1529 r = bus_method_call_with_reply(
1531 "org.freedesktop.systemd1",
1532 "/org/freedesktop/systemd1",
1533 "org.freedesktop.systemd1.Manager",
1537 DBUS_TYPE_STRING, &n,
1538 DBUS_TYPE_STRING, &mode,
1541 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1542 /* There's always a fallback possible for
1543 * legacy actions. */
1546 log_error("Failed to issue method call: %s", bus_error_message(error));
1551 if (!dbus_message_get_args(reply, error,
1552 DBUS_TYPE_OBJECT_PATH, &path,
1553 DBUS_TYPE_INVALID)) {
1554 log_error("Failed to parse reply: %s", bus_error_message(error));
1558 if (need_daemon_reload(bus, n))
1559 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1560 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1569 log_error("Failed to add path to set.");
1579 static enum action verb_to_action(const char *verb) {
1580 if (streq(verb, "halt"))
1582 else if (streq(verb, "poweroff"))
1583 return ACTION_POWEROFF;
1584 else if (streq(verb, "reboot"))
1585 return ACTION_REBOOT;
1586 else if (streq(verb, "kexec"))
1587 return ACTION_KEXEC;
1588 else if (streq(verb, "rescue"))
1589 return ACTION_RESCUE;
1590 else if (streq(verb, "emergency"))
1591 return ACTION_EMERGENCY;
1592 else if (streq(verb, "default"))
1593 return ACTION_DEFAULT;
1594 else if (streq(verb, "exit"))
1596 else if (streq(verb, "suspend"))
1597 return ACTION_SUSPEND;
1598 else if (streq(verb, "hibernate"))
1599 return ACTION_HIBERNATE;
1600 else if (streq(verb, "hybrid-sleep"))
1601 return ACTION_HYBRID_SLEEP;
1603 return ACTION_INVALID;
1606 static int start_unit(DBusConnection *bus, char **args) {
1608 static const char * const table[_ACTION_MAX] = {
1609 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1610 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1611 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1612 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1613 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1614 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1615 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1616 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1617 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1618 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1619 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1620 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1621 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1622 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
1623 [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
1627 const char *method, *mode, *one_name;
1632 dbus_error_init(&error);
1636 ask_password_agent_open_if_enabled();
1638 if (arg_action == ACTION_SYSTEMCTL) {
1640 streq(args[0], "stop") ||
1641 streq(args[0], "condstop") ? "StopUnit" :
1642 streq(args[0], "reload") ? "ReloadUnit" :
1643 streq(args[0], "restart") ? "RestartUnit" :
1645 streq(args[0], "try-restart") ||
1646 streq(args[0], "condrestart") ? "TryRestartUnit" :
1648 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1650 streq(args[0], "reload-or-try-restart") ||
1651 streq(args[0], "condreload") ||
1653 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1657 (streq(args[0], "isolate") ||
1658 streq(args[0], "rescue") ||
1659 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1661 one_name = table[verb_to_action(args[0])];
1664 assert(arg_action < ELEMENTSOF(table));
1665 assert(table[arg_action]);
1667 method = "StartUnit";
1669 mode = (arg_action == ACTION_EMERGENCY ||
1670 arg_action == ACTION_RESCUE ||
1671 arg_action == ACTION_RUNLEVEL2 ||
1672 arg_action == ACTION_RUNLEVEL3 ||
1673 arg_action == ACTION_RUNLEVEL4 ||
1674 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1676 one_name = table[arg_action];
1679 if (!arg_no_block) {
1680 ret = enable_wait_for_jobs(bus);
1682 log_error("Could not watch jobs: %s", strerror(-ret));
1686 s = set_new(string_hash_func, string_compare_func);
1694 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1696 ret = translate_bus_error_to_exit_status(ret, &error);
1698 STRV_FOREACH(name, args+1) {
1699 r = start_unit_one(bus, method, *name, mode, &error, s);
1701 ret = translate_bus_error_to_exit_status(r, &error);
1702 dbus_error_free(&error);
1707 if (!arg_no_block) {
1708 r = wait_for_jobs(bus, s);
1714 /* When stopping units, warn if they can still be triggered by
1715 * another active unit (socket, path, timer) */
1716 if (!arg_quiet && streq(method, "StopUnit")) {
1718 check_triggering_units(bus, one_name);
1720 STRV_FOREACH(name, args+1)
1721 check_triggering_units(bus, *name);
1727 dbus_error_free(&error);
1732 /* Ask systemd-logind, which might grant access to unprivileged users
1733 * through PolicyKit */
1734 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1737 dbus_bool_t interactive = true;
1739 polkit_agent_open_if_enabled();
1747 case ACTION_POWEROFF:
1748 method = "PowerOff";
1751 case ACTION_SUSPEND:
1755 case ACTION_HIBERNATE:
1756 method = "Hibernate";
1759 case ACTION_HYBRID_SLEEP:
1760 method = "HybridSleep";
1767 return bus_method_call_with_reply (
1769 "org.freedesktop.login1",
1770 "/org/freedesktop/login1",
1771 "org.freedesktop.login1.Manager",
1775 DBUS_TYPE_BOOLEAN, &interactive,
1782 static int check_inhibitors(DBusConnection *bus, enum action a) {
1784 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1785 DBusMessageIter iter, sub, sub2;
1789 if (arg_ignore_inhibitors)
1795 r = bus_method_call_with_reply(
1797 "org.freedesktop.login1",
1798 "/org/freedesktop/login1",
1799 "org.freedesktop.login1.Manager",
1805 /* If logind is not around, then there are no inhibitors... */
1808 if (!dbus_message_iter_init(reply, &iter) ||
1809 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1810 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1811 log_error("Failed to parse reply.");
1815 dbus_message_iter_recurse(&iter, &sub);
1816 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1817 const char *what, *who, *why, *mode;
1819 _cleanup_strv_free_ char **sv = NULL;
1820 _cleanup_free_ char *comm = NULL;
1822 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1823 log_error("Failed to parse reply.");
1827 dbus_message_iter_recurse(&sub, &sub2);
1829 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
1830 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
1831 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
1832 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
1833 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
1834 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
1835 log_error("Failed to parse reply.");
1839 if (!streq(mode, "block"))
1842 sv = strv_split(what, ":");
1846 if (!strv_contains(sv,
1848 a == ACTION_POWEROFF ||
1849 a == ACTION_REBOOT ||
1850 a == ACTION_KEXEC ? "shutdown" : "sleep"))
1853 get_process_comm(pid, &comm);
1854 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", UID %lu), reason is \"%s\".", who, (unsigned long) pid, strna(comm), (unsigned long) uid, why);
1858 dbus_message_iter_next(&sub);
1861 dbus_message_iter_recurse(&iter, &sub);
1866 log_error("Please try again after closing inhibitors or ignore them with 'systemctl %s -i'.",
1867 a == ACTION_HALT ? "halt" :
1868 a == ACTION_POWEROFF ? "poweroff" :
1869 a == ACTION_REBOOT ? "reboot" :
1870 a == ACTION_KEXEC ? "kexec" :
1871 a == ACTION_SUSPEND ? "suspend" :
1872 a == ACTION_HIBERNATE ? "hibernate" : "hybrid-sleep");
1880 static int start_special(DBusConnection *bus, char **args) {
1886 a = verb_to_action(args[0]);
1888 if (arg_force >= 2 && geteuid() != 0) {
1889 log_error("Must be root.");
1893 if (arg_force >= 2 &&
1894 (a == ACTION_HALT ||
1895 a == ACTION_POWEROFF ||
1896 a == ACTION_REBOOT))
1899 if (arg_force >= 1 &&
1900 (a == ACTION_HALT ||
1901 a == ACTION_POWEROFF ||
1902 a == ACTION_REBOOT ||
1903 a == ACTION_KEXEC ||
1905 return daemon_reload(bus, args);
1907 if (arg_force <= 0) {
1908 r = check_inhibitors(bus, a);
1913 /* first try logind, to allow authentication with polkit */
1914 if (geteuid() != 0 &&
1915 (a == ACTION_POWEROFF ||
1916 a == ACTION_REBOOT ||
1917 a == ACTION_SUSPEND ||
1918 a == ACTION_HIBERNATE ||
1919 a == ACTION_HYBRID_SLEEP)) {
1920 r = reboot_with_logind(bus, a);
1925 r = start_unit(bus, args);
1932 static int check_unit_active(DBusConnection *bus, char **args) {
1934 int r = 3; /* According to LSB: "program is not running" */
1939 STRV_FOREACH(name, args+1) {
1940 char **check_states = strv_new("active", "reloading", NULL);
1941 int state = check_one_unit(bus, *name, check_states, arg_quiet);
1942 strv_free(check_states);
1952 static int check_unit_failed(DBusConnection *bus, char **args) {
1959 STRV_FOREACH(name, args+1) {
1960 char **check_states = strv_new("failed", NULL);
1961 int state = check_one_unit(bus, *name, check_states, arg_quiet);
1962 strv_free(check_states);
1972 static int kill_unit(DBusConnection *bus, char **args) {
1979 arg_kill_who = "all";
1981 STRV_FOREACH(name, args+1) {
1982 n = unit_name_mangle(*name);
1983 r = bus_method_call_with_reply (
1985 "org.freedesktop.systemd1",
1986 "/org/freedesktop/systemd1",
1987 "org.freedesktop.systemd1.Manager",
1991 DBUS_TYPE_STRING, n ? &n : name,
1992 DBUS_TYPE_STRING, &arg_kill_who,
1993 DBUS_TYPE_INT32, &arg_signal,
2002 typedef struct ExecStatusInfo {
2010 usec_t start_timestamp;
2011 usec_t exit_timestamp;
2016 LIST_FIELDS(struct ExecStatusInfo, exec);
2019 static void exec_status_info_free(ExecStatusInfo *i) {
2028 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2029 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2030 DBusMessageIter sub2, sub3;
2034 int32_t code, status;
2040 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2043 dbus_message_iter_recurse(sub, &sub2);
2045 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2048 if (!(i->path = strdup(path)))
2051 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2052 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2056 dbus_message_iter_recurse(&sub2, &sub3);
2057 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2058 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2059 dbus_message_iter_next(&sub3);
2064 if (!(i->argv = new0(char*, n+1)))
2068 dbus_message_iter_recurse(&sub2, &sub3);
2069 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2072 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2073 dbus_message_iter_get_basic(&sub3, &s);
2074 dbus_message_iter_next(&sub3);
2076 if (!(i->argv[n++] = strdup(s)))
2080 if (!dbus_message_iter_next(&sub2) ||
2081 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2082 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2083 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2084 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2085 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2086 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2087 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2088 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2092 i->start_timestamp = (usec_t) start_timestamp;
2093 i->exit_timestamp = (usec_t) exit_timestamp;
2094 i->pid = (pid_t) pid;
2101 typedef struct UnitStatusInfo {
2103 const char *load_state;
2104 const char *active_state;
2105 const char *sub_state;
2106 const char *unit_file_state;
2108 const char *description;
2109 const char *following;
2111 char **documentation;
2113 const char *fragment_path;
2114 const char *source_path;
2115 const char *default_control_group;
2117 const char *load_error;
2120 usec_t inactive_exit_timestamp;
2121 usec_t inactive_exit_timestamp_monotonic;
2122 usec_t active_enter_timestamp;
2123 usec_t active_exit_timestamp;
2124 usec_t inactive_enter_timestamp;
2126 bool need_daemon_reload;
2131 const char *status_text;
2134 usec_t start_timestamp;
2135 usec_t exit_timestamp;
2137 int exit_code, exit_status;
2139 usec_t condition_timestamp;
2140 bool condition_result;
2143 unsigned n_accepted;
2144 unsigned n_connections;
2148 const char *sysfs_path;
2150 /* Mount, Automount */
2156 LIST_HEAD(ExecStatusInfo, exec);
2159 static void print_status_info(UnitStatusInfo *i) {
2161 const char *on, *off, *ss;
2163 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2164 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2169 /* This shows pretty information about a unit. See
2170 * print_property() for a low-level property printer */
2172 printf("%s", strna(i->id));
2174 if (i->description && !streq_ptr(i->id, i->description))
2175 printf(" - %s", i->description);
2180 printf("\t Follow: unit currently follows state of %s\n", i->following);
2182 if (streq_ptr(i->load_state, "error")) {
2183 on = ansi_highlight_red(true);
2184 off = ansi_highlight_red(false);
2188 path = i->source_path ? i->source_path : i->fragment_path;
2191 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2192 else if (path && i->unit_file_state)
2193 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2195 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2197 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2199 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2201 if (streq_ptr(i->active_state, "failed")) {
2202 on = ansi_highlight_red(true);
2203 off = ansi_highlight_red(false);
2204 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2205 on = ansi_highlight_green(true);
2206 off = ansi_highlight_green(false);
2211 printf("\t Active: %s%s (%s)%s",
2213 strna(i->active_state),
2217 printf("\t Active: %s%s%s",
2219 strna(i->active_state),
2222 if (!isempty(i->result) && !streq(i->result, "success"))
2223 printf(" (Result: %s)", i->result);
2225 timestamp = (streq_ptr(i->active_state, "active") ||
2226 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2227 (streq_ptr(i->active_state, "inactive") ||
2228 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2229 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2230 i->active_exit_timestamp;
2232 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2233 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2236 printf(" since %s; %s\n", s2, s1);
2238 printf(" since %s\n", s2);
2242 if (!i->condition_result && i->condition_timestamp > 0) {
2243 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2244 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2247 printf("\t start condition failed at %s; %s\n", s2, s1);
2249 printf("\t start condition failed at %s\n", s2);
2253 printf("\t Device: %s\n", i->sysfs_path);
2255 printf("\t Where: %s\n", i->where);
2257 printf("\t What: %s\n", i->what);
2259 if (!strv_isempty(i->documentation)) {
2263 STRV_FOREACH(t, i->documentation) {
2265 printf("\t Docs: %s\n", *t);
2268 printf("\t %s\n", *t);
2273 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2275 LIST_FOREACH(exec, p, i->exec) {
2279 /* Only show exited processes here */
2283 t = strv_join(p->argv, " ");
2284 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2287 good = is_clean_exit_lsb(p->code, p->status, NULL);
2289 on = ansi_highlight_red(true);
2290 off = ansi_highlight_red(false);
2294 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2296 if (p->code == CLD_EXITED) {
2299 printf("status=%i", p->status);
2301 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2306 printf("signal=%s", signal_to_string(p->status));
2308 printf(")%s\n", off);
2310 if (i->main_pid == p->pid &&
2311 i->start_timestamp == p->start_timestamp &&
2312 i->exit_timestamp == p->start_timestamp)
2313 /* Let's not show this twice */
2316 if (p->pid == i->control_pid)
2320 if (i->main_pid > 0 || i->control_pid > 0) {
2323 if (i->main_pid > 0) {
2324 printf("Main PID: %u", (unsigned) i->main_pid);
2328 get_process_comm(i->main_pid, &t);
2333 } else if (i->exit_code > 0) {
2334 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2336 if (i->exit_code == CLD_EXITED) {
2339 printf("status=%i", i->exit_status);
2341 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2346 printf("signal=%s", signal_to_string(i->exit_status));
2351 if (i->main_pid > 0 && i->control_pid > 0)
2354 if (i->control_pid > 0) {
2357 printf(" Control: %u", (unsigned) i->control_pid);
2359 get_process_comm(i->control_pid, &t);
2370 printf("\t Status: \"%s\"\n", i->status_text);
2372 if (i->default_control_group &&
2373 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2376 printf("\t CGroup: %s\n", i->default_control_group);
2378 if (arg_transport != TRANSPORT_SSH) {
2388 if (i->main_pid > 0)
2389 extra[k++] = i->main_pid;
2391 if (i->control_pid > 0)
2392 extra[k++] = i->control_pid;
2394 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2398 if (i->id && arg_transport != TRANSPORT_SSH) {
2400 arg_all * OUTPUT_SHOW_ALL |
2401 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2402 on_tty() * OUTPUT_COLOR |
2403 !arg_quiet * OUTPUT_WARN_CUTOFF;
2406 show_journal_by_unit(stdout,
2410 i->inactive_exit_timestamp_monotonic,
2415 if (i->need_daemon_reload)
2416 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2417 ansi_highlight_red(true),
2418 ansi_highlight_red(false),
2419 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2422 static void show_unit_help(UnitStatusInfo *i) {
2427 if (!i->documentation) {
2428 log_info("Documentation for %s not known.", i->id);
2432 STRV_FOREACH(p, i->documentation) {
2434 if (startswith(*p, "man:")) {
2437 char *page = NULL, *section = NULL;
2438 const char *args[4] = { "man", NULL, NULL, NULL };
2443 if ((*p)[k-1] == ')')
2444 e = strrchr(*p, '(');
2447 page = strndup((*p) + 4, e - *p - 4);
2453 section = strndup(e + 1, *p + k - e - 2);
2467 log_error("Failed to fork: %m");
2475 execvp(args[0], (char**) args);
2476 log_error("Failed to execute man: %m");
2477 _exit(EXIT_FAILURE);
2483 wait_for_terminate(pid, NULL);
2485 log_info("Can't show: %s", *p);
2489 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2495 switch (dbus_message_iter_get_arg_type(iter)) {
2497 case DBUS_TYPE_STRING: {
2500 dbus_message_iter_get_basic(iter, &s);
2503 if (streq(name, "Id"))
2505 else if (streq(name, "LoadState"))
2507 else if (streq(name, "ActiveState"))
2508 i->active_state = s;
2509 else if (streq(name, "SubState"))
2511 else if (streq(name, "Description"))
2513 else if (streq(name, "FragmentPath"))
2514 i->fragment_path = s;
2515 else if (streq(name, "SourcePath"))
2517 else if (streq(name, "DefaultControlGroup"))
2518 i->default_control_group = s;
2519 else if (streq(name, "StatusText"))
2521 else if (streq(name, "SysFSPath"))
2523 else if (streq(name, "Where"))
2525 else if (streq(name, "What"))
2527 else if (streq(name, "Following"))
2529 else if (streq(name, "UnitFileState"))
2530 i->unit_file_state = s;
2531 else if (streq(name, "Result"))
2538 case DBUS_TYPE_BOOLEAN: {
2541 dbus_message_iter_get_basic(iter, &b);
2543 if (streq(name, "Accept"))
2545 else if (streq(name, "NeedDaemonReload"))
2546 i->need_daemon_reload = b;
2547 else if (streq(name, "ConditionResult"))
2548 i->condition_result = b;
2553 case DBUS_TYPE_UINT32: {
2556 dbus_message_iter_get_basic(iter, &u);
2558 if (streq(name, "MainPID")) {
2560 i->main_pid = (pid_t) u;
2563 } else if (streq(name, "ControlPID"))
2564 i->control_pid = (pid_t) u;
2565 else if (streq(name, "ExecMainPID")) {
2567 i->main_pid = (pid_t) u;
2568 } else if (streq(name, "NAccepted"))
2570 else if (streq(name, "NConnections"))
2571 i->n_connections = u;
2576 case DBUS_TYPE_INT32: {
2579 dbus_message_iter_get_basic(iter, &j);
2581 if (streq(name, "ExecMainCode"))
2582 i->exit_code = (int) j;
2583 else if (streq(name, "ExecMainStatus"))
2584 i->exit_status = (int) j;
2589 case DBUS_TYPE_UINT64: {
2592 dbus_message_iter_get_basic(iter, &u);
2594 if (streq(name, "ExecMainStartTimestamp"))
2595 i->start_timestamp = (usec_t) u;
2596 else if (streq(name, "ExecMainExitTimestamp"))
2597 i->exit_timestamp = (usec_t) u;
2598 else if (streq(name, "ActiveEnterTimestamp"))
2599 i->active_enter_timestamp = (usec_t) u;
2600 else if (streq(name, "InactiveEnterTimestamp"))
2601 i->inactive_enter_timestamp = (usec_t) u;
2602 else if (streq(name, "InactiveExitTimestamp"))
2603 i->inactive_exit_timestamp = (usec_t) u;
2604 else if (streq(name, "InactiveExitTimestampMonotonic"))
2605 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2606 else if (streq(name, "ActiveExitTimestamp"))
2607 i->active_exit_timestamp = (usec_t) u;
2608 else if (streq(name, "ConditionTimestamp"))
2609 i->condition_timestamp = (usec_t) u;
2614 case DBUS_TYPE_ARRAY: {
2616 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2617 startswith(name, "Exec")) {
2618 DBusMessageIter sub;
2620 dbus_message_iter_recurse(iter, &sub);
2621 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2622 ExecStatusInfo *info;
2625 if (!(info = new0(ExecStatusInfo, 1)))
2628 if (!(info->name = strdup(name))) {
2633 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2638 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2640 dbus_message_iter_next(&sub);
2642 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2643 streq(name, "Documentation")) {
2645 DBusMessageIter sub;
2647 dbus_message_iter_recurse(iter, &sub);
2648 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2652 dbus_message_iter_get_basic(&sub, &s);
2654 l = strv_append(i->documentation, s);
2658 strv_free(i->documentation);
2659 i->documentation = l;
2661 dbus_message_iter_next(&sub);
2668 case DBUS_TYPE_STRUCT: {
2670 if (streq(name, "LoadError")) {
2671 DBusMessageIter sub;
2672 const char *n, *message;
2675 dbus_message_iter_recurse(iter, &sub);
2677 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2681 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2685 if (!isempty(message))
2686 i->load_error = message;
2696 static int print_property(const char *name, DBusMessageIter *iter) {
2700 /* This is a low-level property printer, see
2701 * print_status_info() for the nicer output */
2703 if (arg_property && !strv_find(arg_property, name))
2706 switch (dbus_message_iter_get_arg_type(iter)) {
2708 case DBUS_TYPE_STRUCT: {
2709 DBusMessageIter sub;
2710 dbus_message_iter_recurse(iter, &sub);
2712 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2715 dbus_message_iter_get_basic(&sub, &u);
2718 printf("%s=%u\n", name, (unsigned) u);
2720 printf("%s=\n", name);
2723 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2726 dbus_message_iter_get_basic(&sub, &s);
2728 if (arg_all || s[0])
2729 printf("%s=%s\n", name, s);
2732 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2733 const char *a = NULL, *b = NULL;
2735 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2736 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2738 if (arg_all || !isempty(a) || !isempty(b))
2739 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2747 case DBUS_TYPE_ARRAY:
2749 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2750 DBusMessageIter sub, sub2;
2752 dbus_message_iter_recurse(iter, &sub);
2753 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2757 dbus_message_iter_recurse(&sub, &sub2);
2759 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2760 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2761 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2763 dbus_message_iter_next(&sub);
2768 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2769 DBusMessageIter sub, sub2;
2771 dbus_message_iter_recurse(iter, &sub);
2772 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2773 const char *type, *path;
2775 dbus_message_iter_recurse(&sub, &sub2);
2777 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2778 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2779 printf("%s=%s\n", type, path);
2781 dbus_message_iter_next(&sub);
2786 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2787 DBusMessageIter sub, sub2;
2789 dbus_message_iter_recurse(iter, &sub);
2790 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2792 uint64_t value, next_elapse;
2794 dbus_message_iter_recurse(&sub, &sub2);
2796 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2797 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2798 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2799 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2801 printf("%s={ value=%s ; next_elapse=%s }\n",
2803 format_timespan(timespan1, sizeof(timespan1), value),
2804 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2807 dbus_message_iter_next(&sub);
2812 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2813 DBusMessageIter sub, sub2;
2815 dbus_message_iter_recurse(iter, &sub);
2816 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2817 const char *controller, *attr, *value;
2819 dbus_message_iter_recurse(&sub, &sub2);
2821 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2822 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2823 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2825 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2831 dbus_message_iter_next(&sub);
2836 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2837 DBusMessageIter sub;
2839 dbus_message_iter_recurse(iter, &sub);
2840 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2841 ExecStatusInfo info;
2844 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2845 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2848 t = strv_join(info.argv, " ");
2850 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2854 yes_no(info.ignore),
2855 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2856 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2857 (unsigned) info. pid,
2858 sigchld_code_to_string(info.code),
2860 info.code == CLD_EXITED ? "" : "/",
2861 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2867 strv_free(info.argv);
2869 dbus_message_iter_next(&sub);
2878 if (generic_print_property(name, iter, arg_all) > 0)
2882 printf("%s=[unprintable]\n", name);
2887 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2888 DBusMessage *reply = NULL;
2889 const char *interface = "";
2891 DBusMessageIter iter, sub, sub2, sub3;
2892 UnitStatusInfo info;
2900 r = bus_method_call_with_reply (
2902 "org.freedesktop.systemd1",
2904 "org.freedesktop.DBus.Properties",
2908 DBUS_TYPE_STRING, &interface,
2913 if (!dbus_message_iter_init(reply, &iter) ||
2914 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2915 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2916 log_error("Failed to parse reply.");
2921 dbus_message_iter_recurse(&iter, &sub);
2928 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2931 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2932 log_error("Failed to parse reply.");
2937 dbus_message_iter_recurse(&sub, &sub2);
2939 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2940 log_error("Failed to parse reply.");
2945 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2946 log_error("Failed to parse reply.");
2951 dbus_message_iter_recurse(&sub2, &sub3);
2953 if (show_properties)
2954 r = print_property(name, &sub3);
2956 r = status_property(name, &sub3, &info);
2959 log_error("Failed to parse reply.");
2964 dbus_message_iter_next(&sub);
2969 if (!show_properties) {
2970 if (streq(verb, "help"))
2971 show_unit_help(&info);
2973 print_status_info(&info);
2976 strv_free(info.documentation);
2978 if (!streq_ptr(info.active_state, "active") &&
2979 !streq_ptr(info.active_state, "reloading") &&
2980 streq(verb, "status"))
2981 /* According to LSB: "program not running" */
2984 while ((p = info.exec)) {
2985 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
2986 exec_status_info_free(p);
2991 dbus_message_unref(reply);
2996 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
2997 DBusMessage *reply = NULL;
2998 const char *path = NULL;
3002 dbus_error_init(&error);
3004 r = bus_method_call_with_reply (
3006 "org.freedesktop.systemd1",
3007 "/org/freedesktop/systemd1",
3008 "org.freedesktop.systemd1.Manager",
3012 DBUS_TYPE_UINT32, &pid,
3017 if (!dbus_message_get_args(reply, &error,
3018 DBUS_TYPE_OBJECT_PATH, &path,
3019 DBUS_TYPE_INVALID)) {
3020 log_error("Failed to parse reply: %s", bus_error_message(&error));
3025 r = show_one(verb, bus, path, false, new_line);
3029 dbus_message_unref(reply);
3031 dbus_error_free(&error);
3036 static int show(DBusConnection *bus, char **args) {
3038 bool show_properties, new_line = false;
3044 show_properties = streq(args[0], "show");
3046 if (show_properties)
3047 pager_open_if_enabled();
3049 if (show_properties && strv_length(args) <= 1) {
3050 /* If not argument is specified inspect the manager
3053 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3056 STRV_FOREACH(name, args+1) {
3059 if (safe_atou32(*name, &id) < 0) {
3061 /* Interpret as unit name */
3063 n = unit_name_mangle(*name);
3064 p = unit_dbus_path_from_name(n ? n : *name);
3069 r = show_one(args[0], bus, p, show_properties, &new_line);
3075 } else if (show_properties) {
3077 /* Interpret as job id */
3080 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3083 r = show_one(args[0], bus, p, show_properties, &new_line);
3091 /* Interpret as PID */
3093 r = show_one_by_pid(args[0], bus, id, &new_line);
3102 static int dump(DBusConnection *bus, char **args) {
3103 DBusMessage *reply = NULL;
3108 dbus_error_init(&error);
3110 pager_open_if_enabled();
3112 r = bus_method_call_with_reply (
3114 "org.freedesktop.systemd1",
3115 "/org/freedesktop/systemd1",
3116 "org.freedesktop.systemd1.Manager",
3124 if (!dbus_message_get_args(reply, &error,
3125 DBUS_TYPE_STRING, &text,
3126 DBUS_TYPE_INVALID)) {
3127 log_error("Failed to parse reply: %s", bus_error_message(&error));
3132 fputs(text, stdout);
3136 dbus_message_unref(reply);
3138 dbus_error_free(&error);
3143 static int snapshot(DBusConnection *bus, char **args) {
3144 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3147 dbus_bool_t cleanup = FALSE;
3148 DBusMessageIter iter, sub;
3150 *name = "", *path, *id,
3151 *interface = "org.freedesktop.systemd1.Unit",
3153 _cleanup_free_ char *n = NULL;
3155 dbus_error_init(&error);
3157 if (strv_length(args) > 1) {
3159 n = unit_name_mangle(name);
3162 r = bus_method_call_with_reply (
3164 "org.freedesktop.systemd1",
3165 "/org/freedesktop/systemd1",
3166 "org.freedesktop.systemd1.Manager",
3170 DBUS_TYPE_STRING, n ? (const char**) &n : &name,
3171 DBUS_TYPE_BOOLEAN, &cleanup,
3176 if (!dbus_message_get_args(reply, &error,
3177 DBUS_TYPE_OBJECT_PATH, &path,
3178 DBUS_TYPE_INVALID)) {
3179 log_error("Failed to parse reply: %s", bus_error_message(&error));
3184 dbus_message_unref(reply);
3187 r = bus_method_call_with_reply (
3189 "org.freedesktop.systemd1",
3191 "org.freedesktop.DBus.Properties",
3195 DBUS_TYPE_STRING, &interface,
3196 DBUS_TYPE_STRING, &property,
3201 if (!dbus_message_iter_init(reply, &iter) ||
3202 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3203 log_error("Failed to parse reply.");
3208 dbus_message_iter_recurse(&iter, &sub);
3210 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3211 log_error("Failed to parse reply.");
3216 dbus_message_iter_get_basic(&sub, &id);
3222 dbus_error_free(&error);
3227 static int delete_snapshot(DBusConnection *bus, char **args) {
3232 STRV_FOREACH(name, args+1) {
3233 _cleanup_free_ char *n = NULL;
3236 n = unit_name_mangle(*name);
3237 r = bus_method_call_with_reply(
3239 "org.freedesktop.systemd1",
3240 "/org/freedesktop/systemd1",
3241 "org.freedesktop.systemd1.Manager",
3245 DBUS_TYPE_STRING, n ? &n : name,
3254 static int daemon_reload(DBusConnection *bus, char **args) {
3259 if (arg_action == ACTION_RELOAD)
3261 else if (arg_action == ACTION_REEXEC)
3262 method = "Reexecute";
3264 assert(arg_action == ACTION_SYSTEMCTL);
3267 streq(args[0], "clear-jobs") ||
3268 streq(args[0], "cancel") ? "ClearJobs" :
3269 streq(args[0], "daemon-reexec") ? "Reexecute" :
3270 streq(args[0], "reset-failed") ? "ResetFailed" :
3271 streq(args[0], "halt") ? "Halt" :
3272 streq(args[0], "poweroff") ? "PowerOff" :
3273 streq(args[0], "reboot") ? "Reboot" :
3274 streq(args[0], "kexec") ? "KExec" :
3275 streq(args[0], "exit") ? "Exit" :
3276 /* "daemon-reload" */ "Reload";
3279 r = bus_method_call_with_reply (
3281 "org.freedesktop.systemd1",
3282 "/org/freedesktop/systemd1",
3283 "org.freedesktop.systemd1.Manager",
3289 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3290 /* There's always a fallback possible for
3291 * legacy actions. */
3293 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3294 /* On reexecution, we expect a disconnect, not
3298 log_error("Failed to issue method call: %s", bus_error_message(&error));
3299 dbus_error_free(&error);
3304 static int reset_failed(DBusConnection *bus, char **args) {
3308 if (strv_length(args) <= 1)
3309 return daemon_reload(bus, args);
3311 STRV_FOREACH(name, args+1) {
3312 n = unit_name_mangle(*name);
3313 r = bus_method_call_with_reply (
3315 "org.freedesktop.systemd1",
3316 "/org/freedesktop/systemd1",
3317 "org.freedesktop.systemd1.Manager",
3321 DBUS_TYPE_STRING, n ? &n : name,
3332 static int show_enviroment(DBusConnection *bus, char **args) {
3333 DBusMessage *reply = NULL;
3334 DBusMessageIter iter, sub, sub2;
3337 *interface = "org.freedesktop.systemd1.Manager",
3338 *property = "Environment";
3340 pager_open_if_enabled();
3342 r = bus_method_call_with_reply (
3344 "org.freedesktop.systemd1",
3345 "/org/freedesktop/systemd1",
3346 "org.freedesktop.DBus.Properties",
3350 DBUS_TYPE_STRING, &interface,
3351 DBUS_TYPE_STRING, &property,
3356 if (!dbus_message_iter_init(reply, &iter) ||
3357 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3358 log_error("Failed to parse reply.");
3363 dbus_message_iter_recurse(&iter, &sub);
3365 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3366 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3367 log_error("Failed to parse reply.");
3372 dbus_message_iter_recurse(&sub, &sub2);
3374 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3377 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3378 log_error("Failed to parse reply.");
3383 dbus_message_iter_get_basic(&sub2, &text);
3384 printf("%s\n", text);
3386 dbus_message_iter_next(&sub2);
3393 dbus_message_unref(reply);
3398 static int switch_root(DBusConnection *bus, char **args) {
3401 _cleanup_free_ char *init = NULL;
3403 l = strv_length(args);
3404 if (l < 2 || l > 3) {
3405 log_error("Wrong number of arguments.");
3412 init = strdup(args[2]);
3414 parse_env_file("/proc/cmdline", WHITESPACE,
3426 log_debug("switching root - root: %s; init: %s", root, init);
3428 return bus_method_call_with_reply (
3430 "org.freedesktop.systemd1",
3431 "/org/freedesktop/systemd1",
3432 "org.freedesktop.systemd1.Manager",
3436 DBUS_TYPE_STRING, &root,
3437 DBUS_TYPE_STRING, &init,
3441 static int set_environment(DBusConnection *bus, char **args) {
3442 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3445 DBusMessageIter iter;
3450 dbus_error_init(&error);
3452 method = streq(args[0], "set-environment")
3454 : "UnsetEnvironment";
3456 m = dbus_message_new_method_call(
3457 "org.freedesktop.systemd1",
3458 "/org/freedesktop/systemd1",
3459 "org.freedesktop.systemd1.Manager",
3464 dbus_message_iter_init_append(m, &iter);
3466 r = bus_append_strv_iter(&iter, args + 1);
3470 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3472 log_error("Failed to issue method call: %s", bus_error_message(&error));
3480 dbus_error_free(&error);
3484 static int enable_sysv_units(char **args) {
3487 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3488 const char *verb = args[0];
3489 unsigned f = 1, t = 1;
3492 if (arg_scope != UNIT_FILE_SYSTEM)
3495 if (!streq(verb, "enable") &&
3496 !streq(verb, "disable") &&
3497 !streq(verb, "is-enabled"))
3500 /* Processes all SysV units, and reshuffles the array so that
3501 * afterwards only the native units remain */
3504 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3509 for (f = 1; args[f]; f++) {
3512 bool found_native = false, found_sysv;
3514 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3515 char **k, *l, *q = NULL;
3522 if (!endswith(name, ".service"))
3525 if (path_is_absolute(name))
3528 STRV_FOREACH(k, paths.unit_path) {
3531 if (!isempty(arg_root))
3532 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3534 asprintf(&p, "%s/%s", *k, name);
3541 found_native = access(p, F_OK) >= 0;
3552 if (!isempty(arg_root))
3553 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3555 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3561 p[strlen(p) - sizeof(".service") + 1] = 0;
3562 found_sysv = access(p, F_OK) >= 0;
3569 /* Mark this entry, so that we don't try enabling it as native unit */
3570 args[f] = (char*) "";
3572 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3574 if (!isempty(arg_root))
3575 argv[c++] = q = strappend("--root=", arg_root);
3577 argv[c++] = path_get_file_name(p);
3579 streq(verb, "enable") ? "on" :
3580 streq(verb, "disable") ? "off" : "--level=5";
3583 l = strv_join((char**)argv, " ");
3591 log_info("Executing %s", l);
3596 log_error("Failed to fork: %m");
3601 } else if (pid == 0) {
3604 execv(argv[0], (char**) argv);
3605 _exit(EXIT_FAILURE);
3611 j = wait_for_terminate(pid, &status);
3613 log_error("Failed to wait for child: %s", strerror(-r));
3618 if (status.si_code == CLD_EXITED) {
3619 if (streq(verb, "is-enabled")) {
3620 if (status.si_status == 0) {
3629 } else if (status.si_status != 0) {
3640 lookup_paths_free(&paths);
3642 /* Drop all SysV units */
3643 for (f = 1, t = 1; args[f]; f++) {
3645 if (isempty(args[f]))
3648 args[t++] = args[f];
3657 static int mangle_names(char **original_names, char ***mangled_names) {
3658 char **i, **l, **name;
3660 l = new(char*, strv_length(original_names) + 1);
3665 STRV_FOREACH(name, original_names) {
3667 /* When enabling units qualified path names are OK,
3668 * too, hence allow them explicitly. */
3673 *i = unit_name_mangle(*name);
3689 static int enable_unit(DBusConnection *bus, char **args) {
3690 const char *verb = args[0];
3691 UnitFileChange *changes = NULL;
3692 unsigned n_changes = 0, i;
3693 int carries_install_info = -1;
3694 DBusMessage *m = NULL, *reply = NULL;
3697 char **mangled_names = NULL;
3699 r = enable_sysv_units(args);
3706 dbus_error_init(&error);
3708 if (!bus || avoid_bus()) {
3709 if (streq(verb, "enable")) {
3710 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3711 carries_install_info = r;
3712 } else if (streq(verb, "disable"))
3713 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3714 else if (streq(verb, "reenable")) {
3715 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3716 carries_install_info = r;
3717 } else if (streq(verb, "link"))
3718 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3719 else if (streq(verb, "preset")) {
3720 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3721 carries_install_info = r;
3722 } else if (streq(verb, "mask"))
3723 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3724 else if (streq(verb, "unmask"))
3725 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3727 assert_not_reached("Unknown verb");
3730 log_error("Operation failed: %s", strerror(-r));
3735 for (i = 0; i < n_changes; i++) {
3736 if (changes[i].type == UNIT_FILE_SYMLINK)
3737 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3739 log_info("rm '%s'", changes[i].path);
3746 bool send_force = true, expect_carries_install_info = false;
3748 DBusMessageIter iter, sub, sub2;
3750 if (streq(verb, "enable")) {
3751 method = "EnableUnitFiles";
3752 expect_carries_install_info = true;
3753 } else if (streq(verb, "disable")) {
3754 method = "DisableUnitFiles";
3756 } else if (streq(verb, "reenable")) {
3757 method = "ReenableUnitFiles";
3758 expect_carries_install_info = true;
3759 } else if (streq(verb, "link"))
3760 method = "LinkUnitFiles";
3761 else if (streq(verb, "preset")) {
3762 method = "PresetUnitFiles";
3763 expect_carries_install_info = true;
3764 } else if (streq(verb, "mask"))
3765 method = "MaskUnitFiles";
3766 else if (streq(verb, "unmask")) {
3767 method = "UnmaskUnitFiles";
3770 assert_not_reached("Unknown verb");
3772 m = dbus_message_new_method_call(
3773 "org.freedesktop.systemd1",
3774 "/org/freedesktop/systemd1",
3775 "org.freedesktop.systemd1.Manager",
3782 dbus_message_iter_init_append(m, &iter);
3784 r = mangle_names(args+1, &mangled_names);
3788 r = bus_append_strv_iter(&iter, mangled_names);
3790 log_error("Failed to append unit files.");
3795 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3796 log_error("Failed to append runtime boolean.");
3804 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3805 log_error("Failed to append force boolean.");
3811 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3813 log_error("Failed to issue method call: %s", bus_error_message(&error));
3818 if (!dbus_message_iter_init(reply, &iter)) {
3819 log_error("Failed to initialize iterator.");
3823 if (expect_carries_install_info) {
3824 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3826 log_error("Failed to parse reply.");
3830 carries_install_info = b;
3833 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3834 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3835 log_error("Failed to parse reply.");
3840 dbus_message_iter_recurse(&iter, &sub);
3841 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3842 const char *type, *path, *source;
3844 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3845 log_error("Failed to parse reply.");
3850 dbus_message_iter_recurse(&sub, &sub2);
3852 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3853 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3854 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3855 log_error("Failed to parse reply.");
3861 if (streq(type, "symlink"))
3862 log_info("ln -s '%s' '%s'", source, path);
3864 log_info("rm '%s'", path);
3867 dbus_message_iter_next(&sub);
3870 /* Try to reload if enabeld */
3872 r = daemon_reload(bus, args);
3875 if (carries_install_info == 0)
3877 "The unit files have no [Install] section. They are not meant to be enabled\n"
3878 "using systemctl.\n"
3879 "Possible reasons for having this kind of units are:\n"
3880 "1) A unit may be statically enabled by being symlinked from another unit's\n"
3881 " .wants/ or .requires/ directory.\n"
3882 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
3883 " a requirement dependency on it.\n"
3884 "3) A unit may be started when needed via activation (socket, path, timer,\n"
3885 " D-Bus, udev, scripted systemctl call, ...).\n");
3889 dbus_message_unref(m);
3892 dbus_message_unref(reply);
3894 unit_file_changes_free(changes, n_changes);
3896 dbus_error_free(&error);
3898 strv_free(mangled_names);
3903 static int unit_is_enabled(DBusConnection *bus, char **args) {
3906 DBusMessage *reply = NULL;
3910 dbus_error_init(&error);
3912 r = enable_sysv_units(args);
3918 if (!bus || avoid_bus()) {
3920 STRV_FOREACH(name, args+1) {
3921 UnitFileState state;
3923 state = unit_file_get_state(arg_scope, arg_root, *name);
3929 if (state == UNIT_FILE_ENABLED ||
3930 state == UNIT_FILE_ENABLED_RUNTIME ||
3931 state == UNIT_FILE_STATIC)
3935 puts(unit_file_state_to_string(state));
3939 STRV_FOREACH(name, args+1) {
3942 r = bus_method_call_with_reply (
3944 "org.freedesktop.systemd1",
3945 "/org/freedesktop/systemd1",
3946 "org.freedesktop.systemd1.Manager",
3950 DBUS_TYPE_STRING, name,
3955 if (!dbus_message_get_args(reply, &error,
3956 DBUS_TYPE_STRING, &s,
3957 DBUS_TYPE_INVALID)) {
3958 log_error("Failed to parse reply: %s", bus_error_message(&error));
3963 dbus_message_unref(reply);
3966 if (streq(s, "enabled") ||
3967 streq(s, "enabled-runtime") ||
3976 r = enabled ? 0 : 1;
3980 dbus_message_unref(reply);
3982 dbus_error_free(&error);
3986 static int systemctl_help(void) {
3988 pager_open_if_enabled();
3990 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
3991 "Query or send control commands to the systemd manager.\n\n"
3992 " -h --help Show this help\n"
3993 " --version Show package version\n"
3994 " -t --type=TYPE List only units of a particular type\n"
3995 " -p --property=NAME Show only properties by this name\n"
3996 " -a --all Show all units/properties, including dead/empty ones\n"
3997 " --failed Show only failed units\n"
3998 " --full Don't ellipsize unit names on output\n"
3999 " --fail When queueing a new job, fail if conflicting jobs are\n"
4001 " --ignore-dependencies\n"
4002 " When queueing a new job, ignore all its dependencies\n"
4003 " -i --ignore-inhibitors\n"
4004 " When shutting down or sleeping, ignore inhibitors\n"
4005 " --kill-who=WHO Who to send signal to\n"
4006 " -s --signal=SIGNAL Which signal to send\n"
4007 " -H --host=[USER@]HOST\n"
4008 " Show information for remote host\n"
4009 " -P --privileged Acquire privileges before execution\n"
4010 " -q --quiet Suppress output\n"
4011 " --no-block Do not wait until operation finished\n"
4012 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4013 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4015 " --no-legend Do not print a legend (column headers and hints)\n"
4016 " --no-pager Do not pipe output into a pager\n"
4017 " --no-ask-password\n"
4018 " Do not ask for system passwords\n"
4019 " --order When generating graph for dot, show only order\n"
4020 " --require When generating graph for dot, show only requirement\n"
4021 " --system Connect to system manager\n"
4022 " --user Connect to user service manager\n"
4023 " --global Enable/disable unit files globally\n"
4024 " -f --force When enabling unit files, override existing symlinks\n"
4025 " When shutting down, execute action immediately\n"
4026 " --root=PATH Enable unit files in the specified root directory\n"
4027 " --runtime Enable unit files only temporarily until next reboot\n"
4028 " -n --lines=INTEGER Journal entries to show\n"
4029 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4030 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4032 " list-units List loaded units\n"
4033 " start [NAME...] Start (activate) one or more units\n"
4034 " stop [NAME...] Stop (deactivate) one or more units\n"
4035 " reload [NAME...] Reload one or more units\n"
4036 " restart [NAME...] Start or restart one or more units\n"
4037 " try-restart [NAME...] Restart one or more units if active\n"
4038 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4039 " otherwise start or restart\n"
4040 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4041 " otherwise restart if active\n"
4042 " isolate [NAME] Start one unit and stop all others\n"
4043 " kill [NAME...] Send signal to processes of a unit\n"
4044 " is-active [NAME...] Check whether units are active\n"
4045 " is-failed [NAME...] Check whether units are failed\n"
4046 " status [NAME...|PID...] Show runtime status of one or more units\n"
4047 " show [NAME...|JOB...] Show properties of one or more\n"
4048 " units/jobs or the manager\n"
4049 " help [NAME...|PID...] Show manual for one or more units\n"
4050 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4052 " load [NAME...] Load one or more units\n\n"
4053 "Unit File Commands:\n"
4054 " list-unit-files List installed unit files\n"
4055 " enable [NAME...] Enable one or more unit files\n"
4056 " disable [NAME...] Disable one or more unit files\n"
4057 " reenable [NAME...] Reenable one or more unit files\n"
4058 " preset [NAME...] Enable/disable one or more unit files\n"
4059 " based on preset configuration\n"
4060 " mask [NAME...] Mask one or more units\n"
4061 " unmask [NAME...] Unmask one or more units\n"
4062 " link [PATH...] Link one or more units files into\n"
4063 " the search path\n"
4064 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4066 " list-jobs List jobs\n"
4067 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4068 "Status Commands:\n"
4069 " dump Dump server status\n"
4070 " dot Dump dependency graph for dot(1)\n\n"
4071 "Snapshot Commands:\n"
4072 " snapshot [NAME] Create a snapshot\n"
4073 " delete [NAME...] Remove one or more snapshots\n\n"
4074 "Environment Commands:\n"
4075 " show-environment Dump environment\n"
4076 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4077 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4078 "Manager Lifecycle Commands:\n"
4079 " daemon-reload Reload systemd manager configuration\n"
4080 " daemon-reexec Reexecute systemd manager\n\n"
4081 "System Commands:\n"
4082 " default Enter system default mode\n"
4083 " rescue Enter system rescue mode\n"
4084 " emergency Enter system emergency mode\n"
4085 " halt Shut down and halt the system\n"
4086 " poweroff Shut down and power-off the system\n"
4087 " reboot Shut down and reboot the system\n"
4088 " kexec Shut down and reboot the system with kexec\n"
4089 " exit Request user instance exit\n"
4090 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4091 " suspend Suspend the system\n"
4092 " hibernate Hibernate the system\n"
4093 " hybrid-sleep Hibernate and suspend the system\n",
4094 program_invocation_short_name);
4099 static int halt_help(void) {
4101 printf("%s [OPTIONS...]\n\n"
4102 "%s the system.\n\n"
4103 " --help Show this help\n"
4104 " --halt Halt the machine\n"
4105 " -p --poweroff Switch off the machine\n"
4106 " --reboot Reboot the machine\n"
4107 " -f --force Force immediate halt/power-off/reboot\n"
4108 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4109 " -d --no-wtmp Don't write wtmp record\n"
4110 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4111 program_invocation_short_name,
4112 arg_action == ACTION_REBOOT ? "Reboot" :
4113 arg_action == ACTION_POWEROFF ? "Power off" :
4119 static int shutdown_help(void) {
4121 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4122 "Shut down the system.\n\n"
4123 " --help Show this help\n"
4124 " -H --halt Halt the machine\n"
4125 " -P --poweroff Power-off the machine\n"
4126 " -r --reboot Reboot the machine\n"
4127 " -h Equivalent to --poweroff, overridden by --halt\n"
4128 " -k Don't halt/power-off/reboot, just send warnings\n"
4129 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4130 " -c Cancel a pending shutdown\n",
4131 program_invocation_short_name);
4136 static int telinit_help(void) {
4138 printf("%s [OPTIONS...] {COMMAND}\n\n"
4139 "Send control commands to the init daemon.\n\n"
4140 " --help Show this help\n"
4141 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4143 " 0 Power-off the machine\n"
4144 " 6 Reboot the machine\n"
4145 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4146 " 1, s, S Enter rescue mode\n"
4147 " q, Q Reload init daemon configuration\n"
4148 " u, U Reexecute init daemon\n",
4149 program_invocation_short_name);
4154 static int runlevel_help(void) {
4156 printf("%s [OPTIONS...]\n\n"
4157 "Prints the previous and current runlevel of the init system.\n\n"
4158 " --help Show this help\n",
4159 program_invocation_short_name);
4164 static int help_types(void) {
4167 puts("Available unit types:");
4168 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4169 if (unit_type_table[i])
4170 puts(unit_type_table[i]);
4172 puts("\nAvailable unit load states: ");
4173 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4174 if (unit_type_table[i])
4175 puts(unit_load_state_table[i]);
4180 static int systemctl_parse_argv(int argc, char *argv[]) {
4184 ARG_IGNORE_DEPENDENCIES,
4199 ARG_NO_ASK_PASSWORD,
4205 static const struct option options[] = {
4206 { "help", no_argument, NULL, 'h' },
4207 { "version", no_argument, NULL, ARG_VERSION },
4208 { "type", required_argument, NULL, 't' },
4209 { "property", required_argument, NULL, 'p' },
4210 { "all", no_argument, NULL, 'a' },
4211 { "failed", no_argument, NULL, ARG_FAILED },
4212 { "full", no_argument, NULL, ARG_FULL },
4213 { "fail", no_argument, NULL, ARG_FAIL },
4214 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4215 { "ignore-inhibitors", no_argument, NULL, 'i' },
4216 { "user", no_argument, NULL, ARG_USER },
4217 { "system", no_argument, NULL, ARG_SYSTEM },
4218 { "global", no_argument, NULL, ARG_GLOBAL },
4219 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4220 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4221 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4222 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4223 { "quiet", no_argument, NULL, 'q' },
4224 { "order", no_argument, NULL, ARG_ORDER },
4225 { "require", no_argument, NULL, ARG_REQUIRE },
4226 { "root", required_argument, NULL, ARG_ROOT },
4227 { "force", no_argument, NULL, ARG_FORCE },
4228 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4229 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4230 { "signal", required_argument, NULL, 's' },
4231 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4232 { "host", required_argument, NULL, 'H' },
4233 { "privileged",no_argument, NULL, 'P' },
4234 { "runtime", no_argument, NULL, ARG_RUNTIME },
4235 { "lines", required_argument, NULL, 'n' },
4236 { "output", required_argument, NULL, 'o' },
4237 { NULL, 0, NULL, 0 }
4245 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4254 puts(PACKAGE_STRING);
4255 puts(SYSTEMD_FEATURES);
4259 if (streq(optarg, "help")) {
4264 if (unit_type_from_string(optarg) >= 0) {
4268 if (unit_load_state_from_string(optarg) >= 0) {
4269 arg_load_state = optarg;
4272 log_error("Unkown unit type or load state '%s'.",
4274 log_info("Use -t help to see a list of allowed values.");
4279 if (!(l = strv_append(arg_property, optarg)))
4282 strv_free(arg_property);
4285 /* If the user asked for a particular
4286 * property, show it to him, even if it is
4297 arg_job_mode = "fail";
4300 case ARG_IGNORE_DEPENDENCIES:
4301 arg_job_mode = "ignore-dependencies";
4305 arg_scope = UNIT_FILE_USER;
4309 arg_scope = UNIT_FILE_SYSTEM;
4313 arg_scope = UNIT_FILE_GLOBAL;
4317 arg_no_block = true;
4321 arg_no_legend = true;
4325 arg_no_pager = true;
4333 arg_dot = DOT_ORDER;
4337 arg_dot = DOT_REQUIRE;
4365 arg_no_reload = true;
4369 arg_kill_who = optarg;
4373 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4374 log_error("Failed to parse signal string %s.", optarg);
4379 case ARG_NO_ASK_PASSWORD:
4380 arg_ask_password = false;
4384 arg_transport = TRANSPORT_POLKIT;
4388 arg_transport = TRANSPORT_SSH;
4397 if (safe_atou(optarg, &arg_lines) < 0) {
4398 log_error("Failed to parse lines '%s'", optarg);
4404 arg_output = output_mode_from_string(optarg);
4405 if (arg_output < 0) {
4406 log_error("Unknown output '%s'.", optarg);
4412 arg_ignore_inhibitors = true;
4419 log_error("Unknown option code '%c'.", c);
4424 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4425 log_error("Cannot access user instance remotely.");
4432 static int halt_parse_argv(int argc, char *argv[]) {
4441 static const struct option options[] = {
4442 { "help", no_argument, NULL, ARG_HELP },
4443 { "halt", no_argument, NULL, ARG_HALT },
4444 { "poweroff", no_argument, NULL, 'p' },
4445 { "reboot", no_argument, NULL, ARG_REBOOT },
4446 { "force", no_argument, NULL, 'f' },
4447 { "wtmp-only", no_argument, NULL, 'w' },
4448 { "no-wtmp", no_argument, NULL, 'd' },
4449 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4450 { NULL, 0, NULL, 0 }
4458 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4459 if (runlevel == '0' || runlevel == '6')
4462 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4470 arg_action = ACTION_HALT;
4474 if (arg_action != ACTION_REBOOT)
4475 arg_action = ACTION_POWEROFF;
4479 arg_action = ACTION_REBOOT;
4501 /* Compatibility nops */
4508 log_error("Unknown option code '%c'.", c);
4513 if (optind < argc) {
4514 log_error("Too many arguments.");
4521 static int parse_time_spec(const char *t, usec_t *_u) {
4525 if (streq(t, "now"))
4527 else if (!strchr(t, ':')) {
4530 if (safe_atou64(t, &u) < 0)
4533 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4542 hour = strtol(t, &e, 10);
4543 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4546 minute = strtol(e+1, &e, 10);
4547 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4550 n = now(CLOCK_REALTIME);
4551 s = (time_t) (n / USEC_PER_SEC);
4554 assert_se(localtime_r(&s, &tm));
4556 tm.tm_hour = (int) hour;
4557 tm.tm_min = (int) minute;
4560 assert_se(s = mktime(&tm));
4562 *_u = (usec_t) s * USEC_PER_SEC;
4565 *_u += USEC_PER_DAY;
4571 static int shutdown_parse_argv(int argc, char *argv[]) {
4578 static const struct option options[] = {
4579 { "help", no_argument, NULL, ARG_HELP },
4580 { "halt", no_argument, NULL, 'H' },
4581 { "poweroff", no_argument, NULL, 'P' },
4582 { "reboot", no_argument, NULL, 'r' },
4583 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4584 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4585 { NULL, 0, NULL, 0 }
4593 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4601 arg_action = ACTION_HALT;
4605 arg_action = ACTION_POWEROFF;
4610 arg_action = ACTION_KEXEC;
4612 arg_action = ACTION_REBOOT;
4616 arg_action = ACTION_KEXEC;
4620 if (arg_action != ACTION_HALT)
4621 arg_action = ACTION_POWEROFF;
4634 /* Compatibility nops */
4638 arg_action = ACTION_CANCEL_SHUTDOWN;
4645 log_error("Unknown option code '%c'.", c);
4650 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4651 r = parse_time_spec(argv[optind], &arg_when);
4653 log_error("Failed to parse time specification: %s", argv[optind]);
4657 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4659 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4660 /* No time argument for shutdown cancel */
4661 arg_wall = argv + optind;
4662 else if (argc > optind + 1)
4663 /* We skip the time argument */
4664 arg_wall = argv + optind + 1;
4671 static int telinit_parse_argv(int argc, char *argv[]) {
4678 static const struct option options[] = {
4679 { "help", no_argument, NULL, ARG_HELP },
4680 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4681 { NULL, 0, NULL, 0 }
4684 static const struct {
4688 { '0', ACTION_POWEROFF },
4689 { '6', ACTION_REBOOT },
4690 { '1', ACTION_RESCUE },
4691 { '2', ACTION_RUNLEVEL2 },
4692 { '3', ACTION_RUNLEVEL3 },
4693 { '4', ACTION_RUNLEVEL4 },
4694 { '5', ACTION_RUNLEVEL5 },
4695 { 's', ACTION_RESCUE },
4696 { 'S', ACTION_RESCUE },
4697 { 'q', ACTION_RELOAD },
4698 { 'Q', ACTION_RELOAD },
4699 { 'u', ACTION_REEXEC },
4700 { 'U', ACTION_REEXEC }
4709 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4724 log_error("Unknown option code '%c'.", c);
4729 if (optind >= argc) {
4734 if (optind + 1 < argc) {
4735 log_error("Too many arguments.");
4739 if (strlen(argv[optind]) != 1) {
4740 log_error("Expected single character argument.");
4744 for (i = 0; i < ELEMENTSOF(table); i++)
4745 if (table[i].from == argv[optind][0])
4748 if (i >= ELEMENTSOF(table)) {
4749 log_error("Unknown command '%s'.", argv[optind]);
4753 arg_action = table[i].to;
4760 static int runlevel_parse_argv(int argc, char *argv[]) {
4766 static const struct option options[] = {
4767 { "help", no_argument, NULL, ARG_HELP },
4768 { NULL, 0, NULL, 0 }
4776 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4787 log_error("Unknown option code '%c'.", c);
4792 if (optind < argc) {
4793 log_error("Too many arguments.");
4800 static int parse_argv(int argc, char *argv[]) {
4804 if (program_invocation_short_name) {
4806 if (strstr(program_invocation_short_name, "halt")) {
4807 arg_action = ACTION_HALT;
4808 return halt_parse_argv(argc, argv);
4809 } else if (strstr(program_invocation_short_name, "poweroff")) {
4810 arg_action = ACTION_POWEROFF;
4811 return halt_parse_argv(argc, argv);
4812 } else if (strstr(program_invocation_short_name, "reboot")) {
4814 arg_action = ACTION_KEXEC;
4816 arg_action = ACTION_REBOOT;
4817 return halt_parse_argv(argc, argv);
4818 } else if (strstr(program_invocation_short_name, "shutdown")) {
4819 arg_action = ACTION_POWEROFF;
4820 return shutdown_parse_argv(argc, argv);
4821 } else if (strstr(program_invocation_short_name, "init")) {
4823 if (sd_booted() > 0) {
4824 arg_action = ACTION_INVALID;
4825 return telinit_parse_argv(argc, argv);
4827 /* Hmm, so some other init system is
4828 * running, we need to forward this
4829 * request to it. For now we simply
4830 * guess that it is Upstart. */
4832 execv("/lib/upstart/telinit", argv);
4834 log_error("Couldn't find an alternative telinit implementation to spawn.");
4838 } else if (strstr(program_invocation_short_name, "runlevel")) {
4839 arg_action = ACTION_RUNLEVEL;
4840 return runlevel_parse_argv(argc, argv);
4844 arg_action = ACTION_SYSTEMCTL;
4845 return systemctl_parse_argv(argc, argv);
4848 static int action_to_runlevel(void) {
4850 static const char table[_ACTION_MAX] = {
4851 [ACTION_HALT] = '0',
4852 [ACTION_POWEROFF] = '0',
4853 [ACTION_REBOOT] = '6',
4854 [ACTION_RUNLEVEL2] = '2',
4855 [ACTION_RUNLEVEL3] = '3',
4856 [ACTION_RUNLEVEL4] = '4',
4857 [ACTION_RUNLEVEL5] = '5',
4858 [ACTION_RESCUE] = '1'
4861 assert(arg_action < _ACTION_MAX);
4863 return table[arg_action];
4866 static int talk_upstart(void) {
4867 DBusMessage *m = NULL, *reply = NULL;
4869 int previous, rl, r;
4871 env1_buf[] = "RUNLEVEL=X",
4872 env2_buf[] = "PREVLEVEL=X";
4873 char *env1 = env1_buf, *env2 = env2_buf;
4874 const char *emit = "runlevel";
4875 dbus_bool_t b_false = FALSE;
4876 DBusMessageIter iter, sub;
4877 DBusConnection *bus;
4879 dbus_error_init(&error);
4881 if (!(rl = action_to_runlevel()))
4884 if (utmp_get_runlevel(&previous, NULL) < 0)
4887 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4888 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4893 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4898 if ((r = bus_check_peercred(bus)) < 0) {
4899 log_error("Failed to verify owner of bus.");
4903 if (!(m = dbus_message_new_method_call(
4904 "com.ubuntu.Upstart",
4905 "/com/ubuntu/Upstart",
4906 "com.ubuntu.Upstart0_6",
4909 log_error("Could not allocate message.");
4914 dbus_message_iter_init_append(m, &iter);
4916 env1_buf[sizeof(env1_buf)-2] = rl;
4917 env2_buf[sizeof(env2_buf)-2] = previous;
4919 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4920 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4921 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4922 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4923 !dbus_message_iter_close_container(&iter, &sub) ||
4924 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4925 log_error("Could not append arguments to message.");
4930 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4932 if (bus_error_is_no_service(&error)) {
4937 log_error("Failed to issue method call: %s", bus_error_message(&error));
4946 dbus_message_unref(m);
4949 dbus_message_unref(reply);
4952 dbus_connection_flush(bus);
4953 dbus_connection_close(bus);
4954 dbus_connection_unref(bus);
4957 dbus_error_free(&error);
4962 static int talk_initctl(void) {
4963 struct init_request request;
4967 if (!(rl = action_to_runlevel()))
4971 request.magic = INIT_MAGIC;
4972 request.sleeptime = 0;
4973 request.cmd = INIT_CMD_RUNLVL;
4974 request.runlevel = rl;
4976 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
4978 if (errno == ENOENT)
4981 log_error("Failed to open "INIT_FIFO": %m");
4986 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
4987 close_nointr_nofail(fd);
4990 log_error("Failed to write to "INIT_FIFO": %m");
4991 return errno ? -errno : -EIO;
4997 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
4999 static const struct {
5007 int (* const dispatch)(DBusConnection *bus, char **args);
5009 { "list-units", LESS, 1, list_units },
5010 { "list-unit-files", EQUAL, 1, list_unit_files },
5011 { "list-jobs", EQUAL, 1, list_jobs },
5012 { "clear-jobs", EQUAL, 1, daemon_reload },
5013 { "load", MORE, 2, load_unit },
5014 { "cancel", MORE, 2, cancel_job },
5015 { "start", MORE, 2, start_unit },
5016 { "stop", MORE, 2, start_unit },
5017 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5018 { "reload", MORE, 2, start_unit },
5019 { "restart", MORE, 2, start_unit },
5020 { "try-restart", MORE, 2, start_unit },
5021 { "reload-or-restart", MORE, 2, start_unit },
5022 { "reload-or-try-restart", MORE, 2, start_unit },
5023 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5024 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5025 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5026 { "isolate", EQUAL, 2, start_unit },
5027 { "kill", MORE, 2, kill_unit },
5028 { "is-active", MORE, 2, check_unit_active },
5029 { "check", MORE, 2, check_unit_active },
5030 { "is-failed", MORE, 2, check_unit_failed },
5031 { "show", MORE, 1, show },
5032 { "status", MORE, 2, show },
5033 { "help", MORE, 2, show },
5034 { "dump", EQUAL, 1, dump },
5035 { "dot", EQUAL, 1, dot },
5036 { "snapshot", LESS, 2, snapshot },
5037 { "delete", MORE, 2, delete_snapshot },
5038 { "daemon-reload", EQUAL, 1, daemon_reload },
5039 { "daemon-reexec", EQUAL, 1, daemon_reload },
5040 { "show-environment", EQUAL, 1, show_enviroment },
5041 { "set-environment", MORE, 2, set_environment },
5042 { "unset-environment", MORE, 2, set_environment },
5043 { "halt", EQUAL, 1, start_special },
5044 { "poweroff", EQUAL, 1, start_special },
5045 { "reboot", EQUAL, 1, start_special },
5046 { "kexec", EQUAL, 1, start_special },
5047 { "suspend", EQUAL, 1, start_special },
5048 { "hibernate", EQUAL, 1, start_special },
5049 { "hybrid-sleep", EQUAL, 1, start_special },
5050 { "default", EQUAL, 1, start_special },
5051 { "rescue", EQUAL, 1, start_special },
5052 { "emergency", EQUAL, 1, start_special },
5053 { "exit", EQUAL, 1, start_special },
5054 { "reset-failed", MORE, 1, reset_failed },
5055 { "enable", MORE, 2, enable_unit },
5056 { "disable", MORE, 2, enable_unit },
5057 { "is-enabled", MORE, 2, unit_is_enabled },
5058 { "reenable", MORE, 2, enable_unit },
5059 { "preset", MORE, 2, enable_unit },
5060 { "mask", MORE, 2, enable_unit },
5061 { "unmask", MORE, 2, enable_unit },
5062 { "link", MORE, 2, enable_unit },
5063 { "switch-root", MORE, 2, switch_root },
5073 left = argc - optind;
5076 /* Special rule: no arguments means "list-units" */
5079 if (streq(argv[optind], "help") && !argv[optind+1]) {
5080 log_error("This command expects one or more "
5081 "unit names. Did you mean --help?");
5085 for (i = 0; i < ELEMENTSOF(verbs); i++)
5086 if (streq(argv[optind], verbs[i].verb))
5089 if (i >= ELEMENTSOF(verbs)) {
5090 log_error("Unknown operation '%s'.", argv[optind]);
5095 switch (verbs[i].argc_cmp) {
5098 if (left != verbs[i].argc) {
5099 log_error("Invalid number of arguments.");
5106 if (left < verbs[i].argc) {
5107 log_error("Too few arguments.");
5114 if (left > verbs[i].argc) {
5115 log_error("Too many arguments.");
5122 assert_not_reached("Unknown comparison operator.");
5125 /* Require a bus connection for all operations but
5127 if (!streq(verbs[i].verb, "enable") &&
5128 !streq(verbs[i].verb, "disable") &&
5129 !streq(verbs[i].verb, "is-enabled") &&
5130 !streq(verbs[i].verb, "list-unit-files") &&
5131 !streq(verbs[i].verb, "reenable") &&
5132 !streq(verbs[i].verb, "preset") &&
5133 !streq(verbs[i].verb, "mask") &&
5134 !streq(verbs[i].verb, "unmask") &&
5135 !streq(verbs[i].verb, "link")) {
5137 if (running_in_chroot() > 0) {
5138 log_info("Running in chroot, ignoring request.");
5142 if (((!streq(verbs[i].verb, "reboot") &&
5143 !streq(verbs[i].verb, "halt") &&
5144 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5145 log_error("Failed to get D-Bus connection: %s",
5146 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5152 if (!bus && !avoid_bus()) {
5153 log_error("Failed to get D-Bus connection: %s",
5154 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5159 return verbs[i].dispatch(bus, argv + optind);
5162 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5164 struct msghdr msghdr;
5165 struct iovec iovec[2];
5166 union sockaddr_union sockaddr;
5167 struct sd_shutdown_command c;
5169 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5176 c.dry_run = dry_run;
5180 sockaddr.sa.sa_family = AF_UNIX;
5181 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5184 msghdr.msg_name = &sockaddr;
5185 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5188 iovec[0].iov_base = (char*) &c;
5189 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5191 if (isempty(message))
5192 msghdr.msg_iovlen = 1;
5194 iovec[1].iov_base = (char*) message;
5195 iovec[1].iov_len = strlen(message);
5196 msghdr.msg_iovlen = 2;
5198 msghdr.msg_iov = iovec;
5200 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5201 close_nointr_nofail(fd);
5205 close_nointr_nofail(fd);
5209 static int reload_with_fallback(DBusConnection *bus) {
5212 /* First, try systemd via D-Bus. */
5213 if (daemon_reload(bus, NULL) >= 0)
5217 /* Nothing else worked, so let's try signals */
5218 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5220 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5221 log_error("kill() failed: %m");
5228 static int start_with_fallback(DBusConnection *bus) {
5231 /* First, try systemd via D-Bus. */
5232 if (start_unit(bus, NULL) >= 0)
5236 /* Hmm, talking to systemd via D-Bus didn't work. Then
5237 * let's try to talk to Upstart via D-Bus. */
5238 if (talk_upstart() > 0)
5241 /* Nothing else worked, so let's try
5243 if (talk_initctl() > 0)
5246 log_error("Failed to talk to init daemon.");
5250 warn_wall(arg_action);
5254 static _noreturn_ void halt_now(enum action a) {
5256 /* Make sure C-A-D is handled by the kernel from this
5258 reboot(RB_ENABLE_CAD);
5263 log_info("Halting.");
5264 reboot(RB_HALT_SYSTEM);
5267 case ACTION_POWEROFF:
5268 log_info("Powering off.");
5269 reboot(RB_POWER_OFF);
5273 log_info("Rebooting.");
5274 reboot(RB_AUTOBOOT);
5278 assert_not_reached("Unknown halt action.");
5281 assert_not_reached("Uh? This shouldn't happen.");
5284 static int halt_main(DBusConnection *bus) {
5287 if (arg_when <= 0 && arg_force <= 0) {
5288 r = check_inhibitors(bus, arg_action);
5293 if (geteuid() != 0) {
5294 /* Try logind if we are a normal user and no special
5295 * mode applies. Maybe PolicyKit allows us to shutdown
5298 if (arg_when <= 0 &&
5301 (arg_action == ACTION_POWEROFF ||
5302 arg_action == ACTION_REBOOT)) {
5303 r = reboot_with_logind(bus, arg_action);
5308 log_error("Must be root.");
5315 m = strv_join(arg_wall, " ");
5316 r = send_shutdownd(arg_when,
5317 arg_action == ACTION_HALT ? 'H' :
5318 arg_action == ACTION_POWEROFF ? 'P' :
5319 arg_action == ACTION_KEXEC ? 'K' :
5327 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5329 char date[FORMAT_TIMESTAMP_MAX];
5331 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5332 format_timestamp(date, sizeof(date), arg_when));
5337 if (!arg_dry && !arg_force)
5338 return start_with_fallback(bus);
5341 if (sd_booted() > 0)
5342 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5344 r = utmp_put_shutdown();
5346 log_warning("Failed to write utmp record: %s", strerror(-r));
5353 halt_now(arg_action);
5354 /* We should never reach this. */
5358 static int runlevel_main(void) {
5359 int r, runlevel, previous;
5361 r = utmp_get_runlevel(&runlevel, &previous);
5368 previous <= 0 ? 'N' : previous,
5369 runlevel <= 0 ? 'N' : runlevel);
5374 int main(int argc, char*argv[]) {
5375 int r, retval = EXIT_FAILURE;
5376 DBusConnection *bus = NULL;
5379 dbus_error_init(&error);
5381 setlocale(LC_ALL, "");
5382 log_parse_environment();
5385 r = parse_argv(argc, argv);
5389 retval = EXIT_SUCCESS;
5393 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5394 * let's shortcut this */
5395 if (arg_action == ACTION_RUNLEVEL) {
5396 r = runlevel_main();
5397 retval = r < 0 ? EXIT_FAILURE : r;
5401 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5402 log_info("Running in chroot, ignoring request.");
5408 if (arg_transport == TRANSPORT_NORMAL)
5409 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5410 else if (arg_transport == TRANSPORT_POLKIT) {
5411 bus_connect_system_polkit(&bus, &error);
5412 private_bus = false;
5413 } else if (arg_transport == TRANSPORT_SSH) {
5414 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5415 private_bus = false;
5417 assert_not_reached("Uh, invalid transport...");
5420 switch (arg_action) {
5422 case ACTION_SYSTEMCTL:
5423 r = systemctl_main(bus, argc, argv, &error);
5427 case ACTION_POWEROFF:
5433 case ACTION_RUNLEVEL2:
5434 case ACTION_RUNLEVEL3:
5435 case ACTION_RUNLEVEL4:
5436 case ACTION_RUNLEVEL5:
5438 case ACTION_EMERGENCY:
5439 case ACTION_DEFAULT:
5440 r = start_with_fallback(bus);
5445 r = reload_with_fallback(bus);
5448 case ACTION_CANCEL_SHUTDOWN: {
5452 m = strv_join(arg_wall, " ");
5454 retval = EXIT_FAILURE;
5458 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5460 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5465 case ACTION_INVALID:
5466 case ACTION_RUNLEVEL:
5468 assert_not_reached("Unknown action");
5471 retval = r < 0 ? EXIT_FAILURE : r;
5475 dbus_connection_flush(bus);
5476 dbus_connection_close(bus);
5477 dbus_connection_unref(bus);
5480 dbus_error_free(&error);
5484 strv_free(arg_property);
5487 ask_password_agent_close();
5488 polkit_agent_close();