1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/reboot.h>
29 #include <sys/ioctl.h>
33 #include <sys/socket.h>
36 #include <sys/prctl.h>
37 #include <dbus/dbus.h>
39 #include <systemd/sd-daemon.h>
40 #include <systemd/sd-shutdown.h>
46 #include "utmp-wtmp.h"
49 #include "path-util.h"
51 #include "dbus-common.h"
52 #include "cgroup-show.h"
53 #include "cgroup-util.h"
55 #include "path-lookup.h"
56 #include "conf-parser.h"
57 #include "exit-status.h"
58 #include "bus-errors.h"
60 #include "unit-name.h"
62 #include "spawn-ask-password-agent.h"
63 #include "spawn-polkit-agent.h"
65 #include "logs-show.h"
66 #include "path-util.h"
67 #include "socket-util.h"
69 static const char *arg_type = NULL;
70 static const char *arg_load_state = NULL;
71 static char **arg_property = NULL;
72 static bool arg_all = false;
73 static const char *arg_job_mode = "replace";
74 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
75 static bool arg_no_block = false;
76 static bool arg_no_legend = false;
77 static bool arg_no_pager = false;
78 static bool arg_no_wtmp = false;
79 static bool arg_no_wall = false;
80 static bool arg_no_reload = false;
81 static bool arg_ignore_inhibitors = false;
82 static bool arg_dry = false;
83 static bool arg_quiet = false;
84 static bool arg_full = false;
85 static int arg_force = 0;
86 static bool arg_ask_password = true;
87 static bool arg_failed = false;
88 static bool arg_runtime = false;
89 static char **arg_wall = NULL;
90 static const char *arg_kill_who = NULL;
91 static int arg_signal = SIGTERM;
92 static const char *arg_root = NULL;
93 static usec_t arg_when = 0;
115 ACTION_CANCEL_SHUTDOWN,
117 } arg_action = ACTION_SYSTEMCTL;
123 static enum transport {
127 } arg_transport = TRANSPORT_NORMAL;
128 static const char *arg_host = NULL;
129 static unsigned arg_lines = 10;
130 static OutputMode arg_output = OUTPUT_SHORT;
132 static bool private_bus = false;
134 static int daemon_reload(DBusConnection *bus, char **args);
135 static void halt_now(enum action a);
137 static void pager_open_if_enabled(void) {
145 static void ask_password_agent_open_if_enabled(void) {
147 /* Open the password agent as a child process if necessary */
149 if (!arg_ask_password)
152 if (arg_scope != UNIT_FILE_SYSTEM)
155 ask_password_agent_open();
159 static void polkit_agent_open_if_enabled(void) {
161 /* Open the polkit agent as a child process if necessary */
163 if (!arg_ask_password)
166 if (arg_scope != UNIT_FILE_SYSTEM)
173 static const char *ansi_highlight(bool b) {
178 return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
181 static const char *ansi_highlight_red(bool b) {
186 return b ? ANSI_HIGHLIGHT_RED_ON : ANSI_HIGHLIGHT_OFF;
189 static const char *ansi_highlight_green(bool b) {
194 return b ? ANSI_HIGHLIGHT_GREEN_ON : ANSI_HIGHLIGHT_OFF;
197 static int translate_bus_error_to_exit_status(int r, const DBusError *error) {
200 if (!dbus_error_is_set(error))
203 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED) ||
204 dbus_error_has_name(error, BUS_ERROR_ONLY_BY_DEPENDENCY) ||
205 dbus_error_has_name(error, BUS_ERROR_NO_ISOLATION) ||
206 dbus_error_has_name(error, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE))
207 return EXIT_NOPERMISSION;
209 if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT))
210 return EXIT_NOTINSTALLED;
212 if (dbus_error_has_name(error, BUS_ERROR_JOB_TYPE_NOT_APPLICABLE) ||
213 dbus_error_has_name(error, BUS_ERROR_NOT_SUPPORTED))
214 return EXIT_NOTIMPLEMENTED;
216 if (dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED))
217 return EXIT_NOTCONFIGURED;
225 static void warn_wall(enum action a) {
226 static const char *table[_ACTION_MAX] = {
227 [ACTION_HALT] = "The system is going down for system halt NOW!",
228 [ACTION_REBOOT] = "The system is going down for reboot NOW!",
229 [ACTION_POWEROFF] = "The system is going down for power-off NOW!",
230 [ACTION_KEXEC] = "The system is going down for kexec reboot NOW!",
231 [ACTION_RESCUE] = "The system is going down to rescue mode NOW!",
232 [ACTION_EMERGENCY] = "The system is going down to emergency mode NOW!",
233 [ACTION_CANCEL_SHUTDOWN] = "The system shutdown has been cancelled NOW!"
242 p = strv_join(arg_wall, " ");
244 log_error("Failed to join strings.");
260 utmp_wall(table[a], NULL);
263 static bool avoid_bus(void) {
265 if (running_in_chroot() > 0)
268 if (sd_booted() <= 0)
271 if (!isempty(arg_root))
274 if (arg_scope == UNIT_FILE_GLOBAL)
282 const char *description;
283 const char *load_state;
284 const char *active_state;
285 const char *sub_state;
286 const char *following;
287 const char *unit_path;
289 const char *job_type;
290 const char *job_path;
293 static int compare_unit_info(const void *a, const void *b) {
295 const struct unit_info *u = a, *v = b;
297 d1 = strrchr(u->id, '.');
298 d2 = strrchr(v->id, '.');
303 if ((r = strcasecmp(d1, d2)) != 0)
307 return strcasecmp(u->id, v->id);
310 static bool output_show_unit(const struct unit_info *u) {
314 return streq(u->active_state, "failed");
316 return (!arg_type || ((dot = strrchr(u->id, '.')) &&
317 streq(dot+1, arg_type))) &&
318 (!arg_load_state || streq(u->load_state, arg_load_state)) &&
319 (arg_all || !(streq(u->active_state, "inactive")
320 || u->following[0]) || u->job_id > 0);
323 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
324 unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
325 const struct unit_info *u;
328 max_id_len = sizeof("UNIT")-1;
329 active_len = sizeof("ACTIVE")-1;
330 sub_len = sizeof("SUB")-1;
331 job_len = sizeof("JOB")-1;
334 for (u = unit_infos; u < unit_infos + c; u++) {
335 if (!output_show_unit(u))
338 max_id_len = MAX(max_id_len, strlen(u->id));
339 active_len = MAX(active_len, strlen(u->active_state));
340 sub_len = MAX(sub_len, strlen(u->sub_state));
341 if (u->job_id != 0) {
342 job_len = MAX(job_len, strlen(u->job_type));
349 id_len = MIN(max_id_len, 25);
350 basic_len = 5 + id_len + 5 + active_len + sub_len;
352 basic_len += job_len + 1;
353 if (basic_len < (unsigned) columns()) {
354 unsigned extra_len, incr;
355 extra_len = columns() - basic_len;
356 /* Either UNIT already got 25, or is fully satisfied.
357 * Grant up to 25 to DESC now. */
358 incr = MIN(extra_len, 25);
361 /* split the remaining space between UNIT and DESC,
362 * but do not give UNIT more than it needs. */
364 incr = MIN(extra_len / 2, max_id_len - id_len);
366 desc_len += extra_len - incr;
372 for (u = unit_infos; u < unit_infos + c; u++) {
374 const char *on_loaded, *off_loaded;
375 const char *on_active, *off_active;
377 if (!output_show_unit(u))
380 if (!n_shown && !arg_no_legend) {
381 printf("%-*s %-6s %-*s %-*s ", id_len, "UNIT", "LOAD",
382 active_len, "ACTIVE", sub_len, "SUB");
384 printf("%-*s ", job_len, "JOB");
385 if (!arg_full && arg_no_pager)
386 printf("%.*s\n", desc_len, "DESCRIPTION");
388 printf("%s\n", "DESCRIPTION");
393 if (streq(u->load_state, "error")) {
394 on_loaded = ansi_highlight_red(true);
395 off_loaded = ansi_highlight_red(false);
397 on_loaded = off_loaded = "";
399 if (streq(u->active_state, "failed")) {
400 on_active = ansi_highlight_red(true);
401 off_active = ansi_highlight_red(false);
403 on_active = off_active = "";
405 e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
407 printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s",
408 id_len, e ? e : u->id,
409 on_loaded, u->load_state, off_loaded,
410 on_active, active_len, u->active_state,
411 sub_len, u->sub_state, off_active,
412 job_count ? job_len + 1 : 0, u->job_id ? u->job_type : "");
413 if (!arg_full && arg_no_pager)
414 printf("%.*s\n", desc_len, u->description);
416 printf("%s\n", u->description);
421 if (!arg_no_legend) {
422 const char *on, *off;
425 printf("\nLOAD = Reflects whether the unit definition was properly loaded.\n"
426 "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
427 "SUB = The low-level unit activation state, values depend on unit type.\n");
429 printf("JOB = Pending job for the unit.\n");
431 on = ansi_highlight(true);
432 off = ansi_highlight(false);
434 on = ansi_highlight_red(true);
435 off = ansi_highlight_red(false);
439 printf("%s%u loaded units listed.%s\n"
440 "To show all installed unit files use 'systemctl list-unit-files'.\n",
443 printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
444 "To show all installed unit files use 'systemctl list-unit-files'.\n",
449 static int list_units(DBusConnection *bus, char **args) {
450 DBusMessage *reply = NULL;
452 DBusMessageIter iter, sub, sub2;
453 unsigned c = 0, n_units = 0;
454 struct unit_info *unit_infos = NULL;
456 pager_open_if_enabled();
458 r = bus_method_call_with_reply (
460 "org.freedesktop.systemd1",
461 "/org/freedesktop/systemd1",
462 "org.freedesktop.systemd1.Manager",
470 if (!dbus_message_iter_init(reply, &iter) ||
471 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
472 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
473 log_error("Failed to parse reply.");
478 dbus_message_iter_recurse(&iter, &sub);
480 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
483 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
484 log_error("Failed to parse reply.");
492 n_units = MAX(2*c, 16);
493 w = realloc(unit_infos, sizeof(struct unit_info) * n_units);
496 log_error("Failed to allocate unit array.");
506 dbus_message_iter_recurse(&sub, &sub2);
508 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->id, true) < 0 ||
509 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->description, true) < 0 ||
510 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
511 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
512 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
513 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->following, true) < 0 ||
514 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
515 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
516 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
517 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
518 log_error("Failed to parse reply.");
523 dbus_message_iter_next(&sub);
528 qsort(unit_infos, c, sizeof(struct unit_info), compare_unit_info);
529 output_units_list(unit_infos, c);
534 dbus_message_unref(reply);
541 static int compare_unit_file_list(const void *a, const void *b) {
543 const UnitFileList *u = a, *v = b;
545 d1 = strrchr(u->path, '.');
546 d2 = strrchr(v->path, '.');
551 r = strcasecmp(d1, d2);
556 return strcasecmp(path_get_file_name(u->path), path_get_file_name(v->path));
559 static bool output_show_unit_file(const UnitFileList *u) {
562 return !arg_type || ((dot = strrchr(u->path, '.')) && streq(dot+1, arg_type));
565 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
566 unsigned max_id_len, id_cols, state_cols, n_shown = 0;
567 const UnitFileList *u;
569 max_id_len = sizeof("UNIT FILE")-1;
570 state_cols = sizeof("STATE")-1;
571 for (u = units; u < units + c; u++) {
572 if (!output_show_unit_file(u))
575 max_id_len = MAX(max_id_len, strlen(path_get_file_name(u->path)));
576 state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
581 id_cols = MIN(max_id_len, 25);
582 basic_cols = 1 + id_cols + state_cols;
583 if (basic_cols < (unsigned) columns())
584 id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
586 id_cols = max_id_len;
589 printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
591 for (u = units; u < units + c; u++) {
593 const char *on, *off;
596 if (!output_show_unit_file(u))
601 if (u->state == UNIT_FILE_MASKED ||
602 u->state == UNIT_FILE_MASKED_RUNTIME ||
603 u->state == UNIT_FILE_DISABLED ||
604 u->state == UNIT_FILE_INVALID) {
605 on = ansi_highlight_red(true);
606 off = ansi_highlight_red(false);
607 } else if (u->state == UNIT_FILE_ENABLED) {
608 on = ansi_highlight_green(true);
609 off = ansi_highlight_green(false);
613 id = path_get_file_name(u->path);
615 e = arg_full ? NULL : ellipsize(id, id_cols, 33);
617 printf("%-*s %s%-*s%s\n",
619 on, state_cols, unit_file_state_to_string(u->state), off);
625 printf("\n%u unit files listed.\n", n_shown);
628 static int list_unit_files(DBusConnection *bus, char **args) {
629 DBusMessage *reply = NULL;
631 DBusMessageIter iter, sub, sub2;
632 unsigned c = 0, n_units = 0;
633 UnitFileList *units = NULL;
635 pager_open_if_enabled();
642 h = hashmap_new(string_hash_func, string_compare_func);
646 r = unit_file_get_list(arg_scope, arg_root, h);
648 unit_file_list_free(h);
649 log_error("Failed to get unit file list: %s", strerror(-r));
653 n_units = hashmap_size(h);
654 units = new(UnitFileList, n_units);
656 unit_file_list_free(h);
660 HASHMAP_FOREACH(u, h, i) {
661 memcpy(units + c++, u, sizeof(UnitFileList));
667 r = bus_method_call_with_reply (
669 "org.freedesktop.systemd1",
670 "/org/freedesktop/systemd1",
671 "org.freedesktop.systemd1.Manager",
679 if (!dbus_message_iter_init(reply, &iter) ||
680 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
681 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
682 log_error("Failed to parse reply.");
687 dbus_message_iter_recurse(&iter, &sub);
689 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
693 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
694 log_error("Failed to parse reply.");
702 n_units = MAX(2*c, 16);
703 w = realloc(units, sizeof(struct UnitFileList) * n_units);
706 log_error("Failed to allocate unit array.");
716 dbus_message_iter_recurse(&sub, &sub2);
718 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->path, true) < 0 ||
719 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, false) < 0) {
720 log_error("Failed to parse reply.");
725 u->state = unit_file_state_from_string(state);
727 dbus_message_iter_next(&sub);
733 qsort(units, c, sizeof(UnitFileList), compare_unit_file_list);
734 output_unit_file_list(units, c);
741 dbus_message_unref(reply);
748 static int dot_one_property(const char *name, const char *prop, DBusMessageIter *iter) {
749 static const char * const colors[] = {
750 "Requires", "[color=\"black\"]",
751 "RequiresOverridable", "[color=\"black\"]",
752 "Requisite", "[color=\"darkblue\"]",
753 "RequisiteOverridable", "[color=\"darkblue\"]",
754 "Wants", "[color=\"grey66\"]",
755 "Conflicts", "[color=\"red\"]",
756 "ConflictedBy", "[color=\"red\"]",
757 "After", "[color=\"green\"]"
760 const char *c = NULL;
767 for (i = 0; i < ELEMENTSOF(colors); i += 2)
768 if (streq(colors[i], prop)) {
776 if (arg_dot != DOT_ALL)
777 if ((arg_dot == DOT_ORDER) != streq(prop, "After"))
780 switch (dbus_message_iter_get_arg_type(iter)) {
782 case DBUS_TYPE_ARRAY:
784 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
787 dbus_message_iter_recurse(iter, &sub);
789 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
792 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
793 dbus_message_iter_get_basic(&sub, &s);
794 printf("\t\"%s\"->\"%s\" %s;\n", name, s, c);
796 dbus_message_iter_next(&sub);
806 static int dot_one(DBusConnection *bus, const char *name, const char *path) {
807 DBusMessage *reply = NULL;
808 const char *interface = "org.freedesktop.systemd1.Unit";
810 DBusMessageIter iter, sub, sub2, sub3;
814 r = bus_method_call_with_reply (
816 "org.freedesktop.systemd1",
818 "org.freedesktop.DBus.Properties",
822 DBUS_TYPE_STRING, &interface,
827 if (!dbus_message_iter_init(reply, &iter) ||
828 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
829 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
830 log_error("Failed to parse reply.");
835 dbus_message_iter_recurse(&iter, &sub);
837 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
840 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
841 log_error("Failed to parse reply.");
846 dbus_message_iter_recurse(&sub, &sub2);
848 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &prop, true) < 0) {
849 log_error("Failed to parse reply.");
854 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
855 log_error("Failed to parse reply.");
860 dbus_message_iter_recurse(&sub2, &sub3);
862 if (dot_one_property(name, prop, &sub3)) {
863 log_error("Failed to parse reply.");
868 dbus_message_iter_next(&sub);
873 dbus_message_unref(reply);
878 static int dot(DBusConnection *bus, char **args) {
879 DBusMessage *reply = NULL;
881 DBusMessageIter iter, sub, sub2;
883 r = bus_method_call_with_reply (
885 "org.freedesktop.systemd1",
886 "/org/freedesktop/systemd1",
887 "org.freedesktop.systemd1.Manager",
895 if (!dbus_message_iter_init(reply, &iter) ||
896 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
897 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
898 log_error("Failed to parse reply.");
903 printf("digraph systemd {\n");
905 dbus_message_iter_recurse(&iter, &sub);
906 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
907 const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path;
909 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
910 log_error("Failed to parse reply.");
915 dbus_message_iter_recurse(&sub, &sub2);
917 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &id, true) < 0 ||
918 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &description, true) < 0 ||
919 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
920 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
921 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
922 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
923 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0) {
924 log_error("Failed to parse reply.");
929 if ((r = dot_one(bus, id, unit_path)) < 0)
932 /* printf("\t\"%s\";\n", id); */
933 dbus_message_iter_next(&sub);
938 log_info(" Color legend: black = Requires\n"
939 " dark blue = Requisite\n"
940 " dark grey = Wants\n"
945 log_notice("-- You probably want to process this output with graphviz' dot tool.\n"
946 "-- Try a shell pipeline like 'systemctl dot | dot -Tsvg > systemd.svg'!\n");
952 dbus_message_unref(reply);
957 static int list_jobs(DBusConnection *bus, char **args) {
958 DBusMessage *reply = NULL;
960 DBusMessageIter iter, sub, sub2;
963 pager_open_if_enabled();
965 r = bus_method_call_with_reply (
967 "org.freedesktop.systemd1",
968 "/org/freedesktop/systemd1",
969 "org.freedesktop.systemd1.Manager",
977 if (!dbus_message_iter_init(reply, &iter) ||
978 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
979 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
980 log_error("Failed to parse reply.");
985 dbus_message_iter_recurse(&iter, &sub);
988 printf("%4s %-25s %-15s %-7s\n", "JOB", "UNIT", "TYPE", "STATE");
990 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
991 const char *name, *type, *state, *job_path, *unit_path;
995 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
996 log_error("Failed to parse reply.");
1001 dbus_message_iter_recurse(&sub, &sub2);
1003 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &id, true) < 0 ||
1004 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0 ||
1005 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
1006 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &state, true) < 0 ||
1007 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path, true) < 0 ||
1008 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, false) < 0) {
1009 log_error("Failed to parse reply.");
1014 e = arg_full ? NULL : ellipsize(name, 25, 33);
1015 printf("%4u %-25s %-15s %-7s\n", id, e ? e : name, type, state);
1020 dbus_message_iter_next(&sub);
1024 printf("\n%u jobs listed.\n", k);
1030 dbus_message_unref(reply);
1035 static int load_unit(DBusConnection *bus, char **args) {
1040 STRV_FOREACH(name, args+1) {
1041 _cleanup_free_ char *n = NULL;
1044 n = unit_name_mangle(*name);
1045 r = bus_method_call_with_reply (
1047 "org.freedesktop.systemd1",
1048 "/org/freedesktop/systemd1",
1049 "org.freedesktop.systemd1.Manager",
1053 DBUS_TYPE_STRING, n ? &n : name,
1062 static int cancel_job(DBusConnection *bus, char **args) {
1067 if (strv_length(args) <= 1)
1068 return daemon_reload(bus, args);
1070 STRV_FOREACH(name, args+1) {
1074 r = safe_atou32(*name, &id);
1076 log_error("Failed to parse job id: %s", strerror(-r));
1080 r = bus_method_call_with_reply(
1082 "org.freedesktop.systemd1",
1083 "/org/freedesktop/systemd1",
1084 "org.freedesktop.systemd1.Manager",
1088 DBUS_TYPE_UINT32, &id,
1097 static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
1098 DBusMessage *reply = NULL;
1099 dbus_bool_t b = FALSE;
1100 DBusMessageIter iter, sub;
1102 *interface = "org.freedesktop.systemd1.Unit",
1103 *property = "NeedDaemonReload",
1108 /* We ignore all errors here, since this is used to show a warning only */
1110 n = unit_name_mangle(unit);
1111 r = bus_method_call_with_reply (
1113 "org.freedesktop.systemd1",
1114 "/org/freedesktop/systemd1",
1115 "org.freedesktop.systemd1.Manager",
1119 DBUS_TYPE_STRING, n ? (const char**) &n : &unit,
1125 if (!dbus_message_get_args(reply, NULL,
1126 DBUS_TYPE_OBJECT_PATH, &path,
1130 dbus_message_unref(reply);
1131 r = bus_method_call_with_reply (
1133 "org.freedesktop.systemd1",
1135 "org.freedesktop.DBus.Properties",
1139 DBUS_TYPE_STRING, &interface,
1140 DBUS_TYPE_STRING, &property,
1145 if (!dbus_message_iter_init(reply, &iter) ||
1146 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1149 dbus_message_iter_recurse(&iter, &sub);
1151 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)
1154 dbus_message_iter_get_basic(&sub, &b);
1158 dbus_message_unref(reply);
1163 typedef struct WaitData {
1170 static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *message, void *data) {
1178 dbus_error_init(&error);
1180 log_debug("Got D-Bus request: %s.%s() on %s",
1181 dbus_message_get_interface(message),
1182 dbus_message_get_member(message),
1183 dbus_message_get_path(message));
1185 if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
1186 log_error("Warning! D-Bus connection terminated.");
1187 dbus_connection_close(connection);
1189 } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
1191 const char *path, *result, *unit;
1192 dbus_bool_t success = true;
1194 if (dbus_message_get_args(message, &error,
1195 DBUS_TYPE_UINT32, &id,
1196 DBUS_TYPE_OBJECT_PATH, &path,
1197 DBUS_TYPE_STRING, &unit,
1198 DBUS_TYPE_STRING, &result,
1199 DBUS_TYPE_INVALID)) {
1202 p = set_remove(d->set, (char*) path);
1205 if (!isempty(result))
1206 d->result = strdup(result);
1209 d->name = strdup(unit);
1214 dbus_error_free(&error);
1215 if (dbus_message_get_args(message, &error,
1216 DBUS_TYPE_UINT32, &id,
1217 DBUS_TYPE_OBJECT_PATH, &path,
1218 DBUS_TYPE_STRING, &result,
1219 DBUS_TYPE_INVALID)) {
1222 /* Compatibility with older systemd versions <
1223 * 183 during upgrades. This should be dropped
1225 p = set_remove(d->set, (char*) path);
1229 d->result = strdup(result);
1234 dbus_error_free(&error);
1235 if (dbus_message_get_args(message, &error,
1236 DBUS_TYPE_UINT32, &id,
1237 DBUS_TYPE_OBJECT_PATH, &path,
1238 DBUS_TYPE_BOOLEAN, &success,
1239 DBUS_TYPE_INVALID)) {
1242 /* Compatibility with older systemd versions <
1243 * 19 during upgrades. This should be dropped
1246 p = set_remove(d->set, (char*) path);
1250 d->result = strdup("failed");
1256 log_error("Failed to parse message: %s", bus_error_message(&error));
1260 dbus_error_free(&error);
1261 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1264 static int enable_wait_for_jobs(DBusConnection *bus) {
1272 dbus_error_init(&error);
1273 dbus_bus_add_match(bus,
1275 "sender='org.freedesktop.systemd1',"
1276 "interface='org.freedesktop.systemd1.Manager',"
1277 "member='JobRemoved',"
1278 "path='/org/freedesktop/systemd1'",
1281 if (dbus_error_is_set(&error)) {
1282 log_error("Failed to add match: %s", bus_error_message(&error));
1283 dbus_error_free(&error);
1287 /* This is slightly dirty, since we don't undo the match registrations. */
1291 static int wait_for_jobs(DBusConnection *bus, Set *s) {
1301 if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
1304 while (!set_isempty(s)) {
1306 if (!dbus_connection_read_write_dispatch(bus, -1)) {
1307 log_error("Disconnected from bus.");
1308 return -ECONNREFUSED;
1315 if (streq(d.result, "timeout"))
1316 log_error("Job for %s timed out.", strna(d.name));
1317 else if (streq(d.result, "canceled"))
1318 log_error("Job for %s canceled.", strna(d.name));
1319 else if (streq(d.result, "dependency"))
1320 log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
1321 else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
1322 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
1325 if (streq_ptr(d.result, "timeout"))
1327 else if (streq_ptr(d.result, "canceled"))
1329 else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
1340 dbus_connection_remove_filter(bus, wait_filter, &d);
1344 static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
1345 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1346 DBusMessageIter iter, sub;
1348 *interface = "org.freedesktop.systemd1.Unit",
1349 *property = "ActiveState";
1350 const char *state, *path;
1351 _cleanup_free_ char *n = NULL;
1357 dbus_error_init(&error);
1359 n = unit_name_mangle(name);
1363 r = bus_method_call_with_reply (
1365 "org.freedesktop.systemd1",
1366 "/org/freedesktop/systemd1",
1367 "org.freedesktop.systemd1.Manager",
1371 DBUS_TYPE_STRING, &n,
1374 dbus_error_free(&error);
1381 if (!dbus_message_get_args(reply, NULL,
1382 DBUS_TYPE_OBJECT_PATH, &path,
1383 DBUS_TYPE_INVALID)) {
1384 log_error("Failed to parse reply.");
1388 dbus_message_unref(reply);
1391 r = bus_method_call_with_reply(
1393 "org.freedesktop.systemd1",
1395 "org.freedesktop.DBus.Properties",
1399 DBUS_TYPE_STRING, &interface,
1400 DBUS_TYPE_STRING, &property,
1408 if (!dbus_message_iter_init(reply, &iter) ||
1409 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1410 log_error("Failed to parse reply.");
1414 dbus_message_iter_recurse(&iter, &sub);
1416 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1417 log_error("Failed to parse reply.");
1421 dbus_message_iter_get_basic(&sub, &state);
1426 return strv_find(check_states, state) ? 1 : 0;
1429 static void check_triggering_units(
1430 DBusConnection *bus,
1431 const char *unit_name) {
1433 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1434 DBusMessageIter iter, sub;
1435 const char *interface = "org.freedesktop.systemd1.Unit",
1436 *triggered_by_property = "TriggeredBy";
1438 char _cleanup_free_ *unit_path = NULL, *n = NULL;
1439 bool print_warning_label = true;
1442 n = unit_name_mangle(unit_name);
1448 unit_path = unit_dbus_path_from_name(n);
1454 r = bus_method_call_with_reply(
1456 "org.freedesktop.systemd1",
1458 "org.freedesktop.DBus.Properties",
1462 DBUS_TYPE_STRING, &interface,
1463 DBUS_TYPE_STRING, &triggered_by_property,
1468 if (!dbus_message_iter_init(reply, &iter) ||
1469 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
1470 log_error("Failed to parse reply.");
1474 dbus_message_iter_recurse(&iter, &sub);
1475 dbus_message_iter_recurse(&sub, &iter);
1478 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1479 const char * const check_states[] = {
1484 const char *service_trigger;
1486 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
1487 log_error("Failed to parse reply.");
1491 dbus_message_iter_get_basic(&sub, &service_trigger);
1493 r = check_one_unit(bus, service_trigger, (char**) check_states, true);
1497 if (print_warning_label) {
1498 log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name);
1499 print_warning_label = false;
1502 log_warning(" %s", service_trigger);
1505 dbus_message_iter_next(&sub);
1509 static int start_unit_one(
1510 DBusConnection *bus,
1517 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1520 _cleanup_free_ char *n, *p = NULL;
1527 n = unit_name_mangle(name);
1531 r = bus_method_call_with_reply(
1533 "org.freedesktop.systemd1",
1534 "/org/freedesktop/systemd1",
1535 "org.freedesktop.systemd1.Manager",
1539 DBUS_TYPE_STRING, &n,
1540 DBUS_TYPE_STRING, &mode,
1543 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
1544 /* There's always a fallback possible for
1545 * legacy actions. */
1548 log_error("Failed to issue method call: %s", bus_error_message(error));
1553 if (!dbus_message_get_args(reply, error,
1554 DBUS_TYPE_OBJECT_PATH, &path,
1555 DBUS_TYPE_INVALID)) {
1556 log_error("Failed to parse reply: %s", bus_error_message(error));
1560 if (need_daemon_reload(bus, n))
1561 log_warning("Warning: Unit file of %s changed on disk, 'systemctl %s daemon-reload' recommended.",
1562 n, arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
1571 log_error("Failed to add path to set.");
1581 static enum action verb_to_action(const char *verb) {
1582 if (streq(verb, "halt"))
1584 else if (streq(verb, "poweroff"))
1585 return ACTION_POWEROFF;
1586 else if (streq(verb, "reboot"))
1587 return ACTION_REBOOT;
1588 else if (streq(verb, "kexec"))
1589 return ACTION_KEXEC;
1590 else if (streq(verb, "rescue"))
1591 return ACTION_RESCUE;
1592 else if (streq(verb, "emergency"))
1593 return ACTION_EMERGENCY;
1594 else if (streq(verb, "default"))
1595 return ACTION_DEFAULT;
1596 else if (streq(verb, "exit"))
1598 else if (streq(verb, "suspend"))
1599 return ACTION_SUSPEND;
1600 else if (streq(verb, "hibernate"))
1601 return ACTION_HIBERNATE;
1602 else if (streq(verb, "hybrid-sleep"))
1603 return ACTION_HYBRID_SLEEP;
1605 return ACTION_INVALID;
1608 static int start_unit(DBusConnection *bus, char **args) {
1610 static const char * const table[_ACTION_MAX] = {
1611 [ACTION_HALT] = SPECIAL_HALT_TARGET,
1612 [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
1613 [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
1614 [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
1615 [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
1616 [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
1617 [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
1618 [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
1619 [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
1620 [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
1621 [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
1622 [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
1623 [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
1624 [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
1625 [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
1629 const char *method, *mode, *one_name;
1634 dbus_error_init(&error);
1638 ask_password_agent_open_if_enabled();
1640 if (arg_action == ACTION_SYSTEMCTL) {
1642 streq(args[0], "stop") ||
1643 streq(args[0], "condstop") ? "StopUnit" :
1644 streq(args[0], "reload") ? "ReloadUnit" :
1645 streq(args[0], "restart") ? "RestartUnit" :
1647 streq(args[0], "try-restart") ||
1648 streq(args[0], "condrestart") ? "TryRestartUnit" :
1650 streq(args[0], "reload-or-restart") ? "ReloadOrRestartUnit" :
1652 streq(args[0], "reload-or-try-restart") ||
1653 streq(args[0], "condreload") ||
1655 streq(args[0], "force-reload") ? "ReloadOrTryRestartUnit" :
1659 (streq(args[0], "isolate") ||
1660 streq(args[0], "rescue") ||
1661 streq(args[0], "emergency")) ? "isolate" : arg_job_mode;
1663 one_name = table[verb_to_action(args[0])];
1666 assert(arg_action < ELEMENTSOF(table));
1667 assert(table[arg_action]);
1669 method = "StartUnit";
1671 mode = (arg_action == ACTION_EMERGENCY ||
1672 arg_action == ACTION_RESCUE ||
1673 arg_action == ACTION_RUNLEVEL2 ||
1674 arg_action == ACTION_RUNLEVEL3 ||
1675 arg_action == ACTION_RUNLEVEL4 ||
1676 arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
1678 one_name = table[arg_action];
1681 if (!arg_no_block) {
1682 ret = enable_wait_for_jobs(bus);
1684 log_error("Could not watch jobs: %s", strerror(-ret));
1688 s = set_new(string_hash_func, string_compare_func);
1696 ret = start_unit_one(bus, method, one_name, mode, &error, s);
1698 ret = translate_bus_error_to_exit_status(ret, &error);
1700 STRV_FOREACH(name, args+1) {
1701 r = start_unit_one(bus, method, *name, mode, &error, s);
1703 ret = translate_bus_error_to_exit_status(r, &error);
1704 dbus_error_free(&error);
1709 if (!arg_no_block) {
1710 r = wait_for_jobs(bus, s);
1716 /* When stopping units, warn if they can still be triggered by
1717 * another active unit (socket, path, timer) */
1718 if (!arg_quiet && streq(method, "StopUnit")) {
1720 check_triggering_units(bus, one_name);
1722 STRV_FOREACH(name, args+1)
1723 check_triggering_units(bus, *name);
1729 dbus_error_free(&error);
1734 /* Ask systemd-logind, which might grant access to unprivileged users
1735 * through PolicyKit */
1736 static int reboot_with_logind(DBusConnection *bus, enum action a) {
1739 dbus_bool_t interactive = true;
1744 polkit_agent_open_if_enabled();
1752 case ACTION_POWEROFF:
1753 method = "PowerOff";
1756 case ACTION_SUSPEND:
1760 case ACTION_HIBERNATE:
1761 method = "Hibernate";
1764 case ACTION_HYBRID_SLEEP:
1765 method = "HybridSleep";
1772 return bus_method_call_with_reply (
1774 "org.freedesktop.login1",
1775 "/org/freedesktop/login1",
1776 "org.freedesktop.login1.Manager",
1780 DBUS_TYPE_BOOLEAN, &interactive,
1787 static int check_inhibitors(DBusConnection *bus, enum action a) {
1789 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
1790 DBusMessageIter iter, sub, sub2;
1797 if (arg_ignore_inhibitors || arg_force > 0)
1809 r = bus_method_call_with_reply(
1811 "org.freedesktop.login1",
1812 "/org/freedesktop/login1",
1813 "org.freedesktop.login1.Manager",
1819 /* If logind is not around, then there are no inhibitors... */
1822 if (!dbus_message_iter_init(reply, &iter) ||
1823 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
1824 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
1825 log_error("Failed to parse reply.");
1829 dbus_message_iter_recurse(&iter, &sub);
1830 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1831 const char *what, *who, *why, *mode;
1833 _cleanup_strv_free_ char **sv = NULL;
1834 _cleanup_free_ char *comm = NULL;
1836 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
1837 log_error("Failed to parse reply.");
1841 dbus_message_iter_recurse(&sub, &sub2);
1843 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &what, true) < 0 ||
1844 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &who, true) < 0 ||
1845 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 ||
1846 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 ||
1847 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 ||
1848 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) {
1849 log_error("Failed to parse reply.");
1853 if (!streq(mode, "block"))
1856 sv = strv_split(what, ":");
1860 if (!strv_contains(sv,
1862 a == ACTION_POWEROFF ||
1863 a == ACTION_REBOOT ||
1864 a == ACTION_KEXEC ? "shutdown" : "sleep"))
1867 get_process_comm(pid, &comm);
1868 log_warning("Operation inhibited by \"%s\" (PID %lu \"%s\", UID %lu), reason is \"%s\".", who, (unsigned long) pid, strna(comm), (unsigned long) uid, why);
1872 dbus_message_iter_next(&sub);
1875 dbus_message_iter_recurse(&iter, &sub);
1880 log_error("Please try again after closing inhibitors or ignore them with 'systemctl %s -i'.",
1881 a == ACTION_HALT ? "halt" :
1882 a == ACTION_POWEROFF ? "poweroff" :
1883 a == ACTION_REBOOT ? "reboot" :
1884 a == ACTION_KEXEC ? "kexec" :
1885 a == ACTION_SUSPEND ? "suspend" :
1886 a == ACTION_HIBERNATE ? "hibernate" : "hybrid-sleep");
1894 static int start_special(DBusConnection *bus, char **args) {
1900 a = verb_to_action(args[0]);
1902 r = check_inhibitors(bus, a);
1906 if (arg_force >= 2 && geteuid() != 0) {
1907 log_error("Must be root.");
1911 if (arg_force >= 2 &&
1912 (a == ACTION_HALT ||
1913 a == ACTION_POWEROFF ||
1914 a == ACTION_REBOOT))
1917 if (arg_force >= 1 &&
1918 (a == ACTION_HALT ||
1919 a == ACTION_POWEROFF ||
1920 a == ACTION_REBOOT ||
1921 a == ACTION_KEXEC ||
1923 return daemon_reload(bus, args);
1925 /* first try logind, to allow authentication with polkit */
1926 if (geteuid() != 0 &&
1927 (a == ACTION_POWEROFF ||
1928 a == ACTION_REBOOT ||
1929 a == ACTION_SUSPEND ||
1930 a == ACTION_HIBERNATE ||
1931 a == ACTION_HYBRID_SLEEP)) {
1932 r = reboot_with_logind(bus, a);
1937 r = start_unit(bus, args);
1944 static int check_unit_active(DBusConnection *bus, char **args) {
1945 const char * const check_states[] = {
1952 int r = 3; /* According to LSB: "program is not running" */
1957 STRV_FOREACH(name, args+1) {
1960 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1970 static int check_unit_failed(DBusConnection *bus, char **args) {
1971 const char * const check_states[] = {
1982 STRV_FOREACH(name, args+1) {
1985 state = check_one_unit(bus, *name, (char**) check_states, arg_quiet);
1995 static int kill_unit(DBusConnection *bus, char **args) {
2003 arg_kill_who = "all";
2005 STRV_FOREACH(name, args+1) {
2006 _cleanup_free_ char *n = NULL;
2008 n = unit_name_mangle(*name);
2010 r = bus_method_call_with_reply(
2012 "org.freedesktop.systemd1",
2013 "/org/freedesktop/systemd1",
2014 "org.freedesktop.systemd1.Manager",
2018 DBUS_TYPE_STRING, n ? &n : name,
2019 DBUS_TYPE_STRING, &arg_kill_who,
2020 DBUS_TYPE_INT32, &arg_signal,
2028 typedef struct ExecStatusInfo {
2036 usec_t start_timestamp;
2037 usec_t exit_timestamp;
2042 LIST_FIELDS(struct ExecStatusInfo, exec);
2045 static void exec_status_info_free(ExecStatusInfo *i) {
2054 static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i) {
2055 uint64_t start_timestamp, exit_timestamp, start_timestamp_monotonic, exit_timestamp_monotonic;
2056 DBusMessageIter sub2, sub3;
2060 int32_t code, status;
2066 if (dbus_message_iter_get_arg_type(sub) != DBUS_TYPE_STRUCT)
2069 dbus_message_iter_recurse(sub, &sub2);
2071 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
2074 if (!(i->path = strdup(path)))
2077 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
2078 dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
2082 dbus_message_iter_recurse(&sub2, &sub3);
2083 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2084 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2085 dbus_message_iter_next(&sub3);
2090 if (!(i->argv = new0(char*, n+1)))
2094 dbus_message_iter_recurse(&sub2, &sub3);
2095 while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
2098 assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
2099 dbus_message_iter_get_basic(&sub3, &s);
2100 dbus_message_iter_next(&sub3);
2102 if (!(i->argv[n++] = strdup(s)))
2106 if (!dbus_message_iter_next(&sub2) ||
2107 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
2108 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
2109 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp_monotonic, true) < 0 ||
2110 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
2111 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp_monotonic, true) < 0 ||
2112 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
2113 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) < 0 ||
2114 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
2118 i->start_timestamp = (usec_t) start_timestamp;
2119 i->exit_timestamp = (usec_t) exit_timestamp;
2120 i->pid = (pid_t) pid;
2127 typedef struct UnitStatusInfo {
2129 const char *load_state;
2130 const char *active_state;
2131 const char *sub_state;
2132 const char *unit_file_state;
2134 const char *description;
2135 const char *following;
2137 char **documentation;
2139 const char *fragment_path;
2140 const char *source_path;
2141 const char *default_control_group;
2143 const char *load_error;
2146 usec_t inactive_exit_timestamp;
2147 usec_t inactive_exit_timestamp_monotonic;
2148 usec_t active_enter_timestamp;
2149 usec_t active_exit_timestamp;
2150 usec_t inactive_enter_timestamp;
2152 bool need_daemon_reload;
2157 const char *status_text;
2160 usec_t start_timestamp;
2161 usec_t exit_timestamp;
2163 int exit_code, exit_status;
2165 usec_t condition_timestamp;
2166 bool condition_result;
2169 unsigned n_accepted;
2170 unsigned n_connections;
2174 const char *sysfs_path;
2176 /* Mount, Automount */
2182 LIST_HEAD(ExecStatusInfo, exec);
2185 static void print_status_info(UnitStatusInfo *i) {
2187 const char *on, *off, *ss;
2189 char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
2190 char since2[FORMAT_TIMESTAMP_MAX], *s2;
2195 /* This shows pretty information about a unit. See
2196 * print_property() for a low-level property printer */
2198 printf("%s", strna(i->id));
2200 if (i->description && !streq_ptr(i->id, i->description))
2201 printf(" - %s", i->description);
2206 printf("\t Follow: unit currently follows state of %s\n", i->following);
2208 if (streq_ptr(i->load_state, "error")) {
2209 on = ansi_highlight_red(true);
2210 off = ansi_highlight_red(false);
2214 path = i->source_path ? i->source_path : i->fragment_path;
2217 printf("\t Loaded: %s%s%s (Reason: %s)\n", on, strna(i->load_state), off, i->load_error);
2218 else if (path && i->unit_file_state)
2219 printf("\t Loaded: %s%s%s (%s; %s)\n", on, strna(i->load_state), off, path, i->unit_file_state);
2221 printf("\t Loaded: %s%s%s (%s)\n", on, strna(i->load_state), off, path);
2223 printf("\t Loaded: %s%s%s\n", on, strna(i->load_state), off);
2225 ss = streq_ptr(i->active_state, i->sub_state) ? NULL : i->sub_state;
2227 if (streq_ptr(i->active_state, "failed")) {
2228 on = ansi_highlight_red(true);
2229 off = ansi_highlight_red(false);
2230 } else if (streq_ptr(i->active_state, "active") || streq_ptr(i->active_state, "reloading")) {
2231 on = ansi_highlight_green(true);
2232 off = ansi_highlight_green(false);
2237 printf("\t Active: %s%s (%s)%s",
2239 strna(i->active_state),
2243 printf("\t Active: %s%s%s",
2245 strna(i->active_state),
2248 if (!isempty(i->result) && !streq(i->result, "success"))
2249 printf(" (Result: %s)", i->result);
2251 timestamp = (streq_ptr(i->active_state, "active") ||
2252 streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
2253 (streq_ptr(i->active_state, "inactive") ||
2254 streq_ptr(i->active_state, "failed")) ? i->inactive_enter_timestamp :
2255 streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
2256 i->active_exit_timestamp;
2258 s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
2259 s2 = format_timestamp(since2, sizeof(since2), timestamp);
2262 printf(" since %s; %s\n", s2, s1);
2264 printf(" since %s\n", s2);
2268 if (!i->condition_result && i->condition_timestamp > 0) {
2269 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
2270 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
2273 printf("\t start condition failed at %s; %s\n", s2, s1);
2275 printf("\t start condition failed at %s\n", s2);
2279 printf("\t Device: %s\n", i->sysfs_path);
2281 printf("\t Where: %s\n", i->where);
2283 printf("\t What: %s\n", i->what);
2285 if (!strv_isempty(i->documentation)) {
2289 STRV_FOREACH(t, i->documentation) {
2291 printf("\t Docs: %s\n", *t);
2294 printf("\t %s\n", *t);
2299 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
2301 LIST_FOREACH(exec, p, i->exec) {
2305 /* Only show exited processes here */
2309 t = strv_join(p->argv, " ");
2310 printf("\t Process: %u %s=%s ", p->pid, p->name, strna(t));
2313 good = is_clean_exit_lsb(p->code, p->status, NULL);
2315 on = ansi_highlight_red(true);
2316 off = ansi_highlight_red(false);
2320 printf("%s(code=%s, ", on, sigchld_code_to_string(p->code));
2322 if (p->code == CLD_EXITED) {
2325 printf("status=%i", p->status);
2327 c = exit_status_to_string(p->status, EXIT_STATUS_SYSTEMD);
2332 printf("signal=%s", signal_to_string(p->status));
2334 printf(")%s\n", off);
2336 if (i->main_pid == p->pid &&
2337 i->start_timestamp == p->start_timestamp &&
2338 i->exit_timestamp == p->start_timestamp)
2339 /* Let's not show this twice */
2342 if (p->pid == i->control_pid)
2346 if (i->main_pid > 0 || i->control_pid > 0) {
2349 if (i->main_pid > 0) {
2350 printf("Main PID: %u", (unsigned) i->main_pid);
2354 get_process_comm(i->main_pid, &t);
2359 } else if (i->exit_code > 0) {
2360 printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
2362 if (i->exit_code == CLD_EXITED) {
2365 printf("status=%i", i->exit_status);
2367 c = exit_status_to_string(i->exit_status, EXIT_STATUS_SYSTEMD);
2372 printf("signal=%s", signal_to_string(i->exit_status));
2377 if (i->main_pid > 0 && i->control_pid > 0)
2380 if (i->control_pid > 0) {
2383 printf(" Control: %u", (unsigned) i->control_pid);
2385 get_process_comm(i->control_pid, &t);
2396 printf("\t Status: \"%s\"\n", i->status_text);
2398 if (i->default_control_group &&
2399 (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
2402 printf("\t CGroup: %s\n", i->default_control_group);
2404 if (arg_transport != TRANSPORT_SSH) {
2414 if (i->main_pid > 0)
2415 extra[k++] = i->main_pid;
2417 if (i->control_pid > 0)
2418 extra[k++] = i->control_pid;
2420 show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, extra, k);
2424 if (i->id && arg_transport != TRANSPORT_SSH) {
2426 arg_all * OUTPUT_SHOW_ALL |
2427 (!on_tty() || pager_have()) * OUTPUT_FULL_WIDTH |
2428 on_tty() * OUTPUT_COLOR |
2429 !arg_quiet * OUTPUT_WARN_CUTOFF;
2432 show_journal_by_unit(stdout,
2436 i->inactive_exit_timestamp_monotonic,
2441 if (i->need_daemon_reload)
2442 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
2443 ansi_highlight_red(true),
2444 ansi_highlight_red(false),
2445 arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
2448 static void show_unit_help(UnitStatusInfo *i) {
2453 if (!i->documentation) {
2454 log_info("Documentation for %s not known.", i->id);
2458 STRV_FOREACH(p, i->documentation) {
2460 if (startswith(*p, "man:")) {
2463 char *page = NULL, *section = NULL;
2464 const char *args[4] = { "man", NULL, NULL, NULL };
2469 if ((*p)[k-1] == ')')
2470 e = strrchr(*p, '(');
2473 page = strndup((*p) + 4, e - *p - 4);
2479 section = strndup(e + 1, *p + k - e - 2);
2493 log_error("Failed to fork: %m");
2501 execvp(args[0], (char**) args);
2502 log_error("Failed to execute man: %m");
2503 _exit(EXIT_FAILURE);
2509 wait_for_terminate(pid, NULL);
2511 log_info("Can't show: %s", *p);
2515 static int status_property(const char *name, DBusMessageIter *iter, UnitStatusInfo *i) {
2521 switch (dbus_message_iter_get_arg_type(iter)) {
2523 case DBUS_TYPE_STRING: {
2526 dbus_message_iter_get_basic(iter, &s);
2529 if (streq(name, "Id"))
2531 else if (streq(name, "LoadState"))
2533 else if (streq(name, "ActiveState"))
2534 i->active_state = s;
2535 else if (streq(name, "SubState"))
2537 else if (streq(name, "Description"))
2539 else if (streq(name, "FragmentPath"))
2540 i->fragment_path = s;
2541 else if (streq(name, "SourcePath"))
2543 else if (streq(name, "DefaultControlGroup"))
2544 i->default_control_group = s;
2545 else if (streq(name, "StatusText"))
2547 else if (streq(name, "SysFSPath"))
2549 else if (streq(name, "Where"))
2551 else if (streq(name, "What"))
2553 else if (streq(name, "Following"))
2555 else if (streq(name, "UnitFileState"))
2556 i->unit_file_state = s;
2557 else if (streq(name, "Result"))
2564 case DBUS_TYPE_BOOLEAN: {
2567 dbus_message_iter_get_basic(iter, &b);
2569 if (streq(name, "Accept"))
2571 else if (streq(name, "NeedDaemonReload"))
2572 i->need_daemon_reload = b;
2573 else if (streq(name, "ConditionResult"))
2574 i->condition_result = b;
2579 case DBUS_TYPE_UINT32: {
2582 dbus_message_iter_get_basic(iter, &u);
2584 if (streq(name, "MainPID")) {
2586 i->main_pid = (pid_t) u;
2589 } else if (streq(name, "ControlPID"))
2590 i->control_pid = (pid_t) u;
2591 else if (streq(name, "ExecMainPID")) {
2593 i->main_pid = (pid_t) u;
2594 } else if (streq(name, "NAccepted"))
2596 else if (streq(name, "NConnections"))
2597 i->n_connections = u;
2602 case DBUS_TYPE_INT32: {
2605 dbus_message_iter_get_basic(iter, &j);
2607 if (streq(name, "ExecMainCode"))
2608 i->exit_code = (int) j;
2609 else if (streq(name, "ExecMainStatus"))
2610 i->exit_status = (int) j;
2615 case DBUS_TYPE_UINT64: {
2618 dbus_message_iter_get_basic(iter, &u);
2620 if (streq(name, "ExecMainStartTimestamp"))
2621 i->start_timestamp = (usec_t) u;
2622 else if (streq(name, "ExecMainExitTimestamp"))
2623 i->exit_timestamp = (usec_t) u;
2624 else if (streq(name, "ActiveEnterTimestamp"))
2625 i->active_enter_timestamp = (usec_t) u;
2626 else if (streq(name, "InactiveEnterTimestamp"))
2627 i->inactive_enter_timestamp = (usec_t) u;
2628 else if (streq(name, "InactiveExitTimestamp"))
2629 i->inactive_exit_timestamp = (usec_t) u;
2630 else if (streq(name, "InactiveExitTimestampMonotonic"))
2631 i->inactive_exit_timestamp_monotonic = (usec_t) u;
2632 else if (streq(name, "ActiveExitTimestamp"))
2633 i->active_exit_timestamp = (usec_t) u;
2634 else if (streq(name, "ConditionTimestamp"))
2635 i->condition_timestamp = (usec_t) u;
2640 case DBUS_TYPE_ARRAY: {
2642 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
2643 startswith(name, "Exec")) {
2644 DBusMessageIter sub;
2646 dbus_message_iter_recurse(iter, &sub);
2647 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2648 ExecStatusInfo *info;
2651 if (!(info = new0(ExecStatusInfo, 1)))
2654 if (!(info->name = strdup(name))) {
2659 if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
2664 LIST_PREPEND(ExecStatusInfo, exec, i->exec, info);
2666 dbus_message_iter_next(&sub);
2668 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
2669 streq(name, "Documentation")) {
2671 DBusMessageIter sub;
2673 dbus_message_iter_recurse(iter, &sub);
2674 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING) {
2678 dbus_message_iter_get_basic(&sub, &s);
2680 l = strv_append(i->documentation, s);
2684 strv_free(i->documentation);
2685 i->documentation = l;
2687 dbus_message_iter_next(&sub);
2694 case DBUS_TYPE_STRUCT: {
2696 if (streq(name, "LoadError")) {
2697 DBusMessageIter sub;
2698 const char *n, *message;
2701 dbus_message_iter_recurse(iter, &sub);
2703 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &n, true);
2707 r = bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &message, false);
2711 if (!isempty(message))
2712 i->load_error = message;
2722 static int print_property(const char *name, DBusMessageIter *iter) {
2726 /* This is a low-level property printer, see
2727 * print_status_info() for the nicer output */
2729 if (arg_property && !strv_find(arg_property, name))
2732 switch (dbus_message_iter_get_arg_type(iter)) {
2734 case DBUS_TYPE_STRUCT: {
2735 DBusMessageIter sub;
2736 dbus_message_iter_recurse(iter, &sub);
2738 if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
2741 dbus_message_iter_get_basic(&sub, &u);
2744 printf("%s=%u\n", name, (unsigned) u);
2746 printf("%s=\n", name);
2749 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
2752 dbus_message_iter_get_basic(&sub, &s);
2754 if (arg_all || s[0])
2755 printf("%s=%s\n", name, s);
2758 } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "LoadError")) {
2759 const char *a = NULL, *b = NULL;
2761 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &a, true) >= 0)
2762 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &b, false);
2764 if (arg_all || !isempty(a) || !isempty(b))
2765 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
2773 case DBUS_TYPE_ARRAY:
2775 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "EnvironmentFiles")) {
2776 DBusMessageIter sub, sub2;
2778 dbus_message_iter_recurse(iter, &sub);
2779 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2783 dbus_message_iter_recurse(&sub, &sub2);
2785 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) >= 0 &&
2786 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) >= 0)
2787 printf("EnvironmentFile=%s (ignore_errors=%s)\n", path, yes_no(ignore));
2789 dbus_message_iter_next(&sub);
2794 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
2795 DBusMessageIter sub, sub2;
2797 dbus_message_iter_recurse(iter, &sub);
2798 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2799 const char *type, *path;
2801 dbus_message_iter_recurse(&sub, &sub2);
2803 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
2804 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
2805 printf("%s=%s\n", type, path);
2807 dbus_message_iter_next(&sub);
2812 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
2813 DBusMessageIter sub, sub2;
2815 dbus_message_iter_recurse(iter, &sub);
2816 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2818 uint64_t value, next_elapse;
2820 dbus_message_iter_recurse(&sub, &sub2);
2822 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
2823 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
2824 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
2825 char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
2827 printf("%s={ value=%s ; next_elapse=%s }\n",
2829 format_timespan(timespan1, sizeof(timespan1), value),
2830 format_timespan(timespan2, sizeof(timespan2), next_elapse));
2833 dbus_message_iter_next(&sub);
2838 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "ControlGroupAttributes")) {
2839 DBusMessageIter sub, sub2;
2841 dbus_message_iter_recurse(iter, &sub);
2842 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2843 const char *controller, *attr, *value;
2845 dbus_message_iter_recurse(&sub, &sub2);
2847 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &controller, true) >= 0 &&
2848 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &attr, true) >= 0 &&
2849 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &value, false) >= 0) {
2851 printf("ControlGroupAttribute={ controller=%s ; attribute=%s ; value=\"%s\" }\n",
2857 dbus_message_iter_next(&sub);
2862 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
2863 DBusMessageIter sub;
2865 dbus_message_iter_recurse(iter, &sub);
2866 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
2867 ExecStatusInfo info;
2870 if (exec_status_info_deserialize(&sub, &info) >= 0) {
2871 char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
2874 t = strv_join(info.argv, " ");
2876 printf("%s={ path=%s ; argv[]=%s ; ignore_errors=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
2880 yes_no(info.ignore),
2881 strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
2882 strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
2883 (unsigned) info. pid,
2884 sigchld_code_to_string(info.code),
2886 info.code == CLD_EXITED ? "" : "/",
2887 strempty(info.code == CLD_EXITED ? NULL : signal_to_string(info.status)));
2893 strv_free(info.argv);
2895 dbus_message_iter_next(&sub);
2904 if (generic_print_property(name, iter, arg_all) > 0)
2908 printf("%s=[unprintable]\n", name);
2913 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
2914 DBusMessage *reply = NULL;
2915 const char *interface = "";
2917 DBusMessageIter iter, sub, sub2, sub3;
2918 UnitStatusInfo info;
2926 r = bus_method_call_with_reply (
2928 "org.freedesktop.systemd1",
2930 "org.freedesktop.DBus.Properties",
2934 DBUS_TYPE_STRING, &interface,
2939 if (!dbus_message_iter_init(reply, &iter) ||
2940 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2941 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
2942 log_error("Failed to parse reply.");
2947 dbus_message_iter_recurse(&iter, &sub);
2954 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
2957 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
2958 log_error("Failed to parse reply.");
2963 dbus_message_iter_recurse(&sub, &sub2);
2965 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
2966 log_error("Failed to parse reply.");
2971 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
2972 log_error("Failed to parse reply.");
2977 dbus_message_iter_recurse(&sub2, &sub3);
2979 if (show_properties)
2980 r = print_property(name, &sub3);
2982 r = status_property(name, &sub3, &info);
2985 log_error("Failed to parse reply.");
2990 dbus_message_iter_next(&sub);
2995 if (!show_properties) {
2996 if (streq(verb, "help"))
2997 show_unit_help(&info);
2999 print_status_info(&info);
3002 strv_free(info.documentation);
3004 if (!streq_ptr(info.active_state, "active") &&
3005 !streq_ptr(info.active_state, "reloading") &&
3006 streq(verb, "status"))
3007 /* According to LSB: "program not running" */
3010 while ((p = info.exec)) {
3011 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
3012 exec_status_info_free(p);
3017 dbus_message_unref(reply);
3022 static int show_one_by_pid(const char *verb, DBusConnection *bus, uint32_t pid, bool *new_line) {
3023 DBusMessage *reply = NULL;
3024 const char *path = NULL;
3028 dbus_error_init(&error);
3030 r = bus_method_call_with_reply (
3032 "org.freedesktop.systemd1",
3033 "/org/freedesktop/systemd1",
3034 "org.freedesktop.systemd1.Manager",
3038 DBUS_TYPE_UINT32, &pid,
3043 if (!dbus_message_get_args(reply, &error,
3044 DBUS_TYPE_OBJECT_PATH, &path,
3045 DBUS_TYPE_INVALID)) {
3046 log_error("Failed to parse reply: %s", bus_error_message(&error));
3051 r = show_one(verb, bus, path, false, new_line);
3055 dbus_message_unref(reply);
3057 dbus_error_free(&error);
3062 static int show(DBusConnection *bus, char **args) {
3064 bool show_properties, new_line = false;
3070 show_properties = streq(args[0], "show");
3072 if (show_properties)
3073 pager_open_if_enabled();
3075 if (show_properties && strv_length(args) <= 1) {
3076 /* If not argument is specified inspect the manager
3079 return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line);
3082 STRV_FOREACH(name, args+1) {
3085 if (safe_atou32(*name, &id) < 0) {
3087 /* Interpret as unit name */
3089 n = unit_name_mangle(*name);
3090 p = unit_dbus_path_from_name(n ? n : *name);
3095 r = show_one(args[0], bus, p, show_properties, &new_line);
3101 } else if (show_properties) {
3103 /* Interpret as job id */
3106 if (asprintf(&p, "/org/freedesktop/systemd1/job/%u", id) < 0)
3109 r = show_one(args[0], bus, p, show_properties, &new_line);
3117 /* Interpret as PID */
3119 r = show_one_by_pid(args[0], bus, id, &new_line);
3128 static int dump(DBusConnection *bus, char **args) {
3129 DBusMessage *reply = NULL;
3134 dbus_error_init(&error);
3136 pager_open_if_enabled();
3138 r = bus_method_call_with_reply (
3140 "org.freedesktop.systemd1",
3141 "/org/freedesktop/systemd1",
3142 "org.freedesktop.systemd1.Manager",
3150 if (!dbus_message_get_args(reply, &error,
3151 DBUS_TYPE_STRING, &text,
3152 DBUS_TYPE_INVALID)) {
3153 log_error("Failed to parse reply: %s", bus_error_message(&error));
3158 fputs(text, stdout);
3162 dbus_message_unref(reply);
3164 dbus_error_free(&error);
3169 static int snapshot(DBusConnection *bus, char **args) {
3170 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
3173 dbus_bool_t cleanup = FALSE;
3174 DBusMessageIter iter, sub;
3176 *name = "", *path, *id,
3177 *interface = "org.freedesktop.systemd1.Unit",
3179 _cleanup_free_ char *n = NULL;
3181 dbus_error_init(&error);
3183 if (strv_length(args) > 1) {
3185 n = unit_name_mangle(name);
3188 r = bus_method_call_with_reply (
3190 "org.freedesktop.systemd1",
3191 "/org/freedesktop/systemd1",
3192 "org.freedesktop.systemd1.Manager",
3196 DBUS_TYPE_STRING, n ? (const char**) &n : &name,
3197 DBUS_TYPE_BOOLEAN, &cleanup,
3202 if (!dbus_message_get_args(reply, &error,
3203 DBUS_TYPE_OBJECT_PATH, &path,
3204 DBUS_TYPE_INVALID)) {
3205 log_error("Failed to parse reply: %s", bus_error_message(&error));
3210 dbus_message_unref(reply);
3213 r = bus_method_call_with_reply (
3215 "org.freedesktop.systemd1",
3217 "org.freedesktop.DBus.Properties",
3221 DBUS_TYPE_STRING, &interface,
3222 DBUS_TYPE_STRING, &property,
3227 if (!dbus_message_iter_init(reply, &iter) ||
3228 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3229 log_error("Failed to parse reply.");
3234 dbus_message_iter_recurse(&iter, &sub);
3236 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
3237 log_error("Failed to parse reply.");
3242 dbus_message_iter_get_basic(&sub, &id);
3248 dbus_error_free(&error);
3253 static int delete_snapshot(DBusConnection *bus, char **args) {
3258 STRV_FOREACH(name, args+1) {
3259 _cleanup_free_ char *n = NULL;
3262 n = unit_name_mangle(*name);
3263 r = bus_method_call_with_reply(
3265 "org.freedesktop.systemd1",
3266 "/org/freedesktop/systemd1",
3267 "org.freedesktop.systemd1.Manager",
3271 DBUS_TYPE_STRING, n ? &n : name,
3280 static int daemon_reload(DBusConnection *bus, char **args) {
3285 if (arg_action == ACTION_RELOAD)
3287 else if (arg_action == ACTION_REEXEC)
3288 method = "Reexecute";
3290 assert(arg_action == ACTION_SYSTEMCTL);
3293 streq(args[0], "clear-jobs") ||
3294 streq(args[0], "cancel") ? "ClearJobs" :
3295 streq(args[0], "daemon-reexec") ? "Reexecute" :
3296 streq(args[0], "reset-failed") ? "ResetFailed" :
3297 streq(args[0], "halt") ? "Halt" :
3298 streq(args[0], "poweroff") ? "PowerOff" :
3299 streq(args[0], "reboot") ? "Reboot" :
3300 streq(args[0], "kexec") ? "KExec" :
3301 streq(args[0], "exit") ? "Exit" :
3302 /* "daemon-reload" */ "Reload";
3305 r = bus_method_call_with_reply (
3307 "org.freedesktop.systemd1",
3308 "/org/freedesktop/systemd1",
3309 "org.freedesktop.systemd1.Manager",
3315 if (r == -ENOENT && arg_action != ACTION_SYSTEMCTL)
3316 /* There's always a fallback possible for
3317 * legacy actions. */
3319 else if (r == -ETIMEDOUT && streq(method, "Reexecute"))
3320 /* On reexecution, we expect a disconnect, not
3324 log_error("Failed to issue method call: %s", bus_error_message(&error));
3325 dbus_error_free(&error);
3330 static int reset_failed(DBusConnection *bus, char **args) {
3334 if (strv_length(args) <= 1)
3335 return daemon_reload(bus, args);
3337 STRV_FOREACH(name, args+1) {
3338 n = unit_name_mangle(*name);
3339 r = bus_method_call_with_reply (
3341 "org.freedesktop.systemd1",
3342 "/org/freedesktop/systemd1",
3343 "org.freedesktop.systemd1.Manager",
3347 DBUS_TYPE_STRING, n ? &n : name,
3358 static int show_enviroment(DBusConnection *bus, char **args) {
3359 DBusMessage *reply = NULL;
3360 DBusMessageIter iter, sub, sub2;
3363 *interface = "org.freedesktop.systemd1.Manager",
3364 *property = "Environment";
3366 pager_open_if_enabled();
3368 r = bus_method_call_with_reply (
3370 "org.freedesktop.systemd1",
3371 "/org/freedesktop/systemd1",
3372 "org.freedesktop.DBus.Properties",
3376 DBUS_TYPE_STRING, &interface,
3377 DBUS_TYPE_STRING, &property,
3382 if (!dbus_message_iter_init(reply, &iter) ||
3383 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
3384 log_error("Failed to parse reply.");
3389 dbus_message_iter_recurse(&iter, &sub);
3391 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_ARRAY ||
3392 dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_STRING) {
3393 log_error("Failed to parse reply.");
3398 dbus_message_iter_recurse(&sub, &sub2);
3400 while (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_INVALID) {
3403 if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_STRING) {
3404 log_error("Failed to parse reply.");
3409 dbus_message_iter_get_basic(&sub2, &text);
3410 printf("%s\n", text);
3412 dbus_message_iter_next(&sub2);
3419 dbus_message_unref(reply);
3424 static int switch_root(DBusConnection *bus, char **args) {
3427 _cleanup_free_ char *init = NULL;
3429 l = strv_length(args);
3430 if (l < 2 || l > 3) {
3431 log_error("Wrong number of arguments.");
3438 init = strdup(args[2]);
3440 parse_env_file("/proc/cmdline", WHITESPACE,
3452 log_debug("switching root - root: %s; init: %s", root, init);
3454 return bus_method_call_with_reply (
3456 "org.freedesktop.systemd1",
3457 "/org/freedesktop/systemd1",
3458 "org.freedesktop.systemd1.Manager",
3462 DBUS_TYPE_STRING, &root,
3463 DBUS_TYPE_STRING, &init,
3467 static int set_environment(DBusConnection *bus, char **args) {
3468 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
3471 DBusMessageIter iter;
3477 dbus_error_init(&error);
3479 method = streq(args[0], "set-environment")
3481 : "UnsetEnvironment";
3483 m = dbus_message_new_method_call(
3484 "org.freedesktop.systemd1",
3485 "/org/freedesktop/systemd1",
3486 "org.freedesktop.systemd1.Manager",
3491 dbus_message_iter_init_append(m, &iter);
3493 r = bus_append_strv_iter(&iter, args + 1);
3497 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3499 log_error("Failed to issue method call: %s", bus_error_message(&error));
3507 dbus_error_free(&error);
3511 static int enable_sysv_units(char **args) {
3514 #if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
3515 const char *verb = args[0];
3516 unsigned f = 1, t = 1;
3519 if (arg_scope != UNIT_FILE_SYSTEM)
3522 if (!streq(verb, "enable") &&
3523 !streq(verb, "disable") &&
3524 !streq(verb, "is-enabled"))
3527 /* Processes all SysV units, and reshuffles the array so that
3528 * afterwards only the native units remain */
3531 r = lookup_paths_init(&paths, SYSTEMD_SYSTEM, false, NULL, NULL, NULL);
3536 for (f = 1; args[f]; f++) {
3539 bool found_native = false, found_sysv;
3541 const char *argv[6] = { "/sbin/chkconfig", NULL, NULL, NULL, NULL };
3542 char **k, *l, *q = NULL;
3549 if (!endswith(name, ".service"))
3552 if (path_is_absolute(name))
3555 STRV_FOREACH(k, paths.unit_path) {
3558 if (!isempty(arg_root))
3559 asprintf(&p, "%s/%s/%s", arg_root, *k, name);
3561 asprintf(&p, "%s/%s", *k, name);
3568 found_native = access(p, F_OK) >= 0;
3579 if (!isempty(arg_root))
3580 asprintf(&p, "%s/" SYSTEM_SYSVINIT_PATH "/%s", arg_root, name);
3582 asprintf(&p, SYSTEM_SYSVINIT_PATH "/%s", name);
3588 p[strlen(p) - sizeof(".service") + 1] = 0;
3589 found_sysv = access(p, F_OK) >= 0;
3596 /* Mark this entry, so that we don't try enabling it as native unit */
3597 args[f] = (char*) "";
3599 log_info("%s is not a native service, redirecting to /sbin/chkconfig.", name);
3601 if (!isempty(arg_root))
3602 argv[c++] = q = strappend("--root=", arg_root);
3604 argv[c++] = path_get_file_name(p);
3606 streq(verb, "enable") ? "on" :
3607 streq(verb, "disable") ? "off" : "--level=5";
3610 l = strv_join((char**)argv, " ");
3618 log_info("Executing %s", l);
3623 log_error("Failed to fork: %m");
3628 } else if (pid == 0) {
3631 execv(argv[0], (char**) argv);
3632 _exit(EXIT_FAILURE);
3638 j = wait_for_terminate(pid, &status);
3640 log_error("Failed to wait for child: %s", strerror(-r));
3645 if (status.si_code == CLD_EXITED) {
3646 if (streq(verb, "is-enabled")) {
3647 if (status.si_status == 0) {
3656 } else if (status.si_status != 0) {
3667 lookup_paths_free(&paths);
3669 /* Drop all SysV units */
3670 for (f = 1, t = 1; args[f]; f++) {
3672 if (isempty(args[f]))
3675 args[t++] = args[f];
3684 static int mangle_names(char **original_names, char ***mangled_names) {
3685 char **i, **l, **name;
3687 l = new(char*, strv_length(original_names) + 1);
3692 STRV_FOREACH(name, original_names) {
3694 /* When enabling units qualified path names are OK,
3695 * too, hence allow them explicitly. */
3700 *i = unit_name_mangle(*name);
3716 static int enable_unit(DBusConnection *bus, char **args) {
3717 const char *verb = args[0];
3718 UnitFileChange *changes = NULL;
3719 unsigned n_changes = 0, i;
3720 int carries_install_info = -1;
3721 DBusMessage *m = NULL, *reply = NULL;
3724 char **mangled_names = NULL;
3726 r = enable_sysv_units(args);
3733 dbus_error_init(&error);
3735 if (!bus || avoid_bus()) {
3736 if (streq(verb, "enable")) {
3737 r = unit_file_enable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3738 carries_install_info = r;
3739 } else if (streq(verb, "disable"))
3740 r = unit_file_disable(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3741 else if (streq(verb, "reenable")) {
3742 r = unit_file_reenable(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3743 carries_install_info = r;
3744 } else if (streq(verb, "link"))
3745 r = unit_file_link(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3746 else if (streq(verb, "preset")) {
3747 r = unit_file_preset(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3748 carries_install_info = r;
3749 } else if (streq(verb, "mask"))
3750 r = unit_file_mask(arg_scope, arg_runtime, arg_root, args+1, arg_force, &changes, &n_changes);
3751 else if (streq(verb, "unmask"))
3752 r = unit_file_unmask(arg_scope, arg_runtime, arg_root, args+1, &changes, &n_changes);
3754 assert_not_reached("Unknown verb");
3757 log_error("Operation failed: %s", strerror(-r));
3762 for (i = 0; i < n_changes; i++) {
3763 if (changes[i].type == UNIT_FILE_SYMLINK)
3764 log_info("ln -s '%s' '%s'", changes[i].source, changes[i].path);
3766 log_info("rm '%s'", changes[i].path);
3773 bool send_force = true, expect_carries_install_info = false;
3775 DBusMessageIter iter, sub, sub2;
3777 if (streq(verb, "enable")) {
3778 method = "EnableUnitFiles";
3779 expect_carries_install_info = true;
3780 } else if (streq(verb, "disable")) {
3781 method = "DisableUnitFiles";
3783 } else if (streq(verb, "reenable")) {
3784 method = "ReenableUnitFiles";
3785 expect_carries_install_info = true;
3786 } else if (streq(verb, "link"))
3787 method = "LinkUnitFiles";
3788 else if (streq(verb, "preset")) {
3789 method = "PresetUnitFiles";
3790 expect_carries_install_info = true;
3791 } else if (streq(verb, "mask"))
3792 method = "MaskUnitFiles";
3793 else if (streq(verb, "unmask")) {
3794 method = "UnmaskUnitFiles";
3797 assert_not_reached("Unknown verb");
3799 m = dbus_message_new_method_call(
3800 "org.freedesktop.systemd1",
3801 "/org/freedesktop/systemd1",
3802 "org.freedesktop.systemd1.Manager",
3809 dbus_message_iter_init_append(m, &iter);
3811 r = mangle_names(args+1, &mangled_names);
3815 r = bus_append_strv_iter(&iter, mangled_names);
3817 log_error("Failed to append unit files.");
3822 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &a)) {
3823 log_error("Failed to append runtime boolean.");
3831 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b)) {
3832 log_error("Failed to append force boolean.");
3838 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
3840 log_error("Failed to issue method call: %s", bus_error_message(&error));
3845 if (!dbus_message_iter_init(reply, &iter)) {
3846 log_error("Failed to initialize iterator.");
3850 if (expect_carries_install_info) {
3851 r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &b, true);
3853 log_error("Failed to parse reply.");
3857 carries_install_info = b;
3860 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
3861 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) {
3862 log_error("Failed to parse reply.");
3867 dbus_message_iter_recurse(&iter, &sub);
3868 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
3869 const char *type, *path, *source;
3871 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
3872 log_error("Failed to parse reply.");
3877 dbus_message_iter_recurse(&sub, &sub2);
3879 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) < 0 ||
3880 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0 ||
3881 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &source, false) < 0) {
3882 log_error("Failed to parse reply.");
3888 if (streq(type, "symlink"))
3889 log_info("ln -s '%s' '%s'", source, path);
3891 log_info("rm '%s'", path);
3894 dbus_message_iter_next(&sub);
3897 /* Try to reload if enabeld */
3899 r = daemon_reload(bus, args);
3902 if (carries_install_info == 0)
3904 "The unit files have no [Install] section. They are not meant to be enabled\n"
3905 "using systemctl.\n"
3906 "Possible reasons for having this kind of units are:\n"
3907 "1) A unit may be statically enabled by being symlinked from another unit's\n"
3908 " .wants/ or .requires/ directory.\n"
3909 "2) A unit's purpose may be to act as a helper for some other unit which has\n"
3910 " a requirement dependency on it.\n"
3911 "3) A unit may be started when needed via activation (socket, path, timer,\n"
3912 " D-Bus, udev, scripted systemctl call, ...).\n");
3916 dbus_message_unref(m);
3919 dbus_message_unref(reply);
3921 unit_file_changes_free(changes, n_changes);
3923 dbus_error_free(&error);
3925 strv_free(mangled_names);
3930 static int unit_is_enabled(DBusConnection *bus, char **args) {
3933 DBusMessage *reply = NULL;
3937 dbus_error_init(&error);
3939 r = enable_sysv_units(args);
3945 if (!bus || avoid_bus()) {
3947 STRV_FOREACH(name, args+1) {
3948 UnitFileState state;
3950 state = unit_file_get_state(arg_scope, arg_root, *name);
3956 if (state == UNIT_FILE_ENABLED ||
3957 state == UNIT_FILE_ENABLED_RUNTIME ||
3958 state == UNIT_FILE_STATIC)
3962 puts(unit_file_state_to_string(state));
3966 STRV_FOREACH(name, args+1) {
3969 r = bus_method_call_with_reply (
3971 "org.freedesktop.systemd1",
3972 "/org/freedesktop/systemd1",
3973 "org.freedesktop.systemd1.Manager",
3977 DBUS_TYPE_STRING, name,
3982 if (!dbus_message_get_args(reply, &error,
3983 DBUS_TYPE_STRING, &s,
3984 DBUS_TYPE_INVALID)) {
3985 log_error("Failed to parse reply: %s", bus_error_message(&error));
3990 dbus_message_unref(reply);
3993 if (streq(s, "enabled") ||
3994 streq(s, "enabled-runtime") ||
4003 r = enabled ? 0 : 1;
4007 dbus_message_unref(reply);
4009 dbus_error_free(&error);
4013 static int systemctl_help(void) {
4015 pager_open_if_enabled();
4017 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
4018 "Query or send control commands to the systemd manager.\n\n"
4019 " -h --help Show this help\n"
4020 " --version Show package version\n"
4021 " -t --type=TYPE List only units of a particular type\n"
4022 " -p --property=NAME Show only properties by this name\n"
4023 " -a --all Show all units/properties, including dead/empty ones\n"
4024 " --failed Show only failed units\n"
4025 " --full Don't ellipsize unit names on output\n"
4026 " --fail When queueing a new job, fail if conflicting jobs are\n"
4028 " --ignore-dependencies\n"
4029 " When queueing a new job, ignore all its dependencies\n"
4030 " -i --ignore-inhibitors\n"
4031 " When shutting down or sleeping, ignore inhibitors\n"
4032 " --kill-who=WHO Who to send signal to\n"
4033 " -s --signal=SIGNAL Which signal to send\n"
4034 " -H --host=[USER@]HOST\n"
4035 " Show information for remote host\n"
4036 " -P --privileged Acquire privileges before execution\n"
4037 " -q --quiet Suppress output\n"
4038 " --no-block Do not wait until operation finished\n"
4039 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4040 " --no-reload When enabling/disabling unit files, don't reload daemon\n"
4042 " --no-legend Do not print a legend (column headers and hints)\n"
4043 " --no-pager Do not pipe output into a pager\n"
4044 " --no-ask-password\n"
4045 " Do not ask for system passwords\n"
4046 " --order When generating graph for dot, show only order\n"
4047 " --require When generating graph for dot, show only requirement\n"
4048 " --system Connect to system manager\n"
4049 " --user Connect to user service manager\n"
4050 " --global Enable/disable unit files globally\n"
4051 " -f --force When enabling unit files, override existing symlinks\n"
4052 " When shutting down, execute action immediately\n"
4053 " --root=PATH Enable unit files in the specified root directory\n"
4054 " --runtime Enable unit files only temporarily until next reboot\n"
4055 " -n --lines=INTEGER Journal entries to show\n"
4056 " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
4057 " verbose, export, json, json-pretty, json-sse, cat)\n\n"
4059 " list-units List loaded units\n"
4060 " start [NAME...] Start (activate) one or more units\n"
4061 " stop [NAME...] Stop (deactivate) one or more units\n"
4062 " reload [NAME...] Reload one or more units\n"
4063 " restart [NAME...] Start or restart one or more units\n"
4064 " try-restart [NAME...] Restart one or more units if active\n"
4065 " reload-or-restart [NAME...] Reload one or more units if possible,\n"
4066 " otherwise start or restart\n"
4067 " reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
4068 " otherwise restart if active\n"
4069 " isolate [NAME] Start one unit and stop all others\n"
4070 " kill [NAME...] Send signal to processes of a unit\n"
4071 " is-active [NAME...] Check whether units are active\n"
4072 " is-failed [NAME...] Check whether units are failed\n"
4073 " status [NAME...|PID...] Show runtime status of one or more units\n"
4074 " show [NAME...|JOB...] Show properties of one or more\n"
4075 " units/jobs or the manager\n"
4076 " help [NAME...|PID...] Show manual for one or more units\n"
4077 " reset-failed [NAME...] Reset failed state for all, one, or more\n"
4079 " load [NAME...] Load one or more units\n\n"
4080 "Unit File Commands:\n"
4081 " list-unit-files List installed unit files\n"
4082 " enable [NAME...] Enable one or more unit files\n"
4083 " disable [NAME...] Disable one or more unit files\n"
4084 " reenable [NAME...] Reenable one or more unit files\n"
4085 " preset [NAME...] Enable/disable one or more unit files\n"
4086 " based on preset configuration\n"
4087 " mask [NAME...] Mask one or more units\n"
4088 " unmask [NAME...] Unmask one or more units\n"
4089 " link [PATH...] Link one or more units files into\n"
4090 " the search path\n"
4091 " is-enabled [NAME...] Check whether unit files are enabled\n\n"
4093 " list-jobs List jobs\n"
4094 " cancel [JOB...] Cancel all, one, or more jobs\n\n"
4095 "Status Commands:\n"
4096 " dump Dump server status\n"
4097 " dot Dump dependency graph for dot(1)\n\n"
4098 "Snapshot Commands:\n"
4099 " snapshot [NAME] Create a snapshot\n"
4100 " delete [NAME...] Remove one or more snapshots\n\n"
4101 "Environment Commands:\n"
4102 " show-environment Dump environment\n"
4103 " set-environment [NAME=VALUE...] Set one or more environment variables\n"
4104 " unset-environment [NAME...] Unset one or more environment variables\n\n"
4105 "Manager Lifecycle Commands:\n"
4106 " daemon-reload Reload systemd manager configuration\n"
4107 " daemon-reexec Reexecute systemd manager\n\n"
4108 "System Commands:\n"
4109 " default Enter system default mode\n"
4110 " rescue Enter system rescue mode\n"
4111 " emergency Enter system emergency mode\n"
4112 " halt Shut down and halt the system\n"
4113 " poweroff Shut down and power-off the system\n"
4114 " reboot Shut down and reboot the system\n"
4115 " kexec Shut down and reboot the system with kexec\n"
4116 " exit Request user instance exit\n"
4117 " switch-root [ROOT] [INIT] Change to a different root file system\n"
4118 " suspend Suspend the system\n"
4119 " hibernate Hibernate the system\n"
4120 " hybrid-sleep Hibernate and suspend the system\n",
4121 program_invocation_short_name);
4126 static int halt_help(void) {
4128 printf("%s [OPTIONS...]\n\n"
4129 "%s the system.\n\n"
4130 " --help Show this help\n"
4131 " --halt Halt the machine\n"
4132 " -p --poweroff Switch off the machine\n"
4133 " --reboot Reboot the machine\n"
4134 " -f --force Force immediate halt/power-off/reboot\n"
4135 " -w --wtmp-only Don't halt/power-off/reboot, just write wtmp record\n"
4136 " -d --no-wtmp Don't write wtmp record\n"
4137 " --no-wall Don't send wall message before halt/power-off/reboot\n",
4138 program_invocation_short_name,
4139 arg_action == ACTION_REBOOT ? "Reboot" :
4140 arg_action == ACTION_POWEROFF ? "Power off" :
4146 static int shutdown_help(void) {
4148 printf("%s [OPTIONS...] [TIME] [WALL...]\n\n"
4149 "Shut down the system.\n\n"
4150 " --help Show this help\n"
4151 " -H --halt Halt the machine\n"
4152 " -P --poweroff Power-off the machine\n"
4153 " -r --reboot Reboot the machine\n"
4154 " -h Equivalent to --poweroff, overridden by --halt\n"
4155 " -k Don't halt/power-off/reboot, just send warnings\n"
4156 " --no-wall Don't send wall message before halt/power-off/reboot\n"
4157 " -c Cancel a pending shutdown\n",
4158 program_invocation_short_name);
4163 static int telinit_help(void) {
4165 printf("%s [OPTIONS...] {COMMAND}\n\n"
4166 "Send control commands to the init daemon.\n\n"
4167 " --help Show this help\n"
4168 " --no-wall Don't send wall message before halt/power-off/reboot\n\n"
4170 " 0 Power-off the machine\n"
4171 " 6 Reboot the machine\n"
4172 " 2, 3, 4, 5 Start runlevelX.target unit\n"
4173 " 1, s, S Enter rescue mode\n"
4174 " q, Q Reload init daemon configuration\n"
4175 " u, U Reexecute init daemon\n",
4176 program_invocation_short_name);
4181 static int runlevel_help(void) {
4183 printf("%s [OPTIONS...]\n\n"
4184 "Prints the previous and current runlevel of the init system.\n\n"
4185 " --help Show this help\n",
4186 program_invocation_short_name);
4191 static int help_types(void) {
4194 puts("Available unit types:");
4195 for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
4196 if (unit_type_table[i])
4197 puts(unit_type_table[i]);
4199 puts("\nAvailable unit load states: ");
4200 for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
4201 if (unit_type_table[i])
4202 puts(unit_load_state_table[i]);
4207 static int systemctl_parse_argv(int argc, char *argv[]) {
4211 ARG_IGNORE_DEPENDENCIES,
4226 ARG_NO_ASK_PASSWORD,
4232 static const struct option options[] = {
4233 { "help", no_argument, NULL, 'h' },
4234 { "version", no_argument, NULL, ARG_VERSION },
4235 { "type", required_argument, NULL, 't' },
4236 { "property", required_argument, NULL, 'p' },
4237 { "all", no_argument, NULL, 'a' },
4238 { "failed", no_argument, NULL, ARG_FAILED },
4239 { "full", no_argument, NULL, ARG_FULL },
4240 { "fail", no_argument, NULL, ARG_FAIL },
4241 { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
4242 { "ignore-inhibitors", no_argument, NULL, 'i' },
4243 { "user", no_argument, NULL, ARG_USER },
4244 { "system", no_argument, NULL, ARG_SYSTEM },
4245 { "global", no_argument, NULL, ARG_GLOBAL },
4246 { "no-block", no_argument, NULL, ARG_NO_BLOCK },
4247 { "no-legend", no_argument, NULL, ARG_NO_LEGEND },
4248 { "no-pager", no_argument, NULL, ARG_NO_PAGER },
4249 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4250 { "quiet", no_argument, NULL, 'q' },
4251 { "order", no_argument, NULL, ARG_ORDER },
4252 { "require", no_argument, NULL, ARG_REQUIRE },
4253 { "root", required_argument, NULL, ARG_ROOT },
4254 { "force", no_argument, NULL, ARG_FORCE },
4255 { "no-reload", no_argument, NULL, ARG_NO_RELOAD },
4256 { "kill-who", required_argument, NULL, ARG_KILL_WHO },
4257 { "signal", required_argument, NULL, 's' },
4258 { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
4259 { "host", required_argument, NULL, 'H' },
4260 { "privileged",no_argument, NULL, 'P' },
4261 { "runtime", no_argument, NULL, ARG_RUNTIME },
4262 { "lines", required_argument, NULL, 'n' },
4263 { "output", required_argument, NULL, 'o' },
4264 { NULL, 0, NULL, 0 }
4272 while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:i", options, NULL)) >= 0) {
4281 puts(PACKAGE_STRING);
4282 puts(SYSTEMD_FEATURES);
4286 if (streq(optarg, "help")) {
4291 if (unit_type_from_string(optarg) >= 0) {
4295 if (unit_load_state_from_string(optarg) >= 0) {
4296 arg_load_state = optarg;
4299 log_error("Unkown unit type or load state '%s'.",
4301 log_info("Use -t help to see a list of allowed values.");
4306 if (!(l = strv_append(arg_property, optarg)))
4309 strv_free(arg_property);
4312 /* If the user asked for a particular
4313 * property, show it to him, even if it is
4324 arg_job_mode = "fail";
4327 case ARG_IGNORE_DEPENDENCIES:
4328 arg_job_mode = "ignore-dependencies";
4332 arg_scope = UNIT_FILE_USER;
4336 arg_scope = UNIT_FILE_SYSTEM;
4340 arg_scope = UNIT_FILE_GLOBAL;
4344 arg_no_block = true;
4348 arg_no_legend = true;
4352 arg_no_pager = true;
4360 arg_dot = DOT_ORDER;
4364 arg_dot = DOT_REQUIRE;
4392 arg_no_reload = true;
4396 arg_kill_who = optarg;
4400 if ((arg_signal = signal_from_string_try_harder(optarg)) < 0) {
4401 log_error("Failed to parse signal string %s.", optarg);
4406 case ARG_NO_ASK_PASSWORD:
4407 arg_ask_password = false;
4411 arg_transport = TRANSPORT_POLKIT;
4415 arg_transport = TRANSPORT_SSH;
4424 if (safe_atou(optarg, &arg_lines) < 0) {
4425 log_error("Failed to parse lines '%s'", optarg);
4431 arg_output = output_mode_from_string(optarg);
4432 if (arg_output < 0) {
4433 log_error("Unknown output '%s'.", optarg);
4439 arg_ignore_inhibitors = true;
4446 log_error("Unknown option code '%c'.", c);
4451 if (arg_transport != TRANSPORT_NORMAL && arg_scope != UNIT_FILE_SYSTEM) {
4452 log_error("Cannot access user instance remotely.");
4459 static int halt_parse_argv(int argc, char *argv[]) {
4468 static const struct option options[] = {
4469 { "help", no_argument, NULL, ARG_HELP },
4470 { "halt", no_argument, NULL, ARG_HALT },
4471 { "poweroff", no_argument, NULL, 'p' },
4472 { "reboot", no_argument, NULL, ARG_REBOOT },
4473 { "force", no_argument, NULL, 'f' },
4474 { "wtmp-only", no_argument, NULL, 'w' },
4475 { "no-wtmp", no_argument, NULL, 'd' },
4476 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4477 { NULL, 0, NULL, 0 }
4485 if (utmp_get_runlevel(&runlevel, NULL) >= 0)
4486 if (runlevel == '0' || runlevel == '6')
4489 while ((c = getopt_long(argc, argv, "pfwdnih", options, NULL)) >= 0) {
4497 arg_action = ACTION_HALT;
4501 if (arg_action != ACTION_REBOOT)
4502 arg_action = ACTION_POWEROFF;
4506 arg_action = ACTION_REBOOT;
4528 /* Compatibility nops */
4535 log_error("Unknown option code '%c'.", c);
4540 if (optind < argc) {
4541 log_error("Too many arguments.");
4548 static int parse_time_spec(const char *t, usec_t *_u) {
4552 if (streq(t, "now"))
4554 else if (!strchr(t, ':')) {
4557 if (safe_atou64(t, &u) < 0)
4560 *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u;
4569 hour = strtol(t, &e, 10);
4570 if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
4573 minute = strtol(e+1, &e, 10);
4574 if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
4577 n = now(CLOCK_REALTIME);
4578 s = (time_t) (n / USEC_PER_SEC);
4581 assert_se(localtime_r(&s, &tm));
4583 tm.tm_hour = (int) hour;
4584 tm.tm_min = (int) minute;
4587 assert_se(s = mktime(&tm));
4589 *_u = (usec_t) s * USEC_PER_SEC;
4592 *_u += USEC_PER_DAY;
4598 static int shutdown_parse_argv(int argc, char *argv[]) {
4605 static const struct option options[] = {
4606 { "help", no_argument, NULL, ARG_HELP },
4607 { "halt", no_argument, NULL, 'H' },
4608 { "poweroff", no_argument, NULL, 'P' },
4609 { "reboot", no_argument, NULL, 'r' },
4610 { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
4611 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4612 { NULL, 0, NULL, 0 }
4620 while ((c = getopt_long(argc, argv, "HPrhkt:afFc", options, NULL)) >= 0) {
4628 arg_action = ACTION_HALT;
4632 arg_action = ACTION_POWEROFF;
4637 arg_action = ACTION_KEXEC;
4639 arg_action = ACTION_REBOOT;
4643 arg_action = ACTION_KEXEC;
4647 if (arg_action != ACTION_HALT)
4648 arg_action = ACTION_POWEROFF;
4661 /* Compatibility nops */
4665 arg_action = ACTION_CANCEL_SHUTDOWN;
4672 log_error("Unknown option code '%c'.", c);
4677 if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) {
4678 r = parse_time_spec(argv[optind], &arg_when);
4680 log_error("Failed to parse time specification: %s", argv[optind]);
4684 arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE;
4686 if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN)
4687 /* No time argument for shutdown cancel */
4688 arg_wall = argv + optind;
4689 else if (argc > optind + 1)
4690 /* We skip the time argument */
4691 arg_wall = argv + optind + 1;
4698 static int telinit_parse_argv(int argc, char *argv[]) {
4705 static const struct option options[] = {
4706 { "help", no_argument, NULL, ARG_HELP },
4707 { "no-wall", no_argument, NULL, ARG_NO_WALL },
4708 { NULL, 0, NULL, 0 }
4711 static const struct {
4715 { '0', ACTION_POWEROFF },
4716 { '6', ACTION_REBOOT },
4717 { '1', ACTION_RESCUE },
4718 { '2', ACTION_RUNLEVEL2 },
4719 { '3', ACTION_RUNLEVEL3 },
4720 { '4', ACTION_RUNLEVEL4 },
4721 { '5', ACTION_RUNLEVEL5 },
4722 { 's', ACTION_RESCUE },
4723 { 'S', ACTION_RESCUE },
4724 { 'q', ACTION_RELOAD },
4725 { 'Q', ACTION_RELOAD },
4726 { 'u', ACTION_REEXEC },
4727 { 'U', ACTION_REEXEC }
4736 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4751 log_error("Unknown option code '%c'.", c);
4756 if (optind >= argc) {
4761 if (optind + 1 < argc) {
4762 log_error("Too many arguments.");
4766 if (strlen(argv[optind]) != 1) {
4767 log_error("Expected single character argument.");
4771 for (i = 0; i < ELEMENTSOF(table); i++)
4772 if (table[i].from == argv[optind][0])
4775 if (i >= ELEMENTSOF(table)) {
4776 log_error("Unknown command '%s'.", argv[optind]);
4780 arg_action = table[i].to;
4787 static int runlevel_parse_argv(int argc, char *argv[]) {
4793 static const struct option options[] = {
4794 { "help", no_argument, NULL, ARG_HELP },
4795 { NULL, 0, NULL, 0 }
4803 while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) {
4814 log_error("Unknown option code '%c'.", c);
4819 if (optind < argc) {
4820 log_error("Too many arguments.");
4827 static int parse_argv(int argc, char *argv[]) {
4831 if (program_invocation_short_name) {
4833 if (strstr(program_invocation_short_name, "halt")) {
4834 arg_action = ACTION_HALT;
4835 return halt_parse_argv(argc, argv);
4836 } else if (strstr(program_invocation_short_name, "poweroff")) {
4837 arg_action = ACTION_POWEROFF;
4838 return halt_parse_argv(argc, argv);
4839 } else if (strstr(program_invocation_short_name, "reboot")) {
4841 arg_action = ACTION_KEXEC;
4843 arg_action = ACTION_REBOOT;
4844 return halt_parse_argv(argc, argv);
4845 } else if (strstr(program_invocation_short_name, "shutdown")) {
4846 arg_action = ACTION_POWEROFF;
4847 return shutdown_parse_argv(argc, argv);
4848 } else if (strstr(program_invocation_short_name, "init")) {
4850 if (sd_booted() > 0) {
4851 arg_action = ACTION_INVALID;
4852 return telinit_parse_argv(argc, argv);
4854 /* Hmm, so some other init system is
4855 * running, we need to forward this
4856 * request to it. For now we simply
4857 * guess that it is Upstart. */
4859 execv("/lib/upstart/telinit", argv);
4861 log_error("Couldn't find an alternative telinit implementation to spawn.");
4865 } else if (strstr(program_invocation_short_name, "runlevel")) {
4866 arg_action = ACTION_RUNLEVEL;
4867 return runlevel_parse_argv(argc, argv);
4871 arg_action = ACTION_SYSTEMCTL;
4872 return systemctl_parse_argv(argc, argv);
4875 static int action_to_runlevel(void) {
4877 static const char table[_ACTION_MAX] = {
4878 [ACTION_HALT] = '0',
4879 [ACTION_POWEROFF] = '0',
4880 [ACTION_REBOOT] = '6',
4881 [ACTION_RUNLEVEL2] = '2',
4882 [ACTION_RUNLEVEL3] = '3',
4883 [ACTION_RUNLEVEL4] = '4',
4884 [ACTION_RUNLEVEL5] = '5',
4885 [ACTION_RESCUE] = '1'
4888 assert(arg_action < _ACTION_MAX);
4890 return table[arg_action];
4893 static int talk_upstart(void) {
4894 DBusMessage *m = NULL, *reply = NULL;
4896 int previous, rl, r;
4898 env1_buf[] = "RUNLEVEL=X",
4899 env2_buf[] = "PREVLEVEL=X";
4900 char *env1 = env1_buf, *env2 = env2_buf;
4901 const char *emit = "runlevel";
4902 dbus_bool_t b_false = FALSE;
4903 DBusMessageIter iter, sub;
4904 DBusConnection *bus;
4906 dbus_error_init(&error);
4908 if (!(rl = action_to_runlevel()))
4911 if (utmp_get_runlevel(&previous, NULL) < 0)
4914 if (!(bus = dbus_connection_open_private("unix:abstract=/com/ubuntu/upstart", &error))) {
4915 if (dbus_error_has_name(&error, DBUS_ERROR_NO_SERVER)) {
4920 log_error("Failed to connect to Upstart bus: %s", bus_error_message(&error));
4925 if ((r = bus_check_peercred(bus)) < 0) {
4926 log_error("Failed to verify owner of bus.");
4930 if (!(m = dbus_message_new_method_call(
4931 "com.ubuntu.Upstart",
4932 "/com/ubuntu/Upstart",
4933 "com.ubuntu.Upstart0_6",
4936 log_error("Could not allocate message.");
4941 dbus_message_iter_init_append(m, &iter);
4943 env1_buf[sizeof(env1_buf)-2] = rl;
4944 env2_buf[sizeof(env2_buf)-2] = previous;
4946 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &emit) ||
4947 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub) ||
4948 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env1) ||
4949 !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &env2) ||
4950 !dbus_message_iter_close_container(&iter, &sub) ||
4951 !dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b_false)) {
4952 log_error("Could not append arguments to message.");
4957 if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
4959 if (bus_error_is_no_service(&error)) {
4964 log_error("Failed to issue method call: %s", bus_error_message(&error));
4973 dbus_message_unref(m);
4976 dbus_message_unref(reply);
4979 dbus_connection_flush(bus);
4980 dbus_connection_close(bus);
4981 dbus_connection_unref(bus);
4984 dbus_error_free(&error);
4989 static int talk_initctl(void) {
4990 struct init_request request;
4994 if (!(rl = action_to_runlevel()))
4998 request.magic = INIT_MAGIC;
4999 request.sleeptime = 0;
5000 request.cmd = INIT_CMD_RUNLVL;
5001 request.runlevel = rl;
5003 if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
5005 if (errno == ENOENT)
5008 log_error("Failed to open "INIT_FIFO": %m");
5013 r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
5014 close_nointr_nofail(fd);
5017 log_error("Failed to write to "INIT_FIFO": %m");
5018 return errno ? -errno : -EIO;
5024 static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
5026 static const struct {
5034 int (* const dispatch)(DBusConnection *bus, char **args);
5036 { "list-units", LESS, 1, list_units },
5037 { "list-unit-files", EQUAL, 1, list_unit_files },
5038 { "list-jobs", EQUAL, 1, list_jobs },
5039 { "clear-jobs", EQUAL, 1, daemon_reload },
5040 { "load", MORE, 2, load_unit },
5041 { "cancel", MORE, 2, cancel_job },
5042 { "start", MORE, 2, start_unit },
5043 { "stop", MORE, 2, start_unit },
5044 { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5045 { "reload", MORE, 2, start_unit },
5046 { "restart", MORE, 2, start_unit },
5047 { "try-restart", MORE, 2, start_unit },
5048 { "reload-or-restart", MORE, 2, start_unit },
5049 { "reload-or-try-restart", MORE, 2, start_unit },
5050 { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */
5051 { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */
5052 { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */
5053 { "isolate", EQUAL, 2, start_unit },
5054 { "kill", MORE, 2, kill_unit },
5055 { "is-active", MORE, 2, check_unit_active },
5056 { "check", MORE, 2, check_unit_active },
5057 { "is-failed", MORE, 2, check_unit_failed },
5058 { "show", MORE, 1, show },
5059 { "status", MORE, 2, show },
5060 { "help", MORE, 2, show },
5061 { "dump", EQUAL, 1, dump },
5062 { "dot", EQUAL, 1, dot },
5063 { "snapshot", LESS, 2, snapshot },
5064 { "delete", MORE, 2, delete_snapshot },
5065 { "daemon-reload", EQUAL, 1, daemon_reload },
5066 { "daemon-reexec", EQUAL, 1, daemon_reload },
5067 { "show-environment", EQUAL, 1, show_enviroment },
5068 { "set-environment", MORE, 2, set_environment },
5069 { "unset-environment", MORE, 2, set_environment },
5070 { "halt", EQUAL, 1, start_special },
5071 { "poweroff", EQUAL, 1, start_special },
5072 { "reboot", EQUAL, 1, start_special },
5073 { "kexec", EQUAL, 1, start_special },
5074 { "suspend", EQUAL, 1, start_special },
5075 { "hibernate", EQUAL, 1, start_special },
5076 { "hybrid-sleep", EQUAL, 1, start_special },
5077 { "default", EQUAL, 1, start_special },
5078 { "rescue", EQUAL, 1, start_special },
5079 { "emergency", EQUAL, 1, start_special },
5080 { "exit", EQUAL, 1, start_special },
5081 { "reset-failed", MORE, 1, reset_failed },
5082 { "enable", MORE, 2, enable_unit },
5083 { "disable", MORE, 2, enable_unit },
5084 { "is-enabled", MORE, 2, unit_is_enabled },
5085 { "reenable", MORE, 2, enable_unit },
5086 { "preset", MORE, 2, enable_unit },
5087 { "mask", MORE, 2, enable_unit },
5088 { "unmask", MORE, 2, enable_unit },
5089 { "link", MORE, 2, enable_unit },
5090 { "switch-root", MORE, 2, switch_root },
5100 left = argc - optind;
5103 /* Special rule: no arguments means "list-units" */
5106 if (streq(argv[optind], "help") && !argv[optind+1]) {
5107 log_error("This command expects one or more "
5108 "unit names. Did you mean --help?");
5112 for (i = 0; i < ELEMENTSOF(verbs); i++)
5113 if (streq(argv[optind], verbs[i].verb))
5116 if (i >= ELEMENTSOF(verbs)) {
5117 log_error("Unknown operation '%s'.", argv[optind]);
5122 switch (verbs[i].argc_cmp) {
5125 if (left != verbs[i].argc) {
5126 log_error("Invalid number of arguments.");
5133 if (left < verbs[i].argc) {
5134 log_error("Too few arguments.");
5141 if (left > verbs[i].argc) {
5142 log_error("Too many arguments.");
5149 assert_not_reached("Unknown comparison operator.");
5152 /* Require a bus connection for all operations but
5154 if (!streq(verbs[i].verb, "enable") &&
5155 !streq(verbs[i].verb, "disable") &&
5156 !streq(verbs[i].verb, "is-enabled") &&
5157 !streq(verbs[i].verb, "list-unit-files") &&
5158 !streq(verbs[i].verb, "reenable") &&
5159 !streq(verbs[i].verb, "preset") &&
5160 !streq(verbs[i].verb, "mask") &&
5161 !streq(verbs[i].verb, "unmask") &&
5162 !streq(verbs[i].verb, "link")) {
5164 if (running_in_chroot() > 0) {
5165 log_info("Running in chroot, ignoring request.");
5169 if (((!streq(verbs[i].verb, "reboot") &&
5170 !streq(verbs[i].verb, "halt") &&
5171 !streq(verbs[i].verb, "poweroff")) || arg_force <= 0) && !bus) {
5172 log_error("Failed to get D-Bus connection: %s",
5173 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5179 if (!bus && !avoid_bus()) {
5180 log_error("Failed to get D-Bus connection: %s",
5181 dbus_error_is_set(error) ? error->message : "No connection to service manager.");
5186 return verbs[i].dispatch(bus, argv + optind);
5189 static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
5191 struct msghdr msghdr;
5192 struct iovec iovec[2];
5193 union sockaddr_union sockaddr;
5194 struct sd_shutdown_command c;
5196 fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
5203 c.dry_run = dry_run;
5207 sockaddr.sa.sa_family = AF_UNIX;
5208 strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
5211 msghdr.msg_name = &sockaddr;
5212 msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
5215 iovec[0].iov_base = (char*) &c;
5216 iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
5218 if (isempty(message))
5219 msghdr.msg_iovlen = 1;
5221 iovec[1].iov_base = (char*) message;
5222 iovec[1].iov_len = strlen(message);
5223 msghdr.msg_iovlen = 2;
5225 msghdr.msg_iov = iovec;
5227 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
5228 close_nointr_nofail(fd);
5232 close_nointr_nofail(fd);
5236 static int reload_with_fallback(DBusConnection *bus) {
5239 /* First, try systemd via D-Bus. */
5240 if (daemon_reload(bus, NULL) >= 0)
5244 /* Nothing else worked, so let's try signals */
5245 assert(arg_action == ACTION_RELOAD || arg_action == ACTION_REEXEC);
5247 if (kill(1, arg_action == ACTION_RELOAD ? SIGHUP : SIGTERM) < 0) {
5248 log_error("kill() failed: %m");
5255 static int start_with_fallback(DBusConnection *bus) {
5258 /* First, try systemd via D-Bus. */
5259 if (start_unit(bus, NULL) >= 0)
5263 /* Hmm, talking to systemd via D-Bus didn't work. Then
5264 * let's try to talk to Upstart via D-Bus. */
5265 if (talk_upstart() > 0)
5268 /* Nothing else worked, so let's try
5270 if (talk_initctl() > 0)
5273 log_error("Failed to talk to init daemon.");
5277 warn_wall(arg_action);
5281 static _noreturn_ void halt_now(enum action a) {
5283 /* Make sure C-A-D is handled by the kernel from this
5285 reboot(RB_ENABLE_CAD);
5290 log_info("Halting.");
5291 reboot(RB_HALT_SYSTEM);
5294 case ACTION_POWEROFF:
5295 log_info("Powering off.");
5296 reboot(RB_POWER_OFF);
5300 log_info("Rebooting.");
5301 reboot(RB_AUTOBOOT);
5305 assert_not_reached("Unknown halt action.");
5308 assert_not_reached("Uh? This shouldn't happen.");
5311 static int halt_main(DBusConnection *bus) {
5314 r = check_inhibitors(bus, arg_action);
5318 if (geteuid() != 0) {
5319 /* Try logind if we are a normal user and no special
5320 * mode applies. Maybe PolicyKit allows us to shutdown
5323 if (arg_when <= 0 &&
5326 (arg_action == ACTION_POWEROFF ||
5327 arg_action == ACTION_REBOOT)) {
5328 r = reboot_with_logind(bus, arg_action);
5333 log_error("Must be root.");
5340 m = strv_join(arg_wall, " ");
5341 r = send_shutdownd(arg_when,
5342 arg_action == ACTION_HALT ? 'H' :
5343 arg_action == ACTION_POWEROFF ? 'P' :
5344 arg_action == ACTION_KEXEC ? 'K' :
5352 log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
5354 char date[FORMAT_TIMESTAMP_MAX];
5356 log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
5357 format_timestamp(date, sizeof(date), arg_when));
5362 if (!arg_dry && !arg_force)
5363 return start_with_fallback(bus);
5366 if (sd_booted() > 0)
5367 log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
5369 r = utmp_put_shutdown();
5371 log_warning("Failed to write utmp record: %s", strerror(-r));
5378 halt_now(arg_action);
5379 /* We should never reach this. */
5383 static int runlevel_main(void) {
5384 int r, runlevel, previous;
5386 r = utmp_get_runlevel(&runlevel, &previous);
5393 previous <= 0 ? 'N' : previous,
5394 runlevel <= 0 ? 'N' : runlevel);
5399 int main(int argc, char*argv[]) {
5400 int r, retval = EXIT_FAILURE;
5401 DBusConnection *bus = NULL;
5404 dbus_error_init(&error);
5406 setlocale(LC_ALL, "");
5407 log_parse_environment();
5410 r = parse_argv(argc, argv);
5414 retval = EXIT_SUCCESS;
5418 /* /sbin/runlevel doesn't need to communicate via D-Bus, so
5419 * let's shortcut this */
5420 if (arg_action == ACTION_RUNLEVEL) {
5421 r = runlevel_main();
5422 retval = r < 0 ? EXIT_FAILURE : r;
5426 if (running_in_chroot() > 0 && arg_action != ACTION_SYSTEMCTL) {
5427 log_info("Running in chroot, ignoring request.");
5433 if (arg_transport == TRANSPORT_NORMAL)
5434 bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error);
5435 else if (arg_transport == TRANSPORT_POLKIT) {
5436 bus_connect_system_polkit(&bus, &error);
5437 private_bus = false;
5438 } else if (arg_transport == TRANSPORT_SSH) {
5439 bus_connect_system_ssh(NULL, arg_host, &bus, &error);
5440 private_bus = false;
5442 assert_not_reached("Uh, invalid transport...");
5445 switch (arg_action) {
5447 case ACTION_SYSTEMCTL:
5448 r = systemctl_main(bus, argc, argv, &error);
5452 case ACTION_POWEROFF:
5458 case ACTION_RUNLEVEL2:
5459 case ACTION_RUNLEVEL3:
5460 case ACTION_RUNLEVEL4:
5461 case ACTION_RUNLEVEL5:
5463 case ACTION_EMERGENCY:
5464 case ACTION_DEFAULT:
5465 r = start_with_fallback(bus);
5470 r = reload_with_fallback(bus);
5473 case ACTION_CANCEL_SHUTDOWN: {
5477 m = strv_join(arg_wall, " ");
5479 retval = EXIT_FAILURE;
5483 r = send_shutdownd(arg_when, SD_SHUTDOWN_NONE, false, !arg_no_wall, m);
5485 log_warning("Failed to talk to shutdownd, shutdown hasn't been cancelled: %s", strerror(-r));
5490 case ACTION_INVALID:
5491 case ACTION_RUNLEVEL:
5493 assert_not_reached("Unknown action");
5496 retval = r < 0 ? EXIT_FAILURE : r;
5500 dbus_connection_flush(bus);
5501 dbus_connection_close(bus);
5502 dbus_connection_unref(bus);
5505 dbus_error_free(&error);
5509 strv_free(arg_property);
5512 ask_password_agent_close();
5513 polkit_agent_close();